feat(floorplan): 新增机房平面图功能模块
refactor(models): 为Room和Rack模型添加布局相关字段 feat(routes): 实现机房平面图相关API接口 feat(components): 添加平面图编辑器、画布渲染及交互组件 feat(hooks): 实现平面图数据管理和状态管理 feat(pages): 新增机房平面图页面入口 style(components): 优化平面图组件样式和交互体验
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
import { useContext } from 'react';
|
||||
import FloorPlanContext from '../../context/FloorPlanContext';
|
||||
|
||||
const useFloorPlanContext = () => {
|
||||
const context = useContext(FloorPlanContext);
|
||||
if (!context) {
|
||||
throw new Error('useFloorPlanContext 必须在 FloorPlanProvider 内使用');
|
||||
}
|
||||
return context;
|
||||
};
|
||||
|
||||
export default useFloorPlanContext;
|
||||
@@ -0,0 +1,89 @@
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import axios from 'axios';
|
||||
|
||||
const useFloorPlanData = (roomId) => {
|
||||
const [layoutData, setLayoutData] = useState(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState(null);
|
||||
|
||||
const fetchLayout = useCallback(async () => {
|
||||
if (!roomId) {
|
||||
setLayoutData(null);
|
||||
return;
|
||||
}
|
||||
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
|
||||
try {
|
||||
const response = await axios.get(`/api/rooms/${roomId}/layout`);
|
||||
setLayoutData(response.data);
|
||||
} catch (err) {
|
||||
setError(err.response?.data?.error || err.message);
|
||||
setLayoutData(null);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, [roomId]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchLayout();
|
||||
}, [fetchLayout]);
|
||||
|
||||
const updateRackPosition = useCallback(async (rackId, rowPos, colPos, facing) => {
|
||||
try {
|
||||
await axios.put(`/api/racks/${rackId}/position`, { rowPos, colPos, facing });
|
||||
await fetchLayout();
|
||||
return true;
|
||||
} catch (err) {
|
||||
setError(err.response?.data?.error || err.message);
|
||||
return false;
|
||||
}
|
||||
}, [fetchLayout]);
|
||||
|
||||
const batchUpdatePositions = useCallback(async (positions) => {
|
||||
try {
|
||||
await axios.put(`/api/rooms/${roomId}/racks-positions`, { positions });
|
||||
await fetchLayout();
|
||||
return true;
|
||||
} catch (err) {
|
||||
setError(err.response?.data?.error || err.message);
|
||||
return false;
|
||||
}
|
||||
}, [roomId, fetchLayout]);
|
||||
|
||||
const updateLayout = useCallback(async (gridRows, gridCols, layoutConfig) => {
|
||||
try {
|
||||
await axios.put(`/api/rooms/${roomId}/layout`, { gridRows, gridCols, layoutConfig });
|
||||
await fetchLayout();
|
||||
return true;
|
||||
} catch (err) {
|
||||
setError(err.response?.data?.error || err.message);
|
||||
return false;
|
||||
}
|
||||
}, [roomId, fetchLayout]);
|
||||
|
||||
const initLayout = useCallback(async (gridRows, gridCols, layoutConfig) => {
|
||||
try {
|
||||
await axios.post(`/api/rooms/${roomId}/init-layout`, { gridRows, gridCols, layoutConfig });
|
||||
await fetchLayout();
|
||||
return true;
|
||||
} catch (err) {
|
||||
setError(err.response?.data?.error || err.message);
|
||||
return false;
|
||||
}
|
||||
}, [roomId, fetchLayout]);
|
||||
|
||||
return {
|
||||
layoutData,
|
||||
loading,
|
||||
error,
|
||||
refetch: fetchLayout,
|
||||
updateRackPosition,
|
||||
batchUpdatePositions,
|
||||
updateLayout,
|
||||
initLayout,
|
||||
};
|
||||
};
|
||||
|
||||
export default useFloorPlanData;
|
||||
Reference in New Issue
Block a user