hongjli
2025-04-10 d3841cfca8315382e85cf35a42fa8c01b42ab610
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
"use client";
 
import { useState, useEffect } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
 
// 导入场景数据
const defaultServices = [
  {
    title: '插单2.0',
    description: '智能评估需求插单对产能,原材料和交付服务的影响,提升客户满意度',
    imageUrl: '/images/xuqiu.jpg',
    chatbotId: 'zO9YQDEHdIApG9zC',
    background: '在生产计划执行过程中,常常会遇到紧急订单需要插单的情况。AI系统可以快速评估插单对现有生产计划的影响,并提供最优的插单方案。',
    instructions: '请提供需要插单的订单信息,包括产品类型、数量和期望交付时间,AI助手将为您分析可行性并给出具体的插单建议。'
  },
  {
    title: '补料',
    description: '智能动态分析产线,工位的缺料情况,降低停线风险',
    imageUrl: '/images/kanban.jpg',
    chatbotId: 'JELkWpPLHQfRNhEH',
  },
  {
    title: '插单1.0',
    description: '智能评估需求插单对产能,原材料和交付服务的影响,提升客户满意度',
    imageUrl: '/images/xuqiu.jpg',
    chatbotId: 'DfH4cIzujVGvn5iR',
    background: '在生产计划执行过程中,常常会遇到紧急订单需要插单的情况。AI系统可以快速评估插单对现有生产计划的影响,并提供最优的插单方案。',
    instructions: '请提供需要插单的订单信息,包括产品类型、数量和期望交付时间,AI助手将为您分析可行性并给出具体的插单建议。'
  },
  {
    title: '科沃斯销售推荐小助手',
    description: '智能化产品推荐提升导购效率',
    imageUrl: '/images/robot.jpg',
    chatbotId: 'sUAviPXvcEIw3oQC',
  },
  {
    title: '库存管理知识库问答',
    description: '库存知识,提供专业的供应链库存知识问答',
    imageUrl: '/images/know.jpg',
    chatbotId: 'pDDfkU9HyBl2gzXx',
  },
];
 
export default function AISceneChatPage() {
  const [services, setServices] = useState(defaultServices);
  const [selectedScene, setSelectedScene] = useState(services[0]);
  const [iframeKey, setIframeKey] = useState(0);
 
  // 切换场景时重新加载iframe
  const handleSceneChange = (scene: typeof services[0]) => {
    setSelectedScene(scene);
    setIframeKey(prev => prev + 1);
  };
 
  // 添加新场景
  const handleAddNewScene = () => {
    const newScene = {
      title: `新场景 ${services.length + 1}`,
      description: '这是一个新的AI场景',
      imageUrl: '/images/robot.jpg', // 默认图片
      chatbotId: `new-scene-${Date.now()}`, // 生成唯一ID
    };
    setServices(prev => [...prev, newScene]);
  };
 
  return (
    <div className="h-screen flex bg-white">
      {/* 左侧场景选项卡 */}
      <div className="w-64 bg-white border-r flex flex-col">
        {/* 固定头部 */}
        <div className="p-4 pt-20 bg-white">
          <h2 className="text-xl font-bold flex items-center mb-4">
            <span className="text-gray-900">
              AI场景
            </span>
            <motion.span 
              className="ml-2 inline-block w-2 h-2 rounded-full bg-[#6ADBFF]"
              animate={{ 
                scale: [1, 1.5, 1],
                opacity: [0.7, 1, 0.7] 
              }}
              transition={{ 
                duration: 2,
                repeat: Infinity,
                ease: "easeInOut"
              }}
            />
          </h2>
 
          {/* 新增场景按钮 */}
          <button
            onClick={handleAddNewScene}
            className="w-full p-3 bg-[#EEF3FD] text-[#4080FF] rounded-lg font-medium transition-all duration-300 flex items-center hover:bg-[#E1E9FA] group cursor-pointer"
          >
            <svg 
              className="w-5 h-5 mr-2" 
              viewBox="0 0 24 24"
              fill="none"
              stroke="currentColor"
            >
              <path 
                d="M12 5v14M5 12h14" 
                strokeWidth="2"
                strokeLinecap="round"
                strokeLinejoin="round"
              />
            </svg>
            开启新场景
          </button>
        </div>
 
        {/* 滚动内容区 */}
        <div className="flex-1 overflow-y-auto px-4 [&::-webkit-scrollbar]:w-1 [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:bg-[#E5E6EB] [&::-webkit-scrollbar-thumb]:rounded-full hover:[&::-webkit-scrollbar-thumb]:bg-[#C9CDD4]">
          <div className="space-y-3 py-4">
            {services.map((scene) => (
              <motion.div
                key={scene.chatbotId}
                className="relative group"
              >
                <motion.button
                  onClick={() => handleSceneChange(scene)}
                  className={`w-full p-4 rounded-lg text-left transition-all duration-500 relative cursor-pointer
                    ${selectedScene.chatbotId === scene.chatbotId 
                      ? 'text-[#6ADBFF] bg-gray-100 shadow-sm' 
                      : 'text-gray-600 hover:text-[#6ADBFF] hover:bg-gray-50'
                    }`}
                  whileHover={{ scale: 1.02 }}
                  whileTap={{ scale: 0.98 }}
                >
                  {selectedScene.chatbotId === scene.chatbotId && (
                    <motion.div
                      className="absolute inset-0 bg-gradient-to-r from-gray-100 to-gray-50 -z-10"
                      layoutId="activeBackground"
                      initial={false}
                      transition={{
                        type: "spring",
                        stiffness: 200,
                        damping: 20
                      }}
                    />
                  )}
                  <div className="flex items-center relative z-10">
                    <div className="w-8 h-8 rounded-lg overflow-hidden mr-3 relative flex-shrink-0">
                      <img 
                        src={scene.imageUrl} 
                        alt={scene.title}
                        className="w-full h-full object-cover transform transition-transform duration-700 group-hover:scale-110"
                      />
                      <div className="absolute inset-0 bg-gradient-to-br from-black/20 to-transparent"></div>
                    </div>
                    <div className="relative max-w-[120px] group/text">
                      <span className="font-medium truncate block w-full" ref={(el) => {
                        if (el) {
                          el.dataset.truncated = (el.scrollWidth > el.clientWidth).toString();
                        }
                      }}>{scene.title}</span>
                      {/* Tooltip - 只在文本被截断时显示 */}
                      <div 
                        className="absolute left-1/2 -translate-x-1/2 -top-2 -translate-y-full bg-gray-800/95 text-white text-sm px-3 py-2 rounded-lg opacity-0 invisible data-[show=true]:group-hover/text:opacity-100 data-[show=true]:group-hover/text:visible transition-all duration-200 whitespace-nowrap shadow-lg z-[1000]"
                        data-show={scene.title.length > 8}
                      >
                        <div className="absolute left-1/2 -translate-x-1/2 top-full border-[6px] border-transparent border-t-gray-800/95"></div>
                        {scene.title}
                      </div>
                    </div>
                  </div>
                  {selectedScene.chatbotId === scene.chatbotId && (
                    <motion.div
                      className="absolute right-3 top-1/2 -translate-y-1/2 w-1.5 h-6 bg-[#6ADBFF] rounded-full"
                      layoutId="activeIndicator"
                      initial={{ opacity: 0 }}
                      animate={{ opacity: 1 }}
                      exit={{ opacity: 0 }}
                    />
                  )}
                </motion.button>
              </motion.div>
            ))}
          </div>
        </div>
      </div>
 
      {/* 中间聊天区域 */}
      <div className="flex-1 flex flex-col bg-white pt-20 overflow-hidden">
        {/* 场景标题 */}
        <div className="h-16 bg-white flex items-center justify-center px-6 border-b">
          <h1 className="text-lg font-medium text-gray-900">
            {selectedScene.title}
          </h1>
        </div>
 
        {/* 聊天窗口 */}
        <div className="flex-1 relative [&::-webkit-scrollbar]:w-1 [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:bg-[#E5E6EB] [&::-webkit-scrollbar-thumb]:rounded-full hover:[&::-webkit-scrollbar-thumb]:bg-[#C9CDD4]">
          <AnimatePresence mode="wait">
            <motion.div
              key={iframeKey}
              className="absolute inset-0"
              initial={{ opacity: 0, scale: 0.98 }}
              animate={{ opacity: 1, scale: 1 }}
              exit={{ opacity: 0, scale: 1.02 }}
              transition={{ duration: 0.3 }}
            >
              <iframe
                src={`http://121.43.139.99/chatbot/${selectedScene.chatbotId}`}
                className="w-full h-full"
                style={{ border: 'none' }}
                allow="microphone"
              />
            </motion.div>
          </AnimatePresence>
        </div>
      </div>
    </div>
  );