| | |
| | | 'use client'; |
| | | |
| | | import { useState, useEffect, useRef, useCallback, useContext, createContext } from 'react'; |
| | | import { useState, useEffect, useRef, useCallback, useContext, createContext, Suspense } from 'react'; |
| | | import Link from 'next/link'; |
| | | import { useRouter, useSearchParams } from 'next/navigation'; |
| | | import Image from 'next/image'; |
| | |
| | | import rehypeSanitize from 'rehype-sanitize'; |
| | | import dynamic from 'next/dynamic'; |
| | | import { ReactNode } from 'react'; |
| | | import DataPreviewDialog from '@/components/DataPreviewDialog'; |
| | | |
| | | // 创建一个消息完成状态的Context |
| | | const MessageCompletionContext = createContext<boolean>(true); |
| | |
| | | } |
| | | |
| | | const BASE_URL = 'http://121.43.139.99:7000'; |
| | | |
| | | // 供应链全景洞察场景数据 |
| | | const SUPPLY_CHAIN_SCENE = { |
| | | title: '供应链全景洞察', |
| | | description: '通过AI Agent与APS的深度协同,将插单响应从"被动救火"升级为"预测-决策-执行"三位一体的智能运营模式,助力新能源业务增长。', |
| | | imageUrl: '/images/333.png', |
| | | chatbotId: 'SCPanoramaInsight', |
| | | background: `供应链全景洞察系统是新一代智能供应链管理平台的核心引擎。该AI系统能够解决传统供应链管理中的四大关键问题: |
| | | |
| | | **生产计划与产能影响评估:** |
| | | - 实时监控生产线状态,动态评估产能利用率 |
| | | - 基于历史数据和实时订单,智能预测生产瓶颈 |
| | | - 自动调整生产计划,最大化产能利用效率 |
| | | - 提供多场景生产计划对比分析,辅助决策制定 |
| | | |
| | | **供应协同能力评估:** |
| | | - 实时追踪供应商交付状态,评估供应风险 |
| | | - 智能分析供应商绩效,提供供应商优化建议 |
| | | - 预测原材料需求,提前启动采购流程 |
| | | - 构建供应链网络韧性模型,提升抗风险能力 |
| | | |
| | | **交付履约风险评估:** |
| | | - 基于订单、库存、生产进度进行综合风险评估 |
| | | - 提前识别潜在延期风险,制定应对预案 |
| | | - 实时跟踪交付进度,确保客户满意度 |
| | | - 建立客户预期管理机制,提升服务体验 |
| | | |
| | | **成本与财务影响评估:** |
| | | - 全链路成本追踪,精确计算各环节成本构成 |
| | | - 动态成本优化建议,降低整体运营成本 |
| | | - 财务影响预测分析,支持商业决策 |
| | | - ROI评估模型,量化改进措施的财务效益`, |
| | | instructions: `您可以通过以下方式与供应链全景洞察系统互动: |
| | | |
| | | **场景一:插单影响分析** |
| | | 提供新订单信息,系统将从四个维度评估插单可行性和影响。 |
| | | |
| | | **场景二:生产计划优化** |
| | | 描述当前生产状况,获取智能优化建议和风险预警。 |
| | | |
| | | **场景三:供应链风险评估** |
| | | 输入供应商或原材料信息,获取供应风险分析和应对策略。 |
| | | |
| | | **场景四:成本优化分析** |
| | | 提供成本相关数据,获取成本优化建议和财务影响评估。 |
| | | |
| | | 系统将基于实时数据和AI算法,为您提供专业的分析报告和决策建议。`, |
| | | dataDescription: '本场景整合了OMS、ERP、WMS等多个系统的实时数据,通过AI算法进行深度分析。以下为新能源行业的模拟数据,实际应用中将自动对接企业现有系统。', |
| | | exampleData: ` |
| | | ### 订单需求数据 (OMS系统) |
| | | |
| | | | 订单号 | 产品型号 | 数量 | 客户名称 | 预期交付日期 | 优先级 | 订单金额 | |
| | | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | |
| | | | SO20250201001 | NEV-Battery-A | 500 | 比亚迪 | 2025-02-15 | 高 | 2,500,000 | |
| | | | SO20250201002 | NEV-Motor-B | 200 | 蔚来汽车 | 2025-02-20 | 中 | 1,800,000 | |
| | | | SO20250201003 | NEV-Controller-C | 300 | 理想汽车 | 2025-02-25 | 高 | 3,200,000 | |
| | | | SO20250201004 | NEV-Charger-D | 150 | 小鹏汽车 | 2025-03-01 | 中 | 1,200,000 | |
| | | |
| | | ### 生产工单数据 (ERP系统) |
| | | |
| | | | 工单号 | 产品型号 | 计划数量 | 已完成数量 | 生产状态 | 预计完成时间 | 生产线 | |
| | | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | |
| | | | WO20250201001 | NEV-Battery-A | 600 | 350 | 进行中 | 2025-02-12 | 产线1 | |
| | | | WO20250201002 | NEV-Motor-B | 250 | 180 | 进行中 | 2025-02-18 | 产线2 | |
| | | | WO20250201003 | NEV-Controller-C | 200 | 50 | 计划中 | 2025-02-22 | 产线3 | |
| | | | WO20250201004 | NEV-Charger-D | 100 | 0 | 待排产 | 2025-02-28 | 产线4 | |
| | | |
| | | ### 库存数据 (WMS系统) |
| | | |
| | | | 物料编码 | 物料名称 | 当前库存 | 安全库存 | 在途数量 | 预计到货时间 | 库位 | |
| | | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | |
| | | | MAT001 | 锂电池芯 | 1,200 | 500 | 800 | 2025-02-10 | A区-01 | |
| | | | MAT002 | 电机定子 | 350 | 200 | 150 | 2025-02-12 | B区-02 | |
| | | | MAT003 | 控制芯片 | 180 | 100 | 200 | 2025-02-15 | C区-03 | |
| | | | MAT004 | 充电模块 | 95 | 50 | 100 | 2025-02-18 | D区-04 | |
| | | |
| | | ### 供应商绩效数据 |
| | | |
| | | | 供应商名称 | 供应物料 | 按时交付率 | 质量合格率 | 价格竞争力 | 风险等级 | |
| | | | :--: | :--: | :--: | :--: | :--: | :--: | |
| | | | 宁德时代 | 锂电池芯 | 95% | 99.5% | 高 | 低 | |
| | | | 汇川技术 | 电机定子 | 88% | 98.2% | 中 | 中 | |
| | | | 地平线 | 控制芯片 | 92% | 99.8% | 中 | 低 | |
| | | | 特来电 | 充电模块 | 85% | 97.5% | 高 | 中 | |
| | | |
| | | ### 产能数据 |
| | | |
| | | | 生产线 | 日产能 | 当前利用率 | 瓶颈工序 | 可调配产能 | 维护计划 | |
| | | | :--: | :--: | :--: | :--: | :--: | :--: | |
| | | | 产线1 | 50台 | 85% | 组装 | 10台 | 2025-02-20 | |
| | | | 产线2 | 30台 | 75% | 测试 | 8台 | 2025-02-25 | |
| | | | 产线3 | 40台 | 60% | 焊接 | 15台 | 2025-03-01 | |
| | | | 产线4 | 25台 | 45% | 包装 | 12台 | 2025-03-05 | |
| | | ` |
| | | }; |
| | | |
| | | // 默认用户头像 |
| | | const DEFAULT_USER_AVATAR = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23999999'%3E%3Cpath d='M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 3c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zm0 14.2c-2.5 0-4.71-1.28-6-3.22.03-1.99 4-3.08 6-3.08 1.99 0 5.97 1.09 6 3.08-1.29 1.94-3.5 3.22-6 3.22z'/%3E%3C/svg%3E"; |
| | |
| | | ); |
| | | } |
| | | |
| | | export default function SupplyChainChatPage() { |
| | | // 创建一个独立的组件来处理useSearchParams |
| | | function SupplyChainChatContent() { |
| | | const router = useRouter(); |
| | | const searchParams = useSearchParams(); |
| | | const [apiKey, setApiKey] = useState<string>(''); |
| | |
| | | |
| | | // 添加API密钥加载状态 |
| | | const [isLoadingApiKey, setIsLoadingApiKey] = useState(false); |
| | | |
| | | // 添加说明对话框状态 |
| | | const [showDataPreview, setShowDataPreview] = useState(false); |
| | | const [showSceneBackground, setShowSceneBackground] = useState(false); |
| | | const [showInstructions, setShowInstructions] = useState(false); |
| | | |
| | | // 获取URL参数 |
| | | const keyParam = searchParams.get('key'); |
| | |
| | | </h1> |
| | | </div> |
| | | <div className="flex items-center space-x-4"> |
| | | {/* 说明按钮组 */} |
| | | <div className="flex items-center space-x-2"> |
| | | <button |
| | | onClick={() => setShowSceneBackground(true)} |
| | | className="px-3 py-1.5 text-xs text-gray-600 hover:text-blue-600 hover:bg-blue-50 rounded-lg transition-all duration-300 border border-gray-200 hover:border-blue-200 cursor-pointer" |
| | | title="查看场景背景" |
| | | > |
| | | 场景背景 |
| | | </button> |
| | | <button |
| | | onClick={() => setShowInstructions(true)} |
| | | className="px-3 py-1.5 text-xs text-gray-600 hover:text-blue-600 hover:bg-blue-50 rounded-lg transition-all duration-300 border border-gray-200 hover:border-blue-200 cursor-pointer" |
| | | title="查看使用说明" |
| | | > |
| | | 使用说明 |
| | | </button> |
| | | <button |
| | | onClick={() => setShowDataPreview(true)} |
| | | className="px-3 py-1.5 text-xs text-gray-600 hover:text-blue-600 hover:bg-blue-50 rounded-lg transition-all duration-300 border border-gray-200 hover:border-blue-200 cursor-pointer" |
| | | title="查看数据说明" |
| | | > |
| | | 数据说明 |
| | | </button> |
| | | </div> |
| | | <div className="h-4 w-px bg-gray-200"></div> |
| | | <div className="px-3 py-1 bg-green-100 text-green-700 text-sm rounded-full"> |
| | | AI智能分析 |
| | | </div> |
| | |
| | | </div> |
| | | <h3 className="text-lg font-medium text-gray-900 mb-2">供应链全景洞察</h3> |
| | | <p className="text-gray-500 max-w-md"> |
| | | 欢迎使用供应链全景洞察系统!您可以咨询插单影响分析、生产计划优化、供应链风险评估等问题。 |
| | | 欢迎使用供应链全景洞察系统!您可以咨询生产计划与产能影响、供应协同能力、交付履约风险、成本与财务影响、供应链数据查询、供应链知识咨询等问题。 |
| | | </p> |
| | | </div> |
| | | ) : ( |
| | |
| | | isMessageComplete={isMessageComplete} |
| | | /> |
| | | </div> |
| | | |
| | | {/* 场景背景对话框 */} |
| | | {showSceneBackground && ( |
| | | <div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4"> |
| | | <div className="bg-white rounded-2xl w-full max-w-4xl max-h-[80vh] overflow-hidden shadow-xl"> |
| | | <div className="flex justify-between items-center p-6 border-b border-gray-200"> |
| | | <div className="flex items-center gap-3"> |
| | | <div className="w-10 h-10 bg-blue-100 rounded-lg flex items-center justify-center"> |
| | | <svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 text-blue-600" fill="none" viewBox="0 0 24 24" stroke="currentColor"> |
| | | <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 10V3L4 14h7v7l9-11h-7z" /> |
| | | </svg> |
| | | </div> |
| | | <h2 className="text-xl font-semibold text-gray-900">场景背景</h2> |
| | | </div> |
| | | <button |
| | | onClick={() => setShowSceneBackground(false)} |
| | | className="p-2 text-gray-400 hover:text-gray-600 hover:bg-gray-100 rounded-full transition-colors cursor-pointer" |
| | | > |
| | | <svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"> |
| | | <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" /> |
| | | </svg> |
| | | </button> |
| | | </div> |
| | | <div className="p-6 overflow-y-auto max-h-[60vh]"> |
| | | <div className="prose prose-sm max-w-none"> |
| | | <ReactMarkdown |
| | | remarkPlugins={[remarkGfm]} |
| | | rehypePlugins={[rehypeRaw, rehypeSanitize]} |
| | | > |
| | | {SUPPLY_CHAIN_SCENE.background} |
| | | </ReactMarkdown> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | )} |
| | | |
| | | {/* 使用说明对话框 */} |
| | | {showInstructions && ( |
| | | <div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4"> |
| | | <div className="bg-white rounded-2xl w-full max-w-4xl max-h-[80vh] overflow-hidden shadow-xl"> |
| | | <div className="flex justify-between items-center p-6 border-b border-gray-200"> |
| | | <div className="flex items-center gap-3"> |
| | | <div className="w-10 h-10 bg-green-100 rounded-lg flex items-center justify-center"> |
| | | <svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 text-green-600" fill="none" viewBox="0 0 24 24" stroke="currentColor"> |
| | | <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253" /> |
| | | </svg> |
| | | </div> |
| | | <h2 className="text-xl font-semibold text-gray-900">使用说明</h2> |
| | | </div> |
| | | <button |
| | | onClick={() => setShowInstructions(false)} |
| | | className="p-2 text-gray-400 hover:text-gray-600 hover:bg-gray-100 rounded-full transition-colors cursor-pointer" |
| | | > |
| | | <svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"> |
| | | <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" /> |
| | | </svg> |
| | | </button> |
| | | </div> |
| | | <div className="p-6 overflow-y-auto max-h-[60vh]"> |
| | | <div className="prose prose-sm max-w-none"> |
| | | <ReactMarkdown |
| | | remarkPlugins={[remarkGfm]} |
| | | rehypePlugins={[rehypeRaw, rehypeSanitize]} |
| | | > |
| | | {SUPPLY_CHAIN_SCENE.instructions} |
| | | </ReactMarkdown> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | )} |
| | | |
| | | {/* 数据说明对话框 */} |
| | | <DataPreviewDialog |
| | | isOpen={showDataPreview} |
| | | onClose={() => setShowDataPreview(false)} |
| | | markdownContent={SUPPLY_CHAIN_SCENE.exampleData} |
| | | sceneType="panorama" |
| | | /> |
| | | </div> |
| | | ); |
| | | } |
| | | |
| | | // 主导出组件,使用Suspense包装原有组件 |
| | | export default function SupplyChainChatPage() { |
| | | return ( |
| | | <Suspense fallback={ |
| | | <div className="min-h-screen bg-gradient-to-b from-gray-50 to-white flex items-center justify-center"> |
| | | <div className="text-center"> |
| | | <div className="w-8 h-8 border-4 border-blue-600 border-t-transparent rounded-full animate-spin mx-auto mb-4"></div> |
| | | <p className="text-gray-600">正在加载...</p> |
| | | </div> |
| | | </div> |
| | | }> |
| | | <SupplyChainChatContent /> |
| | | </Suspense> |
| | | ); |
| | | } |