9 changed files with 360 additions and 6 deletions
@ -0,0 +1,311 @@ |
|||||
|
import { Line } from 'react-chartjs-2' |
||||
|
import { |
||||
|
Chart as ChartJS, |
||||
|
CategoryScale, |
||||
|
LinearScale, |
||||
|
PointElement, |
||||
|
LineElement, |
||||
|
Title, |
||||
|
Tooltip, |
||||
|
Legend |
||||
|
} from 'chart.js' |
||||
|
import { FileTextOutlined, ClockCircleOutlined, EyeOutlined } from '@ant-design/icons' |
||||
|
|
||||
|
ChartJS.register(CategoryScale, LinearScale, PointElement, LineElement, Title, Tooltip, Legend) |
||||
|
|
||||
|
function randomAround(base, delta) { |
||||
|
return base + Math.round((Math.random() * 2 - 1) * delta) |
||||
|
} |
||||
|
|
||||
|
function getTimeLabels(count) { |
||||
|
const now = new Date() |
||||
|
return Array.from({ length: count }).map((_, i) => { |
||||
|
const d = new Date(now.getTime() - (count - 1 - i) * 2 * 1000) |
||||
|
return d.toTimeString().slice(0, 8) |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
function DeflectionCollection() { |
||||
|
const count = 10 |
||||
|
const targetCount = 5 // 支持多个target |
||||
|
|
||||
|
// 为每个target生成颜色 |
||||
|
const targetColors = [ |
||||
|
'rgba(75,192,192,1)', // 青色 |
||||
|
'rgba(255,99,132,1)', // 红色 |
||||
|
'rgba(54,162,235,1)', // 蓝色 |
||||
|
'rgba(255,206,86,1)', // 黄色 |
||||
|
'rgba(153,102,255,1)' // 紫色 |
||||
|
] |
||||
|
|
||||
|
// 生成多个target的数据 |
||||
|
const targetsData = Array.from({ length: targetCount }).map((_, targetIndex) => ({ |
||||
|
name: `Target ${targetIndex + 1}`, |
||||
|
color: targetColors[targetIndex % targetColors.length], |
||||
|
data: Array.from({ length: count }).map((_, i) => ({ |
||||
|
x: 350 + targetIndex * 50 + Math.sin(i * 0.5 + targetIndex) * 20 + randomAround(0, 3), |
||||
|
y: 50 + targetIndex * 20 + Math.cos(i * 0.3 + targetIndex) * 15 + randomAround(0, 2), |
||||
|
w: randomAround(125, 5), |
||||
|
h: randomAround(115, 5) |
||||
|
})) |
||||
|
})) |
||||
|
|
||||
|
const timeLabels = getTimeLabels(count) |
||||
|
|
||||
|
const dataY = { |
||||
|
labels: timeLabels, |
||||
|
datasets: targetsData.map((target) => ({ |
||||
|
label: `${target.name}`, |
||||
|
data: target.data.map((d) => d.y), |
||||
|
borderColor: target.color, |
||||
|
backgroundColor: target.color.replace('1)', '0.2)'), |
||||
|
tension: 0.3, |
||||
|
pointRadius: 3, |
||||
|
pointHoverRadius: 5 |
||||
|
})) |
||||
|
} |
||||
|
|
||||
|
const dataX = { |
||||
|
labels: timeLabels, |
||||
|
datasets: targetsData.map((target) => ({ |
||||
|
label: `${target.name}`, |
||||
|
data: target.data.map((d) => d.x), |
||||
|
borderColor: target.color, |
||||
|
backgroundColor: target.color.replace('1)', '0.2)'), |
||||
|
tension: 0.3, |
||||
|
pointRadius: 3, |
||||
|
pointHoverRadius: 5 |
||||
|
})) |
||||
|
} |
||||
|
|
||||
|
const options = { |
||||
|
responsive: true, |
||||
|
maintainAspectRatio: false, |
||||
|
plugins: { |
||||
|
legend: { |
||||
|
display: true, |
||||
|
labels: { |
||||
|
boxWidth: 8, |
||||
|
boxHeight: 8, |
||||
|
font: { |
||||
|
size: 10 |
||||
|
}, |
||||
|
padding: 5 |
||||
|
}, |
||||
|
position: 'top' |
||||
|
}, |
||||
|
title: { display: false } |
||||
|
}, |
||||
|
scales: { |
||||
|
x: { |
||||
|
title: { display: true, text: '时间' }, |
||||
|
ticks: { font: { size: 10 } } |
||||
|
}, |
||||
|
y: { |
||||
|
title: { display: true, text: '挠度值' }, |
||||
|
ticks: { font: { size: 10 } } |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return ( |
||||
|
<div |
||||
|
style={{ |
||||
|
height: 'calc(100vh - 100px)', |
||||
|
maxHeight: '100%', |
||||
|
display: 'flex', |
||||
|
overflow: 'hidden', |
||||
|
margin: '0', |
||||
|
boxSizing: 'border-box' |
||||
|
}} |
||||
|
> |
||||
|
<div |
||||
|
style={{ |
||||
|
flex: 1, |
||||
|
minWidth: 0, |
||||
|
display: 'flex', |
||||
|
flexDirection: 'column', |
||||
|
padding: '10px', |
||||
|
gap: '10px', |
||||
|
overflow: 'hidden' |
||||
|
}} |
||||
|
> |
||||
|
<div |
||||
|
style={{ |
||||
|
flex: 1, |
||||
|
minHeight: 0, |
||||
|
display: 'flex', |
||||
|
flexDirection: 'column', |
||||
|
overflow: 'hidden', |
||||
|
border: '1px solid var(--border-color)' |
||||
|
}} |
||||
|
> |
||||
|
<p style={{ margin: '0 0 5px 0', fontSize: '14px', fontWeight: '500' }}>Y方向曲线</p> |
||||
|
<div style={{ flex: 1, minHeight: 0, position: 'relative' }}> |
||||
|
<Line data={dataY} options={options} /> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div |
||||
|
style={{ |
||||
|
flex: 1, |
||||
|
minHeight: 0, |
||||
|
display: 'flex', |
||||
|
flexDirection: 'column', |
||||
|
overflow: 'hidden', |
||||
|
border: '1px solid var(--border-color)' |
||||
|
}} |
||||
|
> |
||||
|
<p style={{ margin: '0 0 5px 0', fontSize: '14px', fontWeight: '500' }}>X方向曲线</p> |
||||
|
<div style={{ flex: 1, minHeight: 0, position: 'relative' }}> |
||||
|
<Line data={dataX} options={options} /> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div |
||||
|
style={{ |
||||
|
width: '300px', |
||||
|
minWidth: '300px', |
||||
|
maxWidth: '300px', |
||||
|
margin: '10px', |
||||
|
padding: '10px', |
||||
|
border: '1px solid var(--border-color)', |
||||
|
overflow: 'auto', |
||||
|
boxSizing: 'border-box' |
||||
|
}} |
||||
|
> |
||||
|
<div |
||||
|
style={{ |
||||
|
fontSize: '14px', |
||||
|
fontWeight: '600', |
||||
|
marginBottom: '10px', |
||||
|
color: '#333' |
||||
|
}} |
||||
|
> |
||||
|
实时数据 |
||||
|
</div> |
||||
|
|
||||
|
{targetsData.map((target, index) => { |
||||
|
const latestData = target.data[target.data.length - 1] |
||||
|
const latestTime = timeLabels[timeLabels.length - 1] |
||||
|
|
||||
|
return ( |
||||
|
<div |
||||
|
key={index} |
||||
|
style={{ |
||||
|
marginBottom: '15px', |
||||
|
padding: '10px', |
||||
|
backgroundColor: '#fafafa', |
||||
|
border: '1px solid #e8e8e8', |
||||
|
borderRadius: '4px' |
||||
|
}} |
||||
|
> |
||||
|
<div |
||||
|
style={{ |
||||
|
display: 'flex', |
||||
|
alignItems: 'center', |
||||
|
marginBottom: '8px' |
||||
|
}} |
||||
|
> |
||||
|
<div |
||||
|
style={{ |
||||
|
width: '8px', |
||||
|
height: '8px', |
||||
|
backgroundColor: target.color, |
||||
|
borderRadius: '50%', |
||||
|
marginRight: '8px' |
||||
|
}} |
||||
|
></div> |
||||
|
<span |
||||
|
style={{ |
||||
|
fontSize: '14px', |
||||
|
fontWeight: '500', |
||||
|
color: '#333' |
||||
|
}} |
||||
|
> |
||||
|
测点位置:{index + 1} |
||||
|
</span> |
||||
|
</div> |
||||
|
|
||||
|
<div |
||||
|
style={{ |
||||
|
display: 'flex', |
||||
|
alignItems: 'center', |
||||
|
marginBottom: '5px' |
||||
|
}} |
||||
|
> |
||||
|
<FileTextOutlined style={{ fontSize: '12px', color: '#666' }} /> |
||||
|
<span |
||||
|
style={{ |
||||
|
fontSize: '12px', |
||||
|
color: '#666', |
||||
|
marginLeft: '5px' |
||||
|
}} |
||||
|
> |
||||
|
测点描述: |
||||
|
</span> |
||||
|
</div> |
||||
|
|
||||
|
<div |
||||
|
style={{ |
||||
|
display: 'flex', |
||||
|
alignItems: 'center', |
||||
|
marginBottom: '5px' |
||||
|
}} |
||||
|
> |
||||
|
<ClockCircleOutlined style={{ fontSize: '12px', color: '#666' }} /> |
||||
|
<span |
||||
|
style={{ |
||||
|
fontSize: '12px', |
||||
|
color: '#666', |
||||
|
marginLeft: '5px' |
||||
|
}} |
||||
|
> |
||||
|
采集时间:{new Date().toLocaleDateString()} {latestTime} |
||||
|
</span> |
||||
|
</div> |
||||
|
|
||||
|
<div |
||||
|
style={{ |
||||
|
display: 'flex', |
||||
|
alignItems: 'center', |
||||
|
marginBottom: '3px' |
||||
|
}} |
||||
|
> |
||||
|
<EyeOutlined style={{ fontSize: '12px', color: '#666' }} /> |
||||
|
<span |
||||
|
style={{ |
||||
|
fontSize: '12px', |
||||
|
color: '#333', |
||||
|
marginLeft: '5px' |
||||
|
}} |
||||
|
> |
||||
|
X → {latestData.x.toFixed(3)} |
||||
|
</span> |
||||
|
</div> |
||||
|
|
||||
|
<div |
||||
|
style={{ |
||||
|
display: 'flex', |
||||
|
alignItems: 'center' |
||||
|
}} |
||||
|
> |
||||
|
<EyeOutlined style={{ fontSize: '12px', color: '#666' }} /> |
||||
|
<span |
||||
|
style={{ |
||||
|
fontSize: '12px', |
||||
|
color: '#333', |
||||
|
marginLeft: '5px' |
||||
|
}} |
||||
|
> |
||||
|
Y → {latestData.y.toFixed(3)} |
||||
|
</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
) |
||||
|
})} |
||||
|
</div> |
||||
|
</div> |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
export default DeflectionCollection |
@ -0,0 +1,3 @@ |
|||||
|
.chartContainer { |
||||
|
width: 100%; |
||||
|
} |
@ -0,0 +1,7 @@ |
|||||
|
import React from 'react' |
||||
|
|
||||
|
function ImageCollection() { |
||||
|
return <div>ImageCollection</div> |
||||
|
} |
||||
|
|
||||
|
export default ImageCollection |
Loading…
Reference in new issue