hongjli
2025-04-07 603944bff3fa6a0541235ed0ab39ef9ba986e648
场景页面优化
已修改3个文件
已添加1个文件
378 ■■■■■ 文件已修改
package-lock.json 212 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/app/ai-scene/page.tsx 41 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SceneIntroDialog.tsx 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package-lock.json
@@ -8,6 +8,7 @@
      "name": "weiwojunchen",
      "version": "0.1.0",
      "dependencies": {
        "@headlessui/react": "^2.2.1",
        "@types/styled-components": "^5.1.34",
        "axios": "^1.8.4",
        "framer-motion": "^12.6.0",
@@ -231,6 +232,78 @@
      },
      "engines": {
        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
      }
    },
    "node_modules/@floating-ui/core": {
      "version": "1.6.9",
      "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.9.tgz",
      "integrity": "sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==",
      "license": "MIT",
      "dependencies": {
        "@floating-ui/utils": "^0.2.9"
      }
    },
    "node_modules/@floating-ui/dom": {
      "version": "1.6.13",
      "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.13.tgz",
      "integrity": "sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==",
      "license": "MIT",
      "dependencies": {
        "@floating-ui/core": "^1.6.0",
        "@floating-ui/utils": "^0.2.9"
      }
    },
    "node_modules/@floating-ui/react": {
      "version": "0.26.28",
      "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.28.tgz",
      "integrity": "sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw==",
      "license": "MIT",
      "dependencies": {
        "@floating-ui/react-dom": "^2.1.2",
        "@floating-ui/utils": "^0.2.8",
        "tabbable": "^6.0.0"
      },
      "peerDependencies": {
        "react": ">=16.8.0",
        "react-dom": ">=16.8.0"
      }
    },
    "node_modules/@floating-ui/react-dom": {
      "version": "2.1.2",
      "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz",
      "integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==",
      "license": "MIT",
      "dependencies": {
        "@floating-ui/dom": "^1.0.0"
      },
      "peerDependencies": {
        "react": ">=16.8.0",
        "react-dom": ">=16.8.0"
      }
    },
    "node_modules/@floating-ui/utils": {
      "version": "0.2.9",
      "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz",
      "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==",
      "license": "MIT"
    },
    "node_modules/@headlessui/react": {
      "version": "2.2.1",
      "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-2.2.1.tgz",
      "integrity": "sha512-daiUqVLae8CKVjEVT19P/izW0aGK0GNhMSAeMlrDebKmoVZHcRRwbxzgtnEadUVDXyBsWo9/UH4KHeniO+0tMg==",
      "license": "MIT",
      "dependencies": {
        "@floating-ui/react": "^0.26.16",
        "@react-aria/focus": "^3.17.1",
        "@react-aria/interactions": "^3.21.3",
        "@tanstack/react-virtual": "^3.11.1"
      },
      "engines": {
        "node": ">=10"
      },
      "peerDependencies": {
        "react": "^18 || ^19 || ^19.0.0-rc",
        "react-dom": "^18 || ^19 || ^19.0.0-rc"
      }
    },
    "node_modules/@humanfs/core": {
@@ -865,6 +938,103 @@
        "node": ">=12.4.0"
      }
    },
    "node_modules/@react-aria/focus": {
      "version": "3.20.1",
      "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.20.1.tgz",
      "integrity": "sha512-lgYs+sQ1TtBrAXnAdRBQrBo0/7o5H6IrfDxec1j+VRpcXL0xyk0xPq+m3lZp8typzIghqDgpnKkJ5Jf4OrzPIw==",
      "license": "Apache-2.0",
      "dependencies": {
        "@react-aria/interactions": "^3.24.1",
        "@react-aria/utils": "^3.28.1",
        "@react-types/shared": "^3.28.0",
        "@swc/helpers": "^0.5.0",
        "clsx": "^2.0.0"
      },
      "peerDependencies": {
        "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1",
        "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
      }
    },
    "node_modules/@react-aria/interactions": {
      "version": "3.24.1",
      "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.24.1.tgz",
      "integrity": "sha512-OWEcIC6UQfWq4Td5Ptuh4PZQ4LHLJr/JL2jGYvuNL6EgL3bWvzPrRYIF/R64YbfVxIC7FeZpPSkS07sZ93/NoA==",
      "license": "Apache-2.0",
      "dependencies": {
        "@react-aria/ssr": "^3.9.7",
        "@react-aria/utils": "^3.28.1",
        "@react-stately/flags": "^3.1.0",
        "@react-types/shared": "^3.28.0",
        "@swc/helpers": "^0.5.0"
      },
      "peerDependencies": {
        "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1",
        "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
      }
    },
    "node_modules/@react-aria/ssr": {
      "version": "3.9.7",
      "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.7.tgz",
      "integrity": "sha512-GQygZaGlmYjmYM+tiNBA5C6acmiDWF52Nqd40bBp0Znk4M4hP+LTmI0lpI1BuKMw45T8RIhrAsICIfKwZvi2Gg==",
      "license": "Apache-2.0",
      "dependencies": {
        "@swc/helpers": "^0.5.0"
      },
      "engines": {
        "node": ">= 12"
      },
      "peerDependencies": {
        "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
      }
    },
    "node_modules/@react-aria/utils": {
      "version": "3.28.1",
      "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.28.1.tgz",
      "integrity": "sha512-mnHFF4YOVu9BRFQ1SZSKfPhg3z+lBRYoW5mLcYTQihbKhz48+I1sqRkP7ahMITr8ANH3nb34YaMME4XWmK2Mgg==",
      "license": "Apache-2.0",
      "dependencies": {
        "@react-aria/ssr": "^3.9.7",
        "@react-stately/flags": "^3.1.0",
        "@react-stately/utils": "^3.10.5",
        "@react-types/shared": "^3.28.0",
        "@swc/helpers": "^0.5.0",
        "clsx": "^2.0.0"
      },
      "peerDependencies": {
        "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1",
        "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
      }
    },
    "node_modules/@react-stately/flags": {
      "version": "3.1.0",
      "resolved": "https://registry.npmjs.org/@react-stately/flags/-/flags-3.1.0.tgz",
      "integrity": "sha512-KSHOCxTFpBtxhIRcKwsD1YDTaNxFtCYuAUb0KEihc16QwqZViq4hasgPBs2gYm7fHRbw7WYzWKf6ZSo/+YsFlg==",
      "license": "Apache-2.0",
      "dependencies": {
        "@swc/helpers": "^0.5.0"
      }
    },
    "node_modules/@react-stately/utils": {
      "version": "3.10.5",
      "resolved": "https://registry.npmjs.org/@react-stately/utils/-/utils-3.10.5.tgz",
      "integrity": "sha512-iMQSGcpaecghDIh3mZEpZfoFH3ExBwTtuBEcvZ2XnGzCgQjeYXcMdIUwAfVQLXFTdHUHGF6Gu6/dFrYsCzySBQ==",
      "license": "Apache-2.0",
      "dependencies": {
        "@swc/helpers": "^0.5.0"
      },
      "peerDependencies": {
        "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
      }
    },
    "node_modules/@react-types/shared": {
      "version": "3.28.0",
      "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.28.0.tgz",
      "integrity": "sha512-9oMEYIDc3sk0G5rysnYvdNrkSg7B04yTKl50HHSZVbokeHpnU0yRmsDaWb9B/5RprcKj8XszEk5guBO8Sa/Q+Q==",
      "license": "Apache-2.0",
      "peerDependencies": {
        "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
      }
    },
    "node_modules/@rtsao/scc": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz",
@@ -1129,6 +1299,33 @@
        "lightningcss": "1.29.2",
        "postcss": "^8.4.41",
        "tailwindcss": "4.0.16"
      }
    },
    "node_modules/@tanstack/react-virtual": {
      "version": "3.13.6",
      "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.13.6.tgz",
      "integrity": "sha512-WT7nWs8ximoQ0CDx/ngoFP7HbQF9Q2wQe4nh2NB+u2486eX3nZRE40P9g6ccCVq7ZfTSH5gFOuCoVH5DLNS/aA==",
      "license": "MIT",
      "dependencies": {
        "@tanstack/virtual-core": "3.13.6"
      },
      "funding": {
        "type": "github",
        "url": "https://github.com/sponsors/tannerlinsley"
      },
      "peerDependencies": {
        "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
        "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
      }
    },
    "node_modules/@tanstack/virtual-core": {
      "version": "3.13.6",
      "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.13.6.tgz",
      "integrity": "sha512-cnQUeWnhNP8tJ4WsGcYiX24Gjkc9ALstLbHcBj1t3E7EimN6n6kHH+DPV4PpDnuw00NApQp+ViojMj1GRdwYQg==",
      "license": "MIT",
      "funding": {
        "type": "github",
        "url": "https://github.com/sponsors/tannerlinsley"
      }
    },
    "node_modules/@tybys/wasm-util": {
@@ -2065,6 +2262,15 @@
      "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
      "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
      "license": "MIT"
    },
    "node_modules/clsx": {
      "version": "2.1.1",
      "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
      "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
      "license": "MIT",
      "engines": {
        "node": ">=6"
      }
    },
    "node_modules/color": {
      "version": "4.2.3",
@@ -5612,6 +5818,12 @@
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/tabbable": {
      "version": "6.2.0",
      "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz",
      "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==",
      "license": "MIT"
    },
    "node_modules/tailwindcss": {
      "version": "4.0.16",
      "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.0.16.tgz",
package.json
@@ -9,6 +9,7 @@
    "lint": "next lint"
  },
  "dependencies": {
    "@headlessui/react": "^2.2.1",
    "@types/styled-components": "^5.1.34",
    "axios": "^1.8.4",
    "framer-motion": "^12.6.0",
src/app/ai-scene/page.tsx
@@ -3,6 +3,7 @@
import { useState } from 'react';
import Card from '@/components/Card';
import ChatDialog from '@/components/ChatDialog';
import SceneIntroDialog from '@/components/SceneIntroDialog';
import Navbar from '@/components/layout/Navbar';
const services = [
@@ -10,37 +11,51 @@
    title: '补料',
    description: '智能动态分析产线,工位的缺料情况,降低停线风险',
    imageUrl: '/images/kanban.jpg',
    chatbotId: 'JELkWpPLHQfRNhEH'
    chatbotId: 'JELkWpPLHQfRNhEH',
    background: '在生产线运行过程中,及时发现并解决缺料问题是保证生产效率的关键。AI系统通过实时监控和分析,帮助您提前预警可能的缺料风险,优化补料计划。',
    instructions: '您可以描述具体的生产线情况和缺料问题,AI助手将基于历史数据和实时状态,为您提供最优的补料方案和建议。'
  },
  {
    title: '插单',
    description: '智能评估需求插单对产能,原材料和交付服务的影响,提升客户满意度',
    imageUrl: '/images/xuqiu.jpg',
    chatbotId: 'DfH4cIzujVGvn5iR'
    chatbotId: 'DfH4cIzujVGvn5iR',
    background: '在生产计划执行过程中,常常会遇到紧急订单需要插单的情况。AI系统可以快速评估插单对现有生产计划的影响,并提供最优的插单方案。',
    instructions: '请提供需要插单的订单信息,包括产品类型、数量和期望交付时间,AI助手将为您分析可行性并给出具体的插单建议。'
  },
  {
    title: '科沃斯销售推荐小助手',
    description: '智能化产品推荐提升导购效率',
    imageUrl: '/images/robot.jpg',
    chatbotId: 'sUAviPXvcEIw3oQC'
    chatbotId: 'sUAviPXvcEIw3oQC',
    background: '面对不同客户的个性化需求,如何准确推荐合适的产品是提升销售效率的关键。AI助手基于深度学习算法,能够精准分析客户需求,提供个性化的产品推荐。',
    instructions: '您可以描述客户的具体需求和偏好,AI助手将根据这些信息,为您推荐最适合的科沃斯产品,并提供专业的产品介绍和销售建议。'
  },
  {
    title: '库存管理知识库问答',
    description: '库存知识,提供专业的供应链库存知识问答',
    imageUrl: '/images/know.jpg',
    chatbotId: 'pDDfkU9HyBl2gzXx'
    chatbotId: 'pDDfkU9HyBl2gzXx',
    background: '高效的库存管理需要丰富的专业知识和经验。AI知识库整合了大量供应链和库存管理的专业知识,可以快速解答各类库存管理问题。',
    instructions: '您可以询问任何与库存管理相关的问题,包括库存策略、成本控制、周转率优化等,AI助手将为您提供专业的解答和建议。'
  },
];
export default function AIScenePage() {
  const [isChatOpen, setIsChatOpen] = useState(false);
  const [isIntroOpen, setIsIntroOpen] = useState(false);
  const [currentChatbot, setCurrentChatbot] = useState('');
  const [selectedScene, setSelectedScene] = useState(services[0]);
  const handleCardClick = (title: string, chatbotId?: string) => {
    if (chatbotId) {
      setCurrentChatbot(chatbotId);
  const handleCardClick = (service: typeof services[0]) => {
    setSelectedScene(service);
    setIsIntroOpen(true);
  };
  const handleStartChat = () => {
    setIsIntroOpen(false);
    setCurrentChatbot(selectedScene.chatbotId);
      setIsChatOpen(true);
    }
  };
  return (
@@ -62,12 +77,20 @@
                <Card
                  key={index}
                  {...service}
                  onClick={() => handleCardClick(service.title, service.chatbotId)}
                  onClick={() => handleCardClick(service)}
                />
              ))}
            </div>
          </div>
        </div>
        <SceneIntroDialog
          isOpen={isIntroOpen}
          onClose={() => setIsIntroOpen(false)}
          onStartChat={handleStartChat}
          scene={selectedScene}
        />
        <ChatDialog 
          isOpen={isChatOpen} 
          onClose={() => setIsChatOpen(false)}
src/components/SceneIntroDialog.tsx
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,124 @@
"use client";
import { Dialog, Transition } from '@headlessui/react';
import { Fragment } from 'react';
interface SceneIntroDialogProps {
  isOpen: boolean;
  onClose: () => void;
  onStartChat: () => void;
  scene: {
    title: string;
    description: string;
    imageUrl: string;
    background?: string;
    instructions?: string;
  };
}
export default function SceneIntroDialog({
  isOpen,
  onClose,
  onStartChat,
  scene
}: SceneIntroDialogProps) {
  return (
    <Transition appear show={isOpen} as={Fragment}>
      <Dialog as="div" className="relative z-50" onClose={onClose}>
        <Transition.Child
          as={Fragment}
          enter="ease-out duration-300"
          enterFrom="opacity-0"
          enterTo="opacity-100"
          leave="ease-out duration-200"
          leaveFrom="opacity-100"
          leaveTo="opacity-0"
        >
          <div className="fixed inset-0 bg-black/70" />
        </Transition.Child>
        <div className="fixed inset-0 overflow-y-auto">
          <div className="flex min-h-full items-center justify-center p-4">
            <Transition.Child
              as={Fragment}
              enter="ease-out duration-300"
              enterFrom="opacity-0 scale-95"
              enterTo="opacity-100 scale-100"
              leave="ease-out duration-200"
              leaveFrom="opacity-100 scale-100"
              leaveTo="opacity-0 scale-95"
            >
              <Dialog.Panel className="w-full max-w-2xl transform overflow-hidden rounded-2xl bg-gradient-to-br from-[#1E2B63] to-[#0A1033] p-6 shadow-xl transition-all">
                {/* ç§‘技感背景效果 */}
                <div className="absolute inset-0 overflow-hidden pointer-events-none">
                  <div className="absolute inset-0 opacity-10"
                    style={{
                      backgroundImage: 'radial-gradient(circle, rgba(106, 219, 255, 0.3) 1px, transparent 1px)',
                      backgroundSize: '20px 20px'
                    }}>
                  </div>
                  <div className="absolute top-0 left-0 right-0 h-[1px] bg-gradient-to-r from-transparent via-[#6ADBFF]/40 to-transparent"></div>
                  <div className="absolute bottom-0 left-0 right-0 h-[1px] bg-gradient-to-r from-transparent via-[#6ADBFF]/40 to-transparent"></div>
                </div>
                <div className="relative">
                  {/* æ ‡é¢˜ */}
                  <Dialog.Title className="text-2xl font-bold text-white mb-4">
                    <span className="text-transparent bg-clip-text bg-gradient-to-r from-[#6ADBFF] to-[#5E72EB]">
                      {scene.title}
                    </span>
                  </Dialog.Title>
                  {/* åœºæ™¯å›¾ç‰‡ */}
                  <div className="relative h-48 mb-6 rounded-lg overflow-hidden">
                    <img
                      src={scene.imageUrl}
                      alt={scene.title}
                      className="w-full h-full object-cover"
                    />
                    <div className="absolute inset-0 bg-gradient-to-t from-[#0A1033]/80 to-transparent"></div>
                  </div>
                  {/* åœºæ™¯èƒŒæ™¯ */}
                  <div className="mb-6">
                    <h3 className="text-lg font-semibold text-[#6ADBFF] mb-2">场景背景</h3>
                    <p className="text-gray-300 leading-relaxed">
                      {scene.background || scene.description}
                    </p>
                  </div>
                  {/* ä½¿ç”¨è¯´æ˜Ž */}
                  <div className="mb-8">
                    <h3 className="text-lg font-semibold text-[#6ADBFF] mb-2">使用说明</h3>
                    <p className="text-gray-300 leading-relaxed">
                      {scene.instructions || '通过自然语言对话的方式,描述您的具体需求,AI助手将为您提供专业的解决方案。'}
                    </p>
                  </div>
                  {/* æŒ‰é’®ç»„ */}
                  <div className="flex justify-end gap-4">
                    <button
                      onClick={onClose}
                      className="px-4 py-2 text-sm font-medium text-gray-300 hover:text-white transition-colors"
                    >
                      å…³é—­
                    </button>
                    <button
                      onClick={onStartChat}
                      className="relative px-6 py-2 rounded-lg overflow-hidden group backdrop-blur-sm bg-white/5 border border-[#6ADBFF]/30 hover:border-[#6ADBFF]/50 transition-all duration-300"
                    >
                      <div className="absolute inset-0 bg-gradient-to-r from-[#6ADBFF]/5 to-[#5E72EB]/5 group-hover:from-[#6ADBFF]/10 group-hover:to-[#5E72EB]/10 transition-all duration-300"></div>
                      <span className="relative text-white group-hover:text-[#6ADBFF] transition-colors duration-300">
                        å¼€å§‹ä½¿ç”¨
                      </span>
                    </button>
                  </div>
                </div>
              </Dialog.Panel>
            </Transition.Child>
          </div>
        </div>
      </Dialog>
    </Transition>
  );
}