|
|
/* eslint-disable eqeqeq */
|
|
|
/* eslint-disable react/no-unknown-property */
|
|
|
import { PageContainer, ProCard } from '@ant-design/pro-components';
|
|
|
import { Image } from 'antd';
|
|
|
import { fabric } from 'fabric';
|
|
|
import React, { useEffect, useRef, useState } from 'react';
|
|
|
|
|
|
// type
|
|
|
import { ComputePowerPoolItem } from './typing';
|
|
|
|
|
|
// TODO bug左侧
|
|
|
|
|
|
// state
|
|
|
const poolsData: ComputePowerPoolItem[] = [
|
|
|
{
|
|
|
name: '玩手机监控',
|
|
|
type: 0,
|
|
|
proportion: 39,
|
|
|
PretreatmentEfficiency: 15,
|
|
|
color: '#FAA90B',
|
|
|
},
|
|
|
{
|
|
|
name: '离岗监控',
|
|
|
type: 1,
|
|
|
proportion: 30,
|
|
|
PretreatmentEfficiency: 20,
|
|
|
color: '#3879FE',
|
|
|
},
|
|
|
{
|
|
|
name: '空闲算力',
|
|
|
type: 2,
|
|
|
proportion: 1,
|
|
|
PretreatmentEfficiency: 0,
|
|
|
},
|
|
|
];
|
|
|
|
|
|
/**子组件 */
|
|
|
// 参数信息项
|
|
|
const InfoPreview: React.FC<{
|
|
|
name: string;
|
|
|
des: string;
|
|
|
}> = ({ name, des }) => {
|
|
|
return (
|
|
|
<div
|
|
|
style={{
|
|
|
padding: 0,
|
|
|
margin: 0,
|
|
|
display: 'flex',
|
|
|
justifyContent: 'center',
|
|
|
flexDirection: 'column',
|
|
|
minWidth: '13vw',
|
|
|
}}
|
|
|
>
|
|
|
<h6 style={{ color: '#333333', fontSize: 14, fontWeight: 700 }}>{name}</h6>
|
|
|
<div style={{ color: '#666666', fontSize: 14 }}>{des}</div>
|
|
|
</div>
|
|
|
);
|
|
|
};
|
|
|
|
|
|
// 占比信息
|
|
|
const OccupyProportion: React.FC<{
|
|
|
pools: ComputePowerPoolItem[];
|
|
|
}> = ({ pools }) => {
|
|
|
const poolDefault = {
|
|
|
processBarOptions: {
|
|
|
top: 3, // 矩形左上角在y轴的位置
|
|
|
left: 0, // 矩形左上角在x轴的位置
|
|
|
height: 32, // 矩形的高
|
|
|
stroke: 'transparent', // 边框颜色
|
|
|
strokeWidth: 2, // 边框宽度
|
|
|
rx: 15, // 圆角的横向半径
|
|
|
ry: 15, // 圆角的纵向半径
|
|
|
selectable: false,
|
|
|
},
|
|
|
buttonBgOptions: {
|
|
|
width: 20,
|
|
|
height: 40,
|
|
|
fill: 'white', // 填充颜色
|
|
|
strokeWidth: 2, // 边框宽度
|
|
|
left: 0,
|
|
|
top: 0,
|
|
|
selectable: false,
|
|
|
hasControls: false,
|
|
|
},
|
|
|
buttonImageOptions: {
|
|
|
selectable: false,
|
|
|
hasControls: false,
|
|
|
},
|
|
|
buttonGroupOptions: {
|
|
|
width: 20,
|
|
|
height: 40,
|
|
|
top: 0,
|
|
|
lockMovementY: true,
|
|
|
hasControls: false,
|
|
|
// selectable: false,
|
|
|
},
|
|
|
};
|
|
|
const [clipPathData, setClipPathData] = useState({
|
|
|
width: 1000, // 宽
|
|
|
height: 80, // 高
|
|
|
});
|
|
|
const canvasRef = useRef(null);
|
|
|
const [cvs, setCanvas] = useState(null);
|
|
|
const [rect1Witdh, setRect1Witdh] = useState((pools[0].proportion / 100) * clipPathData.width);
|
|
|
const [rect2Witdh, setRect2Witdh] = useState((pools[1].proportion / 100) * clipPathData.width);
|
|
|
|
|
|
useEffect(() => {
|
|
|
const canvasObject = new fabric.Canvas(canvasRef.current);
|
|
|
// 整个进度条 底色块
|
|
|
const rect0 = new fabric.Rect({
|
|
|
...poolDefault.processBarOptions,
|
|
|
width: clipPathData.width, // 矩形的宽
|
|
|
fill: '#E5E5E5', // 填充色
|
|
|
});
|
|
|
// 玩手机监控
|
|
|
const rect1 = new fabric.Rect({
|
|
|
...poolDefault.processBarOptions,
|
|
|
width: rect1Witdh, // 矩形的宽
|
|
|
fill: '#FAA90B', // 填充色
|
|
|
});
|
|
|
// 离岗监控
|
|
|
const rect2 = new fabric.Rect({
|
|
|
...poolDefault.processBarOptions,
|
|
|
left: rect1Witdh,
|
|
|
width: rect2Witdh, // 矩形的宽
|
|
|
fill: '#3879FE', // 填充色
|
|
|
});
|
|
|
// 创建矩形对象
|
|
|
const bgRect1 = new fabric.Rect(poolDefault.buttonBgOptions);
|
|
|
const bgRect2 = new fabric.Rect(poolDefault.buttonBgOptions);
|
|
|
// 添加背景图片到矩形
|
|
|
fabric.Image.fromURL('/images/computePowerAllocation/slideBtn1.png', function (img) {
|
|
|
// 设置图片的宽度和高度为矩形的宽度和高度
|
|
|
img.set({ width: bgRect1.width, height: bgRect1.height, ...poolDefault.buttonImageOptions });
|
|
|
// 将图片置于矩形的底部
|
|
|
// bgRect1.set({ originX: 'center', originY: 'center' });
|
|
|
canvasObject.add(
|
|
|
new fabric.Group([bgRect1, img], {
|
|
|
...poolDefault.buttonGroupOptions,
|
|
|
buttonId: '1',
|
|
|
left: rect1Witdh - 10,
|
|
|
}),
|
|
|
);
|
|
|
// 更新Canvas以应用更改
|
|
|
canvasObject.renderAll();
|
|
|
});
|
|
|
fabric.Image.fromURL('/images/computePowerAllocation/slideBtn2.png', function (img) {
|
|
|
// 设置图片的宽度和高度为矩形的宽度和高度
|
|
|
img.set({ width: bgRect2.width, height: bgRect2.height, ...poolDefault.buttonImageOptions });
|
|
|
// 将图片置于矩形的底部
|
|
|
// bgRect1.set({ originX: 'center', originY: 'center' });
|
|
|
canvasObject.add(
|
|
|
new fabric.Group([bgRect2, img], {
|
|
|
...poolDefault.buttonGroupOptions,
|
|
|
buttonId: '2',
|
|
|
left: rect1Witdh + rect2Witdh - 10,
|
|
|
}),
|
|
|
);
|
|
|
// 更新Canvas以应用更改
|
|
|
canvasObject.renderAll();
|
|
|
});
|
|
|
canvasObject.add(rect0);
|
|
|
canvasObject.add(rect1);
|
|
|
canvasObject.add(rect2);
|
|
|
canvasObject.on('object:moving', (event) => {
|
|
|
// 获取事件的目标对象
|
|
|
const targetObject = event.target;
|
|
|
console.log(targetObject.buttonId, 'targetObject', canvasObject.item(3));
|
|
|
// 算力按钮
|
|
|
switch (targetObject.buttonId) {
|
|
|
case '1':
|
|
|
// 算力按钮1
|
|
|
if (targetObject?.left >= clipPathData.width - 20) {
|
|
|
targetObject?.set({
|
|
|
left: clipPathData.width - 20,
|
|
|
});
|
|
|
}
|
|
|
if (targetObject?.left <= 0) {
|
|
|
targetObject?.set({
|
|
|
left: 0,
|
|
|
});
|
|
|
}
|
|
|
const currObject1Width = targetObject?.left + 10;
|
|
|
canvasObject.item(1).set({
|
|
|
width: currObject1Width,
|
|
|
});
|
|
|
canvasObject.item(2).set({
|
|
|
left: targetObject?.left + 10,
|
|
|
});
|
|
|
canvasObject.item(4).set({
|
|
|
left: canvasObject.item(2).left - 10 + canvasObject.item(2).width,
|
|
|
});
|
|
|
if (currObject1Width + canvasObject.item(2).width >= clipPathData.width) {
|
|
|
canvasObject.item(2).set({
|
|
|
width: clipPathData.width - currObject1Width,
|
|
|
});
|
|
|
canvasObject.item(4).set({
|
|
|
left: clipPathData.width - 20,
|
|
|
});
|
|
|
}
|
|
|
break;
|
|
|
case '2':
|
|
|
// 算力按钮2
|
|
|
if (targetObject?.left >= clipPathData.width - 20) {
|
|
|
targetObject?.set({
|
|
|
left: clipPathData.width - 20,
|
|
|
});
|
|
|
}
|
|
|
const currObject11Width = canvasObject.item(1).width;
|
|
|
const currObject22Width = canvasObject.item(2).width;
|
|
|
if(targetObject?.left <= currObject11Width+ 10){
|
|
|
targetObject?.set({
|
|
|
left: currObject11Width + 10,
|
|
|
});
|
|
|
}
|
|
|
|
|
|
// if (targetObject?.left <= rect1Witdh) {
|
|
|
// targetObject?.set({
|
|
|
// left: currObject11Width + currObject22Width,
|
|
|
// });
|
|
|
// }
|
|
|
console.log(currObject11Width, 'button2', currObject22Width)
|
|
|
canvasObject.item(2).set({
|
|
|
width: targetObject?.left - currObject11Width + 10,
|
|
|
});
|
|
|
// canvasObject.item(2).set({
|
|
|
// left: targetObject?.left + 10,
|
|
|
// });
|
|
|
// canvasObject.item(2).set({
|
|
|
// width: targetObject?.left -rect1Witdh + 10,
|
|
|
// });
|
|
|
break;
|
|
|
}
|
|
|
// set_category_fk_id_open(false);
|
|
|
|
|
|
// 检查目标对象是否为组合对象
|
|
|
setRect1Witdh(targetObject?.left);
|
|
|
canvasObject.renderAll();
|
|
|
});
|
|
|
canvasObject.renderAll();
|
|
|
|
|
|
setCanvas(canvasObject);
|
|
|
return () => {
|
|
|
canvasObject.dispose();
|
|
|
};
|
|
|
}, []);
|
|
|
|
|
|
return (
|
|
|
<div className="occupyProportion_box">
|
|
|
<div
|
|
|
className="occupy_up"
|
|
|
style={{ marginTop: 24, marginBottom: 20, padding: 0, position: 'relative', width: '100%' }}
|
|
|
>
|
|
|
<canvas ref={canvasRef} {...clipPathData} ></canvas>
|
|
|
|
|
|
{/* <ul
|
|
|
className="occupy_progress"
|
|
|
style={{
|
|
|
width: '100%',
|
|
|
height: 32,
|
|
|
backgroundColor: '#E5E5E5',
|
|
|
borderRadius: 16,
|
|
|
padding: 0,
|
|
|
overflow: 'hidden',
|
|
|
display: 'flex',
|
|
|
}}
|
|
|
>
|
|
|
{pools.map((item, index) => {
|
|
|
return (
|
|
|
<li
|
|
|
key={index}
|
|
|
style={{
|
|
|
height: 32,
|
|
|
width: `${item.proportion}%`,
|
|
|
padding: 0,
|
|
|
backgroundColor: item?.color || '#E5E5E5',
|
|
|
}}
|
|
|
></li>
|
|
|
);
|
|
|
})}
|
|
|
</ul>
|
|
|
<ul>
|
|
|
<li
|
|
|
style={{
|
|
|
position: 'absolute',
|
|
|
left: `calc(${pools[0].proportion - 0.8}% )`,
|
|
|
top: -4,
|
|
|
padding: 0,
|
|
|
width: 20,
|
|
|
}}
|
|
|
>
|
|
|
<Image
|
|
|
width={20}
|
|
|
src={'/images/computePowerAllocation/slideBtn1.png'}
|
|
|
preview={false}
|
|
|
></Image>
|
|
|
</li>
|
|
|
<li
|
|
|
style={{
|
|
|
position: 'absolute',
|
|
|
left: `${pools[0].proportion + pools[1].proportion - 0.8}%`,
|
|
|
top: -4,
|
|
|
width: 20,
|
|
|
}}
|
|
|
>
|
|
|
<Image
|
|
|
width={20}
|
|
|
src={'/images/computePowerAllocation/slideBtn2.png'}
|
|
|
preview={false}
|
|
|
></Image>
|
|
|
</li>
|
|
|
</ul> */}
|
|
|
</div>
|
|
|
|
|
|
<div className="occupy_des">
|
|
|
<ul
|
|
|
style={{
|
|
|
display: 'flex',
|
|
|
paddingLeft: 0,
|
|
|
paddingBottom: 24,
|
|
|
margin: 0,
|
|
|
}}
|
|
|
>
|
|
|
{pools.map((item, index) => {
|
|
|
return (
|
|
|
<li key={index} style={{ marginRight: 35 }}>
|
|
|
<span
|
|
|
style={{
|
|
|
width: 12,
|
|
|
height: 12,
|
|
|
display: 'inline-block',
|
|
|
background: item?.color || '#E5E5E5',
|
|
|
}}
|
|
|
></span>
|
|
|
<span style={{ paddingLeft: 8 }}>
|
|
|
{item.name}:{item.proportion}%
|
|
|
</span>
|
|
|
{item.type != 2 ? (
|
|
|
<span style={{ paddingLeft: 8 }}>
|
|
|
预计处理效率:
|
|
|
<span style={{ fontWeight: 700 }}>{item.PretreatmentEfficiency} 帧/秒</span>
|
|
|
</span>
|
|
|
) : (
|
|
|
<></>
|
|
|
)}
|
|
|
</li>
|
|
|
);
|
|
|
})}
|
|
|
</ul>
|
|
|
</div>
|
|
|
</div>
|
|
|
);
|
|
|
};
|
|
|
|
|
|
/**
|
|
|
* @算力资源池页面组件
|
|
|
* @returns
|
|
|
*/
|
|
|
const ComputePowerAllocation: React.FC = () => {
|
|
|
return (
|
|
|
<PageContainer>
|
|
|
<ProCard
|
|
|
title="算力资源池"
|
|
|
style={{ background: 'white' }}
|
|
|
headStyle={{ padding: 20, borderBottom: '1px solid #E0E0E0' }}
|
|
|
bodyStyle={{
|
|
|
paddingLeft: 9,
|
|
|
paddingRight: 9,
|
|
|
paddingTop: 0,
|
|
|
paddingBottom: 0,
|
|
|
margin: 0,
|
|
|
}}
|
|
|
gutter={24}
|
|
|
wrap
|
|
|
ghost
|
|
|
>
|
|
|
{/* 参数信息 */}
|
|
|
<ProCard
|
|
|
gutter={24}
|
|
|
style={{ padding: 0, margin: 0 }}
|
|
|
bodyStyle={{
|
|
|
paddingTop: 24,
|
|
|
paddingBottom: 24,
|
|
|
paddingLeft: 0,
|
|
|
paddingRight: 0,
|
|
|
margin: 0,
|
|
|
display: 'flex',
|
|
|
alignItems: 'center',
|
|
|
borderBottom: '1px solid #E0E0E0',
|
|
|
}}
|
|
|
>
|
|
|
<Image
|
|
|
width={62}
|
|
|
src={'/images/computePowerAllocation/icon1.png'}
|
|
|
placeholder={
|
|
|
<Image preview={false} src={'/images/computePowerAllocation/icon1.png'} width={62} />
|
|
|
}
|
|
|
/>
|
|
|
<div
|
|
|
style={{
|
|
|
paddingLeft: 17,
|
|
|
paddingRight: 17,
|
|
|
margin: 0,
|
|
|
display: 'flex',
|
|
|
justifyContent: 'center',
|
|
|
flexDirection: 'column',
|
|
|
}}
|
|
|
>
|
|
|
<InfoPreview name="苏胜天算力资源池" des="算力资源999Tops"></InfoPreview>
|
|
|
</div>
|
|
|
<InfoPreview
|
|
|
name="硬件组成"
|
|
|
des="NVIDIA GeForce 4090 | NVIDIA GeForce 4090 | NVIDIA GeForce 4090 |"
|
|
|
></InfoPreview>
|
|
|
</ProCard>
|
|
|
{/* 占比信息 */}
|
|
|
<ProCard
|
|
|
gutter={24}
|
|
|
style={{ padding: 0, margin: 0 }}
|
|
|
bodyStyle={{ padding: 0, margin: 0 }}
|
|
|
>
|
|
|
<OccupyProportion pools={poolsData as ComputePowerPoolItem[]} />
|
|
|
</ProCard>
|
|
|
</ProCard>
|
|
|
</PageContainer>
|
|
|
);
|
|
|
};
|
|
|
|
|
|
export default ComputePowerAllocation;
|