feat(iod): 重构数联网搜索功能

- 新增数联网设置页面
- 优化数联网搜索结果展示
- 添加数据集、科创场景和科技企业等不同类型的搜索结果
- 重构搜索结果卡片组件,支持加载状态和不同展示模式
- 更新数联网搜索相关的国际化文案
This commit is contained in:
zhaoweijie
2025-08-22 17:15:19 +08:00
parent efbf2a3eff
commit 17020e8755
33 changed files with 1321 additions and 773 deletions

View File

@@ -1,8 +1,8 @@
import React from "react"
import { Button, Card } from "antd"
import React, { useMemo } from "react"
import { Card } from "antd"
// 使用 CSS-in-JS 方式
import styled, { keyframes } from 'styled-components'
import styled, { keyframes } from "styled-components"
const rotate = keyframes`
0% {
@@ -25,20 +25,22 @@ const breathe = keyframes`
}
`
const CircleElement = styled.div<{ delay: number }>`
const CircleElement = styled.div<{ delay: number; playing: boolean }>`
position: absolute;
width: 300px;
height: 160px;
background: #3b82f6; // blue-500
background: #3b82f6; // blue-500
opacity: 0.2;
border-radius: 50%;
top: 55%;
left: 50%;
animation: ${rotate} 6s linear infinite, ${breathe} 2s infinite alternate;
animation-delay: ${props => props.delay}s;
animation:
${rotate} 6s linear infinite,
${breathe} 2s infinite alternate;
animation-delay: ${(props) => props.delay}s;
animation-play-state: ${(props) => (props.playing ? "running" : "paused")};
`
const SuccessIcon = () => {
return (
<svg
@@ -64,13 +66,13 @@ const LoadingIcon = () => {
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="8408"
p-id="29588"
width="18"
height="18">
<path
d="M512 128C299.936 128 128 296.672 128 504.736c0 130.784 67.904 245.984 170.976 313.536l35.52-52.256C248.576 709.696 192 613.696 192 504.736c0-173.376 143.264-313.92 320-313.92s320 140.544 320 313.92c0 98.112-45.856 185.696-117.696 243.296l-73.792-72.416V864h192l-72.768-71.36C843.072 723.52 896 620.16 896 504.704 896 296.672 724.064 128 512 128z"
fill="#52c41a"
p-id="8409"></path>
d="M483.712 888.064a52.437333 52.437333 0 1 1 52.48 52.352 52.394667 52.394667 0 0 1-52.48-52.352z m-235.434667-53.76a65.578667 65.578667 0 1 1 46.421334 19.242667 65.962667 65.962667 0 0 1-46.378667-19.242667z m499.584-16.597333a41.984 41.984 0 0 1 59.264-59.434667 42.282667 42.282667 0 0 1 0 59.434667 41.941333 41.941333 0 0 1-59.264 0zM112.853333 546.602667a81.92 81.92 0 1 1 81.92 81.92 81.834667 81.834667 0 0 1-81.92-81.877334z m731.008 0a33.536 33.536 0 1 1 33.493334 33.578666 33.578667 33.578667 0 0 1-33.450667-33.536zM222.208 377.6a102.4 102.4 0 1 1 72.533333 29.866667 102.869333 102.869333 0 0 1-72.533333-29.824z m536.32-53.504a26.666667 26.666667 0 1 1 18.816 7.936 26.368 26.368 0 0 1-18.773333-7.893333zM414.378667 205.184a121.642667 121.642667 0 1 1 121.813333 121.6A121.728 121.728 0 0 1 414.378667 205.226667z"
p-id="29589"
fill="#4284f6"></path>
</svg>
)
}
@@ -94,60 +96,110 @@ const SearchIcon = () => {
}
export const PlaygroundIodRelevant: React.FC = () => {
const data = [
{
title: <p><span className="text-[#9d0000]">29</span><span className="text-[#9d0000]">50</span></p>,
description: <p><span className="text-green-700"> 4 </span></p>,
status: "success"
},
{
title: <p><span className="text-[#9d0000]">100</span><span className="text-[#9d0000]">2800</span></p>,
description: "已发现4个数据集",
status: "success"
},
{
title: <p><span className="text-[#9d0000]">1000</span><span className="text-[#9d0000]">12</span></p>,
status: "loading"
}
]
const { messages, iodLoading, currentMessageId, iodSearch } =
useMessageOption()
for (let i = 0; i < 10; i++) {
data.push({
title: <p><span className="text-[#9d0000]">1000</span><span className="text-[#9d0000]">12</span>{i}</p>,
description: "已发现4个数据集",
status: "success"
})
}
const showDescription = useMemo(() => {
return iodSearch && messages.length > 0 && !iodLoading
}, [iodSearch, messages, iodLoading])
const data = useMemo(() => {
const currentMessage = messages?.find(
(message) => message.id === currentMessageId
)
return [
{
title: (
<p className="font-extrabold">
<span className="text-[#f00000]"> 11 </span>
<span className="text-[#f00000]"> 500000+ </span>
</p>
),
description: showDescription ? (
<p>
<span className="text-green-700">
{" "}
{currentMessage?.iodSources.data.total}{" "}
</span>
</p>
) : (
""
)
},
{
title: (
<p className="font-extrabold">
<span className="text-[#f00000]"> 1000000+ </span>
<span className="text-[#f00000]"> 50000+ </span>
</p>
),
description: showDescription ? (
<p>
<span className="text-green-700">
{" "}
{currentMessage?.iodSources.scenario.total}{" "}
</span>
</p>
) : (
""
)
},
{
title: (
<p className="font-extrabold">
<span className="text-[#f00000]"> 1000+ </span>
<span className="text-[#f00000]"> 763 </span>
<span className="text-[#f00000]"> 21000+ </span>
</p>
),
description: showDescription ? (
<p>
<span className="text-green-700">
{" "}
{currentMessage?.iodSources.organization.total}{" "}
</span>
</p>
) : (
""
)
}
]
}, [messages, iodLoading])
return (
<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="flex flex-col h-full [&_.ant-card-body]:h-full [&_.ant-card-body]:!p-[20px] translate-y-[-2px] !bg-[#f0f9ff]">
<div className="h-full flex flex-col relative">
{/* 花瓣效果 */}
<div className="absolute inset-0 pointer-events-none z-0 overflow-hidden">
<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} />
<CircleElement delay={1} />
<CircleElement delay={2} />
<CircleElement delay={0} playing={true} />
<CircleElement delay={1} playing={true} />
<CircleElement delay={2} playing={true} />
</div>
</div>
{/* Header */}
<div className="p-3">
<h2 className="text-xl font-semibold text-[#08307f] flex justify-between items-center">
<div className='flex items-center gap-2'>
<h2 className="text-xl font-semibold text-[#1a3c87] flex justify-center items-center">
<div className="flex items-center gap-2">
<SearchIcon />
</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>
{/*<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-[#08307f] mt-1 align-middle">
<p className="text-sm text-[#1a3c87] mt-1 text-center">
</p>
</div>
@@ -156,25 +208,30 @@ export const PlaygroundIodRelevant: React.FC = () => {
<div className="space-y-2 flex-1 overflow-y-auto">
{data.map((item, index) => (
<Card
className="[&>*:first-child]:!p-3 shadow-md"
key={index}
>
<div className="flex items-start gap-2">
<div className="w-5 h-5 mt-1 flex-shrink-0">
{item.status === "success" ? (
<SuccessIcon />
) : (
<LoadingIcon />
)}
className="[&_.ant-card-body]:!p-3 [&_.ant-card-body]:h-full shadow-md h-[88px]"
key={index}>
<div
className={`flex flex-col gap-2 h-full items-start ${showDescription ? "justify-start" : "justify-center"}`}>
<div className="flex items-center gap-2">
<div className={`${showDescription ? "w-5 h-5" : "w-6 h-6"}`}>
{iodSearch && iodLoading ? (
<LoadingIcon />
) : (
<SuccessIcon />
)}
</div>
<p
className={`text-gray-700 ${showDescription ? "text-sm" : "text-lg"}`}>
{item.title}
</p>
</div>
<div className="flex-1">
<p className="text-sm text-gray-700">{item.title}</p>
{item.description && (
<p className="text-xs text-gray-500 mt-1">
{item.description && (
<div className="flex-1">
<p className="text-xs text-gray-500 mt-1 pl-7">
{item.description}
</p>
)}
</div>
</div>
)}
</div>
</Card>
))}