diff --git a/src/components/Common/DataNavigation.tsx b/src/components/Common/DataNavigation.tsx index bcb7e58..ca60700 100644 --- a/src/components/Common/DataNavigation.tsx +++ b/src/components/Common/DataNavigation.tsx @@ -1,18 +1,22 @@ -import React from "react"; -import { Typography, Button } from "antd"; -import { AcademicCapIcon, ChevronRightIcon } from "@heroicons/react/24/outline"; +import React from "react" +import { Typography } from "antd" +import { ChevronRightIcon } from "@heroicons/react/24/outline" -const { Title } = Typography; +const { Title } = Typography type Props = { - Header: React.ReactNode; - showButton?: boolean; - onClick?: () => void; -}; + Header: React.ReactNode + showButton?: boolean + onClick?: () => void +} -export const DataNavigation: React.FC = ({ Header, showButton = true, onClick }) => { +export const DataNavigation: React.FC = ({ + Header, + showButton = true, + onClick +}) => { return ( -
+
{/* 左侧部分 */}
= ({ Header, showButton = true, onC {/* 右侧部分 */} {showButton && ( - <div className="flex items-center text-[#3a3a3a] cursor-pointer space-x-0.5 hover:text-[#00c0ef] transition" onClick={onClick}> + <div + className="flex items-center text-[#3a3a3a] cursor-pointer space-x-0.5 hover:text-[#3581e3] transition-colors duration-200" + onClick={onClick}> <span className="text-[12px]">更多</span> <ChevronRightIcon className="w-4 h-4" /> </div> )} </div> ) -}; +} diff --git a/src/components/Common/Playground/Data.tsx b/src/components/Common/Playground/Data.tsx index e04084f..d883570 100644 --- a/src/components/Common/Playground/Data.tsx +++ b/src/components/Common/Playground/Data.tsx @@ -1,8 +1,9 @@ -import React, { useMemo, useState } from "react" +import React, { useEffect, useMemo } from "react" import { DataNavigation } from "@/components/Common/DataNavigation.tsx" -import { Card, Drawer, Skeleton } from "antd" +import { Card, Skeleton } from "antd" import { useMessageOption } from "@/hooks/useMessageOption.tsx" import { IodRegistryEntry } from "@/types/iod.ts" +import { useIodPlaygroundContext } from "@/components/Option/Playground/PlaygroundIod.tsx" // import { Drawer } from './Drawer.tsx' @@ -32,45 +33,89 @@ const defaultData: IodRegistryEntry[] = [ } ] -type ShowCardProps = { +type HeaderProps = { + title: string + showButton?: boolean + onClick?: () => void +} +const Header: React.FC<HeaderProps> = ({ + title, + showButton = true, + onClick +}) => ( + <DataNavigation + Header={ + <div className="flex items-center gap-0.5 text-[#3581e3]"> + <svg + className="icon" + viewBox="0 0 1024 1024" + version="1.1" + xmlns="http://www.w3.org/2000/svg" + p-id="3572" + width="18" + height="18"> + <path + d="M877.714286 54.857143H754.285714V9.142857c0-5.028571-4.114286-9.142857-9.142857-9.142857h-64c-5.028571 0-9.142857 4.114286-9.142857 9.142857v45.714286H498.285714V9.142857c0-5.028571-4.114286-9.142857-9.142857-9.142857h-64c-5.028571 0-9.142857 4.114286-9.142857 9.142857v45.714286H292.571429c-20.228571 0-36.571429 16.342857-36.571429 36.571428v137.142858h-109.714286c-20.228571 0-36.571429 16.342857-36.571428 36.571428v722.285714c0 20.228571 16.342857 36.571429 36.571428 36.571429h585.142857c20.228571 0 36.571429-16.342857 36.571429-36.571429v-109.714285h109.714286c20.228571 0 36.571429-16.342857 36.571428-36.571429V91.428571c0-20.228571-16.342857-36.571429-36.571428-36.571428zM685.714286 941.714286H192V310.857143h249.142857v198.857143c0 25.257143 20.457143 45.714286 45.714286 45.714285h198.857143v386.285715z m0-459.428572H514.285714V310.857143h0.228572L685.714286 482.057143v0.228571z m146.285714 313.142857h-64V448L548.571429 228.571429H338.285714v-91.428572h77.714286v36.571429c0 5.028571 4.114286 9.142857 9.142857 9.142857h64c5.028571 0 9.142857-4.114286 9.142857-9.142857v-36.571429h173.714286v36.571429c0 5.028571 4.114286 9.142857 9.142857 9.142857h64c5.028571 0 9.142857-4.114286 9.142857-9.142857v-36.571429h77.714286v658.285714z" + p-id="3573" + fill="#3581e3"></path> + </svg> + {title} + </div> + } + showButton={showButton} + onClick={onClick} + /> +) + +type MainProps = { loading: boolean - record: IodRegistryEntry + data: IodRegistryEntry[] truncate?: boolean } - -const ShowCard: React.FC<ShowCardProps> = ({ - loading, - record, - truncate = true -}) => ( - <Card className="[&_.ant-card-body]:!p-2 !bg-[gb(248, 248, 248)] border !border-[#e9e9e9]"> - {loading ? ( - <Skeleton title={false} active /> - ) : ( - <div className="flex flex-col gap-0.5"> - <h3 - className={`text-base font-medium mb-1 text-[#222222] break-all ${truncate ? "line-clamp-2" : ""}`} - title={record.name}> - {record.name} - </h3> - <p - className={`text-sm text-[#383838] break-all ${truncate ? "line-clamp-2" : ""}`} - title={record.doId}> - 数字对象标识:{record.doId} - </p> - <p - className={`text-[#828282] text-xs break-all ${truncate ? "truncate" : ""}`} - title={record.description}> - {record.description} - </p> - </div> - )} - </Card> +const Main: React.FC<MainProps> = ({ data, loading, truncate = true }) => ( + <div className="space-y-1.5 flex-1 overflow-y-auto"> + {data.map((item, index) => { + return ( + <Card + className="[&_.ant-card-body]:!p-2 !bg-[gb(248, 248, 248)] border !border-[#e9e9e9]" + key={item.doId}> + {loading ? ( + <Skeleton title={false} active /> + ) : ( + <div className="flex flex-col gap-0.5"> + <h3 + className={`text-base font-medium mb-1 text-[#222222] break-all ${truncate ? "line-clamp-2" : ""}`} + title={item.name}> + {item.name} + </h3> + <p + className={`text-sm text-[#383838] break-all ${truncate ? "line-clamp-2" : ""}`} + title={item.doId}> + 数字对象标识:{item.doId} + </p> + <p + className={`text-[#828282] text-xs break-all ${truncate ? "truncate" : ""}`} + title={item.description}> + {item.description} + </p> + </div> + )} + </Card> + ) + })} + </div> ) -export const PlaygroundData = () => { + +type Props = { + className?: string +} +export const PlaygroundData: React.FC<Props> = ({className}) => { const { messages, iodLoading, currentMessageId, iodSearch } = useMessageOption() + const { setShowPlayground, setDetailHeader, setDetailMain } = + useIodPlaygroundContext() + const data = useMemo<IodRegistryEntry[]>(() => { // 确保loading状态时数据大于3 if (iodLoading) { @@ -91,74 +136,27 @@ export const PlaygroundData = () => { return messages.length > 0 ? "推荐数据" : "热点数据" }, [messages]) - const [open, setOpen] = useState(false) - - const showDrawer = () => { - if (iodLoading) { - return - } - setOpen(true) - } - - const onClose = () => { - setOpen(false) - } + useEffect(() => { + setDetailHeader( + <Header + title={title} + showButton={false} + onClick={() => setShowPlayground(false)} + /> + ) + setDetailMain(<Main loading={iodLoading} data={data} truncate={false} />) + }, [title, iodLoading, data]) return ( <Card - className="h-full [&_.ant-card-body]:h-full [&_.ant-card-body]:!p-[20px] overflow-y-hidden" + className={`${className}`} hoverable> - <div className="h-full flex flex-col relative"> + <div className="h-full flex flex-col gap-2 relative"> {/* 数据导航 */} - <DataNavigation - Header={ - <div className="flex items-center gap-0.5 text-[#3581e3]"> - <svg - className="icon" - viewBox="0 0 1024 1024" - version="1.1" - xmlns="http://www.w3.org/2000/svg" - p-id="3572" - width="18" - height="18"> - <path - d="M877.714286 54.857143H754.285714V9.142857c0-5.028571-4.114286-9.142857-9.142857-9.142857h-64c-5.028571 0-9.142857 4.114286-9.142857 9.142857v45.714286H498.285714V9.142857c0-5.028571-4.114286-9.142857-9.142857-9.142857h-64c-5.028571 0-9.142857 4.114286-9.142857 9.142857v45.714286H292.571429c-20.228571 0-36.571429 16.342857-36.571429 36.571428v137.142858h-109.714286c-20.228571 0-36.571429 16.342857-36.571428 36.571428v722.285714c0 20.228571 16.342857 36.571429 36.571428 36.571429h585.142857c20.228571 0 36.571429-16.342857 36.571429-36.571429v-109.714285h109.714286c20.228571 0 36.571429-16.342857 36.571428-36.571429V91.428571c0-20.228571-16.342857-36.571429-36.571428-36.571428zM685.714286 941.714286H192V310.857143h249.142857v198.857143c0 25.257143 20.457143 45.714286 45.714286 45.714285h198.857143v386.285715z m0-459.428572H514.285714V310.857143h0.228572L685.714286 482.057143v0.228571z m146.285714 313.142857h-64V448L548.571429 228.571429H338.285714v-91.428572h77.714286v36.571429c0 5.028571 4.114286 9.142857 9.142857 9.142857h64c5.028571 0 9.142857-4.114286 9.142857-9.142857v-36.571429h173.714286v36.571429c0 5.028571 4.114286 9.142857 9.142857 9.142857h64c5.028571 0 9.142857-4.114286 9.142857-9.142857v-36.571429h77.714286v658.285714z" - p-id="3573" - fill="#3581e3"></path> - </svg> - {title} - </div> - } - onClick={showDrawer} - /> - + <Header title={title} onClick={() => setShowPlayground(false)} /> {/* 数据列表 */} - <div className="space-y-1.5 flex-1 overflow-y-auto"> - {data.slice(0, 3).map((item, index) => { - return ( - <ShowCard key={item.doId} loading={iodLoading} record={item} /> - ) - })} - </div> + <Main loading={iodLoading} data={data.slice(0, 3)} /> </div> - {/* 抽屉 */} - <Drawer - title={title} - closable={{ "aria-label": "Close Button" }} - onClose={onClose} - open={open} - width="33.33%"> - <div className="grid grid-cols-1 gap-3 overflow-y-auto"> - {data.map((item, index) => ( - <ShowCard - key={item.doId} - loading={iodLoading} - record={item} - truncate={false} - /> - ))} - </div> - </Drawer> </Card> ) } diff --git a/src/components/Common/Playground/History.tsx b/src/components/Common/Playground/History.tsx index 8d0a306..0c57ebd 100644 --- a/src/components/Common/Playground/History.tsx +++ b/src/components/Common/Playground/History.tsx @@ -74,8 +74,10 @@ export const PlaygroundHistory = () => { children: qaPrompt.map((item) => { return { key: item.id, - label: <span title={item.title}>{item.title}</span>, - icon: <p className="w-3.5">{item.icon}</p> + label: <div className="flex items-center gap-2"> + <p className="w-5 h-5 [&_.ant-avatar]:!w-full [&_.ant-avatar]:!h-full [&_.ant-avatar]:relative [&_.ant-avatar]:-top-3">{item.icon}</p> + <span title={item.title}>{item.title}</span> + </div>, } }) } diff --git a/src/components/Common/Playground/IodRelevant.tsx b/src/components/Common/Playground/IodRelevant.tsx index 550dc70..91073ff 100644 --- a/src/components/Common/Playground/IodRelevant.tsx +++ b/src/components/Common/Playground/IodRelevant.tsx @@ -150,10 +150,9 @@ const StatCard: React.FC<{ ) } -// 主组件 export const StatisticGrid: React.FC = () => { return ( - <div className="p-6 min-h-screen"> + <div className="p-6"> {/* 第一行:3 个卡片 */} <div className="grid grid-cols-3 gap-6 mb-6"> <StatCard @@ -203,7 +202,7 @@ export const StatisticGrid: React.FC = () => { <ResearchPaperIcon className="w-6 h-6 text-white" color="#3581e3" /> } number={1380026} - label="科研论文" + label="数据论文" /> <StatCard icon={ @@ -218,7 +217,10 @@ export const StatisticGrid: React.FC = () => { ) } -export const PlaygroundIodRelevant: React.FC = () => { +type Props = { + className?: string +} +export const PlaygroundIodRelevant: React.FC<Props> = ({ className }) => { const { messages, iodLoading, currentMessageId, iodSearch } = useMessageOption() @@ -348,10 +350,11 @@ export const PlaygroundIodRelevant: React.FC = () => { <Card hoverable variant="outlined" - className="flex flex-col h-full [&_.ant-card-body]:h-full [&_.ant-card-body]:!p-[20px] translate-y-[-2px] !bg-[#f0f9ff]"> + className={`${className} translate-y-[-2px] !bg-[#d0e6ff] shadow-[#d0e6ff]/30`}> <div className="h-full flex flex-col relative"> {/* 花瓣效果 */} - <div className={`absolute inset-0 pointer-events-none z-0 overflow-hidden ${showSearchData ? '' : ''}`}> + <div + className={`absolute inset-0 pointer-events-none z-0 overflow-hidden ${showSearchData ? "" : ""}`}> <div className="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-64 h-64"> <CircleElement delay={0} playing={true} /> <CircleElement delay={1} playing={true} /> @@ -364,20 +367,24 @@ export const PlaygroundIodRelevant: React.FC = () => { <h2 className="text-xl font-semibold text-[#1a3c87] flex justify-center items-center"> <div className="flex items-center gap-2"> <SearchIcon /> - 数联网搜索相关内容 + {messages.length > 0 + ? "科创数联网深度搜索" + : "科创数联网连接资源"} </div> {/*<button className="bg-[#2563eb1a] text-[#08307f] font-medium py-1 px-3 rounded-full text-sm hover:bg-[#2563eb1a] transition-colors float-right">*/} {/* {data.length}个结果*/} {/*</button>*/} </h2> <p className="text-sm text-[#1a3c87] mt-1 text-center"> - 下面是在数联网上进行深度搜索得到的科创相关数据、场景和团队 + {messages.length > 0 + ? "下面是在科创数联网上进行深度搜索得到的相关数据、场景和团队" + : "下面是科创数联网连接的数据、场景和团队"} </p> </div> {/* Content */} <div className="space-y-2 flex-1 overflow-y-auto"> - {showSearchData ? ( + {messages.length ? ( <AnimatePresence mode="wait"> <motion.div key="search-results" diff --git a/src/components/Common/Playground/Scene.tsx b/src/components/Common/Playground/Scene.tsx index 27204d9..e277f34 100644 --- a/src/components/Common/Playground/Scene.tsx +++ b/src/components/Common/Playground/Scene.tsx @@ -1,7 +1,8 @@ -import React, { useMemo, useState } from "react" +import React, { useEffect, useMemo, useState } from "react" import { DataNavigation } from "@/components/Common/DataNavigation.tsx" import { Card, Drawer, Skeleton } from "antd" import { IodRegistryEntry } from "@/types/iod.ts" +import { useIodPlaygroundContext } from "@/components/Option/Playground/PlaygroundIod.tsx" const defaultData: IodRegistryEntry[] = [ { @@ -27,46 +28,86 @@ const defaultData: IodRegistryEntry[] = [ } ] -type ShowCardProps = { - loading: boolean - record: IodRegistryEntry - truncate?: boolean +type HeaderProps = { + title: string + showButton?: boolean + onClick?: () => void } - -const ShowCard: React.FC<ShowCardProps> = ({ - loading, - record, - truncate = true -}) => ( - <Card className="[&_.ant-card-body]:!p-2 !bg-[gb(248, 248, 248)] border !border-[#e9e9e9]"> - {loading ? ( - <Skeleton title={false} active /> - ) : ( - <div className="flex flex-col gap-0.5"> - <h3 - className={`text-base font-medium mb-1 text-[#222222] break-all ${truncate ? "line-clamp-2" : ""}`} - title={record.name}> - {record.name} - </h3> - <p - className={`text-sm text-[#383838] break-all ${truncate ? "line-clamp-2" : ""}`} - title={record.doId}> - 数字对象标识:{record.doId} - </p> - <p - className={`text-[#828282] text-xs break-all ${truncate ? "truncate" : ""}`} - title={record.description}> - {record.description} - </p> +const Header: React.FC<HeaderProps> = ({ title, showButton = true, onClick }) => ( + <DataNavigation + Header={ + <div className="flex items-center text-[#54c41d] gap-1"> + <svg + className="icon" + viewBox="0 0 1025 1024" + version="1.1" + xmlns="http://www.w3.org/2000/svg" + p-id="6235" + width="18" + height="18"> + <path + d="M980.34571 1.143792c-4.850903 0-9.824354 0.888481-14.797806 2.930966L229.773215 299.724504H20.428686c-11.233669 0-20.424853 9.446494-20.424853 21.180572V702.584302c0 11.74429 9.191184 21.180572 20.424853 21.180573h129.820365c-4.728353 14.808018-7.271248 30.51473-7.271248 46.46654 0 84.119757 68.678568 152.543014 153.176184 152.543014 70.721053 0 130.330986-47.998404 147.93721-112.847312l521.569043 209.59984c4.983664 1.919936 9.957116 2.930966 14.808019 2.930967 21.568645 0 40.839493-18.127057 40.839493-42.371358V43.525362C1021.195415 19.270849 1002.047116 1.143792 980.34571 1.143792zM296.153987 831.250663c-33.833769 0-61.274559-27.308028-61.274558-61.009035 0-14.297397 4.983664-27.951411 14.042086-38.807221l108.374269 43.525362c-2.553107 31.403211-28.972654 56.290895-61.141797 56.290894z m633.12959 74.550713L263.984844 638.501326l-16.462431-6.638077H91.915671V391.626129h155.606742l16.462431-6.638077 665.298733-267.30005v788.113374z m0 0" + fill="#54c41d" + p-id="6236"></path> + </svg> + {title} </div> - )} - </Card> + } + showButton={showButton} + onClick={onClick} + /> ) -export const PlaygroundScene = () => { +type MainProps = { + loading: boolean + data: IodRegistryEntry[] + truncate?: boolean +} +const Main: React.FC<MainProps> = ({ data, loading, truncate = true }) => ( + <div className="space-y-1.5 flex-1 overflow-y-auto"> + {data.map((item, index) => { + return ( + <Card + className="[&_.ant-card-body]:!p-2 !bg-[gb(248, 248, 248)] border !border-[#e9e9e9]" + key={item.doId}> + {loading ? ( + <Skeleton title={false} active /> + ) : ( + <div className="flex flex-col gap-0.5"> + <h3 + className={`text-base font-medium mb-1 text-[#222222] break-all ${truncate ? "line-clamp-2" : ""}`} + title={item.name}> + {item.name} + </h3> + <p + className={`text-sm text-[#383838] break-all ${truncate ? "line-clamp-2" : ""}`} + title={item.doId}> + 数字对象标识:{item.doId} + </p> + <p + className={`text-[#828282] text-xs break-all ${truncate ? "truncate" : ""}`} + title={item.description}> + {item.description} + </p> + </div> + )} + </Card> + ) + })} + </div> +) + + +type Props = { + className?: string +} +export const PlaygroundScene: React.FC<Props> = ({ className }) => { const { messages, iodLoading, currentMessageId, iodSearch } = useMessageOption() + const { setShowPlayground, setDetailHeader, setDetailMain } = + useIodPlaygroundContext() + const data = useMemo<IodRegistryEntry[]>(() => { // 确保loading状态时数据大于3 if (iodLoading) { @@ -87,74 +128,24 @@ export const PlaygroundScene = () => { return messages.length > 0 ? "推荐场景" : "热点场景" }, [messages]) - const [open, setOpen] = useState(false) - - const showDrawer = () => { - if (iodLoading) { - return - } - setOpen(true) - } - - const onClose = () => { - setOpen(false) - } + useEffect(() => { + setDetailHeader( + <Header title={title} showButton={false} onClick={() => setShowPlayground(false)} /> + ) + setDetailMain(<Main loading={iodLoading} data={data} truncate={false} />) + }, [title, iodLoading, data]) return ( <Card - className="h-full [&_.ant-card-body]:h-full [&_.ant-card-body]:!p-[20px] overflow-y-hidden" + className={`${className}`} hoverable> - <div className="h-full flex flex-col relative"> + <div className="h-full flex flex-col gap-2 relative"> {/* 数据导航 */} - <DataNavigation - Header={ - <div className="flex items-center text-[#54c41d] gap-1"> - <svg - className="icon" - viewBox="0 0 1025 1024" - version="1.1" - xmlns="http://www.w3.org/2000/svg" - p-id="6235" - width="18" - height="18"> - <path - d="M980.34571 1.143792c-4.850903 0-9.824354 0.888481-14.797806 2.930966L229.773215 299.724504H20.428686c-11.233669 0-20.424853 9.446494-20.424853 21.180572V702.584302c0 11.74429 9.191184 21.180572 20.424853 21.180573h129.820365c-4.728353 14.808018-7.271248 30.51473-7.271248 46.46654 0 84.119757 68.678568 152.543014 153.176184 152.543014 70.721053 0 130.330986-47.998404 147.93721-112.847312l521.569043 209.59984c4.983664 1.919936 9.957116 2.930966 14.808019 2.930967 21.568645 0 40.839493-18.127057 40.839493-42.371358V43.525362C1021.195415 19.270849 1002.047116 1.143792 980.34571 1.143792zM296.153987 831.250663c-33.833769 0-61.274559-27.308028-61.274558-61.009035 0-14.297397 4.983664-27.951411 14.042086-38.807221l108.374269 43.525362c-2.553107 31.403211-28.972654 56.290895-61.141797 56.290894z m633.12959 74.550713L263.984844 638.501326l-16.462431-6.638077H91.915671V391.626129h155.606742l16.462431-6.638077 665.298733-267.30005v788.113374z m0 0" - fill="#54c41d" - p-id="6236"></path> - </svg> - {title} - </div> - } - onClick={showDrawer} - /> + <Header title={title} onClick={() => setShowPlayground(false)} /> {/* 数据列表 */} - <div className="space-y-1.5 flex-1 overflow-y-auto"> - {data.slice(0, 3).map((item, index) => { - return ( - <ShowCard key={item.doId} loading={iodLoading} record={item} /> - ) - })} - </div> + <Main loading={iodLoading} data={data.slice(0, 3)} /> </div> - {/* 抽屉 */} - <Drawer - title={title} - closable={{ "aria-label": "Close Button" }} - onClose={onClose} - open={open} - width="33.33%"> - <div className="grid grid-cols-1 gap-3 overflow-y-auto"> - {data.map((item, index) => ( - <ShowCard - key={item.doId} - loading={iodLoading} - record={item} - truncate={false} - /> - ))} - </div> - </Drawer> </Card> ) } diff --git a/src/components/Common/Playground/Team.tsx b/src/components/Common/Playground/Team.tsx index 8f937aa..e9b49be 100644 --- a/src/components/Common/Playground/Team.tsx +++ b/src/components/Common/Playground/Team.tsx @@ -1,45 +1,10 @@ -import React, { useMemo, useState } from "react" +import React, { useEffect, useMemo } from "react" import { DataNavigation } from "@/components/Common/DataNavigation.tsx" -import { Card, Drawer, Skeleton } from "antd" +import { Card, Skeleton } from "antd" import { IodRegistryEntry } from "@/types/iod.ts" +import { useIodPlaygroundContext } from "@/components/Option/Playground/PlaygroundIod.tsx" -type ShowCardProps = { - loading: boolean - record: IodRegistryEntry - truncate?: boolean -} - -const ShowCard: React.FC<ShowCardProps> = ({ - loading, - record, - truncate = true -}) => ( - <Card className="[&_.ant-card-body]:!p-2 !bg-[gb(248, 248, 248)] border !border-[#e9e9e9]"> - {loading ? ( - <Skeleton title={false} active /> - ) : ( - <div className="flex flex-col gap-0.5"> - <h3 - className={`text-base font-medium mb-1 text-[#222222] break-all ${truncate ? "line-clamp-2" : ""}`} - title={record.name}> - {record.name} - </h3> - <p - className={`text-sm text-[#383838] break-all ${truncate ? "line-clamp-2" : ""}`} - title={record.doId}> - 数字对象标识:{record.doId} - </p> - <p - className={`text-[#828282] text-xs break-all ${truncate ? "truncate" : ""}`} - title={record.description}> - {record.description} - </p> - </div> - )} - </Card> -) - -const defaultData:IodRegistryEntry[] = [ +const defaultData: IodRegistryEntry[] = [ { name: "上海芯飞睿科技有限公司", description: @@ -54,12 +19,104 @@ const defaultData:IodRegistryEntry[] = [ { name: "清华大学智能系统实验室", description: "清华大学", - doId: "CSTR:15552.13.04.91.2021.614", - }, + doId: "CSTR:15552.13.04.91.2021.614" + } ] -export const PlaygroundTeam = () => { - const { messages, iodLoading, currentMessageId, iodSearch } = useMessageOption() +type HeaderProps = { + title: string + showButton?: boolean + onClick?: () => void +} +const Header: React.FC<HeaderProps> = ({ + title, + showButton = true, + onClick +}) => ( + <DataNavigation + Header={ + <div className="flex items-center text-[#BE0BAC] gap-1"> + <svg + className="icon" + viewBox="0 0 1024 1024" + version="1.1" + xmlns="http://www.w3.org/2000/svg" + p-id="7272" + width="18" + height="18"> + <path + d="M824.2 699.9c-25.4-25.4-54.7-45.7-86.4-60.4C783.1 602.8 812 546.8 812 484c0-110.8-92.4-201.7-203.2-200-109.1 1.7-197 90.6-197 200 0 62.8 29 118.8 74.2 155.5-31.7 14.7-60.9 34.9-86.4 60.4C345 754.6 314 826.8 312 903.8c-0.1 4.5 3.5 8.2 8 8.2h56c4.3 0 7.9-3.4 8-7.7 1.9-58 25.4-112.3 66.7-153.5C493.8 707.7 551.1 684 612 684c60.9 0 118.2 23.7 161.3 66.8C814.5 792 838 846.3 840 904.3c0.1 4.3 3.7 7.7 8 7.7h56c4.5 0 8.1-3.7 8-8.2-2-77-33-149.2-87.8-203.9zM612 612c-34.2 0-66.4-13.3-90.5-37.5-24.5-24.5-37.9-57.1-37.5-91.8 0.3-32.8 13.4-64.5 36.3-88 24-24.6 56.1-38.3 90.4-38.7 33.9-0.3 66.8 12.9 91 36.6 24.8 24.3 38.4 56.8 38.4 91.4 0 34.2-13.3 66.3-37.5 90.5-24.2 24.2-56.4 37.5-90.6 37.5z" + p-id="7273" + fill="#BE0BAC"></path> + <path + d="M361.5 510.4c-0.9-8.7-1.4-17.5-1.4-26.4 0-15.9 1.5-31.4 4.3-46.5 0.7-3.6-1.2-7.3-4.5-8.8-13.6-6.1-26.1-14.5-36.9-25.1-25.8-25.2-39.7-59.3-38.7-95.4 0.9-32.1 13.8-62.6 36.3-85.6 24.7-25.3 57.9-39.1 93.2-38.7 31.9 0.3 62.7 12.6 86 34.4 7.9 7.4 14.7 15.6 20.4 24.4 2 3.1 5.9 4.4 9.3 3.2 17.6-6.1 36.2-10.4 55.3-12.4 5.6-0.6 8.8-6.6 6.3-11.6-32.5-64.3-98.9-108.7-175.7-109.9-110.9-1.7-203.3 89.2-203.3 199.9 0 62.8 28.9 118.8 74.2 155.5-31.8 14.7-61.1 35-86.5 60.4-54.8 54.7-85.8 126.9-87.8 204-0.1 4.5 3.5 8.2 8 8.2h56.1c4.3 0 7.9-3.4 8-7.7 1.9-58 25.4-112.3 66.7-153.5 29.4-29.4 65.4-49.8 104.7-59.7 3.9-1 6.5-4.7 6-8.7z" + p-id="7274" + fill="#BE0BAC"></path> + </svg> + {title} + </div> + } + showButton={showButton} + onClick={onClick} + /> +) + +type MainProps = { + loading: boolean + data: IodRegistryEntry[] + truncate?: boolean + // 水平展示三个还是按列展示(页面和详情展示不一样) + flat?: boolean +} +const Main: React.FC<MainProps> = ({ + data, + loading, + truncate = true, + flat = true +}) => ( + <div + className={`${flat ? "grid grid-cols-3 gap-3" : "space-y-1.5"} flex-1 overflow-y-auto`}> + {data.map((item) => { + return ( + <Card + className="[&_.ant-card-body]:!p-2 !bg-[gb(248, 248, 248)] border !border-[#e9e9e9]" + key={item.doId}> + {loading ? ( + <Skeleton title={false} active /> + ) : ( + <div className="flex flex-col gap-0.5"> + <h3 + className={`text-base font-medium mb-1 text-[#222222] break-all ${truncate ? "line-clamp-2" : ""}`} + title={item.name}> + {item.name} + </h3> + <p + className={`text-sm text-[#383838] break-all ${truncate ? "line-clamp-2" : ""}`} + title={item.doId}> + 数字对象标识:{item.doId} + </p> + <p + className={`text-[#828282] text-xs break-all ${truncate ? "truncate" : ""}`} + title={item.description}> + {item.description} + </p> + </div> + )} + </Card> + ) + })} + </div> +) + +type Props = { + className?: string +} +export const PlaygroundTeam: React.FC<Props> = ({ className }) => { + const { messages, iodLoading, currentMessageId, iodSearch } = + useMessageOption() + + const { setShowPlayground, setDetailHeader, setDetailMain } = + useIodPlaygroundContext() const data = useMemo<IodRegistryEntry[]>(() => { // 确保loading状态时数据大于3 @@ -81,74 +138,27 @@ export const PlaygroundTeam = () => { return messages.length > 0 ? "推荐团队" : "热点团队" }, [messages]) - const [open, setOpen] = useState(false) - - const showDrawer = () => { - setOpen(true) - } - - const onClose = () => { - setOpen(false) - } + useEffect(() => { + setDetailHeader( + <Header + title={title} + showButton={false} + onClick={() => setShowPlayground(false)} + /> + ) + setDetailMain( + <Main loading={iodLoading} data={data} truncate={false} flat={false} /> + ) + }, [title, iodLoading, data]) return ( - <Card - className="h-full [&_.ant-card-body]:h-full [&_.ant-card-body]:!p-[20px] overflow-y-hidden" - hoverable> - <div className="h-full flex flex-col relative"> + <Card className={`${className}`} hoverable> + <div className="h-full flex flex-col gap-2 relative"> {/* 数据导航 */} - <DataNavigation - Header={ - <div className="flex items-center text-[#BE0BAC] gap-1"> - <svg - className="icon" - viewBox="0 0 1024 1024" - version="1.1" - xmlns="http://www.w3.org/2000/svg" - p-id="7272" - width="18" - height="18"> - <path - d="M824.2 699.9c-25.4-25.4-54.7-45.7-86.4-60.4C783.1 602.8 812 546.8 812 484c0-110.8-92.4-201.7-203.2-200-109.1 1.7-197 90.6-197 200 0 62.8 29 118.8 74.2 155.5-31.7 14.7-60.9 34.9-86.4 60.4C345 754.6 314 826.8 312 903.8c-0.1 4.5 3.5 8.2 8 8.2h56c4.3 0 7.9-3.4 8-7.7 1.9-58 25.4-112.3 66.7-153.5C493.8 707.7 551.1 684 612 684c60.9 0 118.2 23.7 161.3 66.8C814.5 792 838 846.3 840 904.3c0.1 4.3 3.7 7.7 8 7.7h56c4.5 0 8.1-3.7 8-8.2-2-77-33-149.2-87.8-203.9zM612 612c-34.2 0-66.4-13.3-90.5-37.5-24.5-24.5-37.9-57.1-37.5-91.8 0.3-32.8 13.4-64.5 36.3-88 24-24.6 56.1-38.3 90.4-38.7 33.9-0.3 66.8 12.9 91 36.6 24.8 24.3 38.4 56.8 38.4 91.4 0 34.2-13.3 66.3-37.5 90.5-24.2 24.2-56.4 37.5-90.6 37.5z" - p-id="7273" - fill="#BE0BAC"></path> - <path - d="M361.5 510.4c-0.9-8.7-1.4-17.5-1.4-26.4 0-15.9 1.5-31.4 4.3-46.5 0.7-3.6-1.2-7.3-4.5-8.8-13.6-6.1-26.1-14.5-36.9-25.1-25.8-25.2-39.7-59.3-38.7-95.4 0.9-32.1 13.8-62.6 36.3-85.6 24.7-25.3 57.9-39.1 93.2-38.7 31.9 0.3 62.7 12.6 86 34.4 7.9 7.4 14.7 15.6 20.4 24.4 2 3.1 5.9 4.4 9.3 3.2 17.6-6.1 36.2-10.4 55.3-12.4 5.6-0.6 8.8-6.6 6.3-11.6-32.5-64.3-98.9-108.7-175.7-109.9-110.9-1.7-203.3 89.2-203.3 199.9 0 62.8 28.9 118.8 74.2 155.5-31.8 14.7-61.1 35-86.5 60.4-54.8 54.7-85.8 126.9-87.8 204-0.1 4.5 3.5 8.2 8 8.2h56.1c4.3 0 7.9-3.4 8-7.7 1.9-58 25.4-112.3 66.7-153.5 29.4-29.4 65.4-49.8 104.7-59.7 3.9-1 6.5-4.7 6-8.7z" - p-id="7274" - fill="#BE0BAC"></path> - </svg> - {title} - </div> - } - onClick={showDrawer} - /> - - {/* 场景列表 */} - <div className="grid grid-cols-3 gap-3 flex-1 overflow-y-auto"> - {data.slice(0, 3).map((item, index) => ( - <ShowCard key={item.doId} loading={iodLoading} record={item} /> - ))} - </div> + <Header title={title} onClick={() => setShowPlayground(false)} /> + {/* 数据列表 */} + <Main loading={iodLoading} data={data.slice(0, 3)} /> </div> - - {/* 抽屉 */} - <Drawer - title={title} - closable={{ "aria-label": "Close Button" }} - onClose={onClose} - open={open} - width="33.33%"> - <div className="grid grid-cols-1 gap-3 overflow-y-auto"> - {data.map((item, index) => ( - <ShowCard - key={item.doId} - loading={iodLoading} - record={item} - truncate={false} - /> - ))} - </div> - </Drawer> </Card> ) } diff --git a/src/components/Icons/Battery.tsx b/src/components/Icons/Battery.tsx new file mode 100644 index 0000000..14acc0f --- /dev/null +++ b/src/components/Icons/Battery.tsx @@ -0,0 +1,21 @@ +import React from "react" + +export const BatteryIcon = React.forwardRef< + SVGSVGElement, + React.SVGProps<SVGSVGElement> +>((props, ref) => { + return ( + <svg + className="icon" + viewBox="0 0 1024 1024" + version="1.1" + fill="currentColor" + fillRule="evenodd" + ref={ref} + {...props}> + <path + d="M604.16 112.64c13.568-35.0208-5.9904-57.7024-24.1152-80.8448H452.7616C436.2752 56.32 419.84 80.4864 434.176 112.64zM194.56 888.3712a213.4528 213.4528 0 0 0 21.504 2.304c195.7888 0 391.5776 0 587.3152 0.6656 25.1904 0 29.4912-10.24 29.3888-32.1024-0.6144-202.0864-3.1232-633.7024-3.1232-633.7024H194.56zM597.3504 307.712l7.1168 4.2496c-25.6 73.1136-50.8928 146.2272-78.4384 225.28h139.0592L437.9648 824.32l-8.6016-2.7648c17.92-71.0144 35.84-142.0288 54.9888-217.7536l-134.656-5.7856zM192.6656 926.72c-4.096 41.8304 14.7456 64.4096 54.3744 64.8192 66.56 0.6656 133.12 0 200.0384 0 105.8304 0 211.6608 0.3072 317.44 0 44.6464 0 69.6832-25.856 64.512-64.8704zM777.4208 141.0048c-20.992-1.6896-42.24-0.4096-63.3856-0.4096H257.4848c-41.3696 0-57.9584 12.3904-66.0992 49.3568h641.2288c-6.5024-32.5632-26.368-46.592-55.1936-48.9472z" + p-id="50919"></path> + </svg> + ) +}) diff --git a/src/components/Icons/Check.tsx b/src/components/Icons/Check.tsx new file mode 100644 index 0000000..6b2dcb7 --- /dev/null +++ b/src/components/Icons/Check.tsx @@ -0,0 +1,26 @@ +import React from "react" + +export const CheckIcon = React.forwardRef< + SVGSVGElement, + React.SVGProps<SVGSVGElement> +>((props, ref) => { + return ( + <svg + className="icon" + viewBox="0 0 1024 1024" + version="1.1" + xmlns="http://www.w3.org/2000/svg" + p-id="41530" + fill="currentColor" + fillRule="evenodd" + ref={ref} + {...props}> + <path + d="M334.935114 642.334328l-185.247485-227.447917c-16.445757-20.169324-13.342784-49.957864 6.826541-66.713918L571.071355 10.569036c20.169324-16.445757 49.957864-13.342784 66.713919 6.826541l185.247484 227.447916c16.445757 20.169324 13.342784 49.957864-6.82654 66.713919L401.649033 649.160868c-20.479621 16.445757-50.268162 13.342784-66.713919-6.82654zM189.71598 693.843679L39.53209 509.216788c-14.273676-17.376648-11.481-43.131324 5.895648-57.404999l5.585352-4.654459c17.376648-14.273676 43.131324-11.481 57.404999 5.895648l150.494188 184.62689c14.273676 17.376648 11.481 43.131324-5.895649 57.405l-5.585351 4.654459c-17.686946 14.273676-43.441621 11.481-57.715297-5.895648zM877.024488 1024H275.668331a44.372513 44.372513 0 1 1 0-88.745026h601.356157a44.372513 44.372513 0 1 1 0 88.745026z" + p-id="41531"></path> + <path + d="M564.555112 345.06952l-77.264026-94.950972c-16.445757-20.169324-13.342784-49.957864 6.82654-66.713919l199.521161-162.595782c20.169324-16.445757 49.957864-13.342784 66.713918 6.82654l77.264026 94.950972c16.445757 20.169324 13.342784 49.957864-6.82654 66.713919l-199.521161 162.595782c-20.169324 16.445757-50.268162 13.342784-66.713918-6.82654zM646.163301 1020.58673l-94.950973-79.746405c51.509351-61.438864 77.574324-137.771999 72.919865-215.346322-4.344162-76.022837-37.85627-143.977945-94.330378-191.143134l79.746405-94.950972c82.849378 69.506594 131.87635 168.491431 138.392593 278.957268 6.205946 109.224648-29.78854 216.587512-101.777512 302.229565z" + p-id="41532"></path> + </svg> + ) +}) diff --git a/src/components/Icons/MedicineBottleFill.tsx b/src/components/Icons/MedicineBottleFill.tsx new file mode 100644 index 0000000..7b367e4 --- /dev/null +++ b/src/components/Icons/MedicineBottleFill.tsx @@ -0,0 +1,22 @@ +import React from "react" + +export const MedicineBottleFillIcon = React.forwardRef< + SVGSVGElement, + React.SVGProps<SVGSVGElement> +>((props, ref) => { + return ( + <svg + className="icon" + viewBox="0 0 1024 1024" + version="1.1" + p-id="25925" + fill="currentColor" + fillRule="evenodd" + ref={ref} + {...props}> + <path + d="M725.333333 213.333333v85.333334a128 128 0 0 1 128 128v469.333333a42.666667 42.666667 0 0 1-42.666666 42.666667H213.333333a42.666667 42.666667 0 0 1-42.666666-42.666667V426.666667a128 128 0 0 1 128-128V213.333333h426.666666z m-170.666666 256h-85.333334v85.333334H384v85.333333h85.290667L469.333333 725.333333h85.333334l-0.042667-85.333333H640v-85.333333h-85.333333v-85.333334z m256-384v85.333334H213.333333V85.333333h597.333334z" + p-id="25926"></path> + </svg> + ) +}) diff --git a/src/components/Icons/NewBottle.tsx b/src/components/Icons/NewBottle.tsx new file mode 100644 index 0000000..5d5662a --- /dev/null +++ b/src/components/Icons/NewBottle.tsx @@ -0,0 +1,23 @@ +import React from "react" + +export const NewBottleIcon = React.forwardRef< + SVGSVGElement, + React.SVGProps<SVGSVGElement> +>((props, ref) => { + return ( + <svg + className="icon" + viewBox="0 0 1024 1024" + version="1.1" + xmlns="http://www.w3.org/2000/svg" + p-id="40222" + fill="currentColor" + fillRule="evenodd" + ref={ref} + {...props}> + <path + d="M848.818342 511.548501l-319.661376 308.373898c-14.899471 16.705467-35.216931 27.541446-56.888888 30.70194 16.705467-17.608466 29.798942-38.828924 37.474426-61.40388l175.633157-164.345679-105.199294-105.650794L717.883598 397.770723c4.96649-4.514991 8.126984-10.835979 8.126984-17.608466s-3.160494-13.093474-8.126984-17.608465c-9.029982-10.38448-24.832451-11.738977-35.216931-2.708995L542.250441 478.589065l-30.70194-30.70194v-30.70194L632.098765 295.731922s92.557319-92.557319 199.562611 13.544974c107.45679 106.102293 16.253968 201.820106 16.253968 201.820106h0.902998z m-339.075838 74.948853v-74.948853l30.70194-30.70194 38.828925 38.828924-69.530865 66.821869z m-200.465608 294.828925C216.719577 881.326279 139.964727 819.470899 139.964727 758.067019v-492.134038c0-61.40388 80.818342-123.259259 169.312169-123.25926S478.589065 204.077601 478.589065 265.932981v492.134038c0 61.40388-76.75485 123.259259-169.312169 123.25926zM447.887125 263.223986C425.763668 206.335097 370.229277 169.312169 309.276896 170.666667c-60.952381-1.354497-116.938272 35.216931-139.061728 92.557319v246.067019h61.40388v215.816579c-1.354497 11.738977 4.514991 23.026455 14.447971 29.347442 9.932981 6.320988 23.026455 6.320988 32.959436 0s15.802469-17.608466 14.447972-29.347442v-213.559083h153.961199l0.451499-248.324515z m-184.663139 30.70194c8.126984 0 16.253968 3.160494 22.123457 9.029982 5.869489 5.869489 9.029982 13.996473 9.029982 22.123457v184.663139H232.522046V326.433862c0-8.126984 2.708995-16.253968 9.029982-22.123456 5.869489-5.869489 13.996473-9.029982 22.123457-9.029983l-0.451499-1.354497z m0 0" + p-id="40223"></path> + </svg> + ) +}) diff --git a/src/components/Icons/Ship.tsx b/src/components/Icons/Ship.tsx new file mode 100644 index 0000000..d62c6d7 --- /dev/null +++ b/src/components/Icons/Ship.tsx @@ -0,0 +1,23 @@ +import React from "react" + +export const ShipIcon = React.forwardRef< + SVGSVGElement, + React.SVGProps<SVGSVGElement> +>((props, ref) => { + return ( + <svg + className="icon" + viewBox="0 0 1024 1024" + version="1.1" + xmlns="http://www.w3.org/2000/svg" + p-id="42662" + fill="currentColor" + fillRule="evenodd" + ref={ref} + {...props}> + <path + d="M96.0512 356.20864c-32.68608 23.88992-84.23424 61.60384-86.75328 75.43808-3.76832 20.11136 37.72416 126.976 71.66976 170.98752 26.39872 33.9456 168.46848 262.76864 231.33184 364.60544-8.79616-106.86464-41.49248-199.90528-91.78112-297.97376-44.00128-85.49376-101.8368-177.27488-119.43936-272.82432-2.5088-13.83424-3.76832-27.65824-5.02784-40.23296zM505.91744 78.35648V50.69824h10.05568v27.65824h10.05568v21.37088h45.2608v3.76832-3.76832l160.93184 228.82304 216.24832 287.90784v25.14944L614.0416 224.19456h-28.91776v37.71392h28.91776l335.68768 409.86624v25.14944L614.0416 315.97568H98.57024v-54.05696h27.65824v-37.71392H98.57024v-54.05696h75.43808V99.72736h223.7952V83.38432h61.60384V10.46528h8.79616v90.5216h15.08352V79.616h22.6304v-1.25952z m423.70048 614.79936v20.11136l18.86208 20.11136v-18.86208l-18.86208-21.36064zM653.01504 398.9504v25.14944c8.79616 8.79616 16.34304 17.60256 25.14944 26.39872v-25.14944c-8.79616-8.79616-16.34304-17.59232-25.14944-26.39872z m38.98368 42.752v25.14944c7.54688 8.79616 16.34304 17.60256 23.88992 25.14944v-25.14944c-7.54688-8.8064-15.09376-17.60256-23.88992-25.14944z m40.22272 41.49248v23.88992c7.54688 8.79616 15.08352 16.34304 22.6304 25.14944v-23.88992c-7.53664-8.8064-15.08352-16.35328-22.6304-25.14944z m38.98368 42.74176v22.6304c7.54688 7.54688 15.08352 16.34304 22.6304 23.88992v-22.6304c-7.54688-8.8064-15.09376-16.34304-22.6304-23.88992z m40.23296 41.49248v22.6304c7.54688 7.54688 13.83424 15.08352 21.37088 22.6304v-22.6304c-7.54688-7.54688-15.09376-15.09376-21.37088-22.6304z m38.97344 41.49248v21.37088c6.28736 7.54688 13.83424 15.08352 20.11136 22.6304v-21.37088c-6.28736-7.54688-13.824-15.09376-20.11136-22.6304z m38.97344 42.74176v20.11136c6.28736 7.54688 13.83424 13.83424 20.11136 21.37088v-20.11136c-6.28736-7.53664-12.57472-13.824-20.11136-21.37088z m-275.34336-294.1952H406.59968c21.37088 3.76832 41.49248 8.79616 61.60384 13.83424 15.08352 3.76832 32.68608 7.54688 50.28864 13.83424h95.54944v-1.25952l25.14944 27.65824V385.1264l-25.14944-27.65824z m-153.38496-203.6736h55.31648v16.34304h26.39872V127.3856H201.66656v42.74176h22.6304v-16.34304h55.31648v16.34304h25.14944v-16.34304h55.31648v16.34304h26.39872v-16.34304h55.31648v16.34304h17.60256v-16.34304c0.01024 0.01024 1.25952 0.01024 1.25952 0.01024z m109.38368 108.12416v-37.71392h-41.49248v37.71392h41.49248z m-373.4016-37.72416v37.71392h41.49248v-37.71392h-41.49248z m-15.09376 37.72416v-37.71392h-41.49248v37.71392h41.49248z m70.41024-37.72416v37.71392h41.49248v-37.71392h-41.49248z m55.31648 0v37.71392h41.49248v-37.71392h-41.49248z m55.32672 0v37.71392h41.49248v-37.71392H362.5984z m55.31648 0v37.71392h41.49248v-37.71392h-41.49248z m55.31648 0v37.71392h41.49248v-37.71392h-41.49248z m-349.51168 113.152s354.54976 51.54816 417.41312 85.49376C603.98592 456.78592 1018.88 830.19776 1018.88 830.19776l-23.88992 186.07104H343.73632c-6.28736-331.91936-220.01664-479.01696-220.01664-678.92224zM647.9872 578.74432c-6.28736 0-12.57472 7.54688-12.57472 17.60256s5.02784 18.86208 12.57472 18.86208c6.28736 0 12.57472-7.54688 12.57472-17.60256 0-11.32544-5.02784-18.86208-12.57472-18.86208z m-40.23296-31.4368c-7.54688 0-12.57472 8.79616-12.57472 18.86208 0 11.3152 6.28736 20.11136 12.57472 20.11136 7.54688 0 12.57472-8.79616 12.57472-18.86208 1.25952-11.30496-5.02784-20.11136-12.57472-20.11136z m80.46592 62.86336c-6.28736 0-11.3152 7.54688-11.3152 17.60256s5.02784 17.60256 11.3152 17.60256c6.28736 0 11.3152-7.54688 11.3152-16.34304 0-11.3152-5.02784-18.86208-11.3152-18.86208z m40.23296 30.17728c-6.28736 0-10.05568 7.54688-10.05568 16.34304s5.02784 16.34304 10.05568 16.34304c6.28736 0 10.05568-7.54688 10.05568-16.34304s-3.76832-15.08352-10.05568-16.34304z m40.23296 31.42656c-5.02784 0-10.05568 6.28736-10.05568 15.08352s3.76832 15.08352 10.05568 15.08352c5.02784 0 10.05568-6.28736 10.05568-15.08352 0-7.53664-5.02784-15.08352-10.05568-15.08352z m40.23296 31.4368c-5.02784 0-8.79616 6.28736-8.79616 13.83424s3.76832 13.83424 8.79616 13.83424 8.79616-6.28736 8.79616-13.83424-3.76832-13.83424-8.79616-13.83424z m40.23296 31.42656c-5.02784 0-8.79616 5.02784-8.79616 12.57472 0 7.54688 3.76832 12.57472 8.79616 12.57472s8.79616-5.02784 8.79616-12.57472c-1.24928-6.28736-5.02784-12.57472-8.79616-12.57472z m40.23296 31.4368c-3.76832 0-7.54688 5.02784-7.54688 11.3152s3.76832 11.3152 7.54688 11.3152 7.54688-5.02784 7.54688-11.3152-3.77856-11.3152-7.54688-11.3152z m40.23296 31.42656c-3.76832 0-6.28736 5.02784-6.28736 10.05568s2.51904 10.05568 6.28736 10.05568c3.76832 0 6.28736-5.02784 6.28736-10.05568 0-6.27712-2.51904-10.05568-6.28736-10.05568z m40.23296 31.4368c-3.76832 0-6.28736 3.76832-6.28736 8.79616s2.51904 8.79616 6.28736 8.79616c3.76832 0 6.28736-3.76832 6.28736-8.79616-1.25952-5.02784-3.77856-8.79616-6.28736-8.79616z m-595.93728-189.8496c0 1.25952-1.25952 1.25952-1.25952 1.25952-1.25952 1.25952-3.76832 2.51904-6.28736 2.51904-2.51904 0-5.02784-1.25952-6.28736-2.51904l-1.25952-1.25952c-1.25952 0-1.25952 1.25952-2.51904 2.51904-2.51904 2.51904-3.76832 6.28736-3.76832 10.05568 0 3.76832 1.25952 7.54688 3.76832 10.05568 2.51904 2.51904 6.28736 3.76832 10.05568 3.76832 3.76832 0 7.54688-1.25952 10.05568-3.76832 2.51904-2.51904 3.76832-6.28736 3.76832-10.05568 0-3.76832-1.25952-7.54688-3.76832-10.05568 0.01024-1.25952-1.24928-2.51904-2.49856-2.51904z m-11.3152-12.57472h7.54688v-8.8064 1.25952c0 1.25952-1.25952 3.76832-3.76832 3.76832-1.25952 0-3.76832-1.25952-3.76832-3.76832V616.448v10.06592z m6.27712 10.06592h-5.02784c1.25952 0 1.25952 1.25952 2.51904 1.25952 0-0.01024 1.25952-0.01024 2.5088-1.25952z m-2.5088-42.752c1.25952 0 3.76832 1.25952 3.76832 3.76832v-16.34304 1.25952c0 1.25952-1.25952 3.76832-3.76832 3.76832-1.25952 0-3.76832-1.25952-3.76832-3.76832v-2.51904 20.11136-1.25952c0-3.75808 1.24928-5.0176 3.76832-5.0176z m0-37.71392c1.25952 0 3.76832 1.25952 3.76832 3.76832V543.5392v1.25952c0 1.25952-1.25952 3.76832-3.76832 3.76832-1.25952 0-3.76832-1.25952-3.76832-3.76832v-2.51904 20.11136-2.51904c0-2.49856 1.24928-3.75808 3.76832-3.75808z m0-90.5216c11.3152 0 20.11136 8.79616 20.11136 20.11136 0 8.79616-5.02784 15.08352-11.3152 18.86208v16.34304c0 2.51904-1.25952 5.02784-2.51904 6.28736-1.25952 1.25952-2.51904 1.25952-2.51904 2.51904v5.02784c1.25952 0 2.51904 1.25952 2.51904 2.51904 1.25952 1.25952 2.51904 3.76832 2.51904 6.28736v15.08352c0 2.51904-1.25952 5.02784-2.51904 6.28736-1.25952 1.25952-2.51904 1.25952-2.51904 2.51904v5.02784c1.25952 0 2.51904 1.25952 2.51904 2.51904 1.25952 1.25952 2.51904 3.76832 2.51904 6.28736v15.08352c0 2.51904-1.25952 5.02784-2.51904 6.28736-1.25952 1.25952-2.51904 1.25952-2.51904 2.51904v5.02784c1.25952 0 2.51904 1.25952 2.51904 2.51904 1.25952 1.25952 2.51904 3.76832 2.51904 6.28736v8.79616c3.76832 1.25952 6.28736 3.76832 8.79616 6.28736 5.02784 5.02784 7.54688 11.3152 7.54688 18.86208 0 7.54688-2.51904 13.83424-7.54688 18.86208-3.76832 3.76832-7.54688 5.02784-11.3152 6.28736v76.68736c23.88992 0 28.91776-11.3152 32.68608-22.6304 1.25952-3.76832 3.76832-8.79616 6.28736-12.57472h-2.51904v-11.3152h13.83424l16.34304-1.25952-12.57472 10.05568c-5.02784 5.02784-8.79616 11.3152-11.3152 18.86208-6.28736 16.34304-12.57472 32.68608-49.02912 28.91776-36.46464 2.51904-42.74176-12.57472-49.02912-28.91776-2.51904-6.28736-5.02784-13.83424-11.3152-18.86208l-11.3152-10.05568 16.34304 1.25952h13.83424v11.3152h-2.51904c2.51904 3.76832 3.76832 8.79616 6.28736 12.57472 5.02784 11.3152 8.79616 22.6304 32.68608 22.6304v-77.94688c-5.02784-1.25952-10.05568-3.76832-12.57472-7.54688-6.28736-3.76832-8.79616-10.05568-8.79616-17.60256s2.51904-13.83424 7.54688-18.86208c2.51904-2.51904 5.02784-5.02784 8.79616-6.28736v-8.79616c0-2.51904 1.25952-5.02784 2.51904-6.28736 1.25952-1.25952 2.51904-1.25952 3.76832-2.51904v-5.02784c-1.25952 0-2.51904-1.25952-3.76832-2.51904-1.25952-1.25952-2.51904-3.76832-2.51904-6.28736v-15.08352c0-2.51904 1.25952-5.02784 2.51904-6.28736 1.25952-1.25952 2.51904-1.25952 3.76832-2.51904v-5.02784c-1.25952 0-2.51904-1.25952-3.76832-2.51904-1.25952-1.25952-2.51904-3.76832-2.51904-6.28736v-15.08352c0-2.51904 1.25952-5.02784 2.51904-6.28736 1.25952-1.25952 2.51904-1.25952 3.76832-2.51904v-3.76832c-1.25952 0-2.51904-1.25952-3.76832-2.51904s-2.51904-3.76832-2.51904-6.28736v-17.60256c-6.28736-3.76832-10.05568-10.05568-10.05568-17.60256 0-10.05568 8.8064-20.11136 20.1216-20.11136z m3.76832 40.23296h-7.54688v18.86208-2.51904c0-2.51904 1.25952-3.76832 3.76832-3.76832 1.25952 0 3.76832 1.25952 3.76832 3.76832l0.01024-16.34304z" + p-id="42663"></path> + </svg> + ) +}) diff --git a/src/components/Icons/Ship1.tsx b/src/components/Icons/Ship1.tsx new file mode 100644 index 0000000..bd9087b --- /dev/null +++ b/src/components/Icons/Ship1.tsx @@ -0,0 +1,23 @@ +import React from "react" + +export const Ship1Icon = React.forwardRef< + SVGSVGElement, + React.SVGProps<SVGSVGElement> +>((props, ref) => { + return ( + <svg + className="icon" + viewBox="0 0 1024 1024" + version="1.1" + xmlns="http://www.w3.org/2000/svg" + p-id="42511" + fill="currentColor" + fillRule="evenodd" + ref={ref} + {...props}> + <path + d="M532.48 241.777778h-28.444444a151.608889 151.608889 0 0 0-48.924445 8.533333l-142.222222 76.231111V199.111111a42.382222 42.382222 0 0 1 42.382222-42.097778H455.111111V102.115556a42.666667 42.666667 0 0 1 43.52-42.382223H540.444444a42.666667 42.666667 0 0 1 42.382223 42.382223v59.164444h101.546666a42.666667 42.666667 0 0 1 42.382223 42.382222v131.413334l-156.728889-85.333334a209.351111 209.351111 0 0 0-38.115556-8.533333z m309.191111 461.653333a768 768 0 0 0-220.16 85.333333c-113.777778 63.715556-118.613333 50.915556-207.644444 8.533334a961.422222 961.422222 0 0 0-203.093334-76.231111L151.608889 631.466667c-63.715556-80.497778-76.231111-119.466667-42.382222-139.946667L455.111111 309.475556a127.431111 127.431111 0 0 1 122.88 0l347.022222 182.044444c21.333333 17.066667 38.115556 55.182222-25.315555 139.946667z m122.595556 186.311111a42.097778 42.097778 0 0 1-42.382223 42.097778c-8.248889 0-12.515556 0-16.782222-3.982222a199.111111 199.111111 0 0 0-105.813333-34.133334c-63.431111 0-143.928889 59.448889-143.928889 59.448889S612.977778 995.555556 512 995.555556a220.728889 220.728889 0 0 1-143.928889-42.382223s-89.031111-63.431111-143.928889-59.448889a129.706667 129.706667 0 0 0-106.097778 34.133334 25.884444 25.884444 0 0 1-16.782222 3.982222 42.097778 42.097778 0 0 1-42.382222-42.097778 46.933333 46.933333 0 0 1 21.048889-42.382222s119.182222-136.248889 304.355555 0c0 0 59.448889 42.382222 101.546667 42.382222h42.382222a216.462222 216.462222 0 0 0 101.546667-42.382222c50.915556-33.848889 178.062222-118.613333 304.924444 0a47.502222 47.502222 0 0 1 28.444445 42.382222z m0 0" + p-id="42512"></path> + </svg> + ) +}) diff --git a/src/components/Option/Playground/PlaygroundEmpty.tsx b/src/components/Option/Playground/PlaygroundEmpty.tsx index 366862c..206cd32 100644 --- a/src/components/Option/Playground/PlaygroundEmpty.tsx +++ b/src/components/Option/Playground/PlaygroundEmpty.tsx @@ -1,5 +1,3 @@ -import { Card, Col, Row } from "antd" - import { useMessageOption } from "@/hooks/useMessageOption.tsx" import { useMutation, useQueryClient } from "@tanstack/react-query" import { qaPrompt } from "@/libs/playground.tsx" @@ -23,36 +21,19 @@ export const PlaygroundEmpty = () => { } return ( - <div className="w-full pb-4 pt-[20%]"> - {/* 标题区域 */} - {/*<div className="mb-4">*/} - {/* <h2*/} - {/* className="text-xl font-bold text-gray-800"*/} - {/* style={{ lineHeight: "0" }}>*/} - {/* 数联网科创智能体*/} - {/* </h2>*/} - {/* <p className="text-sm text-gray-500">您好!请问有什么可以帮您?</p>*/} - {/*</div>*/} - - {/* 卡片网格布局 */} - <Row gutter={[16, 16]} className="w-full"> - {qaPrompt.map((item, index) => ( - <Col key={index} xs={24} sm={12} md={8}> - <Card - hoverable - style={{ backgroundColor: "#f3f4f6" }} - className="border border-gray-200 rounded-lg shadow-sm hover:shadow-md transition-shadow duration-200 cursor-pointer" - onClick={() => handleQuestion(item.title)}> - <div className="flex items-center"> - <div className="text-blue-500 mr-2 w-10">{item.icon}</div> - <div className="font-medium text-sm text-gray-800"> - {item.title} - </div> - </div> - </Card> - </Col> - ))} - </Row> + <div className="w-full pb-4 pt-[20%] grid grid-cols-3 gap-3"> + {qaPrompt.map((item, index) => ( + <div + className="p-6 bg-gradient-to-br from-blue-50/90 via-indigo-50/90 to-purple-50/90 backdrop-blur-xl border border-white/60 shadow-xl rounded-2xl cursor-pointer hover:shadow-blue-200/40 hover:from-blue-100/90 hover:to-indigo-100/90 transition-all duration-500 hover:-translate-y-1" + onClick={() => handleQuestion(item.title)}> + <div className="flex items-center"> + <div className="text-blue-500 mr-2 w-10">{item.icon}</div> + <div className="font-medium text-sm text-gray-800"> + {item.title} + </div> + </div> + </div> + ))} </div> ) } diff --git a/src/components/Option/Playground/PlaygroundForm.tsx b/src/components/Option/Playground/PlaygroundForm.tsx index 0f7c098..9e2a0f9 100644 --- a/src/components/Option/Playground/PlaygroundForm.tsx +++ b/src/components/Option/Playground/PlaygroundForm.tsx @@ -249,13 +249,11 @@ export const PlaygroundForm = ({ dropedFile }: Props) => { }, [iodSearch]) return ( - <div className="flex w-full flex-col items-center p-2 px-5 pt-1 pb-4"> + <div className="flex w-full flex-col items-center pt-1 px-5 pb-4"> <div className="relative z-10 flex w-full flex-col items-center justify-center gap-2 text-base"> <div className="relative flex w-full flex-row justify-center gap-2 lg:w-5/5"> <div - className={` bg-neutral-50 dark:bg-[#262626] relative w-full max-w-[65rem] p-1 backdrop-blur-lg duration-100 border border-gray-300 rounded-xl dark:border-gray-600 - ${temporaryChat ? "!bg-gray-200 dark:!bg-black " : ""} - `}> + className={`shadow-xl relative w-full max-w-[65rem] p-1 rounded-xl bg-gradient-to-br from-white/90 via-blue-50/90 to-cyan-50/90 backdrop-blur-lg border border-blue-100/70 cursor-pointer hover:shadow-blue-100/60 transition-all duration-500`}> <div className={`border-b border-gray-200 dark:border-gray-600 relative ${ form.values.image.length === 0 ? "hidden" : "block" @@ -361,38 +359,23 @@ export const PlaygroundForm = ({ dropedFile }: Props) => { /> </div> </Tooltip> - {/*<Tooltip*/} - {/* title={t("tooltip.searchIod")}*/} - {/* className="ml-3">*/} - {/* <div className="inline-flex items-center gap-2">*/} - {/* <PiNetwork*/} - {/* className={`h-5 w-5 dark:text-gray-300 `}*/} - {/* />*/} - {/* <Switch*/} - {/* value={iodSearch}*/} - {/* onChange={(e) => setIodSearch(e)}*/} - {/* checkedChildren={t("form.webSearch.on")}*/} - {/* unCheckedChildren={t("form.webSearch.off")}*/} - {/* />*/} - {/* </div>*/} - {/*</Tooltip>*/} <Dropdown menu={{ items: iodSearchItems }} placement="bottom" trigger={["click"]} arrow> <Button - color="purple" + color="default" variant="filled" size="large" className="w-full mt-4 hover:!bg-[#0057ff1a]" - style={{ + style={iodSearch ? { color: "#0057ff", background: "#0057ff0f", border: "1px solid #0066ff26" - }}> + } : {}}> <PiNetwork className="h-5 w-5" /> - 数联网深度搜索:{iodSearch ? "开" : "关"} + 数联网深度搜索{iodSearch ? ":开" : ""} </Button> </Dropdown> </div> diff --git a/src/components/Option/Playground/PlaygroundIod.tsx b/src/components/Option/Playground/PlaygroundIod.tsx index 948c37d..ae79040 100644 --- a/src/components/Option/Playground/PlaygroundIod.tsx +++ b/src/components/Option/Playground/PlaygroundIod.tsx @@ -1,25 +1,121 @@ -import React from "react" +import React, { createContext, useContext, useState } from "react" + +import { AnimatePresence, motion } from "framer-motion" import { PlaygroundIodRelevant } from "@/components/Common/Playground/IodRelevant.tsx" import { PlaygroundData } from "@/components/Common/Playground/Data.tsx" import { PlaygroundScene } from "@/components/Common/Playground/Scene.tsx" import { PlaygroundTeam } from "@/components/Common/Playground/Team.tsx" +import { Card } from "antd" +import { CloseOutlined } from "@ant-design/icons" + +// 定义 Context 类型 +interface IodPlaygroundContextType { + showPlayground: boolean + setShowPlayground: React.Dispatch<React.SetStateAction<boolean>> + detailHeader: React.ReactNode + setDetailHeader: React.Dispatch<React.SetStateAction<React.ReactNode>> + detailMain: React.ReactNode + setDetailMain: React.Dispatch<React.SetStateAction<React.ReactNode>> +} + +// 创建 Context +const PlaygroundContext = createContext<IodPlaygroundContextType | undefined>( + undefined +) + +// 创建自定义 hook 以便子组件使用 +export const useIodPlaygroundContext = () => { + const context = useContext(PlaygroundContext) + if (context === undefined) { + throw new Error( + "usePlaygroundContext must be used within a PlaygroundProvider" + ) + } + return context +} export const PlaygroundIod = () => { + const [showPlayground, setShowPlayground] = useState<boolean>(true) + const [detailHeader, setDetailHeader] = useState(<></>) + const [detailMain, setDetailMain] = useState(<></>) + return ( - <div - className="w-[36%] h-full grid grid-rows-12 gap-3 pt-16 pr-5 pb-0" - style={{ paddingTop: "4rem" }}> - <div className="w-full row-span-5"> - <PlaygroundIodRelevant /> + <PlaygroundContext.Provider + value={{ + showPlayground, + setShowPlayground, + detailMain, + setDetailMain, + detailHeader, + setDetailHeader + }}> + <div className="w-[36%] h-full pt-16 pr-5 pb-0"> + <PlaygroundContent /> </div> - <div className="w-full row-span-4 grid grid-cols-2 gap-3 custom-scrollbar"> - <PlaygroundData /> - <PlaygroundScene /> - </div> - <div className="w-full row-span-3 pb-3"> - <PlaygroundTeam /> - </div> - </div> + </PlaygroundContext.Provider> + ) +} + +// 子组件使用修改card的默认样式 +const classNames = + "h-full [&_.ant-card-body]:h-full [&_.ant-card-body]:!p-[20px] overflow-y-hidden !bg-[rgba(240,245,255,0.3)] backdrop-blur-sm border border-white/30 shadow-xl rounded-2xl" +// 将原来的返回内容移到这个组件中 +const PlaygroundContent = () => { + const { showPlayground, detailMain, detailHeader, setShowPlayground } = + useIodPlaygroundContext() + + + return ( + <AnimatePresence mode="popLayout"> + {showPlayground ? ( + <motion.div + key="playground" + initial={{ x: "100%" }} + animate={{ x: 0 }} + exit={{ x: "100%" }} + transition={{ + duration: 0.6, + ease: "easeInOut" + }} + className="h-full grid grid-rows-12 gap-3"> + <div className="w-full row-span-5"> + <PlaygroundIodRelevant className={classNames.replace('!bg-[rgba(240,245,255,0.3)]', '')} /> + </div> + <div className="w-full row-span-4 grid grid-cols-2 gap-3 custom-scrollbar"> + <PlaygroundData className={classNames} /> + <PlaygroundScene className={classNames} /> + </div> + <div className="w-full row-span-3 pb-3"> + <PlaygroundTeam className={classNames} /> + </div> + </motion.div> + ) : ( + <motion.div + key="alternative" + initial={{ x: "100%" }} + animate={{ x: 0 }} + exit={{ x: "100%" }} + transition={{ + duration: 0.6, + ease: "easeInOut" + }} + className="h-full pb-5"> + <Card className="h-full shadow-xl shadow-gray-500/20 [&_.ant-card-body]:h-full"> + <div className="flex flex-col h-full"> + <div className="pb-6 flex items-center justify-between"> + <div>{detailHeader}</div> + <CloseOutlined + size={30} + className="hover:text-red-500 cursor-pointer transition-colors duration-200 text-xl" + onClick={() => setShowPlayground(true)} + /> + </div> + {detailMain} + </div> + </Card> + </motion.div> + )} + </AnimatePresence> ) } diff --git a/src/hooks/useDynamicTextareaSize.tsx b/src/hooks/useDynamicTextareaSize.tsx index b977c16..c2609e8 100644 --- a/src/hooks/useDynamicTextareaSize.tsx +++ b/src/hooks/useDynamicTextareaSize.tsx @@ -21,13 +21,15 @@ const useDynamicTextareaSize = ( const contentHeight = currentTextarea.scrollHeight; if (maxHeight) { - + // Set max-height and adjust overflow behavior if maxHeight is provided currentTextarea.style.maxHeight = `${maxHeight}px`; currentTextarea.style.overflowY = contentHeight > maxHeight ? "scroll" : "hidden"; - currentTextarea.style.height = `${Math.min(contentHeight, maxHeight)}px`; + currentTextarea.style.height = `${Math.min(contentHeight, maxHeight) < 60 ? 60 : Math.min(contentHeight, maxHeight)}px`; + currentTextarea.style.fontWeight = "normal"; + currentTextarea.style.color = "#374151"; } else { - + // Adjust height without max height constraint currentTextarea.style.height = `${contentHeight}px`; } @@ -35,4 +37,4 @@ const useDynamicTextareaSize = ( }, [textareaRef, textContent, maxHeight]); }; -export default useDynamicTextareaSize; \ No newline at end of file +export default useDynamicTextareaSize; diff --git a/src/libs/playground.tsx b/src/libs/playground.tsx index ee61f58..3ff4032 100644 --- a/src/libs/playground.tsx +++ b/src/libs/playground.tsx @@ -1,14 +1,12 @@ -import RocketSvg from "@/assets/icons/rocket.svg" -import BulbSvg from "@/assets/icons/bulb.svg" -import EyeSvg from "@/assets/icons/eye.svg" -import ASvg from "@/assets/icons/a.svg" -import BSvg from "@/assets/icons/b.svg" -import CSvg from "@/assets/icons/c.svg" -import DSvg from "@/assets/icons/d.svg" -import ESvg from "@/assets/icons/e.svg" -import FSvg from "@/assets/icons/f.svg" +import { Avatar } from "antd" +import { MedicineBottleFillIcon } from "@/components/Icons/MedicineBottleFill.tsx" +import { CheckIcon } from "@/components/Icons/Check.tsx" +import { NewBottleIcon } from "@/components/Icons/NewBottle.tsx" +import { BatteryIcon } from "@/components/Icons/Battery.tsx" +import { ShipIcon } from "@/components/Icons/Ship.tsx" +import { Ship1Icon } from "@/components/Icons/Ship1.tsx" -export const qaPrompt =[ +export const qaPrompt = [ // { // title: "如何开发一个适合超大型城市的碳普惠方法学?", // icon: <img src={RocketSvg} alt="Rocket" className="w-10 my-0" />, @@ -23,29 +21,71 @@ export const qaPrompt =[ // }, { title: "新药临床研究如何提升实验安全性?", - icon: <img src={ASvg} alt="Rocket" className="w-10 my-0" />, + icon: ( + <Avatar + className="!bg-[#3581e3b3]" + shape="square" + size={40} + icon={<MedicineBottleFillIcon className="w-7" />} + /> + ) }, { title: "如何加速新药申报和审批?", - icon: <img src={BSvg} alt="Rocket" className="w-10 my-0" />, + icon: ( + <Avatar + className="!bg-[#3581e3b3]" + shape="square" + size={40} + icon={<CheckIcon className="w-7" />} + /> + ) }, { title: "如何研制与司美格鲁肽相似的新药?", - icon: <img src={CSvg} alt="Rocket" className="w-10 my-0" />, + icon: ( + <Avatar + className="!bg-[#3581e3b3]" + shape="square" + size={40} + icon={<NewBottleIcon className="w-7" />} + /> + ) }, { title: "如何解决固态电池的成本和寿命难题?", - icon: <img src={DSvg} alt="Rocket" className="w-10 my-0" />, + icon: ( + <Avatar + className="!bg-[#3581e3b3]" + shape="square" + size={40} + icon={<BatteryIcon className="w-7" />} + /> + ) }, { title: "如何解决船舶制造中的材料腐蚀难题?", - icon: <img src={ESvg} alt="Rocket" className="w-10 my-0" />, + icon: ( + <Avatar + className="!bg-[#3581e3b3]" + shape="square" + size={40} + icon={<ShipIcon className="w-7" />} + /> + ) }, { title: "如何解决船舶制造中流体模拟和建模优化难题?", - icon: <img src={FSvg} alt="Rocket" className="w-10 my-0" />, - }, + icon: ( + <Avatar + className="!bg-[#3581e3b3]" + shape="square" + size={40} + icon={<Ship1Icon className="w-7" />} + /> + ) + } ].map((item, index) => ({ ...item, - id: index.toString(), + id: index.toString() }))