You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

405 lines
11 KiB
TypeScript

2 years ago
/* 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';
2 years ago
// type
import { ComputePowerPoolItem } from './typing';
// TODO 整个页面的字体、颜色、间距处理
// state
const poolsData: ComputePowerPoolItem[] = [
{
name: '玩手机监控',
type: 0,
proportion: 39,
PretreatmentEfficiency: 15,
color: '#FAA90B',
},
{
name: '离岗监控',
type: 1,
proportion: 60,
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,
selectable: false,
}),
);
// 更新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,
left: rect1Witdh + 10,
buttonId: '2',
}),
);
// 更新Canvas以应用更改
canvasObject.renderAll();
});
canvasObject.add(rect0);
canvasObject.add(rect1);
canvasObject.add(rect2);
canvasObject.on('object:moving', (event) => {
// 获取事件的目标对象
const targetObject = event.target;
console.log(targetObject, 'targetObject', canvasObject.item(0));
// 算力按钮1
switch (targetObject.buttonId) {
case '1':
// 算力按钮2
if (targetObject?.left >= 960) {
targetObject?.set({
left: 960,
});
}
if (targetObject?.left <= 0) {
targetObject?.set({
left: 0,
});
}
canvasObject.item(1).set({
width: targetObject?.left + 10,
});
canvasObject.item(2).set({
left: targetObject?.left + 10 ,
});
break;
case '2':
// 算力按钮2
if (targetObject?.left >= 980) {
targetObject?.set({
left: 980,
});
}
if (targetObject?.left <= rect1Witdh) {
targetObject?.set({
left: rect1Witdh + 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();
};
}, []);
2 years ago
return (
<div className="occupyProportion_box">
<div
className="occupy_up"
style={{ marginTop: 24, marginBottom: 20, padding: 0, position: 'relative', width: '100%' }}
>
<canvas ref={canvasRef} {...clipPathData} style={{ border: '1px dashed red' }}></canvas>
{/* <ul
2 years ago
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>
2 years ago
</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>
2 years ago
</li>
</ul> */}
2 years ago
</div>
<div className="occupy_des">
<ul
style={{
display: 'flex',
paddingLeft: 0,
paddingBottom: 24,
margin: 0,
2 years ago
}}
>
{pools.map((item, index) => {
return (
<li key={index} style={{ marginRight: 35 }}>
2 years ago
<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>
2 years ago
</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} />
}
2 years ago
/>
<div
style={{
paddingLeft: 17,
paddingRight: 17,
margin: 0,
display: 'flex',
justifyContent: 'center',
flexDirection: 'column',
}}
>
<InfoPreview name="苏胜天算力资源池" des="算力资源999Tops"></InfoPreview>
2 years ago
</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;