zhaoweijie 2b4885ae2d refactor(iod): 重构数联网相关组件和逻辑
-优化了 Data、Scene 和 Team组件的逻辑,使用 currentIodMessage 替代复杂的条件判断- 改进了 IodRelevant 组件的动画和数据处理方式
- 调整了 Message 组件以支持数联网搜索功能
- 重构了 PlaygroundIodProvider,简化了上下文类型和数据处理
- 更新了数据库相关操作,使用新的 HistoryMessage 类型
- 新增了 IodDb 类来管理数联网连接配置
2025-08-24 19:00:49 +08:00

159 lines
5.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useMemo } from "react"
import { DataNavigation } from "@/components/Common/DataNavigation.tsx"
import { Card, Skeleton } from "antd"
import { IodRegistryEntry } from "@/types/iod.ts"
import { useIodPlaygroundContext } from "@/components/Option/Playground/PlaygroundIod.tsx"
const defaultData: IodRegistryEntry[] = [
{
name: "北京大学",
description:
"北大是常为新的,改进的运动的先锋,要使中国向着好的,往上的道路走。",
doId: "12100000400002259P"
},
{
name: "长三角先进材料研究院",
description: "由江苏省人民政府联合中国科学院、中国钢研科技集团和中国",
doId: "91320507MAEKWL5Y2L"
},
{
name: "伊利诺伊大学香槟分校UIUC",
description: "创建于1867年坐落于伊利诺伊州双子城厄巴纳香槟市",
doId: "bdware.org/uiuc"
}
]
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 { iodLoading } = useMessageOption()
const {
setShowPlayground,
setDetailHeader,
setDetailMain,
currentIodMessage
} = useIodPlaygroundContext()
const data = useMemo<IodRegistryEntry[]>(() => {
return currentIodMessage
? currentIodMessage.organization?.data ?? []
: defaultData
}, [currentIodMessage])
const title = useMemo(() => {
return currentIodMessage ? "推荐团队" : "热点团队"
}, [currentIodMessage])
const showMore = () => {
setShowPlayground(false)
setDetailHeader(
<Header
title={title}
showButton={false}
onClick={() => setShowPlayground(false)}
/>
)
setDetailMain(
<Main loading={iodLoading && Boolean(currentIodMessage)} data={data} truncate={false} flat={false} />
)
}
return (
<Card className={`${className}`} hoverable>
<div className="h-full flex flex-col gap-2 relative">
{/* 数据导航 */}
<Header title={title} onClick={showMore} />
{/* 数据列表 */}
<Main loading={iodLoading && Boolean(currentIodMessage)} data={data.slice(0, 3)} />
</div>
</Card>
)
}