refactor(iod): 重构数联网相关组件和逻辑

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

View File

@@ -10,6 +10,7 @@ import { DatasetIcon } from "@/components/Icons/Dataset.tsx"
import { TechCompanyIcon } from "@/components/Icons/TechCompany.tsx"
import { ResearchInstitutesIcon } from "@/components/Icons/ResearchInstitutes.tsx"
import { NSDCIcon } from "@/components/Icons/NSDC.tsx"
import { useIodPlaygroundContext } from "@/components/Option/Playground/PlaygroundIod.tsx"
const rotate = keyframes`
0% {
@@ -32,8 +33,8 @@ const breathe = keyframes`
}
`
// 花瓣
const CircleElement = styled.div<{ delay: number; playing: boolean }>`
// 花瓣 /* ${(props) => (props.playing ? "running" : "paused")}; */
const CircleElement = styled.div<{ delay: number }>`
position: absolute;
width: 300px;
height: 160px;
@@ -46,7 +47,7 @@ const CircleElement = styled.div<{ delay: number; playing: boolean }>`
${rotate} 6s linear infinite,
${breathe} 2s infinite alternate;
animation-delay: ${(props) => props.delay}s;
animation-play-state: ${(props) => (props.playing ? "running" : "paused")};
animation-play-state: running;
animation-duration: 3s; /* 添加动画总持续时间 */
animation-fill-mode: forwards; /* 保持动画结束时的状态 */
`
@@ -221,24 +222,19 @@ type Props = {
className?: string
}
export const PlaygroundIodRelevant: React.FC<Props> = ({ className }) => {
const { messages, iodLoading, currentMessageId, iodSearch } =
useMessageOption()
const { iodLoading, iodSearch } = useMessageOption()
const { currentIodMessage } = useIodPlaygroundContext()
const showSearchData = useMemo(() => {
return iodSearch && messages.length > 0 && !iodLoading
}, [iodSearch, messages, iodLoading])
return currentIodMessage && !iodLoading
}, [currentIodMessage, iodLoading])
const data = useMemo(() => {
const currentMessage = messages?.find(
(message) => message.id === currentMessageId
)
const loading = (iodSearch && iodLoading)
const text = loading ? '正' : '已'
const text2 = loading ? '进行' : '完成'
const text3 = loading ? '……' : ''
const loading = iodSearch && iodLoading
const text = loading ? "正" : "已"
const text2 = loading ? "进行" : "完成"
const text3 = loading ? "……" : ""
const duration = loading ? 2.5 : 0
return [
@@ -256,7 +252,12 @@ export const PlaygroundIodRelevant: React.FC<Props> = ({ className }) => {
</span>
<span className="text-[#f00000]">
<CountUp decimals={1} end={53.7} duration={duration} separator="," />
<CountUp
decimals={1}
end={53.7}
duration={duration}
separator=","
/>
</span>
{text2}{text3}
@@ -268,7 +269,7 @@ export const PlaygroundIodRelevant: React.FC<Props> = ({ className }) => {
<span className="text-green-700">
{" "}
<CountUp
end={currentMessage?.iodSources.data.total ?? 0}
end={currentIodMessage?.data.total ?? 0}
duration={2.5}
separator=","
/>
@@ -288,9 +289,14 @@ export const PlaygroundIodRelevant: React.FC<Props> = ({ className }) => {
<CountUp end={138} duration={duration} separator="," />
</span>
<span className="text-[#f00000]">
<CountUp end={18.3} decimals={1} duration={duration} separator="," />
<CountUp
end={18.3}
decimals={1}
duration={duration}
separator=","
/>
</span>
{text2}{text3}
@@ -302,7 +308,7 @@ export const PlaygroundIodRelevant: React.FC<Props> = ({ className }) => {
<span className="text-green-700">
{" "}
<CountUp
end={currentMessage?.iodSources.scenario.total ?? 0}
end={currentIodMessage?.scenario.total ?? 0}
duration={2.5}
separator=","
/>
@@ -324,7 +330,13 @@ export const PlaygroundIodRelevant: React.FC<Props> = ({ className }) => {
<span className="text-[#f00000]">
{" "}
<CountUp end={2.1} decimals={1} duration={duration} separator="," />
<CountUp
end={2.1}
decimals={1}
duration={duration}
separator=","
/>
</span>
<span className="text-[#f00000]">
@@ -340,7 +352,7 @@ export const PlaygroundIodRelevant: React.FC<Props> = ({ className }) => {
<span className="text-green-700">
{" "}
<CountUp
end={currentMessage?.iodSources.organization.total ?? 0}
end={currentIodMessage?.organization.total ?? 0}
duration={2.5}
separator=","
/>
@@ -353,7 +365,7 @@ export const PlaygroundIodRelevant: React.FC<Props> = ({ className }) => {
)
}
]
}, [messages, iodLoading])
}, [showSearchData, iodLoading])
return (
<Card
@@ -365,9 +377,9 @@ export const PlaygroundIodRelevant: React.FC<Props> = ({ className }) => {
<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} />
<CircleElement delay={2} playing={true} />
<CircleElement delay={0} />
<CircleElement delay={1} />
<CircleElement delay={2} />
</div>
</div>
@@ -376,16 +388,14 @@ export const PlaygroundIodRelevant: React.FC<Props> = ({ className }) => {
<h2 className="text-xl font-semibold text-[#1a3c87] flex justify-center items-center">
<div className="flex items-center gap-2">
<SearchIcon />
{messages.length > 0
? "科创数联网深度搜索"
: "科创数联网连接资源"}
{currentIodMessage ? "科创数联网深度搜索" : "科创数联网连接资源"}
</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
{currentIodMessage
? "下面是在科创数联网上进行深度搜索得到的相关数据、场景和团队"
: "下面是科创数联网连接的数据、场景和团队"}
</p>
@@ -393,7 +403,7 @@ export const PlaygroundIodRelevant: React.FC<Props> = ({ className }) => {
{/* Content */}
<div className="space-y-2 flex-1 overflow-y-auto">
{messages.length ? (
{currentIodMessage ? (
<AnimatePresence mode="wait">
<motion.div
key="search-results"
@@ -422,16 +432,16 @@ export const PlaygroundIodRelevant: React.FC<Props> = ({ className }) => {
/>
)}
</div>
<p
<div
className={`text-gray-700 ${showSearchData ? "text-sm" : "text-lg"}`}>
{item.title}
</p>
</div>
</div>
{item.description && (
<div className="flex-1">
<p className="text-xs text-gray-500 mt-1 pl-7">
<div className="text-xs text-gray-500 mt-1 pl-7">
{item.description}
</p>
</div>
</div>
)}
</div>