服务状态监控
这是一个模拟服务器集群状态监控的实时数据展示示例。该示例展示了如何将各个服务节点的运行状态数据实时展示在场景中,包含以下核心功能:
-
实时监控多个关键指标:
- 💻 CPU 使用率
- 💾 内存占用率
- ⏱️ 服务运行时间
-
灵活的展示方式:
- 支持悬浮提示框展示(默认)
- 支持固定位置展示(可通过左上角开关切换)
- 数据卡片支持毛玻璃效果
-
智能的状态展示:
- ✅ 正常运行状态(绿色)
- ⚠️ 警告状态(黄色,资源占用超过 80%)
- ❌ 危险状态(红色,资源占用超过 90%)
点击场景中的服务节点可查看详细状态信息,通过左上角的开关可以切换数据卡片的显示模式。数据每 100ms 自动更新一次,模拟真实的监控场景。
演示效果
fixed
示例代码
import { MouseEventParams, Element3D, ICraftPlayer, ICraftPlayerInstance } from "@icraft/player-react";
import { useEffect, useRef, useState } from "react";
import { createPortal } from "react-dom";
import { getData } from "./utils";
import { StatusCardProps } from "./interface";
import StatusCard from "./StatusCard";
import styles from "./index.module.css";
export default () => {
const playerRef = useRef<ICraftPlayerInstance>(null);
const [tipContainer, setTipContainer] = useState<HTMLDivElement | null>(null);
const [activeService, setActiveService] = useState<string | null>("DTS");
const [activeData, setActiveData] = useState<StatusCardProps | null>(null);
const [fixed, setFixed] = useState<boolean>(false);
const elementRef = useRef<Element3D | null>(null);
const onReady = () => {
const player = playerRef.current;
if (!activeService) {
return;
}
const element = player?.getElementsByName(activeService)?.[0];
if (!element) return;
elementRef.current = element;
if (element?.tip) {
const container = document.createElement("div");
element.tip.updateInnerHTML(container);
element.tip.updateVisible(true);
setTipContainer(container);
}
};
const onClick = (params: MouseEventParams) => {
const { instance: element } = params;
const player = playerRef.current;
// clear old tip
elementRef.current?.tip?.reset();
// clear old fixed container
if (fixed && tipContainer) {
tipContainer.remove();
}
elementRef.current = element;
if (!element) {
setActiveService(null);
setTipContainer(null);
return;
}
const activeName = element.options?.name;
setActiveService(activeName || null);
if (fixed) {
const container = document.createElement("div");
container.style.position = "absolute";
container.style.top = "10px";
container.style.right = "10px";
container.style.zIndex = "100";
player?.getDom().appendChild(container);
setTipContainer(container);
} else {
if (element?.tip) {
const container = document.createElement("div");
element.tip.updateInnerHTML(container);
element.tip.updateVisible(true);
setTipContainer(container);
}
}
};
useEffect(() => {
if (!activeService) return;
const interval = setInterval(() => {
setActiveData(getData(activeService));
}, 100);
return () => clearInterval(interval);
}, [activeService]);
return (
<div className={styles.container}>
<ICraftPlayer
src='/templates/ControlPlatform.iplayer'
ref={playerRef}
onReady={onReady}
onClick={onClick}
addons={["ZoomBar"]}
/>
<div className={styles.checkbox}>
<label className={styles.switch}>
<input
type='checkbox'
checked={fixed}
onChange={(e) => setFixed(e.target.checked)}
/>
<span className={styles.slider}></span>
</label>
<span>fixed</span>
</div>
{tipContainer &&
activeData &&
createPortal(
<StatusCard
serviceName={activeData.serviceName}
status={activeData.status}
metrics={activeData.metrics}
/>,
tipContainer
)}
</div>
);
};