在管理页面增加设备 IP 信息

This commit is contained in:
dushixiang committed 2026-01-11 11:43:39 +08:00
1 parent 80de85d51d
commit ab1a13d5b2
8 files changed
+68 -3

No files matched your search

+1
View File
@@ -243,6 +243,7 @@ func setupApi(app *orz.App, components *AppComponents) {
adminApi.GET("/agents/statistics", components.AgentHandler.GetStatistics)
adminApi.GET("/agents/tags", components.AgentHandler.GetTags)
adminApi.GET("/agents/:id", components.AgentHandler.GetForAdmin)
adminApi.GET("/agents/:id/metrics/latest", components.AgentHandler.GetAdminLatestMetrics)
adminApi.PUT("/agents/:id", components.AgentHandler.UpdateInfo)
adminApi.POST("/agents/batch/tags", components.AgentHandler.BatchUpdateTags)
adminApi.DELETE("/agents/:id", components.AgentHandler.Delete)
+11
View File
@@ -51,6 +51,17 @@ func (h *AgentHandler) GetForAdmin(c echo.Context) error {
return orz.Ok(c, agent)
}
// GetAdminLatestMetrics 获取探针最新指标(管理员接口,显示完整信息)
func (h *AgentHandler) GetAdminLatestMetrics(c echo.Context) error {
id := c.Param("id")
metrics, ok := h.metricService.GetLatestMetrics(id)
if !ok {
return orz.NewError(404, "探针最新指标不存在")
}
return orz.Ok(c, metrics)
}
// SendCommand 向探针发送指令
func (h *AgentHandler) SendCommand(c echo.Context) error {
agentID := c.Param("id")
@@ -142,6 +142,8 @@ func (h *AgentHandler) GetLatestMetrics(c echo.Context) error {
if !ok {
return orz.NewError(404, "探针最新指标不存在")
}
// 清空网络接口指标,避免返回敏感信息
metrics.NetworkInterfaces = nil
return orz.Ok(c, metrics)
}
+1
View File
@@ -26,6 +26,7 @@ type LatestMetrics struct {
Memory *protocol.MemoryData `json:"memory,omitempty"`
Disk *DiskSummary `json:"disk,omitempty"`
Network *NetworkSummary `json:"network,omitempty"`
NetworkInterfaces []protocol.NetworkData `json:"networkInterfaces,omitempty"`
NetworkConnection *protocol.NetworkConnectionData `json:"networkConnection,omitempty"`
Host *protocol.HostInfoData `json:"host,omitempty"`
GPU []protocol.GPUData `json:"gpu,omitempty"`
+1
View File
@@ -127,6 +127,7 @@ func (s *MetricService) HandleMetricData(ctx context.Context, agentID string, me
TotalBytesRecvTotal: totalRecvTotal,
TotalInterfaces: len(networkDataList),
}
latestMetrics.NetworkInterfaces = networkDataList
// 更新流量统计
if err := s.trafficService.UpdateAgentTraffic(ctx, agentID, totalRecvTotal, totalSentTotal); err != nil {
s.logger.Error("更新探针流量统计失败",
+37 -3
View File
@@ -6,8 +6,14 @@ import {Activity, ArrowLeft, Clock, FileWarning, Lock, RefreshCw, Shield, Termin
import TamperProtection from './TamperProtection.tsx';
import SSHLoginMonitor from './SSHLoginMonitor.tsx';
import TrafficStats from './TrafficStats.tsx';
import {getAgentForAdmin, getAuditResult, sendAuditCommand, type VPSAuditResult} from '@/api/agent.ts';
import type {Agent} from '@/types';
import {
getAgentForAdmin,
getAgentLatestMetricsForAdmin,
getAuditResult,
sendAuditCommand,
type VPSAuditResult
} from '@/api/agent.ts';
import type {Agent, LatestMetrics} from '@/types';
import dayjs from 'dayjs';
import {getErrorMessage} from '@/lib/utils';
import AuditResultView from './AuditResultView';
@@ -19,6 +25,7 @@ const AgentDetail = () => {
const {message: messageApi} = App.useApp();
const [loading, setLoading] = useState(false);
const [agent, setAgent] = useState<Agent | null>(null);
const [latestMetrics, setLatestMetrics] = useState<LatestMetrics | null>(null);
const [auditResult, setAuditResult] = useState<VPSAuditResult | null>(null);
const [auditing, setAuditing] = useState(false);
const [activeTab, setActiveTab] = useState<string>(searchParams.get('tab') || 'info');
@@ -28,13 +35,15 @@ const AgentDetail = () => {
setLoading(true);
try {
const [agentRes, auditRes] = await Promise.all([
const [agentRes, auditRes, latestMetricsRes] = await Promise.all([
getAgentForAdmin(id),
getAuditResult(id).catch(() => ({data: null})),
getAgentLatestMetricsForAdmin(id).catch(() => ({data: null})),
]);
setAgent(agentRes.data);
setAuditResult(auditRes.data);
setLatestMetrics(latestMetricsRes.data || null);
} catch (error: any) {
messageApi.error(error.response?.data?.message || '获取探针信息失败');
} finally {
@@ -104,6 +113,13 @@ const AgentDetail = () => {
];
const deviceIpInterfaces = (latestMetrics?.networkInterfaces || [])
.map((netInterface) => ({
name: netInterface.interface,
addrs: Array.from(new Set((netInterface.addrs || []).map((addr) => addr.trim()).filter(Boolean))),
}))
.filter((netInterface) => netInterface.addrs.length > 0);
// Tab 项配置
const tabItems: TabsProps['items'] = [
{
@@ -120,6 +136,24 @@ const AgentDetail = () => {
<Descriptions.Item label="探针ID">{agent?.id}</Descriptions.Item>
<Descriptions.Item label="主机名">{agent?.hostname}</Descriptions.Item>
<Descriptions.Item label="通信IP">{agent?.ip}</Descriptions.Item>
<Descriptions.Item label="设备IP" span={2}>
{deviceIpInterfaces.length > 0 ? (
<div className="flex flex-col gap-2">
{deviceIpInterfaces.map((netInterface) => (
<div key={netInterface.name} className="flex flex-col gap-1">
<span className="text-xs text-gray-500">{netInterface.name}</span>
<div className="flex flex-wrap gap-2">
{netInterface.addrs.map((addr) => (
<Tag key={`${netInterface.name}-${addr}`}>{addr}</Tag>
))}
</div>
</div>
))}
</div>
) : (
'-'
)}
</Descriptions.Item>
<Descriptions.Item label="操作系统">
<Tag color="blue">{agent?.os}</Tag>
</Descriptions.Item>
+4
View File
@@ -78,6 +78,10 @@ export const getAgentForAdmin = (id: string) => {
return get<Agent>(`/admin/agents/${id}`);
};
export const getAgentLatestMetricsForAdmin = (agentId: string) => {
return get<LatestMetrics>(`/admin/agents/${agentId}/metrics/latest`);
};
export const getAgentMetrics = (params: GetAgentMetricsRequest) => {
const {agentId, type, range = '1h', start, end, interface: interfaceName} = params;
const query = new URLSearchParams();
+11
View File
@@ -207,6 +207,16 @@ export interface NetworkSummary {
totalInterfaces: number; // 网卡数量
}
export interface NetworkInterfaceMetric {
interface: string;
macAddress?: string;
addrs?: string[];
bytesSentRate: number;
bytesRecvRate: number;
bytesSentTotal: number;
bytesRecvTotal: number;
}
// 主机信息
export interface HostInfo {
hostname: string;
@@ -416,6 +426,7 @@ export interface LatestMetrics {
memory?: MemoryMetric;
disk?: DiskSummary; // 改为汇总数据
network?: NetworkSummary; // 改为汇总数据
networkInterfaces?: NetworkInterfaceMetric[];
networkConnection?: NetworkConnectionMetric; // 网络连接统计
host?: HostInfo; // 主机信息
gpu?: GPUMetric[]; // GPU 列表