hongjli
2025-06-05 7c75be06b084a57193d9915c6197294049a365c5
src/app/supply-chain-chat/page.tsx
@@ -10,6 +10,7 @@
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);
@@ -35,6 +36,101 @@
}
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";
@@ -420,6 +516,11 @@
  // 添加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');
@@ -986,6 +1087,31 @@
            </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>
@@ -1202,6 +1328,86 @@
          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>
  );