refactor(components): 重构 playground组件

- 移除 Data、Scene 和 IodRelevant 组件中的 Drawer
- 优化 Data、Scene 和 IodRelevant 组件的结构
- 添加 Header 组件用于展示标题和关闭按钮
- 使用 Main 组件替代原来的 ShowCard 组件
- 调整样式和布局,提高组件的可复用性和可维护性
This commit is contained in:
zhaoweijie
2025-08-23 17:03:14 +08:00
parent 6fb71b01f0
commit e640b1254d
17 changed files with 664 additions and 410 deletions

View File

@@ -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<Props> = ({ Header, showButton = true, onClick }) => {
export const DataNavigation: React.FC<Props> = ({
Header,
showButton = true,
onClick
}) => {
return (
<div className="flex items-center justify-between bg-white dark:bg-gray-800 rounded-lg mb-3">
<div className="flex items-center justify-between bg-white dark:bg-gray-800 rounded-lg">
{/* 左侧部分 */}
<div className="flex items-center">
<Title
@@ -25,11 +29,13 @@ export const DataNavigation: React.FC<Props> = ({ 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>
)
};
}

View File

@@ -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>
)
}

View File

@@ -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>,
}
})
}

View File

@@ -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"

View File

@@ -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>
)
}

View File

@@ -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>
)
}