refactor(models): 为Room和Rack模型添加布局相关字段 feat(routes): 实现机房平面图相关API接口 feat(components): 添加平面图编辑器、画布渲染及交互组件 feat(hooks): 实现平面图数据管理和状态管理 feat(pages): 新增机房平面图页面入口 style(components): 优化平面图组件样式和交互体验
113 lines
3.4 KiB
React
113 lines
3.4 KiB
React
import React from 'react';
|
|
import { Drawer, Descriptions, Tag, Progress, Button, Space } from 'antd';
|
|
import {
|
|
CloudServerOutlined,
|
|
ThunderboltOutlined,
|
|
RightOutlined,
|
|
EyeOutlined,
|
|
} from '@ant-design/icons';
|
|
import { useNavigate } from 'react-router-dom';
|
|
import { RACK_STATUS_COLORS } from '../canvas/CanvasConstants';
|
|
|
|
const statusMap = {
|
|
active: { text: '在用', color: 'blue' },
|
|
maintenance: { text: '维护中', color: 'orange' },
|
|
inactive: { text: '停用', color: 'default' },
|
|
};
|
|
|
|
const RackDetailPanel = ({ rack, visible, onClose }) => {
|
|
const navigate = useNavigate();
|
|
|
|
if (!rack) return null;
|
|
|
|
const statusInfo = statusMap[rack.status] || { text: rack.status, color: 'default' };
|
|
const utilization = rack.utilization != null ? Math.round(rack.utilization * 100) : 0;
|
|
const powerPercent = rack.maxPower > 0
|
|
? Math.round(((rack.currentPower || 0) / rack.maxPower) * 100)
|
|
: 0;
|
|
|
|
const handleView3D = () => {
|
|
navigate('/visualization-3d', { state: { rackId: rack.rackId } });
|
|
};
|
|
|
|
const handleViewDevices = () => {
|
|
navigate('/devices', { state: { rackId: rack.rackId } });
|
|
};
|
|
|
|
return (
|
|
<Drawer
|
|
title={
|
|
<Space>
|
|
<CloudServerOutlined style={{ color: RACK_STATUS_COLORS[rack.status] || '#1677ff' }} />
|
|
{rack.name}
|
|
</Space>
|
|
}
|
|
placement="right"
|
|
width={360}
|
|
open={visible}
|
|
onClose={onClose}
|
|
extra={
|
|
<Space>
|
|
<Button
|
|
size="small"
|
|
icon={<EyeOutlined />}
|
|
onClick={handleView3D}
|
|
>
|
|
3D视图
|
|
</Button>
|
|
<Button
|
|
size="small"
|
|
icon={<RightOutlined />}
|
|
onClick={handleViewDevices}
|
|
>
|
|
设备
|
|
</Button>
|
|
</Space>
|
|
}
|
|
>
|
|
<Descriptions column={1} size="small" bordered>
|
|
<Descriptions.Item label="机柜ID">{rack.rackId}</Descriptions.Item>
|
|
<Descriptions.Item label="状态">
|
|
<Tag color={statusInfo.color}>{statusInfo.text}</Tag>
|
|
</Descriptions.Item>
|
|
<Descriptions.Item label="位置">
|
|
{rack.rowPos != null && rack.colPos != null
|
|
? `第${rack.rowPos + 1}排 第${rack.colPos + 1}列`
|
|
: '未分配'}
|
|
</Descriptions.Item>
|
|
<Descriptions.Item label="朝向">{rack.facing || 'front'}</Descriptions.Item>
|
|
<Descriptions.Item label="高度">{rack.height}U</Descriptions.Item>
|
|
<Descriptions.Item label="设备数量">{rack.deviceCount || 0} 台</Descriptions.Item>
|
|
</Descriptions>
|
|
|
|
<div style={{ marginTop: 16 }}>
|
|
<div style={{ marginBottom: 8, fontWeight: 500 }}>U位使用率</div>
|
|
<Progress
|
|
percent={utilization}
|
|
strokeColor={
|
|
utilization < 30 ? '#52c41a' :
|
|
utilization < 70 ? '#faad14' : '#ff4d4f'
|
|
}
|
|
format={() => `${rack.usedU || 0}/${rack.totalU || rack.height || 0}U`}
|
|
/>
|
|
</div>
|
|
|
|
<div style={{ marginTop: 16 }}>
|
|
<div style={{ marginBottom: 8, fontWeight: 500 }}>
|
|
<ThunderboltOutlined /> 功率
|
|
</div>
|
|
<Progress
|
|
percent={powerPercent}
|
|
strokeColor={
|
|
powerPercent < 50 ? '#52c41a' :
|
|
powerPercent < 80 ? '#faad14' : '#ff4d4f'
|
|
}
|
|
format={() => `${rack.currentPower || 0}/${rack.maxPower || 0}W`}
|
|
/>
|
|
</div>
|
|
</Drawer>
|
|
);
|
|
};
|
|
|
|
export default RackDetailPanel;
|