init commit
This commit is contained in:
23
src/components/Container.jsx
Normal file
23
src/components/Container.jsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import { useEffect, useRef } from 'react';
|
||||
import useIcon from '../hooks/useIcon';
|
||||
import cls from './container.module.less';
|
||||
|
||||
const Container = (props) => {
|
||||
let icon = useIcon(props.icon);
|
||||
|
||||
return (
|
||||
<div className={`${cls.container} ${props.className}`} style={props.style}>
|
||||
<div className={cls.container__head}>
|
||||
<img
|
||||
src={icon}
|
||||
alt="#"
|
||||
className={props.icon == 'kiln' ? cls.bigger : ''}
|
||||
/>
|
||||
<h2>{props.title}</h2>
|
||||
</div>
|
||||
<div className={cls.container__content}>{props.children}</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Container;
|
||||
64
src/components/container.module.less
Normal file
64
src/components/container.module.less
Normal file
@@ -0,0 +1,64 @@
|
||||
.container {
|
||||
padding: 24px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-size: 100% 100%;
|
||||
background-repeat: no-repeat;
|
||||
|
||||
.container__head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
img {
|
||||
width: 20px;
|
||||
|
||||
&.bigger {
|
||||
width: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-family: '微软雅黑', 'Microsoft YaHei UI', -apple-system,
|
||||
BlinkMacSystemFont, 'Helvetica Neue', 'PingFang SC', 'Microsoft YaHei',
|
||||
'Source Han Sans SC', 'Noto Sans CJK SC', 'WenQuanYi Micro Hei',
|
||||
sans-serif;
|
||||
margin: 0;
|
||||
margin-left: 6px;
|
||||
font-size: 18px;
|
||||
color: #fff;
|
||||
letter-spacing: 2px;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
.container__content {
|
||||
height: 1px;
|
||||
flex: 1;
|
||||
// background: #25a78672;
|
||||
}
|
||||
}
|
||||
|
||||
.bgKiln {
|
||||
background: url('');
|
||||
}
|
||||
.bgGood {
|
||||
background: url('../assets/good.png');
|
||||
}
|
||||
.bgFaultTotal {
|
||||
background: url('');
|
||||
}
|
||||
.bgFaultType {
|
||||
background: url('');
|
||||
}
|
||||
.bgGas {
|
||||
background: url('');
|
||||
}
|
||||
.bgWind {
|
||||
background: url('');
|
||||
}
|
||||
.bgEnergy {
|
||||
background: url('../assets/energy.png');
|
||||
}
|
||||
.bgSmoke {
|
||||
background: url('../assets/smoke.png');
|
||||
}
|
||||
17
src/components/公共组件/BottomItemBackground/index.jsx
Normal file
17
src/components/公共组件/BottomItemBackground/index.jsx
Normal file
@@ -0,0 +1,17 @@
|
||||
import cls from './index.module.css';
|
||||
import Container from '../../Container';
|
||||
|
||||
function BottomBarItem(props) {
|
||||
return (
|
||||
<Container
|
||||
icon={props.icon}
|
||||
title={props.title}
|
||||
className={`${cls.bottomBarItem} ${props.className}`}
|
||||
style={props.style}
|
||||
>
|
||||
{props.children}
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
export default BottomBarItem;
|
||||
@@ -0,0 +1,5 @@
|
||||
.bottomBarItem {
|
||||
background: url(../../../assets/bg-bottom-item.png) no-repeat;
|
||||
background-size: 100% 100%;
|
||||
width: 600px;
|
||||
}
|
||||
25
src/components/公共组件/GradientText/index.jsx
Normal file
25
src/components/公共组件/GradientText/index.jsx
Normal file
@@ -0,0 +1,25 @@
|
||||
const GradientText = ({ text, spacing }) => {
|
||||
return (
|
||||
<svg>
|
||||
<defs>
|
||||
<linearGradient id="smoke-text" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||
<stop offset="0%" style={{ stopColor: '#4EFFF6', stopOpacity: 1 }} />
|
||||
<stop
|
||||
offset="100%"
|
||||
style={{ stopColor: '#00B2F9', stopOpacity: 1 }}
|
||||
/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<text
|
||||
x={0}
|
||||
y={36}
|
||||
fill="url(#smoke-text)"
|
||||
style={{ fontSize: '28px', letterSpacing: spacing || '2px' }}
|
||||
>
|
||||
{text}
|
||||
</text>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
export default GradientText;
|
||||
124
src/components/公共组件/GraphBase/index.jsx
Normal file
124
src/components/公共组件/GraphBase/index.jsx
Normal file
@@ -0,0 +1,124 @@
|
||||
// TODO: 通用组件 - 按钮 菜单控制层
|
||||
import useIcon from '../../../hooks/useIcon';
|
||||
import cls from './index.module.css';
|
||||
import { useMemo, useState } from 'react';
|
||||
import { Switch, Radio } from 'antd';
|
||||
|
||||
function choseBg(size) {
|
||||
const [width, height] = size;
|
||||
return width === 'long' && height === 'middle'
|
||||
? 'long-middle'
|
||||
: width === 'long' && height === 'short'
|
||||
? 'long-short'
|
||||
: width === 'short' && height === 'middle'
|
||||
? 'short-middle'
|
||||
: width === 'short' && height === 'short'
|
||||
? 'short-short'
|
||||
: width === 'short' && height === 'long'
|
||||
? 'short-long'
|
||||
: width === 'middle' && height === 'middle'
|
||||
? 'middle-middle'
|
||||
: width === 'middle' && height === 'short'
|
||||
? 'middle-short'
|
||||
: width === 'middle' && height === 'long'
|
||||
? 'middle-long'
|
||||
: width === 'middle' && height === 'full'
|
||||
? 'middle-full'
|
||||
: 'middle-middle';
|
||||
}
|
||||
|
||||
function GraphBase(props) {
|
||||
const size = props.size || ['middle', 'middle'];
|
||||
const bgClass = choseBg(size);
|
||||
const {
|
||||
icon,
|
||||
title,
|
||||
desc,
|
||||
switchOptions,
|
||||
onSwitch,
|
||||
dateOptions,
|
||||
onDateChange,
|
||||
legend,
|
||||
} = props;
|
||||
const iconSrc = useIcon(icon);
|
||||
const colors = useMemo(() => ['#ffd160', '#2760ff', '#15e8f5'], []);
|
||||
const [showChart, setShowChart] = useState(true);
|
||||
|
||||
let dto = null;
|
||||
const switchStyle = {};
|
||||
|
||||
if (props.switchPosition) {
|
||||
props.switchPosition.forEach((item, index) => {
|
||||
if (item != null) {
|
||||
switchStyle[index == 0 ? 'top' : 'left'] = item + 'px';
|
||||
}
|
||||
});
|
||||
}
|
||||
if (dateOptions) {
|
||||
dto = dateOptions.map((item) => (
|
||||
<Radio.Button value={item} key={item} className="radio-group__item">
|
||||
{item}
|
||||
</Radio.Button>
|
||||
));
|
||||
}
|
||||
|
||||
function handleSwitchChange(v) {
|
||||
v ? setShowChart(true) : setShowChart(false);
|
||||
onSwitch(v);
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={
|
||||
'graph-base ' +
|
||||
cls[bgClass] +
|
||||
' ' +
|
||||
cls.graphBase +
|
||||
' ' +
|
||||
props.className
|
||||
}
|
||||
style={{ ...props.style }}
|
||||
>
|
||||
<div className={cls.graphBaseTitle}>
|
||||
<img src={iconSrc} alt="#" />
|
||||
<h2>{title}</h2>
|
||||
</div>
|
||||
<div className={cls.graphBaseContent}>
|
||||
{desc && <div className={cls.graphBaseDesc}>{desc}</div>}
|
||||
{switchOptions && (
|
||||
<div className={cls.graphBaseSwitch} style={switchStyle}>
|
||||
<Switch size="small" defaultChecked onChange={handleSwitchChange} />
|
||||
{showChart && <span className={cls.switchLabel}>历史详情</span>}
|
||||
{!showChart && <span className={cls.switchLabel}>实时流量</span>}
|
||||
</div>
|
||||
)}
|
||||
{legend && showChart && (
|
||||
<div className={cls.legend}>
|
||||
{legend.map((item, index) => (
|
||||
<div className={cls.legendItem} key={item}>
|
||||
<span
|
||||
className={cls.lengedItemPrefix}
|
||||
style={{ backgroundColor: colors[index] }}
|
||||
></span>
|
||||
<span className={cls.legendItemLabel}>{item}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
{dateOptions && (
|
||||
<Radio.Group
|
||||
defaultValue={dateOptions[0]}
|
||||
buttonStyle="solid"
|
||||
className={cls.graphBaseDate + ' ' + cls.radioGroup}
|
||||
onChange={({ target }) => onDateChange(target.value)}
|
||||
>
|
||||
{dto}
|
||||
</Radio.Group>
|
||||
)}
|
||||
{props.children}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default GraphBase;
|
||||
153
src/components/公共组件/GraphBase/index.module.css
Normal file
153
src/components/公共组件/GraphBase/index.module.css
Normal file
@@ -0,0 +1,153 @@
|
||||
/* .long-long {
|
||||
background: url('../../../../assets/long-long.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
background-position: 0 0;
|
||||
} */
|
||||
|
||||
.long-middle {
|
||||
background: url('../../../assets/long-middle.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
background-position: 0 0;
|
||||
}
|
||||
|
||||
.long-short {
|
||||
background: url('../../../assets/long-short.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
background-position: 0 0;
|
||||
}
|
||||
|
||||
.middle-long {
|
||||
background: url('../../../assets/middle-middle.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
background-position: 0 0;
|
||||
}
|
||||
|
||||
.middle-full {
|
||||
background: url('../../../assets/middle-long.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
background-position: 0 0;
|
||||
}
|
||||
|
||||
.middle-middle {
|
||||
background: url('../../../assets/middle-middle-2.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
background-position: 0 0;
|
||||
}
|
||||
|
||||
.middle-short {
|
||||
/* background: url('../../../assets/middle-short.png') no-repeat; */
|
||||
/* background: url('../../../assets/energy.png') no-repeat; */
|
||||
background: url('../../../assets/bg-bottom-item.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
background-position: 0 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* more...
|
||||
*/
|
||||
|
||||
.graphBase {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
/* justify-content: flex-end;
|
||||
align-items: center; */
|
||||
position: relative;
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.graphBaseTitle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.graphBaseTitle > img {
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
.graphBaseTitle > h2 {
|
||||
font-family: '微软雅黑', 'Microsoft YaHei UI', -apple-system,
|
||||
BlinkMacSystemFont, 'Helvetica Neue', 'PingFang SC', 'Microsoft YaHei',
|
||||
'Source Han Sans SC', 'Noto Sans CJK SC', 'WenQuanYi Micro Hei', sans-serif;
|
||||
margin: 0;
|
||||
margin-left: 6px;
|
||||
font-size: 20px;
|
||||
color: #fff;
|
||||
letter-spacing: 2px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.graphBaseContent {
|
||||
height: 1px;
|
||||
flex: 1;
|
||||
/* background: #fff3; */
|
||||
}
|
||||
|
||||
.graphBaseDesc {
|
||||
position: absolute;
|
||||
top: 25px;
|
||||
left: 150px;
|
||||
font-size: 19px;
|
||||
color: #76fff9;
|
||||
}
|
||||
|
||||
.graphBaseSwitch {
|
||||
position: absolute;
|
||||
top: 30px;
|
||||
left: 258px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.graphBaseDate {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 24px;
|
||||
color: #fff;
|
||||
margin-right: 24px;
|
||||
}
|
||||
|
||||
.radioGroup {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.radioGroup * {
|
||||
border: none !important;
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
|
||||
.radioGroup *:focus-within {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.radioGroup *::before {
|
||||
width: 0 !important;
|
||||
}
|
||||
|
||||
.switchLabel {
|
||||
color: white;
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
.legend {
|
||||
position: absolute;
|
||||
top: 30px;
|
||||
left: 360px;
|
||||
color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.legendItem {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.lengedItemPrefix {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 2px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
7
src/components/公共组件/TechSplitline/index.jsx
Normal file
7
src/components/公共组件/TechSplitline/index.jsx
Normal file
@@ -0,0 +1,7 @@
|
||||
import cls from './index.module.less';
|
||||
|
||||
const TechSplitline = (props) => {
|
||||
return <div className={cls.techSplitline}></div>;
|
||||
};
|
||||
|
||||
export default TechSplitline;
|
||||
5
src/components/公共组件/TechSplitline/index.module.less
Normal file
5
src/components/公共组件/TechSplitline/index.module.less
Normal file
@@ -0,0 +1,5 @@
|
||||
.techSplitline {
|
||||
height: 2px;
|
||||
width: 100%;
|
||||
background: radial-gradient(#3ce7ff, #3ce8ff92, #3ce8ff32, transparent);
|
||||
}
|
||||
107
src/components/公共组件/产线当日缺陷分类/index.jsx
Normal file
107
src/components/公共组件/产线当日缺陷分类/index.jsx
Normal file
@@ -0,0 +1,107 @@
|
||||
import cls from './index.module.css';
|
||||
import GraphBase from '../GraphBase';
|
||||
import ReactECharts from 'echarts-for-react';
|
||||
import { useState } from 'react';
|
||||
|
||||
function FaultType(props) {
|
||||
const options = {
|
||||
colors: [
|
||||
'#2760FF',
|
||||
'#5B9BFF',
|
||||
'#FFD160',
|
||||
'#8167F6',
|
||||
'#99D66C',
|
||||
'#FF8A40',
|
||||
'#12FFF5',
|
||||
],
|
||||
grid: {
|
||||
left: 24,
|
||||
top: 10,
|
||||
bottom: 10,
|
||||
right: 24,
|
||||
},
|
||||
legend: {
|
||||
icon: 'circle',
|
||||
top: 32,
|
||||
right: 0,
|
||||
bottom: 32,
|
||||
width: 296,
|
||||
height: 130,
|
||||
itemGap: 30,
|
||||
formatter: function (name) {
|
||||
return `${name} {sub|${
|
||||
options.series[0].data.find((o) => o.name == name).value
|
||||
}}`;
|
||||
},
|
||||
textStyle: {
|
||||
color: '#DFF1FE',
|
||||
fontSize: 18,
|
||||
rich: {
|
||||
sub: {
|
||||
color: '#fff9',
|
||||
fontSize: 18,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
series: [
|
||||
{
|
||||
type: 'pie',
|
||||
center: ['26%', '54%'],
|
||||
radius: ['55%', '75%'],
|
||||
avoidLabelOverlap: false,
|
||||
label: {
|
||||
show: true,
|
||||
formatter: '{d}%',
|
||||
fontSize: 14,
|
||||
color: 'inherit',
|
||||
},
|
||||
labelLine: {
|
||||
length: 0,
|
||||
},
|
||||
data: [
|
||||
{ value: 1048, name: '缺陷1' },
|
||||
{ value: 735, name: '缺陷2' },
|
||||
{ value: 580, name: '缺陷3' },
|
||||
{ value: 484, name: '缺陷4' },
|
||||
{ value: 300, name: '缺陷5' },
|
||||
{ value: 300, name: '缺陷6' },
|
||||
{ value: 300, name: '缺陷8' },
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const [lines, setLines] = useState([
|
||||
{ id: 1, label: '产线1', value: 'l1' },
|
||||
{ id: 2, label: '产线2', value: 'l2' },
|
||||
{ id: 3, label: '产线3', value: 'l3' },
|
||||
{ id: 4, label: '产线4', value: 'l4' },
|
||||
{ id: 5, label: '产线5', value: 'l5' },
|
||||
]);
|
||||
|
||||
function handleDateChange(v) {
|
||||
console.log('date ', v);
|
||||
}
|
||||
|
||||
// 根据使用的页面决定背景的大小
|
||||
const bgSize =
|
||||
props.page == 'home' ? ['middle', 'short'] : ['middle', 'short'];
|
||||
|
||||
return (
|
||||
<GraphBase
|
||||
icon="battery"
|
||||
title="产线当日缺陷分类"
|
||||
dateOptions={lines.map((item) => item.label)}
|
||||
onDateChange={handleDateChange}
|
||||
size={bgSize}
|
||||
style={{ width: '600px' }}
|
||||
>
|
||||
<div className={cls.chart}>
|
||||
<ReactECharts option={options} style={{ height: '100%' }} />
|
||||
</div>
|
||||
</GraphBase>
|
||||
);
|
||||
}
|
||||
|
||||
export default FaultType;
|
||||
34
src/components/公共组件/产线当日缺陷分类/index.module.css
Normal file
34
src/components/公共组件/产线当日缺陷分类/index.module.css
Normal file
@@ -0,0 +1,34 @@
|
||||
.chart {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.faultType {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.headWidget {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 24px;
|
||||
height: 32px;
|
||||
width: 340px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.radioGroup * {
|
||||
border: none !important;
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
|
||||
.radioGroup *:focus-within {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.radioGroup *::before {
|
||||
width: 0 !important;
|
||||
}
|
||||
|
||||
.radioGroup_button_wrapper {
|
||||
color: #fff !important;
|
||||
background: #03233c !important;
|
||||
}
|
||||
163
src/components/公共组件/产线缺陷统计/index.jsx
Normal file
163
src/components/公共组件/产线缺陷统计/index.jsx
Normal file
@@ -0,0 +1,163 @@
|
||||
import cls from './index.module.css';
|
||||
import GraphBase from '../GraphBase';
|
||||
import ReactECharts from 'echarts-for-react';
|
||||
|
||||
function FaultTotal(props) {
|
||||
const options = {
|
||||
color: [
|
||||
'#2760FF',
|
||||
'#5B9BFF',
|
||||
'#FFD160',
|
||||
'#8167F6',
|
||||
'#99D66C',
|
||||
'#FF8A40',
|
||||
'#12FFF5',
|
||||
],
|
||||
grid: { top: 42, right: 12, bottom: 20, left: 48 },
|
||||
legend: {
|
||||
top: 10,
|
||||
padding: 5,
|
||||
itemWidth: 12,
|
||||
itemHeight: 12,
|
||||
itemGap: 12,
|
||||
height: 12,
|
||||
textStyle: {
|
||||
color: '#DFF1FE',
|
||||
fontSize: 12,
|
||||
},
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: Array(5)
|
||||
.fill(1)
|
||||
.map((_, index) => {
|
||||
return '产线' + (index + 1);
|
||||
}),
|
||||
axisLabel: {
|
||||
color: '#fff',
|
||||
fontSize: 12,
|
||||
},
|
||||
axisTick: { show: false },
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
width: 1,
|
||||
color: '#213259',
|
||||
},
|
||||
},
|
||||
},
|
||||
yAxis: {
|
||||
name: '单位/个',
|
||||
nameTextStyle: {
|
||||
color: '#fff',
|
||||
fontSize: 10,
|
||||
align: 'right',
|
||||
},
|
||||
type: 'value',
|
||||
axisLabel: {
|
||||
color: '#fff',
|
||||
fontSize: 12,
|
||||
formatter: '{value}',
|
||||
},
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: '#213259',
|
||||
},
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: '#213259a0',
|
||||
},
|
||||
},
|
||||
// interval: 10,
|
||||
// min: 0,
|
||||
// max: 100,
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '缺陷1',
|
||||
type: 'bar',
|
||||
stack: 'abcd',
|
||||
emphasis: {
|
||||
focus: 'series',
|
||||
},
|
||||
data: [320, 332, 301, 334, 390, 330, 320],
|
||||
},
|
||||
{
|
||||
name: '缺陷2',
|
||||
type: 'bar',
|
||||
stack: 'abcd',
|
||||
emphasis: {
|
||||
focus: 'series',
|
||||
},
|
||||
data: [120, 132, 101, 134, 90, 230, 210],
|
||||
},
|
||||
{
|
||||
name: '缺陷3',
|
||||
type: 'bar',
|
||||
stack: 'abcd',
|
||||
emphasis: {
|
||||
focus: 'series',
|
||||
},
|
||||
data: [220, 182, 191, 234, 290, 330, 310],
|
||||
},
|
||||
{
|
||||
name: '缺陷4',
|
||||
type: 'bar',
|
||||
stack: 'abcd',
|
||||
emphasis: {
|
||||
focus: 'series',
|
||||
},
|
||||
data: [150, 232, 201, 154, 190, 330, 410],
|
||||
},
|
||||
{
|
||||
name: '缺陷5',
|
||||
type: 'bar',
|
||||
stack: 'abcd',
|
||||
emphasis: {
|
||||
focus: 'series',
|
||||
},
|
||||
data: [862, 1018, 964, 1026, 1679, 1600, 1570],
|
||||
},
|
||||
{
|
||||
name: '缺陷6',
|
||||
type: 'bar',
|
||||
barGap: 20,
|
||||
barWidth: 12,
|
||||
stack: 'abcd',
|
||||
emphasis: {
|
||||
focus: 'series',
|
||||
},
|
||||
data: [620, 732, 701, 734, 1090, 1130, 1120],
|
||||
},
|
||||
],
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
},
|
||||
};
|
||||
|
||||
function handleDateChange(v) {
|
||||
console.log('date ', v);
|
||||
}
|
||||
|
||||
// 根据使用的页面决定背景的大小
|
||||
const bgSize =
|
||||
props.page == 'home' ? ['middle', 'short'] : ['middle', 'long'];
|
||||
|
||||
return (
|
||||
<GraphBase
|
||||
icon="battery"
|
||||
title="产线当日缺陷分类"
|
||||
dateOptions={['日', '周', '月', '年']}
|
||||
onDateChange={handleDateChange}
|
||||
size={bgSize}
|
||||
style={{ width: '600px' }}
|
||||
>
|
||||
<div className={cls.chart}>
|
||||
<ReactECharts option={options} style={{ height: '100%' }} />
|
||||
</div>
|
||||
</GraphBase>
|
||||
);
|
||||
}
|
||||
|
||||
export default FaultTotal;
|
||||
36
src/components/公共组件/产线缺陷统计/index.module.css
Normal file
36
src/components/公共组件/产线缺陷统计/index.module.css
Normal file
@@ -0,0 +1,36 @@
|
||||
.chart {
|
||||
height: 100%;
|
||||
/* background-color: #00ee33; */
|
||||
}
|
||||
|
||||
.faultTotal {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.headWidget {
|
||||
position: absolute;
|
||||
/* background: #00ee33; */
|
||||
top: 20px;
|
||||
right: 24px;
|
||||
height: 32px;
|
||||
width: 190px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.radioGroup * {
|
||||
border: none !important;
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
|
||||
.radioGroup *:focus-within {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.radioGroup *::before {
|
||||
width: 0 !important;
|
||||
}
|
||||
|
||||
.radioGroup_button_wrapper {
|
||||
color: #fff !important;
|
||||
background: #03233c !important;
|
||||
}
|
||||
187
src/components/公共组件/助燃风流量/index.jsx
Normal file
187
src/components/公共组件/助燃风流量/index.jsx
Normal file
@@ -0,0 +1,187 @@
|
||||
// 助燃风流量
|
||||
import cls from './index.module.css';
|
||||
import BottomBarItem from '../BottomItemBackground';
|
||||
import ReactECharts from 'echarts-for-react';
|
||||
import * as echarts from 'echarts';
|
||||
import { randomInt } from '../../../utils';
|
||||
import { Switch } from 'antd';
|
||||
import { useState, useContext } from 'react';
|
||||
// import SocketContext from '../../../store/socket-data-provider';
|
||||
|
||||
function GasI(props) {
|
||||
const [showChart, setShowChart] = useState(true);
|
||||
// const { runState, hisState } = useContext(SocketContext);
|
||||
|
||||
const runState = null;
|
||||
const hisState = null;
|
||||
|
||||
let dataList = [];
|
||||
let seriesData = [];
|
||||
const colors = [
|
||||
'#12FFF5',
|
||||
'#2760FF',
|
||||
'#FFD160',
|
||||
'#E80091',
|
||||
'#8064ff',
|
||||
'#ff8a3b',
|
||||
'#8cd26d',
|
||||
'#2aa1ff',
|
||||
];
|
||||
let options = null;
|
||||
if (showChart) {
|
||||
// keys() 结果不是按照顺序,需要 sort()
|
||||
seriesData = hisState?.combustionAir
|
||||
? Object.keys(hisState.combustionAir)
|
||||
.sort()
|
||||
.map((key) => hisState.combustionAir[key])
|
||||
: Array(8)
|
||||
.fill(1)
|
||||
.map((_) => Array(7).fill(0));
|
||||
|
||||
// debug
|
||||
console.log(
|
||||
'助燃风 chart series data',
|
||||
hisState?.combustionAir,
|
||||
seriesData,
|
||||
);
|
||||
options = {
|
||||
color: colors,
|
||||
grid: { top: 32, right: 12, bottom: 20, left: 48 },
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: Array(7)
|
||||
.fill(1)
|
||||
.map((_, index) => {
|
||||
const today = new Date();
|
||||
const dtimestamp = today - index * 24 * 60 * 60 * 1000;
|
||||
return `${new Date(dtimestamp).getMonth() + 1}.${new Date(
|
||||
dtimestamp,
|
||||
).getDate()}`;
|
||||
})
|
||||
.reverse(),
|
||||
axisLabel: {
|
||||
color: '#fff',
|
||||
fontSize: 12,
|
||||
},
|
||||
axisTick: { show: false },
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
width: 1,
|
||||
color: '#213259',
|
||||
},
|
||||
},
|
||||
},
|
||||
yAxis: {
|
||||
name: '单位/m³',
|
||||
nameTextStyle: {
|
||||
color: '#fff',
|
||||
fontSize: 10,
|
||||
align: 'right',
|
||||
},
|
||||
type: 'value',
|
||||
axisLabel: {
|
||||
color: '#fff',
|
||||
fontSize: 12,
|
||||
},
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: '#213259',
|
||||
},
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: '#213259a0',
|
||||
},
|
||||
},
|
||||
// interval: 10,
|
||||
// min: 0,
|
||||
// max: 100,
|
||||
},
|
||||
series: seriesData.map((v, i) => ({
|
||||
name: i + 1 + '#助燃风',
|
||||
data: v,
|
||||
type: 'line',
|
||||
symbol: 'circle',
|
||||
areaStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{ offset: 0, color: colors[i] + '40' },
|
||||
{ offset: 0.5, color: colors[i] + '20' },
|
||||
{ offset: 1, color: colors[i] + '00' },
|
||||
]),
|
||||
},
|
||||
})),
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
},
|
||||
};
|
||||
} else {
|
||||
dataList = runState?.combustionAirPressureArr
|
||||
? [
|
||||
{ id: 1, name: '1#助燃风', value: '0m³/h' },
|
||||
{ id: 2, name: '2#助燃风', value: '0m³/h' },
|
||||
{ id: 3, name: '3#助燃风', value: '0m³/h' },
|
||||
{ id: 4, name: '4#助燃风', value: '0m³/h' },
|
||||
{ id: 5, name: '5#助燃风', value: '0m³/h' },
|
||||
{ id: 6, name: '6#助燃风', value: '0m³/h' },
|
||||
{ id: 7, name: '7#助燃风', value: '0m³/h' },
|
||||
{ id: 8, name: '8#助燃风', value: '0m³/h' },
|
||||
].map((item, index) => ({
|
||||
...item,
|
||||
value: runState.combustionAirPressureArr[index] ?? '/',
|
||||
}))
|
||||
: [
|
||||
{ id: 1, name: '1#助燃风', value: '0m³/h' },
|
||||
{ id: 2, name: '2#助燃风', value: '0m³/h' },
|
||||
{ id: 3, name: '3#助燃风', value: '0m³/h' },
|
||||
{ id: 4, name: '4#助燃风', value: '0m³/h' },
|
||||
{ id: 5, name: '5#助燃风', value: '0m³/h' },
|
||||
{ id: 6, name: '6#助燃风', value: '0m³/h' },
|
||||
{ id: 7, name: '7#助燃风', value: '0m³/h' },
|
||||
{ id: 8, name: '8#助燃风', value: '0m³/h' },
|
||||
];
|
||||
// debug
|
||||
console.log('助燃风 实时 data', runState?.combustionAirPressureArr);
|
||||
}
|
||||
|
||||
function handleSwitchChange(val) {
|
||||
if (val) {
|
||||
setShowChart(true);
|
||||
} else {
|
||||
setShowChart(false);
|
||||
}
|
||||
}
|
||||
return (
|
||||
<BottomBarItem
|
||||
icon="pause"
|
||||
title="助燃风流量"
|
||||
className={cls.gas}
|
||||
style={props.style}
|
||||
>
|
||||
<div className={cls.headWidget}>
|
||||
<div className="flex items-center">
|
||||
<Switch size="small" defaultChecked onChange={handleSwitchChange} />
|
||||
{showChart && <span className={cls.switchLabel}>历史详情</span>}
|
||||
{!showChart && <span className={cls.switchLabel}>实时流量</span>}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={cls.chart}>
|
||||
{showChart && (
|
||||
<ReactECharts option={options} style={{ height: '100%' }} />
|
||||
)}
|
||||
{!showChart && (
|
||||
<div className={cls.gridList}>
|
||||
{dataList.map((item) => (
|
||||
<div key={item.id} className={cls.listItem}>
|
||||
{item.name}: {item.value}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</BottomBarItem>
|
||||
);
|
||||
}
|
||||
|
||||
export default GasI;
|
||||
83
src/components/公共组件/助燃风流量/index.module.css
Normal file
83
src/components/公共组件/助燃风流量/index.module.css
Normal file
@@ -0,0 +1,83 @@
|
||||
.chart {
|
||||
height: 100%;
|
||||
/* background-color: #00ee33; */
|
||||
}
|
||||
|
||||
.gas {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.currentFlow {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
padding: 8px 22px;
|
||||
border-radius: 2px;
|
||||
letter-spacing: 2px;
|
||||
box-shadow: inset 0 0 22px 0px hsla(0, 0%, 100%, 0.15);
|
||||
line-height: 18px;
|
||||
font-size: 18px;
|
||||
text-align: center;
|
||||
color: #12fff5;
|
||||
}
|
||||
|
||||
.headWidget {
|
||||
position: absolute;
|
||||
/* background: #00ee33; */
|
||||
top: 20px;
|
||||
right: 24px;
|
||||
height: 32px;
|
||||
width: 190px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.radioGroup * {
|
||||
border: none !important;
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
|
||||
.radioGroup *:focus-within {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.radioGroup *::before {
|
||||
width: 0 !important;
|
||||
}
|
||||
|
||||
.radioGroup_button_wrapper {
|
||||
color: #fff !important;
|
||||
background: #03233c !important;
|
||||
}
|
||||
|
||||
.gridList {
|
||||
margin-top: 12px;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.listItem {
|
||||
border-radius: 2px;
|
||||
padding: 12px 0;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
box-shadow: inset 0 0 16px 4px rgba(255, 255, 255, 0.197);
|
||||
}
|
||||
|
||||
.headWidget {
|
||||
position: absolute;
|
||||
/* background: #00ee33; */
|
||||
top: 22px;
|
||||
right: 24px;
|
||||
height: 32px;
|
||||
width: 410px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.switchLabel {
|
||||
color: white;
|
||||
margin-left: 6px;
|
||||
}
|
||||
98
src/components/公共组件/天然气流量/gasChart/chart.config.js
Normal file
98
src/components/公共组件/天然气流量/gasChart/chart.config.js
Normal file
@@ -0,0 +1,98 @@
|
||||
import * as echarts from 'echarts';
|
||||
import { randomInt } from '../../../../utils';
|
||||
|
||||
export default function getOptions(seriesData, name) {
|
||||
const colors = [
|
||||
'#12FFF5',
|
||||
'#2760FF',
|
||||
'#FFD160',
|
||||
'#E80091',
|
||||
'#8064ff',
|
||||
'#ff8a3b',
|
||||
'#8cd26d',
|
||||
'#2aa1ff',
|
||||
];
|
||||
return {
|
||||
color: colors,
|
||||
grid: { top: 38, right: 12, bottom: 20, left: 48 },
|
||||
legend: {
|
||||
show: true,
|
||||
icon: 'roundRect',
|
||||
top: 10,
|
||||
right: 10,
|
||||
padding: 0,
|
||||
itemWidth: 8,
|
||||
itemHeight: 8,
|
||||
itemGap: 3,
|
||||
height: 8,
|
||||
textStyle: {
|
||||
color: '#DFF1FE',
|
||||
fontSize: 10,
|
||||
},
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: Array(7)
|
||||
.fill(1)
|
||||
.map((_, index) => {
|
||||
const today = new Date();
|
||||
const dtimestamp = today - index * 24 * 60 * 60 * 1000;
|
||||
return `${new Date(dtimestamp).getMonth() + 1}.${new Date(
|
||||
dtimestamp,
|
||||
).getDate()}`;
|
||||
})
|
||||
.reverse(),
|
||||
axisLabel: {
|
||||
color: '#fff',
|
||||
fontSize: 12,
|
||||
},
|
||||
axisTick: { show: false },
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
width: 1,
|
||||
color: '#213259',
|
||||
},
|
||||
},
|
||||
},
|
||||
yAxis: {
|
||||
name: '单位m³/h',
|
||||
nameTextStyle: {
|
||||
color: '#fff',
|
||||
fontSize: 10,
|
||||
align: 'right',
|
||||
},
|
||||
type: 'value',
|
||||
axisLabel: {
|
||||
color: '#fff',
|
||||
fontSize: 12,
|
||||
formatter: '{value}',
|
||||
},
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: '#213259',
|
||||
},
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: '#213259a0',
|
||||
},
|
||||
},
|
||||
},
|
||||
series: seriesData.map((arr, index) => ({
|
||||
name: index + 1 + '#' + name,
|
||||
data: arr,
|
||||
type: 'line',
|
||||
areaStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{ offset: 0, color: colors[index] + '40' },
|
||||
{ offset: 0.5, color: colors[index] + '20' },
|
||||
{ offset: 1, color: colors[index] + '00' },
|
||||
]),
|
||||
},
|
||||
})),
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
},
|
||||
};
|
||||
}
|
||||
37
src/components/公共组件/天然气流量/gasChart/index.jsx
Normal file
37
src/components/公共组件/天然气流量/gasChart/index.jsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import cls from './index.module.css';
|
||||
import ReactECharts from 'echarts-for-react';
|
||||
import getOptions from './chart.config';
|
||||
// import SocketContext from '../../../../store/socket-data-provider';
|
||||
import { useContext } from 'react';
|
||||
|
||||
function GasChart(props) {
|
||||
const { dataSource } = props;
|
||||
// const { hisState } = useContext(SocketContext);
|
||||
const hisState = null;
|
||||
const dataName = dataSource == 'gas-i' ? 'kilnGasT1' : 'kilnGasT2';
|
||||
|
||||
// keys() 的结果不是按照顺序的,需要 sort()
|
||||
const seriesData = hisState?.[dataName]
|
||||
? Object.keys(hisState?.[dataName])
|
||||
.sort()
|
||||
.map((key, index) => hisState?.[dataName][key])
|
||||
: Array(dataSource == 'gas-i' ? 8 : 4).fill(Array(7).fill(0));
|
||||
|
||||
// debug
|
||||
console.log('天然气 series data', dataName, hisState?.[dataName], seriesData);
|
||||
|
||||
return (
|
||||
<div className={cls.gasChart}>
|
||||
<ReactECharts
|
||||
key={Math.random()}
|
||||
option={getOptions(
|
||||
seriesData,
|
||||
dataSource == 'gas-i' ? '天然气I' : '天然气II',
|
||||
)}
|
||||
style={{ height: '100%' }}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default GasChart;
|
||||
3
src/components/公共组件/天然气流量/gasChart/index.module.css
Normal file
3
src/components/公共组件/天然气流量/gasChart/index.module.css
Normal file
@@ -0,0 +1,3 @@
|
||||
.gasChart {
|
||||
height: 100%;
|
||||
}
|
||||
55
src/components/公共组件/天然气流量/gridList/index.jsx
Normal file
55
src/components/公共组件/天然气流量/gridList/index.jsx
Normal file
@@ -0,0 +1,55 @@
|
||||
import cls from './index.module.css';
|
||||
import { useContext, useEffect, useState } from 'react';
|
||||
// import SocketContext from '../../../../store/socket-data-provider';
|
||||
|
||||
function getData(type) {
|
||||
let data = [];
|
||||
switch (type) {
|
||||
case 'gas-i':
|
||||
data = [
|
||||
{ id: 1, name: '1#天然气I', value: '0m³/h' },
|
||||
{ id: 2, name: '2#天然气I', value: '0m³/h' },
|
||||
{ id: 3, name: '3#天然气I', value: '0m³/h' },
|
||||
{ id: 4, name: '4#天然气I', value: '0m³/h' },
|
||||
{ id: 5, name: '5#天然气I', value: '0m³/h' },
|
||||
{ id: 6, name: '6#天然气I', value: '0m³/h' },
|
||||
{ id: 7, name: '7#天然气I', value: '0m³/h' },
|
||||
{ id: 8, name: '8#天然气I', value: '0m³/h' },
|
||||
];
|
||||
break;
|
||||
case 'gas-ii':
|
||||
data = [
|
||||
{ id: 11, name: '1#天然气II', value: '0m³/h' },
|
||||
{ id: 12, name: '2#天然气II', value: '0m³/h' },
|
||||
{ id: 13, name: '3#天然气II', value: '0m³/h' },
|
||||
{ id: 14, name: '4#天然气II', value: '0m³/h' },
|
||||
// { id: 15, name: '5#天然气II', value: '0m³/h' },
|
||||
];
|
||||
break;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
function GridList(props) {
|
||||
// const { runState } = useContext(SocketContext);
|
||||
const runState = null;
|
||||
|
||||
const key = props.dataSource == 'gas-i' ? 'gasFlowArr' : 'furnaceGasFlowArr';
|
||||
|
||||
let dataList = getData(props.dataSource);
|
||||
dataList = runState?.[key]
|
||||
? dataList.map((v, i) => ({ ...v, value: runState[key][i] ?? '/' }))
|
||||
: dataList;
|
||||
|
||||
return (
|
||||
<div className={cls.gridList}>
|
||||
{dataList.map((item) => (
|
||||
<div key={item.id} className={cls.listItem}>
|
||||
{item.name}: {item.value}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default GridList;
|
||||
14
src/components/公共组件/天然气流量/gridList/index.module.css
Normal file
14
src/components/公共组件/天然气流量/gridList/index.module.css
Normal file
@@ -0,0 +1,14 @@
|
||||
.gridList {
|
||||
margin-top: 12px;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.listItem {
|
||||
border-radius: 2px;
|
||||
padding: 12px 0;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
box-shadow: inset 0 0 16px 4px rgba(255, 255, 255, 0.197);
|
||||
}
|
||||
71
src/components/公共组件/天然气流量/index.jsx
Normal file
71
src/components/公共组件/天然气流量/index.jsx
Normal file
@@ -0,0 +1,71 @@
|
||||
// 天然气流量
|
||||
import cls from './index.module.css';
|
||||
import BottomBarItem from '../BottomItemBackground';
|
||||
|
||||
import { Switch, Radio } from 'antd';
|
||||
import { useState } from 'react';
|
||||
import GridList from './gridList';
|
||||
import GasChart from './gasChart';
|
||||
|
||||
function GasII(props) {
|
||||
const [dataSource, setDataSource] = useState('gas-i'); // gas-i , gas-ii
|
||||
const [showChart, setShowChart] = useState(true);
|
||||
|
||||
function handleSwitchChange(val) {
|
||||
if (val) {
|
||||
setShowChart(true);
|
||||
} else {
|
||||
setShowChart(false);
|
||||
}
|
||||
}
|
||||
|
||||
function handleSourceChange(e) {
|
||||
console.log('val', e.target.value);
|
||||
if (e.target.value == 'ii') {
|
||||
// 天然气II
|
||||
setDataSource('gas-ii');
|
||||
} else if (e.target.value == 'i') {
|
||||
// 天然气 I
|
||||
setDataSource('gas-i');
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<BottomBarItem
|
||||
icon="pause"
|
||||
title="天然气流量"
|
||||
className={`${cls.gas} ${props.className}`}
|
||||
style={props.style}
|
||||
>
|
||||
{/* legend */}
|
||||
<div className={cls.headWidget}>
|
||||
<div className="flex items-center">
|
||||
<Switch size="small" defaultChecked onChange={handleSwitchChange} />
|
||||
{showChart && <span className={cls.switchLabel}>历史详情</span>}
|
||||
{!showChart && <span className={cls.switchLabel}>实时流量</span>}
|
||||
</div>
|
||||
|
||||
<Radio.Group
|
||||
defaultValue="i"
|
||||
buttonStyle="solid"
|
||||
className={cls.radioGroup}
|
||||
onChange={handleSourceChange}
|
||||
>
|
||||
<Radio.Button value="i" className="radio-group__item">
|
||||
天然气 I
|
||||
</Radio.Button>
|
||||
<Radio.Button value="ii" className="radio-group__item">
|
||||
天然气 II
|
||||
</Radio.Button>
|
||||
</Radio.Group>
|
||||
</div>
|
||||
|
||||
<div className={cls.chart}>
|
||||
{showChart && <GasChart dataSource={dataSource} />}
|
||||
{!showChart && <GridList dataSource={dataSource} />}
|
||||
</div>
|
||||
</BottomBarItem>
|
||||
);
|
||||
}
|
||||
|
||||
export default GasII;
|
||||
86
src/components/公共组件/天然气流量/index.module.css
Normal file
86
src/components/公共组件/天然气流量/index.module.css
Normal file
@@ -0,0 +1,86 @@
|
||||
.chart {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.gas {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.currentFlow {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
padding: 8px 22px;
|
||||
border-radius: 2px;
|
||||
letter-spacing: 2px;
|
||||
box-shadow: inset 0 0 22px 0px hsla(0, 0%, 100%, 0.15);
|
||||
line-height: 18px;
|
||||
font-size: 18px;
|
||||
text-align: center;
|
||||
color: #12fff5;
|
||||
}
|
||||
|
||||
.headWidget {
|
||||
position: absolute;
|
||||
top: 22px;
|
||||
right: 24px;
|
||||
height: 32px;
|
||||
width: 410px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.switchLabel {
|
||||
color: white;
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
.legend:last-child {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.legend > span {
|
||||
display: inline-block;
|
||||
color: #dff1fe;
|
||||
font-size: 14px;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
.legend > span:first-child {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
margin-right: 4px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.gasIcon {
|
||||
background: #12fff5;
|
||||
}
|
||||
|
||||
.gas2Icon {
|
||||
background: #2760ff;
|
||||
}
|
||||
|
||||
.radioGroup {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.radioGroup * {
|
||||
border: none !important;
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
|
||||
.radioGroup *:focus-within {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.radioGroup *::before {
|
||||
width: 0 !important;
|
||||
}
|
||||
|
||||
.radioGroup_button_wrapper {
|
||||
color: #fff !important;
|
||||
background: #03233c !important;
|
||||
}
|
||||
25
src/components/公共组件/导航菜单/index.jsx
Normal file
25
src/components/公共组件/导航菜单/index.jsx
Normal file
@@ -0,0 +1,25 @@
|
||||
import { useCallback, useState } from 'react';
|
||||
import cls from './index.module.less';
|
||||
|
||||
export default function CenterMenu({ active, onChangeActive }) {
|
||||
const menuList = [
|
||||
['窑炉总览', '/kilnSummary'],
|
||||
['窑炉内部', '/kilnInner'],
|
||||
['退火监测', '/stopFire'],
|
||||
['质检统计', '/quailtyCheck'],
|
||||
['能耗分析', '/energyCost'],
|
||||
];
|
||||
return (
|
||||
<div className={`${cls.centerMenu} flex`}>
|
||||
{menuList.map((menu) => (
|
||||
<div
|
||||
key={menu[0]}
|
||||
className={`${cls.menuItem} ${active == menu[0] ? cls.active : ''}`}
|
||||
onClick={() => onChangeActive(menu[0])}
|
||||
>
|
||||
{menu[0]}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
33
src/components/公共组件/导航菜单/index.module.less
Normal file
33
src/components/公共组件/导航菜单/index.module.less
Normal file
@@ -0,0 +1,33 @@
|
||||
.centerMenu {
|
||||
position: fixed;
|
||||
top: 120px;
|
||||
left: 1340px;
|
||||
color: white;
|
||||
z-index: 10000;
|
||||
}
|
||||
|
||||
.menuItem {
|
||||
transition: all 0.3s ease-out;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
padding: 10px 20px;
|
||||
font-size: 32px;
|
||||
line-height: 48px;
|
||||
letter-spacing: 6px;
|
||||
background: url(../../../assets/bg_center_menu.png) no-repeat;
|
||||
background-size: 100% 50%;
|
||||
background-position: bottom;
|
||||
color: #00fff788;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue',
|
||||
'PingFang SC', 'Microsoft YaHei', '微软雅黑', 'Microsoft YaHei UI',
|
||||
'Source Han Sans SC', 'Noto Sans CJK SC', 'WenQuanYi Micro Hei', sans-serif;
|
||||
}
|
||||
|
||||
.menuItem.active,
|
||||
.menuItem:hover {
|
||||
color: #00fff7;
|
||||
}
|
||||
|
||||
.menuItem:not(:first-child) {
|
||||
margin-left: 50px;
|
||||
}
|
||||
78
src/components/公共组件/当前产线生产规格/index.jsx
Normal file
78
src/components/公共组件/当前产线生产规格/index.jsx
Normal file
@@ -0,0 +1,78 @@
|
||||
import BottomBarItem from '../BottomItemBackground';
|
||||
import React, { Component } from 'react';
|
||||
import './righttable.module.less';
|
||||
|
||||
// import { ScrollBoard } from '@jiaminghi/data-view-react';
|
||||
|
||||
let data = [
|
||||
['产线0', '10mm', '10mm', '10mm'],
|
||||
['产线2', '8mm', '8mm', '8mm'],
|
||||
['产线3', '15mm', '15mm', '15mm'],
|
||||
['产线4', '15mm', '15mm', '15mm'],
|
||||
['产线42', '15mm', '15mm', '15mm'],
|
||||
['产线5', '15mm', '15mm', '15mm'],
|
||||
['产线6', '15mm', '15mm', '15mm'],
|
||||
];
|
||||
|
||||
let header = ['产线名', '原板宽度', '净板宽', '玻璃厚度'];
|
||||
|
||||
let config = {
|
||||
headerBGC: 'rgba(4, 44, 76, 0.3)',
|
||||
header: [
|
||||
'<span style="color:#fff">产线名<span/>',
|
||||
'<span style="color:#fff">原板宽度<span/>',
|
||||
'<span style="color:#fff">净板宽<span/>',
|
||||
'<span style="color:#fff">玻璃厚度<span/>',
|
||||
],
|
||||
oddRowBGC: '#042444',
|
||||
evenRowBGC: '#042c4c',
|
||||
columnWidth: [128],
|
||||
headerHeight: 40,
|
||||
hoverPause: false,
|
||||
data: replaceStyle(data, 0.7),
|
||||
};
|
||||
|
||||
function replaceStyle(Arr, opencity) {
|
||||
let temp = [];
|
||||
|
||||
for (let i = 0; i < Arr.length; i++) {
|
||||
temp[i] = [];
|
||||
for (let j = 0; j < Arr[i].length; j++) {
|
||||
temp[i][
|
||||
j
|
||||
] = ` <span style="color:rgba(255, 255, 255,${opencity})">${Arr[i][j]}<span/>`;
|
||||
}
|
||||
}
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
class Chart1 extends Component {
|
||||
render() {
|
||||
return (
|
||||
<BottomBarItem
|
||||
icon="pause"
|
||||
title="当前产线生产规格"
|
||||
className={this.props.className}
|
||||
style={this.props.style}
|
||||
>
|
||||
<div
|
||||
className="CenterChart1itemDetailBorder"
|
||||
style={{ paddingTop: '6px' }}
|
||||
>
|
||||
<div className="CenterChart1itemContainer">
|
||||
<span className="CenterFormitemDetailBorderLine1"></span>
|
||||
<span className="CenterFormitemDetailBorderLine2"></span>
|
||||
<span className="CenterFormitemDetailBorderLine3"></span>
|
||||
{/* <ScrollBoard
|
||||
config={config}
|
||||
style={{ width: '105%', height: '240%' }}
|
||||
/> */}
|
||||
</div>
|
||||
</div>
|
||||
</BottomBarItem>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Chart1;
|
||||
50
src/components/公共组件/当前产线生产规格/righttable.module.less
Normal file
50
src/components/公共组件/当前产线生产规格/righttable.module.less
Normal file
@@ -0,0 +1,50 @@
|
||||
.CenterChart1itemDetailBorder {
|
||||
width: 100%;
|
||||
height: 240px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
|
||||
background-color: rgba(4, 44, 76, 0.2);
|
||||
.CenterChart1itemTXT {
|
||||
width: 100%;
|
||||
height: 10%;
|
||||
font-size: 20px;
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
text-align: center;
|
||||
margin-top: 2%;
|
||||
}
|
||||
.CenterChart1itemContainer {
|
||||
width: 95%;
|
||||
height: 100px;
|
||||
position: relative;
|
||||
|
||||
.CenterFormitemDetailBorderLine1 {
|
||||
width: 1px;
|
||||
height: 200px;
|
||||
background-color: #041c2c;
|
||||
float: left;
|
||||
margin-left: 18%;
|
||||
z-index: 10;
|
||||
position: absolute;
|
||||
}
|
||||
.CenterFormitemDetailBorderLine2 {
|
||||
width: 1px;
|
||||
height: 200px;
|
||||
background-color: #041c2c;
|
||||
float: left;
|
||||
margin-left: 46%;
|
||||
z-index: 10;
|
||||
position: absolute;
|
||||
}
|
||||
.CenterFormitemDetailBorderLine3 {
|
||||
width: 1px;
|
||||
height: 200px;
|
||||
background-color: #041c2c;
|
||||
float: left;
|
||||
margin-left: 72%;
|
||||
z-index: 10;
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
}
|
||||
138
src/components/公共组件/当前温度/index.jsx
Normal file
138
src/components/公共组件/当前温度/index.jsx
Normal file
@@ -0,0 +1,138 @@
|
||||
import BottomBarItem from '../BottomItemBackground';
|
||||
import GraphBase from '../GraphBase';
|
||||
import { Radio } from 'antd';
|
||||
import cls from './index.module.css';
|
||||
import { useState } from 'react';
|
||||
|
||||
const SmallBox = (props) => {
|
||||
return (
|
||||
<div
|
||||
className="small-box"
|
||||
style={{
|
||||
boxShadow: 'inset 0 0 18px 10px #fff1',
|
||||
borderRadius: '3px',
|
||||
padding: '6px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
color: '#fff',
|
||||
position: 'relative',
|
||||
userSelect: 'none',
|
||||
}}
|
||||
>
|
||||
{props.split !== false && (
|
||||
<span
|
||||
className="vertical-line"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
display: 'inline-block',
|
||||
width: '2px',
|
||||
height: '80%',
|
||||
top: '10%',
|
||||
left: '50%',
|
||||
background:
|
||||
'linear-gradient(to bottom, transparent, #fff3, #fffa, #fff3, transparent)',
|
||||
}}
|
||||
></span>
|
||||
)}
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
function WindFrequence(props) {
|
||||
const [dataSource, setDataSource] = useState('风机');
|
||||
|
||||
function handleSourceChange(v) {
|
||||
console.log('val', v);
|
||||
}
|
||||
|
||||
return (
|
||||
<GraphBase
|
||||
icon="pause"
|
||||
title="当前温度"
|
||||
dateOptions={['风机', '风阀', '电加热']}
|
||||
onDateChange={handleSourceChange}
|
||||
size={['middle', 'long']}
|
||||
>
|
||||
<div className={cls.mainContent + ' ' + cls.grid}>
|
||||
<SmallBox>
|
||||
<h1 className={cls.areaName}>A1区板上</h1>
|
||||
<div className={cls.areaContent}>
|
||||
<span className={cls.areaValue}>123.8℃</span>
|
||||
<span className={cls.areaValue}>123.8℃</span>
|
||||
<span className={cls.areaValue}>123.8℃</span>
|
||||
</div>
|
||||
</SmallBox>
|
||||
<SmallBox>
|
||||
<h1 className={cls.areaName}>A1区板上</h1>
|
||||
<div className={cls.areaContent}>
|
||||
<span className={cls.areaValue}>123.8℃</span>
|
||||
<span className={cls.areaValue}>123.8℃</span>
|
||||
<span className={cls.areaValue}>123.8℃</span>
|
||||
</div>
|
||||
</SmallBox>
|
||||
<SmallBox>
|
||||
<h1 className={cls.areaName}>A1区板上</h1>
|
||||
<div className={cls.areaContent}>
|
||||
<span className={cls.areaValue}>123.8℃</span>
|
||||
<span className={cls.areaValue}>123.8℃</span>
|
||||
<span className={cls.areaValue}>123.8℃</span>
|
||||
</div>
|
||||
</SmallBox>
|
||||
<SmallBox>
|
||||
<h1 className={cls.areaName}>A1区板上</h1>
|
||||
<div className={cls.areaContent}>
|
||||
<span className={cls.areaValue}>123.8℃</span>
|
||||
<span className={cls.areaValue}>123.8℃</span>
|
||||
<span className={cls.areaValue}>123.8℃</span>
|
||||
</div>
|
||||
</SmallBox>
|
||||
<SmallBox>
|
||||
<h1 className={cls.areaName}>A1区板上</h1>
|
||||
<div className={cls.areaContent}>
|
||||
<span className={cls.areaValue}>123.8℃</span>
|
||||
<span className={cls.areaValue}>123.8℃</span>
|
||||
<span className={cls.areaValue}>123.8℃</span>
|
||||
</div>
|
||||
</SmallBox>
|
||||
<SmallBox split={false}>
|
||||
<div className={cls.areaPureContent}>
|
||||
<span className={cls.areaPureValue}>123.8℃</span>
|
||||
<span className={cls.areaPureValue}>123.8℃</span>
|
||||
<span className={cls.areaPureValue}>123.8℃</span>
|
||||
</div>
|
||||
</SmallBox>
|
||||
<SmallBox>
|
||||
<h1 className={cls.areaName}>A1区板上</h1>
|
||||
<div className={cls.areaContent}>
|
||||
<span className={cls.areaValue}>123.8℃</span>
|
||||
<span className={cls.areaValue}>123.8℃</span>
|
||||
<span className={cls.areaValue}>123.8℃</span>
|
||||
</div>
|
||||
</SmallBox>
|
||||
<SmallBox split={false}>
|
||||
<div className={cls.areaPureContent}>
|
||||
<span className={cls.areaPureValue}>123.8℃</span>
|
||||
<span className={cls.areaPureValue}>123.8℃</span>
|
||||
<span className={cls.areaPureValue}>123.8℃</span>
|
||||
</div>
|
||||
</SmallBox>
|
||||
<SmallBox>
|
||||
<h1 className={cls.areaName}>A1区板上</h1>
|
||||
<div className={cls.areaContent}>
|
||||
<span className={cls.areaValue}>123.8℃</span>
|
||||
</div>
|
||||
</SmallBox>
|
||||
<SmallBox>
|
||||
<h1 className={cls.areaName}>A1区板上</h1>
|
||||
<div className={cls.areaContent}>
|
||||
<span className={cls.areaValue}>123.8℃</span>
|
||||
</div>
|
||||
</SmallBox>
|
||||
</div>
|
||||
</GraphBase>
|
||||
);
|
||||
}
|
||||
|
||||
export default WindFrequence;
|
||||
139
src/components/公共组件/当前温度/index.module.css
Normal file
139
src/components/公共组件/当前温度/index.module.css
Normal file
@@ -0,0 +1,139 @@
|
||||
.chart {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.gas {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.currentFlow {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
padding: 8px 22px;
|
||||
border-radius: 2px;
|
||||
letter-spacing: 2px;
|
||||
box-shadow: inset 0 0 22px 0px hsla(0, 0%, 100%, 0.15);
|
||||
line-height: 18px;
|
||||
font-size: 18px;
|
||||
text-align: center;
|
||||
color: #12fff5;
|
||||
}
|
||||
|
||||
.floatHead {
|
||||
position: absolute;
|
||||
top: 22px;
|
||||
right: 24px;
|
||||
height: 32px;
|
||||
width: 410px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.mainContent {
|
||||
padding-top: 16px;
|
||||
}
|
||||
|
||||
.alignRight {
|
||||
text-align: right;
|
||||
justify-self: flex-end;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
grid-template-columns: repeat(2, minmax(100px, 1fr));
|
||||
grid-auto-rows: minmax(64px, min-content);
|
||||
}
|
||||
|
||||
.areaName {
|
||||
color: #fff;
|
||||
font-size: 20px;
|
||||
line-height: 1;
|
||||
letter-spacing: 1.5px;
|
||||
margin: 0;
|
||||
padding-left: 20px;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.areaPureContent {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.areaPureValue {
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
.areaPureValue:not(:first-child) {
|
||||
border-left: 2px solid #fff6;
|
||||
}
|
||||
|
||||
.areaContent {
|
||||
width: 50%;
|
||||
padding-left: 12px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.areaPureValue,
|
||||
.areaValue {
|
||||
display: inline-block;
|
||||
font-size: 17px;
|
||||
line-height: 22px;
|
||||
letter-spacing: 1.2px;
|
||||
}
|
||||
|
||||
.switchLabel {
|
||||
color: white;
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
.legend:last-child {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.legend > span {
|
||||
display: inline-block;
|
||||
color: #dff1fe;
|
||||
font-size: 14px;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
.legend > span:first-child {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
margin-right: 4px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.gasIcon {
|
||||
background: #12fff5;
|
||||
}
|
||||
|
||||
.gas2Icon {
|
||||
background: #2760ff;
|
||||
}
|
||||
|
||||
.radioGroup {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.radioGroup * {
|
||||
border: none !important;
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
|
||||
.radioGroup *:focus-within {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.radioGroup *::before {
|
||||
width: 0 !important;
|
||||
}
|
||||
|
||||
.radioGroup_button_wrapper {
|
||||
color: #fff !important;
|
||||
background: #03233c !important;
|
||||
}
|
||||
111
src/components/公共组件/时间火向数据/index.jsx
Normal file
111
src/components/公共组件/时间火向数据/index.jsx
Normal file
@@ -0,0 +1,111 @@
|
||||
import React, { useState, useContext, useEffect } from "react";
|
||||
// import SocketContext from '../../../store/socket-data-provider';
|
||||
import icon1 from "../../../assets/CenterChart2icon1.svg";
|
||||
import icon2 from "../../../assets/CenterChart2icon2.svg";
|
||||
import icon3 from "../../../assets/CenterChart2icon3.svg";
|
||||
import icon4 from "../../../assets/CenterChart2icon4.svg";
|
||||
|
||||
import cls from "./leftbox.module.less";
|
||||
|
||||
const Chart2 = () => {
|
||||
// const ctx = useContext(SocketContext);
|
||||
const ctx = null;
|
||||
|
||||
let [time, setTime] = useState([0, 0]);
|
||||
|
||||
useEffect(() => {
|
||||
const restTime = ctx?.runState?.lastFireChangeTime;
|
||||
if (restTime == null) return;
|
||||
console.log("restTime is:", restTime);
|
||||
let timer = null;
|
||||
if (/分/.test(restTime) && /秒/.test(restTime)) {
|
||||
let [min, sec] = restTime.replace(/分/, ":").replace(/秒/, "").split(":");
|
||||
timer = setInterval(() => {
|
||||
if (Number(sec) === 0 && Number(min) === 0) {
|
||||
clearInterval(timer);
|
||||
return;
|
||||
}
|
||||
if (Number(sec) === 0) {
|
||||
sec = 59;
|
||||
min--;
|
||||
} else {
|
||||
sec--;
|
||||
}
|
||||
setTime([min, sec]);
|
||||
}, 1000);
|
||||
} else if (/分/.test(restTime)) {
|
||||
let sec,
|
||||
min = restTime.replace(/分/, ":");
|
||||
sec = 0;
|
||||
|
||||
timer = setInterval(() => {
|
||||
if (Number(sec) === 0 && Number(min) === 0) {
|
||||
clearInterval(timer);
|
||||
return;
|
||||
}
|
||||
if (Number(sec) === 0) {
|
||||
sec = 59;
|
||||
min--;
|
||||
} else {
|
||||
sec--;
|
||||
}
|
||||
setTime([min, sec]);
|
||||
}, 1000);
|
||||
} else if (/秒/.test(restTime)) {
|
||||
let min,
|
||||
sec = restTime.replace(/秒/, "");
|
||||
min = 0;
|
||||
|
||||
timer = setInterval(() => {
|
||||
if (Number(sec) === 0 && Number(min) === 0) {
|
||||
clearInterval(timer);
|
||||
return;
|
||||
}
|
||||
if (Number(sec) === 0) {
|
||||
sec = 59;
|
||||
min--;
|
||||
} else {
|
||||
sec--;
|
||||
}
|
||||
setTime([min, sec]);
|
||||
}, 1000);
|
||||
}
|
||||
return () => {
|
||||
clearInterval(timer);
|
||||
};
|
||||
}, [ctx?.runState?.lastFireChangeTime]);
|
||||
|
||||
const data = [
|
||||
{
|
||||
icon: icon1,
|
||||
label: "换火时间",
|
||||
value: ctx?.runState?.fireChangeTime || "00:00",
|
||||
},
|
||||
{
|
||||
icon: icon3,
|
||||
label: "剩余时间",
|
||||
value: `${time[0]}分${time[1]}秒`,
|
||||
},
|
||||
{
|
||||
icon: icon2,
|
||||
label: "当前火向",
|
||||
value: ctx?.runState?.fireDirection || "东火",
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div className={`${cls.leftbox} flex h-half`}>
|
||||
{data.map((item) => (
|
||||
<div className={cls.box} key={item.label}>
|
||||
<img src={item.icon} alt="Error" className="box__logo" />
|
||||
<div className={cls.box__inner}>
|
||||
<h2 className={cls.box__label}>{item.label}</h2>
|
||||
<h2 className={cls.box__value}> {item.value}</h2>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Chart2;
|
||||
33
src/components/公共组件/时间火向数据/leftbox.module.less
Normal file
33
src/components/公共组件/时间火向数据/leftbox.module.less
Normal file
@@ -0,0 +1,33 @@
|
||||
.leftbox {
|
||||
// width: 440px;
|
||||
// background: rgb(127, 202, 42);
|
||||
|
||||
.box {
|
||||
margin-right: 16px;
|
||||
width: 200px;
|
||||
padding: 8px;
|
||||
background: url(../../../assets/CenterChart2ItemBg.png);
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
user-select: none;
|
||||
|
||||
.box__inner {
|
||||
padding-top: 12px;
|
||||
|
||||
.box__label {
|
||||
color: #fffa;
|
||||
font-size: 18px;
|
||||
line-height: 14px;
|
||||
}
|
||||
|
||||
.box__value {
|
||||
color: #fff;
|
||||
font-weight: 400;
|
||||
font-size: 30px;
|
||||
line-height: 34px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
19
src/components/公共组件/本日生产良品率/GoodProduction.jsx
Normal file
19
src/components/公共组件/本日生产良品率/GoodProduction.jsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import cls from './good.module.less';
|
||||
import Container from '../../Container';
|
||||
import TodayTableData from './components/TodayTableData';
|
||||
import GoodRateChart from './components/GoodRateChart';
|
||||
import TechSplitline from '../TechSplitline';
|
||||
|
||||
const GoodProduction = () => {
|
||||
return (
|
||||
<Container icon="good" title="本日生产良品率" className={cls.goodProd}>
|
||||
<div className={`${cls.goodProd__content} h-full`}>
|
||||
<TodayTableData />
|
||||
<TechSplitline />
|
||||
<GoodRateChart />
|
||||
</div>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
export default GoodProduction;
|
||||
155
src/components/公共组件/本日生产良品率/components/GoodRateChart/index.jsx
Normal file
155
src/components/公共组件/本日生产良品率/components/GoodRateChart/index.jsx
Normal file
@@ -0,0 +1,155 @@
|
||||
import cls from './index.module.css';
|
||||
import './overwrite.css'; // 覆写 antd 默认样式,全局
|
||||
import ReactECharts from 'echarts-for-react';
|
||||
import * as echarts from 'echarts';
|
||||
import { Switch, Radio } from 'antd';
|
||||
import { randomInt } from '../../../../../utils';
|
||||
|
||||
const GoodRateChart = (props) => {
|
||||
const options = {
|
||||
color: ['#FFD160', '#12FFF5', '#2760FF'],
|
||||
grid: { top: 28, right: 12, bottom: 32, left: 48 },
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: Array(7)
|
||||
.fill(1)
|
||||
.map((_, index) => {
|
||||
const today = new Date();
|
||||
const dtimestamp = today - index * 24 * 60 * 60 * 1000;
|
||||
return `${new Date(dtimestamp).getMonth() + 1}.${new Date(
|
||||
dtimestamp,
|
||||
).getDate()}`;
|
||||
})
|
||||
.reverse(),
|
||||
axisLabel: {
|
||||
color: '#fff',
|
||||
fontSize: 12,
|
||||
},
|
||||
axisTick: { show: false },
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
width: 1,
|
||||
color: '#213259',
|
||||
},
|
||||
},
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
axisLabel: {
|
||||
color: '#fff',
|
||||
fontSize: 12,
|
||||
formatter: '{value} %',
|
||||
},
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: '#213259',
|
||||
},
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: '#213259a0',
|
||||
},
|
||||
},
|
||||
interval: 10,
|
||||
min: 0,
|
||||
max: 100,
|
||||
},
|
||||
series: [
|
||||
{
|
||||
data: Array(7)
|
||||
.fill(1)
|
||||
.map((_) => {
|
||||
return randomInt(60, 100);
|
||||
}),
|
||||
type: 'line',
|
||||
areaStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{ offset: 0, color: '#FFD16040' },
|
||||
{ offset: 0.5, color: '#FFD16020' },
|
||||
{ offset: 1, color: '#FFD16010' },
|
||||
]),
|
||||
},
|
||||
// smooth: true,
|
||||
},
|
||||
{
|
||||
data: Array(7)
|
||||
.fill(1)
|
||||
.map((_) => {
|
||||
return randomInt(60, 100);
|
||||
}),
|
||||
type: 'line',
|
||||
areaStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{ offset: 0, color: '#12FFF540' },
|
||||
{ offset: 0.5, color: '#12FFF520' },
|
||||
{ offset: 1, color: '#12FFF510' },
|
||||
]),
|
||||
},
|
||||
// smooth: true,
|
||||
},
|
||||
{
|
||||
data: Array(7)
|
||||
.fill(1)
|
||||
.map((_) => {
|
||||
return randomInt(60, 100);
|
||||
}),
|
||||
type: 'line',
|
||||
areaStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{ offset: 0, color: '#2760FF40' },
|
||||
{ offset: 0.5, color: '#2760FF20' },
|
||||
{ offset: 1, color: '#2760FF10' },
|
||||
]),
|
||||
},
|
||||
// smooth: true,
|
||||
},
|
||||
],
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
},
|
||||
};
|
||||
|
||||
function handleSwitchChange(val) {
|
||||
// val: boolean
|
||||
console.log('switch change', val);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={cls.GoodRateChart}>
|
||||
<div className={cls.titleBar}>
|
||||
<h2>生产良品率</h2>
|
||||
<Switch defaultChecked onChange={handleSwitchChange} />
|
||||
<div className={cls.legend}>
|
||||
<span className="legend__title">班次详情</span>
|
||||
<ul className="legend__list">
|
||||
<li>总量</li>
|
||||
<li>白班</li>
|
||||
<li>夜班</li>
|
||||
</ul>
|
||||
</div>
|
||||
<Radio.Group
|
||||
defaultValue="week"
|
||||
buttonStyle="solid"
|
||||
className={cls.radioGroup}
|
||||
>
|
||||
<Radio.Button value="day" className="radio-group__item">
|
||||
日
|
||||
</Radio.Button>
|
||||
<Radio.Button value="week" className="radio-group__item">
|
||||
周
|
||||
</Radio.Button>
|
||||
<Radio.Button value="month" className="radio-group__item">
|
||||
月
|
||||
</Radio.Button>
|
||||
<Radio.Button value="year" className="radio-group__item">
|
||||
年
|
||||
</Radio.Button>
|
||||
</Radio.Group>
|
||||
</div>
|
||||
<ReactECharts option={options} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default GoodRateChart;
|
||||
@@ -0,0 +1,86 @@
|
||||
.GoodRateChart {
|
||||
height: 1px;
|
||||
flex: 1;
|
||||
padding-top: 8px;
|
||||
/* background: #ae27276a; */
|
||||
}
|
||||
.GoodRateChart .titleBar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
color: white;
|
||||
}
|
||||
.GoodRateChart .titleBar h2 {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
line-height: 32px;
|
||||
letter-spacing: 1.2px;
|
||||
color: #52fff8;
|
||||
}
|
||||
|
||||
.GoodRateChart .titleBar .legend {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.GoodRateChart .titleBar .legend * {
|
||||
font-size: 14px;
|
||||
line-height: 14px;
|
||||
color: #dff1fe;
|
||||
}
|
||||
|
||||
.GoodRateChart .titleBar .legend ul {
|
||||
display: flex;
|
||||
margin: 0;
|
||||
margin-left: 8px;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
align-items: center;
|
||||
}
|
||||
.GoodRateChart .titleBar .legend ul li {
|
||||
position: relative;
|
||||
margin: 4px;
|
||||
padding-left: 16px;
|
||||
}
|
||||
.GoodRateChart .titleBar .legend ul li::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 2px;
|
||||
top: 2px;
|
||||
display: inline-block;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.GoodRateChart .titleBar .legend ul li:first-child::before {
|
||||
background-color: #ffd160;
|
||||
}
|
||||
|
||||
.GoodRateChart .titleBar .legend ul li:nth-child(2)::before {
|
||||
background-color: #12fff5;
|
||||
}
|
||||
|
||||
.GoodRateChart .titleBar .legend ul li:nth-child(3)::before {
|
||||
background-color: #2760ff;
|
||||
}
|
||||
|
||||
.radioGroup * {
|
||||
border: none !important;
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
.radioGroup *:focus-within {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.radioGroup *::before {
|
||||
width: 0 !important;
|
||||
}
|
||||
|
||||
.radioGroup_button_wrapper {
|
||||
color: #fff !important;
|
||||
background: #03233c !important;
|
||||
}
|
||||
|
||||
.radioGroup_button_wrapper.ant-radio-button-wrapper-checked {
|
||||
background: #02457e !important;
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
.GoodRateChart {
|
||||
height: 1px;
|
||||
flex: 1;
|
||||
padding-top: 8px;
|
||||
// background: #ae27276a;
|
||||
|
||||
.titleBar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
background: #0003;
|
||||
color: white;
|
||||
|
||||
h2 {
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
line-height: 32px;
|
||||
letter-spacing: 1.2px;
|
||||
color: #52fff8;
|
||||
}
|
||||
|
||||
.legend {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
* {
|
||||
font-size: 14px;
|
||||
line-height: 14px;
|
||||
color: #dff1fe;
|
||||
}
|
||||
|
||||
ul {
|
||||
display: flex;
|
||||
margin: 0;
|
||||
margin-left: 8px;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
align-items: center;
|
||||
|
||||
li {
|
||||
position: relative;
|
||||
margin: 4px;
|
||||
padding-left: 16px;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 2px;
|
||||
top: 2px;
|
||||
display: inline-block;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
&:first-child::before {
|
||||
background-color: #ffd160;
|
||||
}
|
||||
|
||||
&:nth-child(2)::before {
|
||||
background-color: #12fff5;
|
||||
}
|
||||
|
||||
&:nth-child(3)::before {
|
||||
background-color: #2760ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.radioGroup {
|
||||
* {
|
||||
border: none !important;
|
||||
border-radius: 0 !important;
|
||||
|
||||
&:focus-within {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
&::before {
|
||||
width: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.radioGroup_button_wrapper {
|
||||
color: #fff !important;
|
||||
background: #03233c !important;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
.radio-group__item {
|
||||
color: #fff !important;
|
||||
background: #03233c !important;
|
||||
}
|
||||
|
||||
.radio-group__item:first-child {
|
||||
border-top-left-radius: 4px !important;
|
||||
border-bottom-left-radius: 4px !important;
|
||||
}
|
||||
|
||||
.radio-group__item:last-child {
|
||||
border-top-right-radius: 4px !important;
|
||||
border-bottom-right-radius: 4px !important;
|
||||
}
|
||||
|
||||
.radio-group__item.ant-radio-button-wrapper-checked {
|
||||
background: #02457e !important;
|
||||
}
|
||||
|
||||
.ant-switch {
|
||||
background: #004782 !important;
|
||||
}
|
||||
.ant-switch .ant-switch-handle::before {
|
||||
background-color: #00233f !important;
|
||||
}
|
||||
.ant-switch-checked {
|
||||
background: #b4fffdb1 !important;
|
||||
}
|
||||
.ant-switch-checked:focus {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
.ant-switch-checked .ant-switch-handle::before {
|
||||
background-color: #76fff9 !important;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import { useState } from 'react';
|
||||
import cls from './index.module.less';
|
||||
// import { ScrollBoard } from '@jiaminghi/data-view-react';
|
||||
|
||||
const TodayTableData = (props) => {
|
||||
const [config, setConfig] = useState({
|
||||
// headerBGC: 'rgba(4, 44, 76, 0.3)',
|
||||
headerBGC: 'rgba(4, 44, 76, .8)',
|
||||
header: [
|
||||
'<span style="color:#fff">产线<span/>',
|
||||
'<span style="color:#fff">一等率<span/>',
|
||||
'<span style="color:#fff">二等率<span/>',
|
||||
'<span style="color:#fff">成品率<span/>',
|
||||
'<span style="color:#fff">废品率<span/>',
|
||||
],
|
||||
oddRowBGC: '#042444',
|
||||
evenRowBGC: '#042c4c',
|
||||
columnWidth: [90],
|
||||
headerHeight: 40,
|
||||
hoverPause: false,
|
||||
data: [
|
||||
['产线1', '37%', '62%', '97%', '7%'],
|
||||
['产线2', '95%', '10%', '99%', '3%'],
|
||||
['产线3', '68%', '1%', '92%', '4%'],
|
||||
['产线4', '94%', '21%', '97%', '2%'],
|
||||
['产线5', '99%', '30%', '95%', '5%'],
|
||||
],
|
||||
});
|
||||
return (
|
||||
<div className={cls.todayTableData}>
|
||||
{/* <ScrollBoard config={config} style={{ width: '100%' }} /> */}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TodayTableData;
|
||||
@@ -0,0 +1,5 @@
|
||||
.todayTableData {
|
||||
height: 240px;
|
||||
// flex: 1;
|
||||
padding-top: 12px;
|
||||
}
|
||||
14
src/components/公共组件/本日生产良品率/good.module.less
Normal file
14
src/components/公共组件/本日生产良品率/good.module.less
Normal file
@@ -0,0 +1,14 @@
|
||||
.goodProd {
|
||||
background: url(../../../assets/good.png) no-repeat;
|
||||
background-size: 100% 100%;
|
||||
width: 625px;
|
||||
// height: 626px;
|
||||
flex: 1;
|
||||
height: 1px;
|
||||
margin-top: 24px;
|
||||
|
||||
.goodProd__content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
183
src/components/公共组件/烟气处理/SmokeTrendChart/index.jsx
Normal file
183
src/components/公共组件/烟气处理/SmokeTrendChart/index.jsx
Normal file
@@ -0,0 +1,183 @@
|
||||
import cls from './index.module.css';
|
||||
import { randomInt } from '../../../../utils';
|
||||
|
||||
import * as echarts from 'echarts';
|
||||
import { Switch, Radio } from 'antd';
|
||||
import ReactECharts from 'echarts-for-react';
|
||||
|
||||
const SmokeTrendChart = (props) => {
|
||||
const options = {
|
||||
color: ['#FFD160', '#12FFF5', '#2760FF'],
|
||||
grid: { top: 38, right: 12, bottom: 20, left: 48 },
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: Array(7)
|
||||
.fill(1)
|
||||
.map((_, index) => {
|
||||
const today = new Date();
|
||||
const dtimestamp = today - index * 24 * 60 * 60 * 1000;
|
||||
return `${new Date(dtimestamp).getMonth() + 1}.${new Date(
|
||||
dtimestamp,
|
||||
).getDate()}`;
|
||||
})
|
||||
.reverse(),
|
||||
axisLabel: {
|
||||
color: '#fff',
|
||||
fontSize: 12,
|
||||
},
|
||||
axisTick: { show: false },
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
width: 1,
|
||||
color: '#213259',
|
||||
},
|
||||
},
|
||||
},
|
||||
yAxis: {
|
||||
name: '单位m³/h',
|
||||
nameTextStyle: {
|
||||
color: '#fff',
|
||||
fontSize: 10,
|
||||
align: 'right',
|
||||
},
|
||||
type: 'value',
|
||||
axisLabel: {
|
||||
color: '#fff',
|
||||
fontSize: 12,
|
||||
formatter: '{value} %',
|
||||
},
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: '#213259',
|
||||
},
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: '#213259a0',
|
||||
},
|
||||
},
|
||||
interval: 10,
|
||||
min: 0,
|
||||
max: 100,
|
||||
},
|
||||
series: [
|
||||
{
|
||||
data: Array(7)
|
||||
.fill(1)
|
||||
.map((_) => {
|
||||
return randomInt(60, 100);
|
||||
}),
|
||||
type: 'line',
|
||||
areaStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{ offset: 0, color: '#FFD16040' },
|
||||
{ offset: 0.5, color: '#FFD16020' },
|
||||
{ offset: 1, color: '#FFD16010' },
|
||||
]),
|
||||
},
|
||||
// smooth: true,
|
||||
},
|
||||
{
|
||||
data: Array(7)
|
||||
.fill(1)
|
||||
.map((_) => {
|
||||
return randomInt(60, 100);
|
||||
}),
|
||||
type: 'line',
|
||||
areaStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{ offset: 0, color: '#12FFF540' },
|
||||
{ offset: 0.5, color: '#12FFF520' },
|
||||
{ offset: 1, color: '#12FFF510' },
|
||||
]),
|
||||
},
|
||||
// smooth: true,
|
||||
},
|
||||
{
|
||||
data: Array(7)
|
||||
.fill(1)
|
||||
.map((_) => {
|
||||
return randomInt(60, 100);
|
||||
}),
|
||||
type: 'line',
|
||||
areaStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{ offset: 0, color: '#2760FF40' },
|
||||
{ offset: 0.5, color: '#2760FF20' },
|
||||
{ offset: 1, color: '#2760FF10' },
|
||||
]),
|
||||
},
|
||||
// smooth: true,
|
||||
},
|
||||
],
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
},
|
||||
};
|
||||
|
||||
function handleSwitchChange(val) {
|
||||
// val: boolean
|
||||
console.log('switch change', val);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={cls.energyCostChart}>
|
||||
<div className={cls.titleBar}>
|
||||
<h2>烟气趋势图</h2>
|
||||
<Switch defaultChecked onChange={handleSwitchChange} />
|
||||
<div className={cls.legend}>
|
||||
<span className="legend__title">班次详情</span>
|
||||
<ul className="legend__list">
|
||||
<li>总量</li>
|
||||
<li>白班</li>
|
||||
<li>夜班</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={`${cls.choiceBar} flex items-center justify-between`}>
|
||||
<Radio.Group
|
||||
defaultValue="oxygen"
|
||||
buttonStyle="solid"
|
||||
className={`${cls.radioGroup} flex items-center justify-between`}
|
||||
>
|
||||
<Radio.Button value="oxygen" className="radio-group__item">
|
||||
氧气含量
|
||||
</Radio.Button>
|
||||
<Radio.Button value="so2" className="radio-group__item">
|
||||
二氧化硫
|
||||
</Radio.Button>
|
||||
<Radio.Button value="no" className="radio-group__item">
|
||||
一氧化氮
|
||||
</Radio.Button>
|
||||
<Radio.Button value="no2" className="radio-group__item">
|
||||
二氧化氮
|
||||
</Radio.Button>
|
||||
</Radio.Group>
|
||||
|
||||
<Radio.Group
|
||||
defaultValue="week"
|
||||
buttonStyle="solid"
|
||||
className={cls.radioGroup}
|
||||
>
|
||||
<Radio.Button value="day" className="radio-group__item">
|
||||
日
|
||||
</Radio.Button>
|
||||
<Radio.Button value="week" className="radio-group__item">
|
||||
周
|
||||
</Radio.Button>
|
||||
<Radio.Button value="month" className="radio-group__item">
|
||||
月
|
||||
</Radio.Button>
|
||||
<Radio.Button value="year" className="radio-group__item">
|
||||
年
|
||||
</Radio.Button>
|
||||
</Radio.Group>
|
||||
</div>
|
||||
<ReactECharts option={options} style={{ height: '240px' }} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SmokeTrendChart;
|
||||
91
src/components/公共组件/烟气处理/SmokeTrendChart/index.module.css
Normal file
91
src/components/公共组件/烟气处理/SmokeTrendChart/index.module.css
Normal file
@@ -0,0 +1,91 @@
|
||||
.energyCostChart {
|
||||
height: 1px;
|
||||
flex: 1;
|
||||
padding-top: 8px;
|
||||
}
|
||||
.energyCostChart .titleBar {
|
||||
width: 400px;
|
||||
margin-bottom: 4px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
color: white;
|
||||
}
|
||||
.energyCostChart .titleBar h2 {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
line-height: 32px;
|
||||
letter-spacing: 1.2px;
|
||||
color: #52fff8;
|
||||
}
|
||||
|
||||
.energyCostChart .titleBar .legend {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.energyCostChart .titleBar .legend * {
|
||||
font-size: 14px;
|
||||
line-height: 14px;
|
||||
color: #dff1fe;
|
||||
}
|
||||
|
||||
.energyCostChart .titleBar .legend ul {
|
||||
display: flex;
|
||||
margin: 0;
|
||||
margin-left: 8px;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
align-items: center;
|
||||
}
|
||||
.energyCostChart .titleBar .legend ul li {
|
||||
position: relative;
|
||||
margin: 4px;
|
||||
padding-left: 16px;
|
||||
}
|
||||
.energyCostChart .titleBar .legend ul li::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 2px;
|
||||
top: 2px;
|
||||
display: inline-block;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.energyCostChart .titleBar .legend ul li:first-child::before {
|
||||
background-color: #ffd160;
|
||||
}
|
||||
|
||||
.energyCostChart .titleBar .legend ul li:nth-child(2)::before {
|
||||
background-color: #12fff5;
|
||||
}
|
||||
|
||||
.energyCostChart .titleBar .legend ul li:nth-child(3)::before {
|
||||
background-color: #2760ff;
|
||||
}
|
||||
|
||||
.choiceBar {
|
||||
margin: 4px 0;
|
||||
}
|
||||
|
||||
.radioGroup * {
|
||||
border: none !important;
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
.radioGroup *:focus-within {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.radioGroup *::before {
|
||||
width: 0 !important;
|
||||
}
|
||||
|
||||
.radioGroup_button_wrapper {
|
||||
color: #fff !important;
|
||||
background: #03233c !important;
|
||||
}
|
||||
|
||||
.radioGroup_button_wrapper.ant-radio-button-wrapper-checked {
|
||||
background: #02457e !important;
|
||||
}
|
||||
23
src/components/公共组件/烟气处理/index.jsx
Normal file
23
src/components/公共组件/烟气处理/index.jsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import cls from './index.module.less';
|
||||
import Container from '../../Container';
|
||||
import TechSplitline from '../TechSplitline';
|
||||
import SmokeTrendChart from './SmokeTrendChart';
|
||||
|
||||
function SmokeHandle(props) {
|
||||
return (
|
||||
<Container title="烟气处理" icon="smoke" className={cls.smokeHandle}>
|
||||
<div className={`${cls.smokeHandle__content} flex flex-col`}>
|
||||
<div className={cls.info__item_groups}>
|
||||
<div className={cls.info__item}>氧 气 含 量 : 72%</div>
|
||||
<div className={cls.info__item}>一氧化氮排放浓度:59mg/m³</div>
|
||||
<div className={cls.info__item}>二氧化硫排放浓度:59mg/m³</div>
|
||||
<div className={cls.info__item}>二氧化氮排放浓度:59mg/m³</div>
|
||||
</div>
|
||||
<TechSplitline />
|
||||
<SmokeTrendChart />
|
||||
</div>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
export default SmokeHandle;
|
||||
31
src/components/公共组件/烟气处理/index.module.less
Normal file
31
src/components/公共组件/烟气处理/index.module.less
Normal file
@@ -0,0 +1,31 @@
|
||||
.smokeHandle {
|
||||
// background: #b730305c;
|
||||
background: url(../../../assets/smoke.png) no-repeat;
|
||||
background-size: 100% 100%;
|
||||
width: 626px;
|
||||
height: 540px;
|
||||
.smokeHandle__content {
|
||||
margin-top: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.info__item {
|
||||
border-radius: 2px;
|
||||
color: hsl(0, 0%, 100%, 0.9);
|
||||
box-shadow: inset 0 0 17px 0px hsla(0, 0%, 100%, 0.15);
|
||||
// width: 288px;
|
||||
height: 56px;
|
||||
font-size: 20px;
|
||||
letter-spacing: 1.43px;
|
||||
line-height: 56px;
|
||||
text-align: center;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.info__item_groups {
|
||||
margin-bottom: 12px;
|
||||
margin-left: 8px;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 8px;
|
||||
}
|
||||
37
src/components/公共组件/窑炉信息/Kiln.jsx
Normal file
37
src/components/公共组件/窑炉信息/Kiln.jsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import React from "react";
|
||||
import { useContext } from "react";
|
||||
import Container from "../../Container";
|
||||
// import SocketContext from '../../../store/socket-data-provider';
|
||||
|
||||
import cls from "./kiln.module.less";
|
||||
|
||||
export default function Kiln() {
|
||||
// const ctx = useContext(SocketContext);
|
||||
const ctx = null;
|
||||
|
||||
const infos = [
|
||||
{ label: "窑炉压力", value: ctx?.runState?.kilnPressure || "0Pa" },
|
||||
{ label: "循环水温度", value: ctx?.runState?.waterTemp || "0℃" },
|
||||
{ label: "循环水流量", value: ctx?.runState?.waterFlow || "0㎡/h" },
|
||||
{ label: "循环水压力", value: ctx?.runState?.waterPressure || "0Pa" },
|
||||
{ label: "助燃风压力", value: ctx?.runState?.combustionAirPressure || "0℃" },
|
||||
{ label: "碹顶加权温度", value: ctx?.runState?.topTemp || "0℃" },
|
||||
{
|
||||
label: "压缩气压力",
|
||||
value: ctx?.runState?.compressedAirPressure || "0Pa",
|
||||
},
|
||||
{ label: "融化加权温度", value: ctx?.runState?.meltTemp || "0℃" },
|
||||
];
|
||||
|
||||
return (
|
||||
<Container title="窑炉信息" icon="kiln" className={cls.leftBar__top}>
|
||||
<div className={cls.leftBar__top__content}>
|
||||
{infos.map((item) => (
|
||||
<div key={item.label} className={cls.info__item}>
|
||||
{item.label}: {item.value}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
29
src/components/公共组件/窑炉信息/kiln.module.less
Normal file
29
src/components/公共组件/窑炉信息/kiln.module.less
Normal file
@@ -0,0 +1,29 @@
|
||||
.leftBar__top {
|
||||
width: 625px;
|
||||
// height: 305px;
|
||||
height: 300px;
|
||||
background: url('../../../assets/ItemBg.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
|
||||
.leftBar__top__content {
|
||||
flex: 1;
|
||||
height: 1px;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 10px;
|
||||
padding-top: 18px;
|
||||
|
||||
.info__item {
|
||||
border-radius: 2px;
|
||||
color: hsl(0, 0%, 100%, 0.9);
|
||||
box-shadow: inset 0 0 17px 0px hsla(0, 0%, 100%, 0.15);
|
||||
// width: 288px;
|
||||
height: 43px;
|
||||
font-size: 20px;
|
||||
letter-spacing: 1.43px;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
user-select: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
128
src/components/公共组件/能耗/EnergyCostChart/index.jsx
Normal file
128
src/components/公共组件/能耗/EnergyCostChart/index.jsx
Normal file
@@ -0,0 +1,128 @@
|
||||
import cls from './index.module.css';
|
||||
import { randomInt } from '../../../../utils';
|
||||
import * as echarts from 'echarts';
|
||||
import { Switch, Radio } from 'antd';
|
||||
import ReactECharts from 'echarts-for-react';
|
||||
|
||||
const EnergyCostChart = (props) => {
|
||||
const options = {
|
||||
color: ['#FFD160', '#12FFF5', '#2760FF'],
|
||||
grid: { top: 32, right: 12, bottom: 20, left: 48 },
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: Array(7)
|
||||
.fill(1)
|
||||
.map((_, index) => {
|
||||
const today = new Date();
|
||||
const dtimestamp = today - index * 24 * 60 * 60 * 1000;
|
||||
return `${new Date(dtimestamp).getMonth() + 1}.${new Date(
|
||||
dtimestamp,
|
||||
).getDate()}`;
|
||||
})
|
||||
.reverse(),
|
||||
axisLabel: {
|
||||
color: '#fff',
|
||||
fontSize: 12,
|
||||
},
|
||||
axisTick: { show: false },
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
width: 1,
|
||||
color: '#213259',
|
||||
},
|
||||
},
|
||||
},
|
||||
yAxis: {
|
||||
name: '单位/m³',
|
||||
nameTextStyle: {
|
||||
color: '#fff',
|
||||
fontSize: 10,
|
||||
align: 'right',
|
||||
},
|
||||
type: 'value',
|
||||
axisLabel: {
|
||||
color: '#fff',
|
||||
fontSize: 12,
|
||||
formatter: '{value} %',
|
||||
},
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: '#213259',
|
||||
},
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: '#213259a0',
|
||||
},
|
||||
},
|
||||
interval: 10,
|
||||
min: 0,
|
||||
max: 100,
|
||||
},
|
||||
series: [
|
||||
{
|
||||
data: Array(7)
|
||||
.fill(1)
|
||||
.map((_) => {
|
||||
return randomInt(60, 100);
|
||||
}),
|
||||
type: 'line',
|
||||
areaStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{ offset: 0, color: '#FFD16040' },
|
||||
{ offset: 0.5, color: '#FFD16020' },
|
||||
{ offset: 1, color: '#FFD16010' },
|
||||
]),
|
||||
},
|
||||
// smooth: true,
|
||||
},
|
||||
],
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
},
|
||||
};
|
||||
|
||||
function handleSwitchChange(val) {
|
||||
// val: boolean
|
||||
console.log('switch change', val);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={cls.energyCostChart}>
|
||||
<div className={cls.titleBar}>
|
||||
<h2>能耗趋势图</h2>
|
||||
<Switch defaultChecked onChange={handleSwitchChange} />
|
||||
<div className={cls.legend}>
|
||||
<span className="legend__title">班次详情</span>
|
||||
<ul className="legend__list">
|
||||
<li>总量</li>
|
||||
</ul>
|
||||
</div>
|
||||
<Radio.Group
|
||||
defaultValue="week"
|
||||
buttonStyle="solid"
|
||||
className={cls.radioGroup}
|
||||
>
|
||||
<Radio.Button value="day" className="radio-group__item">
|
||||
日
|
||||
</Radio.Button>
|
||||
<Radio.Button value="week" className="radio-group__item">
|
||||
周
|
||||
</Radio.Button>
|
||||
<Radio.Button value="month" className="radio-group__item">
|
||||
月
|
||||
</Radio.Button>
|
||||
<Radio.Button value="year" className="radio-group__item">
|
||||
年
|
||||
</Radio.Button>
|
||||
</Radio.Group>
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<ReactECharts option={options} style={{ height: '180px' }} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default EnergyCostChart;
|
||||
85
src/components/公共组件/能耗/EnergyCostChart/index.module.css
Normal file
85
src/components/公共组件/能耗/EnergyCostChart/index.module.css
Normal file
@@ -0,0 +1,85 @@
|
||||
.energyCostChart {
|
||||
height: 1px;
|
||||
flex: 1;
|
||||
padding-top: 8px;
|
||||
}
|
||||
.energyCostChart .titleBar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
color: white;
|
||||
}
|
||||
.energyCostChart .titleBar h2 {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
line-height: 32px;
|
||||
letter-spacing: 1.2px;
|
||||
color: #52fff8;
|
||||
}
|
||||
|
||||
.energyCostChart .titleBar .legend {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.energyCostChart .titleBar .legend * {
|
||||
font-size: 14px;
|
||||
line-height: 14px;
|
||||
color: #dff1fe;
|
||||
}
|
||||
|
||||
.energyCostChart .titleBar .legend ul {
|
||||
display: flex;
|
||||
margin: 0;
|
||||
margin-left: 8px;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
align-items: center;
|
||||
}
|
||||
.energyCostChart .titleBar .legend ul li {
|
||||
position: relative;
|
||||
margin: 4px;
|
||||
padding-left: 16px;
|
||||
}
|
||||
.energyCostChart .titleBar .legend ul li::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 2px;
|
||||
top: 2px;
|
||||
display: inline-block;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.energyCostChart .titleBar .legend ul li:first-child::before {
|
||||
background-color: #ffd160;
|
||||
}
|
||||
|
||||
.energyCostChart .titleBar .legend ul li:nth-child(2)::before {
|
||||
background-color: #12fff5;
|
||||
}
|
||||
|
||||
.energyCostChart .titleBar .legend ul li:nth-child(3)::before {
|
||||
background-color: #2760ff;
|
||||
}
|
||||
|
||||
.radioGroup * {
|
||||
border: none !important;
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
.radioGroup *:focus-within {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.radioGroup *::before {
|
||||
width: 0 !important;
|
||||
}
|
||||
|
||||
.radioGroup_button_wrapper {
|
||||
color: #fff !important;
|
||||
background: #03233c !important;
|
||||
}
|
||||
|
||||
.radioGroup_button_wrapper.ant-radio-button-wrapper-checked {
|
||||
background: #02457e !important;
|
||||
}
|
||||
33
src/components/公共组件/能耗/index.jsx
Normal file
33
src/components/公共组件/能耗/index.jsx
Normal file
@@ -0,0 +1,33 @@
|
||||
import cls from './index.module.less';
|
||||
import Container from '../../Container';
|
||||
import TechSplitline from '../TechSplitline';
|
||||
import EnergyCostChart from './EnergyCostChart';
|
||||
|
||||
function EnergyCost(props) {
|
||||
return (
|
||||
<Container title="能耗" icon="charger" className={cls.energyCost}>
|
||||
<div className={`flex flex-col`}>
|
||||
<div className={`${cls.cost__info} flex`}>
|
||||
<div
|
||||
className={`${cls.info__item} ${cls.hAuto} flex flex-col justify-center items-center self-stretch`}
|
||||
>
|
||||
<span>余 热 发 电</span>
|
||||
<span>922kWh</span>
|
||||
</div>
|
||||
<div className={cls.info__item_groups}>
|
||||
<div className={cls.info__item}>水 耗 量 : 32Km³</div>
|
||||
<div className={cls.info__item}>天 然 气 I : 83m³</div>
|
||||
<div className={cls.info__item}>电 耗 量 : 52kWh</div>
|
||||
<div className={cls.info__item}>天 然 气 II: 32m³</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<TechSplitline />
|
||||
|
||||
<EnergyCostChart />
|
||||
</div>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
export default EnergyCost;
|
||||
39
src/components/公共组件/能耗/index.module.less
Normal file
39
src/components/公共组件/能耗/index.module.less
Normal file
@@ -0,0 +1,39 @@
|
||||
.energyCost {
|
||||
background: url(../../../assets/energy.png) no-repeat;
|
||||
background-size: 100% 100%;
|
||||
width: 626px;
|
||||
height: 400px;
|
||||
}
|
||||
|
||||
.cost__info {
|
||||
margin-top: 4px;
|
||||
margin-bottom: 12px;
|
||||
|
||||
div {
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.info__item {
|
||||
border-radius: 2px;
|
||||
color: hsl(0, 0%, 100%, 0.9);
|
||||
box-shadow: inset 0 0 17px 0px hsla(0, 0%, 100%, 0.15);
|
||||
// width: 288px;
|
||||
height: 43px;
|
||||
font-size: 20px;
|
||||
letter-spacing: 1.43px;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.hAuto {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.info__item_groups {
|
||||
margin-left: 8px;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 8px;
|
||||
}
|
||||
50
src/components/公共组件/顶部公司名称/index.jsx
Normal file
50
src/components/公共组件/顶部公司名称/index.jsx
Normal file
@@ -0,0 +1,50 @@
|
||||
import React, { useEffect, useState, useRef } from 'react';
|
||||
|
||||
import TopSide from '../../../assets/TopSide.png';
|
||||
import LeftLine from '../../../assets/TopTitleLeftIcon.png';
|
||||
import RightLine from '../../../assets/TopTitleRightIcon.png';
|
||||
import ButtonLine from '../../../assets/TopButtonLine.png';
|
||||
import './index.less';
|
||||
|
||||
export default function CompanyName() {
|
||||
const [now, setNow] = useState('2023.07.01 12:00:00');
|
||||
|
||||
useEffect(() => {
|
||||
setInterval(() => {
|
||||
const now = new Date();
|
||||
setNow(
|
||||
now
|
||||
.toLocaleDateString('zh-hans', {
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
second: '2-digit',
|
||||
})
|
||||
.replaceAll('/', '.'),
|
||||
);
|
||||
}, 1000);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="TopTitleBoder">
|
||||
<img src={TopSide} alt="图片丢失" className="TopSideLeft" />
|
||||
<div className="TopSideLeftLine">
|
||||
<img src={LeftLine} alt="图片丢失" className="TopSideLeftLineicon" />
|
||||
<h2 className="TopSideLeftTxt">单位:河南汇融科技服务有限公司</h2>
|
||||
</div>
|
||||
<div>
|
||||
<h2 className="TopTitleText">
|
||||
许昌安彩新能科技  4800万方光伏轻质基板生产线{' '}
|
||||
</h2>
|
||||
<img src={ButtonLine} alt="图片加载错误" className="TopButtonLine" />
|
||||
</div>
|
||||
<div className="TopSideRightLine">
|
||||
<h2 className="TopSideRightTxt">{now}</h2>
|
||||
<img src={RightLine} alt="图片丢失" className="TopSideRightLineicon" />
|
||||
</div>
|
||||
<img src={TopSide} alt="图片丢失" className="TopSideRight" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
88
src/components/公共组件/顶部公司名称/index.less
Normal file
88
src/components/公共组件/顶部公司名称/index.less
Normal file
@@ -0,0 +1,88 @@
|
||||
.TopTitleBoder {
|
||||
width: 3840px;
|
||||
height: 84px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
|
||||
.TopSideRight {
|
||||
margin-top: 40px;
|
||||
margin-right: 40px;
|
||||
width: 493px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.TopSideLeft {
|
||||
margin-left: 40px;
|
||||
margin-top: 40px;
|
||||
width: 493px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.TopSideLeftLine {
|
||||
background: url('../../../assets/TopTitleLeft.png');
|
||||
width: 899px;
|
||||
height: 40px;
|
||||
margin-top: 42px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: right;
|
||||
|
||||
.TopSideLeftLineicon {
|
||||
margin-right: 40px;
|
||||
margin-top: 25px;
|
||||
width: 204.32px;
|
||||
height: 2.79px;
|
||||
}
|
||||
|
||||
.TopSideLeftTxt {
|
||||
margin-right: 120px;
|
||||
margin-top: 15px;
|
||||
color: rgb(255, 255, 255, 0.8);
|
||||
font-size: 20px;
|
||||
font-weight: 300px;
|
||||
line-height: 22.174976px;
|
||||
}
|
||||
}
|
||||
|
||||
.TopSiderightLine {
|
||||
background: url('../../../assets/TopTitleRight.png');
|
||||
width: 899px;
|
||||
height: 40px;
|
||||
margin-top: 42px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: left;
|
||||
|
||||
.TopSideRightLineicon {
|
||||
margin-left: 40px;
|
||||
margin-top: 25px;
|
||||
width: 204.32px;
|
||||
height: 2.79px;
|
||||
}
|
||||
|
||||
.TopSideRightTxt {
|
||||
margin-left: 120px;
|
||||
margin-top: 15px;
|
||||
color: rgb(255, 255, 255, 0.8);
|
||||
font-size: 20px;
|
||||
font-weight: 600px;
|
||||
line-height: 22.174976px;
|
||||
}
|
||||
}
|
||||
|
||||
.TopButtonLine {
|
||||
margin-top: -9px;
|
||||
width: 760px;
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
.TopTitleText {
|
||||
margin-top: 16px;
|
||||
letter-spacing: 8px;
|
||||
font-size: 32px;
|
||||
color: #00fff7;
|
||||
text-align: center;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
}
|
||||
115
src/components/公共组件/风机信息/index.jsx
Normal file
115
src/components/公共组件/风机信息/index.jsx
Normal file
@@ -0,0 +1,115 @@
|
||||
import GraphBase from "../../公共组件/GraphBase";
|
||||
import "./index.module.less";
|
||||
|
||||
// import { ScrollBoard } from '@jiaminghi/data-view-react';
|
||||
|
||||
function getRandomRow() {
|
||||
const idx = Math.ceil(Math.random() * 100);
|
||||
return [idx, `${idx}#风机`, Math.ceil(Math.random() * 2) - 1];
|
||||
}
|
||||
|
||||
function getRandomRows(rows) {
|
||||
return Array(rows)
|
||||
.fill(0)
|
||||
.map(() => getRandomRow());
|
||||
}
|
||||
|
||||
// let data = [
|
||||
// [1, '1#风机', 1], // 1 正常 2 故障 0 离线
|
||||
// [2, '2#风机', 1],
|
||||
// [3, '3#风机', 1],
|
||||
// [4, '4#风机', 0],
|
||||
// [5, '5#风机', 1],
|
||||
// [6, '6#风机', 1],
|
||||
// [7, '7#风机', 0],
|
||||
// [8, '8#风机', 1],
|
||||
// [9, '9#风机', 1],
|
||||
// [10, '10#风机', 1],
|
||||
// ];
|
||||
|
||||
// let header = ['序号', '风机名称', '故障情况'];
|
||||
|
||||
function attachStyle(data) {
|
||||
return data.map((arr) => {
|
||||
return arr.map((item, index) => {
|
||||
if (index == arr.length - 1) {
|
||||
return `<div style="display: flex; align-items: center">
|
||||
<span style="box-shadow: 0 0 4px 4px ${
|
||||
item == 1 ? "#2760ff55" : "#a81b2655"
|
||||
}; margin-right: 8px; width: 8px; height: 8px; border-radius: 8px; background: ${
|
||||
item == 1 ? "#2760ff" : "#a81b26"
|
||||
}"></span><span style="color: ${item == 1 ? "#2760ff" : "#a81b26"}">${
|
||||
item == 1 ? "正常" : "故障"
|
||||
}</span></div>`;
|
||||
}
|
||||
return `<span style='color: #fffa'>${item}</span>`;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function FanInfo(props) {
|
||||
const rowNum = props.rows || 8;
|
||||
let data = getRandomRows(100);
|
||||
|
||||
let config = {
|
||||
headerBGC: "rgba(4, 44, 76, 0.3)",
|
||||
header: [
|
||||
'<span style="color:#fff">序号<span/>',
|
||||
'<span style="color:#fff">风机名称<span/>',
|
||||
'<span style="color:#fff">故障情况<span/>',
|
||||
],
|
||||
oddRowBGC: "#042444",
|
||||
evenRowBGC: "#042c4c",
|
||||
columnWidth: [70, 96],
|
||||
rowNum,
|
||||
// headerHeight: 40,
|
||||
hoverPause: false,
|
||||
// data: replaceStyle(data, 0.7),
|
||||
data: attachStyle(data),
|
||||
};
|
||||
|
||||
return (
|
||||
<GraphBase
|
||||
icon="kiln"
|
||||
title="风机信息"
|
||||
size={props.longBg ? ["middle", "full"] : ["middle", "short"]}
|
||||
>
|
||||
<div
|
||||
className="flex"
|
||||
style={{
|
||||
display: "flex",
|
||||
gap: "20px",
|
||||
height: "100%",
|
||||
position: "relative",
|
||||
}}
|
||||
>
|
||||
<div className="flex-1" style={{ flex: 1 }}>
|
||||
{/* <ScrollBoard
|
||||
config={config}
|
||||
style={{ width: "280px", height: "100%" }}
|
||||
/> */}
|
||||
</div>
|
||||
<div
|
||||
className="verticalLine"
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: "10%",
|
||||
left: "50%",
|
||||
height: "80%",
|
||||
width: "2px",
|
||||
background:
|
||||
"linear-gradient(transparent, #15E8F563, #15E8F599, #15E8F563, transparent)",
|
||||
}}
|
||||
></div>
|
||||
<div className="flex-1" style={{ flex: 1 }}>
|
||||
{/* <ScrollBoard
|
||||
config={config}
|
||||
style={{ width: '280px', height: '100%' }}
|
||||
/> */}
|
||||
</div>
|
||||
</div>
|
||||
</GraphBase>
|
||||
);
|
||||
}
|
||||
|
||||
export default FanInfo;
|
||||
50
src/components/公共组件/风机信息/index.module.less
Normal file
50
src/components/公共组件/风机信息/index.module.less
Normal file
@@ -0,0 +1,50 @@
|
||||
.CenterChart1itemDetailBorder {
|
||||
width: 100%;
|
||||
height: 240px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
|
||||
background-color: rgba(4, 44, 76, 0.2);
|
||||
.CenterChart1itemTXT {
|
||||
width: 100%;
|
||||
height: 10%;
|
||||
font-size: 20px;
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
text-align: center;
|
||||
margin-top: 2%;
|
||||
}
|
||||
.CenterChart1itemContainer {
|
||||
width: 95%;
|
||||
height: 100px;
|
||||
position: relative;
|
||||
|
||||
.CenterFormitemDetailBorderLine1 {
|
||||
width: 1px;
|
||||
height: 200px;
|
||||
background-color: #041c2c;
|
||||
float: left;
|
||||
margin-left: 18%;
|
||||
z-index: 10;
|
||||
position: absolute;
|
||||
}
|
||||
.CenterFormitemDetailBorderLine2 {
|
||||
width: 1px;
|
||||
height: 200px;
|
||||
background-color: #041c2c;
|
||||
float: left;
|
||||
margin-left: 46%;
|
||||
z-index: 10;
|
||||
position: absolute;
|
||||
}
|
||||
.CenterFormitemDetailBorderLine3 {
|
||||
width: 1px;
|
||||
height: 200px;
|
||||
background-color: #041c2c;
|
||||
float: left;
|
||||
margin-left: 72%;
|
||||
z-index: 10;
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
}
|
||||
194
src/components/公共组件/风机运行频率/index.jsx
Normal file
194
src/components/公共组件/风机运行频率/index.jsx
Normal file
@@ -0,0 +1,194 @@
|
||||
// 风机运行频率
|
||||
import cls from "./index.module.css";
|
||||
import ReactECharts from "echarts-for-react";
|
||||
import * as echarts from "echarts";
|
||||
import { Switch } from "antd";
|
||||
import GraphBase from "../../公共组件/GraphBase";
|
||||
import { useState, useContext } from "react";
|
||||
// import SocketContext from '../../../store/socket-data-provider';
|
||||
|
||||
function WindFrequence(props) {
|
||||
const [showChart, setShowChart] = useState(true);
|
||||
// const { runState, hisState } = useContext(SocketContext);
|
||||
|
||||
const runState = null;
|
||||
const hisState = null;
|
||||
|
||||
let dataList = [];
|
||||
let seriesData = [];
|
||||
const colors = [
|
||||
"#12FFF5",
|
||||
"#2760FF",
|
||||
"#FFD160",
|
||||
"#E80091",
|
||||
"#8064ff",
|
||||
"#ff8a3b",
|
||||
"#8cd26d",
|
||||
"#2aa1ff",
|
||||
];
|
||||
let options = null;
|
||||
if (showChart) {
|
||||
// keys() 结果不是按照顺序,需要 sort()
|
||||
seriesData = hisState?.combustionAir
|
||||
? Object.keys(hisState.combustionAir)
|
||||
.sort()
|
||||
.map((key) => hisState.combustionAir[key])
|
||||
: Array(8)
|
||||
.fill(1)
|
||||
.map((_) => Array(7).fill(0));
|
||||
|
||||
// debug
|
||||
console.log(
|
||||
"助燃风 chart series data",
|
||||
hisState?.combustionAir,
|
||||
seriesData
|
||||
);
|
||||
options = {
|
||||
color: colors,
|
||||
grid: { top: 32, right: 12, bottom: 20, left: 48 },
|
||||
xAxis: {
|
||||
type: "category",
|
||||
data: Array(7)
|
||||
.fill(1)
|
||||
.map((_, index) => {
|
||||
const today = new Date();
|
||||
const dtimestamp = today - index * 24 * 60 * 60 * 1000;
|
||||
return `${new Date(dtimestamp).getMonth() + 1}.${new Date(
|
||||
dtimestamp
|
||||
).getDate()}`;
|
||||
})
|
||||
.reverse(),
|
||||
axisLabel: {
|
||||
color: "#fff",
|
||||
fontSize: 12,
|
||||
},
|
||||
axisTick: { show: false },
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
width: 1,
|
||||
color: "#213259",
|
||||
},
|
||||
},
|
||||
},
|
||||
yAxis: {
|
||||
name: "单位/m³",
|
||||
nameTextStyle: {
|
||||
color: "#fff",
|
||||
fontSize: 10,
|
||||
align: "right",
|
||||
},
|
||||
type: "value",
|
||||
axisLabel: {
|
||||
color: "#fff",
|
||||
fontSize: 12,
|
||||
},
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: "#213259",
|
||||
},
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: "#213259a0",
|
||||
},
|
||||
},
|
||||
// interval: 10,
|
||||
// min: 0,
|
||||
// max: 100,
|
||||
},
|
||||
series: seriesData.map((v, i) => ({
|
||||
name: i + 1 + "#风机",
|
||||
data: v,
|
||||
type: "line",
|
||||
symbol: "circle",
|
||||
areaStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{ offset: 0, color: colors[i] + "40" },
|
||||
{ offset: 0.5, color: colors[i] + "20" },
|
||||
{ offset: 1, color: colors[i] + "00" },
|
||||
]),
|
||||
},
|
||||
})),
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
},
|
||||
};
|
||||
} else {
|
||||
dataList = runState?.combustionAirPressureArr
|
||||
? [
|
||||
{ id: 1, name: "1#风机", value: "0m³/h" },
|
||||
{ id: 2, name: "2#风机", value: "0m³/h" },
|
||||
{ id: 3, name: "3#风机", value: "0m³/h" },
|
||||
{ id: 4, name: "4#风机", value: "0m³/h" },
|
||||
{ id: 5, name: "5#风机", value: "0m³/h" },
|
||||
{ id: 6, name: "6#风机", value: "0m³/h" },
|
||||
{ id: 7, name: "7#风机", value: "0m³/h" },
|
||||
{ id: 8, name: "8#风机", value: "0m³/h" },
|
||||
{ id: 9, name: "9#风机", value: "0m³/h" },
|
||||
{ id: 10, name: "10#风机", value: "0m³/h" },
|
||||
{ id: 11, name: "11#风机", value: "0m³/h" },
|
||||
{ id: 12, name: "12#风机", value: "0m³/h" },
|
||||
{ id: 13, name: "13#风机", value: "0m³/h" },
|
||||
{ id: 14, name: "14#风机", value: "0m³/h" },
|
||||
{ id: 15, name: "15#风机", value: "0m³/h" },
|
||||
{ id: 16, name: "16#风机", value: "0m³/h" },
|
||||
].map((item, index) => ({
|
||||
...item,
|
||||
value: runState.combustionAirPressureArr[index] ?? "/",
|
||||
}))
|
||||
: [
|
||||
{ id: 1, name: "1#风机", value: "0m³/h" },
|
||||
{ id: 2, name: "2#风机", value: "0m³/h" },
|
||||
{ id: 3, name: "3#风机", value: "0m³/h" },
|
||||
{ id: 4, name: "4#风机", value: "0m³/h" },
|
||||
{ id: 5, name: "5#风机", value: "0m³/h" },
|
||||
{ id: 6, name: "6#风机", value: "0m³/h" },
|
||||
{ id: 7, name: "7#风机", value: "0m³/h" },
|
||||
{ id: 8, name: "8#风机", value: "0m³/h" },
|
||||
{ id: 9, name: "9#风机", value: "0m³/h" },
|
||||
{ id: 10, name: "10#风机", value: "0m³/h" },
|
||||
{ id: 11, name: "11#风机", value: "0m³/h" },
|
||||
{ id: 12, name: "12#风机", value: "0m³/h" },
|
||||
{ id: 13, name: "13#风机", value: "0m³/h" },
|
||||
{ id: 14, name: "14#风机", value: "0m³/h" },
|
||||
{ id: 15, name: "15#风机", value: "0m³/h" },
|
||||
{ id: 16, name: "16#风机", value: "0m³/h" },
|
||||
];
|
||||
}
|
||||
|
||||
function handleSwitchChange(val) {
|
||||
if (val) {
|
||||
setShowChart(true);
|
||||
} else {
|
||||
setShowChart(false);
|
||||
}
|
||||
}
|
||||
return (
|
||||
<GraphBase
|
||||
icon="kiln"
|
||||
title="风机运行频率"
|
||||
size={["middle", "long"]}
|
||||
switchOptions={true}
|
||||
switchPosition={[null, 200]} // [top, left]
|
||||
onSwitch={handleSwitchChange}
|
||||
>
|
||||
<div className={cls.chart}>
|
||||
{showChart && (
|
||||
<ReactECharts option={options} style={{ height: "100%" }} />
|
||||
)}
|
||||
{!showChart && (
|
||||
<div className={cls.gridList}>
|
||||
{dataList.map((item) => (
|
||||
<div key={item.id} className={cls.listItem}>
|
||||
{item.name}: {item.value}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</GraphBase>
|
||||
);
|
||||
}
|
||||
|
||||
export default WindFrequence;
|
||||
29
src/components/公共组件/风机运行频率/index.module.css
Normal file
29
src/components/公共组件/风机运行频率/index.module.css
Normal file
@@ -0,0 +1,29 @@
|
||||
.gridList {
|
||||
margin-top: 12px;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
/* grid-auto-row: ; */
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.listItem {
|
||||
border-radius: 2px;
|
||||
padding: 9px 0;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
box-shadow: inset 0 0 16px 4px rgba(255, 255, 255, 0.197);
|
||||
}
|
||||
.headWidget {
|
||||
position: absolute;
|
||||
top: 22px;
|
||||
right: 24px;
|
||||
height: 32px;
|
||||
width: 410px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
color: #fff;
|
||||
}
|
||||
.relative {
|
||||
position: relative;
|
||||
}
|
||||
115
src/components/工具组件/Ruler.jsx
Normal file
115
src/components/工具组件/Ruler.jsx
Normal file
@@ -0,0 +1,115 @@
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
function Ruler(props) {
|
||||
const ruler = useRef(null);
|
||||
const [left, setLeft] = useState(props.left || '100px');
|
||||
const [top, setTop] = useState(props.top || '100px');
|
||||
const [dragging, setDragging] = useState(false);
|
||||
const isVertical = props.type == 'vertical';
|
||||
const handleUp = useCallback(() => {
|
||||
setDragging(false);
|
||||
}, []);
|
||||
const handleMove = useCallback(
|
||||
(e) => {
|
||||
if (!dragging) return;
|
||||
const v = isVertical ? e.clientX : e.clientY;
|
||||
isVertical ? setLeft(v + 'px') : setTop(v + 'px');
|
||||
},
|
||||
[dragging],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
document.addEventListener('mouseup', handleUp);
|
||||
document.addEventListener('mousemove', handleMove);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener('mouseup', handleUp);
|
||||
document.removeEventListener('mousemove', handleMove);
|
||||
};
|
||||
}, [dragging]);
|
||||
|
||||
function handleMouseDown() {
|
||||
setDragging(true);
|
||||
}
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
ref={ruler}
|
||||
className="ruler-line"
|
||||
style={{
|
||||
position: 'fixed',
|
||||
top: isVertical ? 0 : top,
|
||||
left: isVertical ? left : 0,
|
||||
overflow: 'visible',
|
||||
height: isVertical ? '100vh' : '1px',
|
||||
width: isVertical ? '1px' : '100vw',
|
||||
cursor: 'pointer',
|
||||
userSelect: 'none',
|
||||
background: props.background || '#ccc',
|
||||
}}
|
||||
onMouseDown={handleMouseDown}
|
||||
>
|
||||
<div
|
||||
className="ruler-tooltip"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: isVertical ? '200px' : '20px',
|
||||
right: isVertical ? '-132px' : '50px',
|
||||
width: '128px',
|
||||
border: '1px solid #0008',
|
||||
padding: '0 12px',
|
||||
background: '#ecc100',
|
||||
color: '#0008',
|
||||
}}
|
||||
>
|
||||
{isVertical ? `left: ${left}` : `top: ${top}`}
|
||||
</div>
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
||||
function RulerContainer(props) {
|
||||
const [rulers, setRulers] = useState([]);
|
||||
|
||||
// 监听事件
|
||||
useEffect(() => {
|
||||
let fn = (e) => {
|
||||
if (e.shiftKey && e.key === 'R') {
|
||||
setRulers((rulers) => [
|
||||
...rulers,
|
||||
{
|
||||
width: '1px',
|
||||
height: '100vh',
|
||||
background: '#ccc',
|
||||
type: 'vertical',
|
||||
},
|
||||
]);
|
||||
}
|
||||
if (e.shiftKey && e.key === 'H') {
|
||||
setRulers((rulers) => [
|
||||
...rulers,
|
||||
{ width: '100vw', height: '1px', background: '#ccc' },
|
||||
]);
|
||||
}
|
||||
if (e.shiftKey && e.key === 'Q') {
|
||||
setRulers((rulers) => []);
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('keydown', fn);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
id="ruler-container"
|
||||
style={{ position: 'fixed', top: 0, left: 0, width: 0, height: 0 }}
|
||||
>
|
||||
{rulers.map((ruler) => (
|
||||
<Ruler key={Math.random()} {...ruler} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default RulerContainer;
|
||||
21
src/components/模块组件/总览/Bottom/index.jsx
Normal file
21
src/components/模块组件/总览/Bottom/index.jsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import React from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import GasI from '../../../公共组件/助燃风流量';
|
||||
import GasII from '../../../公共组件/天然气流量';
|
||||
import FaultTotal from '../../../公共组件/产线缺陷统计';
|
||||
import FaultType from '../../../公共组件/产线当日缺陷分类';
|
||||
|
||||
import './index.less';
|
||||
import cls from './index.module.css';
|
||||
|
||||
export default function index() {
|
||||
return (
|
||||
<div className={`${cls.bottomBar} flex justify-between`}>
|
||||
<FaultTotal page="home" />
|
||||
<FaultType page="home" />
|
||||
<GasII />
|
||||
<GasI />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
16
src/components/模块组件/总览/Bottom/index.less
Normal file
16
src/components/模块组件/总览/Bottom/index.less
Normal file
@@ -0,0 +1,16 @@
|
||||
.ButtonBorder {
|
||||
// width: 100%;
|
||||
// height: 100%;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-around;
|
||||
|
||||
position: fixed;
|
||||
bottom: 0px;
|
||||
left: 200px;
|
||||
|
||||
z-index: 10000;
|
||||
|
||||
background-color: #000;
|
||||
}
|
||||
6
src/components/模块组件/总览/Bottom/index.module.css
Normal file
6
src/components/模块组件/总览/Bottom/index.module.css
Normal file
@@ -0,0 +1,6 @@
|
||||
.bottomBar {
|
||||
/* background-color: #3894; */
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: visible;
|
||||
}
|
||||
20
src/components/模块组件/总览/CenterTop/CenterMenu/index.jsx
Normal file
20
src/components/模块组件/总览/CenterTop/CenterMenu/index.jsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import cls from './index.module.less';
|
||||
|
||||
export default function CenterMenu() {
|
||||
const menuList = [
|
||||
['窑炉总览', '/kilnSummary'],
|
||||
['窑炉内部', '/kilnInner'],
|
||||
['退火监测', '/stopFire'],
|
||||
['质检统计', '/quailtyCheck'],
|
||||
['能耗分析', '/energyCost'],
|
||||
];
|
||||
return (
|
||||
<div className={`${cls.centerMenu} flex`}>
|
||||
{menuList.map((menu) => (
|
||||
<div key={menu[0]} className={cls.menuItem}>
|
||||
{menu[0]}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
.centerMenu {
|
||||
position: fixed;
|
||||
top: 120px;
|
||||
left: 1340px;
|
||||
color: white;
|
||||
z-index: 10000;
|
||||
}
|
||||
|
||||
.menuItem {
|
||||
transition: all 0.3s ease-out;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
padding: 10px 20px;
|
||||
font-size: 32px;
|
||||
line-height: 48px;
|
||||
letter-spacing: 6px;
|
||||
background: url(../../../assets/bg_center_menu.png) no-repeat;
|
||||
background-size: 100% 50%;
|
||||
background-position: bottom;
|
||||
color: #00fff788;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue',
|
||||
'PingFang SC', 'Microsoft YaHei', '微软雅黑', 'Microsoft YaHei UI',
|
||||
'Source Han Sans SC', 'Noto Sans CJK SC', 'WenQuanYi Micro Hei', sans-serif;
|
||||
}
|
||||
|
||||
.menuItem:hover {
|
||||
color: #00fff7;
|
||||
}
|
||||
|
||||
.menuItem:not(:first-child) {
|
||||
margin-left: 50px;
|
||||
}
|
||||
65
src/components/模块组件/总览/CenterTop/RightTable/index.jsx
Normal file
65
src/components/模块组件/总览/CenterTop/RightTable/index.jsx
Normal file
@@ -0,0 +1,65 @@
|
||||
import React, { Component } from "react";
|
||||
import "./righttable.module.less";
|
||||
|
||||
// import { ScrollBoard } from '@jiaminghi/data-view-react';
|
||||
|
||||
let data = [
|
||||
["产线0", "10mm", "10mm", "10mm"],
|
||||
["产线2", "8mm", "8mm", "8mm"],
|
||||
["产线3", "15mm", "15mm", "15mm"],
|
||||
["产线4", "15mm", "15mm", "15mm"],
|
||||
];
|
||||
|
||||
let header = ["产线名", "原板宽度", "净板宽", "玻璃厚度"];
|
||||
|
||||
let config = {
|
||||
headerBGC: "rgba(4, 44, 76, 0.3)",
|
||||
header: [
|
||||
'<span style="color:#fff">产线名<span/>',
|
||||
'<span style="color:#fff">原板宽度<span/>',
|
||||
'<span style="color:#fff">净板宽<span/>',
|
||||
'<span style="color:#fff">玻璃厚度<span/>',
|
||||
],
|
||||
oddRowBGC: "#042444",
|
||||
evenRowBGC: "#042c4c",
|
||||
columnWidth: [90],
|
||||
headerHeight: 40,
|
||||
hoverPause: false,
|
||||
data: replaceStyle(data, 0.7),
|
||||
};
|
||||
|
||||
function replaceStyle(Arr, opencity) {
|
||||
let temp = [];
|
||||
|
||||
for (let i = 0; i < Arr.length; i++) {
|
||||
temp[i] = [];
|
||||
for (let j = 0; j < Arr[i].length; j++) {
|
||||
temp[i][
|
||||
j
|
||||
] = ` <span style="color:rgba(255, 255, 255,${opencity})">${Arr[i][j]}<span/>`;
|
||||
}
|
||||
}
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
class Chart1 extends Component {
|
||||
render() {
|
||||
return (
|
||||
<div className="CenterChart1itemDetailBorder" style={{ opacity: 0.75 }}>
|
||||
<h2 className="CenterChart1itemTXT"> 当前产线生产规格</h2>
|
||||
<div className="CenterChart1itemContainer">
|
||||
<span className="CenterFormitemDetailBorderLine1"></span>
|
||||
<span className="CenterFormitemDetailBorderLine2"></span>
|
||||
<span className="CenterFormitemDetailBorderLine3"></span>
|
||||
{/* <ScrollBoard
|
||||
config={config}
|
||||
style={{ width: '105%', height: '240%' }}
|
||||
/> */}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Chart1;
|
||||
@@ -0,0 +1,50 @@
|
||||
.CenterChart1itemDetailBorder {
|
||||
width: 100%;
|
||||
height: 240px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
|
||||
background-color: rgba(4, 44, 76, 0.2);
|
||||
.CenterChart1itemTXT {
|
||||
width: 100%;
|
||||
height: 10%;
|
||||
font-size: 20px;
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
text-align: center;
|
||||
margin-top: 2%;
|
||||
}
|
||||
.CenterChart1itemContainer {
|
||||
width: 95%;
|
||||
height: 100px;
|
||||
position: relative;
|
||||
|
||||
.CenterFormitemDetailBorderLine1 {
|
||||
width: 1px;
|
||||
height: 200px;
|
||||
background-color: #041c2c;
|
||||
float: left;
|
||||
margin-left: 18%;
|
||||
z-index: 10;
|
||||
position: absolute;
|
||||
}
|
||||
.CenterFormitemDetailBorderLine2 {
|
||||
width: 1px;
|
||||
height: 200px;
|
||||
background-color: #041c2c;
|
||||
float: left;
|
||||
margin-left: 46%;
|
||||
z-index: 10;
|
||||
position: absolute;
|
||||
}
|
||||
.CenterFormitemDetailBorderLine3 {
|
||||
width: 1px;
|
||||
height: 200px;
|
||||
background-color: #041c2c;
|
||||
float: left;
|
||||
margin-left: 72%;
|
||||
z-index: 10;
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
}
|
||||
20
src/components/模块组件/总览/CenterTop/index.jsx
Normal file
20
src/components/模块组件/总览/CenterTop/index.jsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import React from 'react';
|
||||
import Item2 from './RightTable';
|
||||
import Item1 from '../../../公共组件/时间火向数据';
|
||||
|
||||
import cls from './index.module.less';
|
||||
|
||||
export default function index() {
|
||||
return (
|
||||
<>
|
||||
<div className="flex justify-between w-full h-full">
|
||||
<div className={cls.leftGrid}>
|
||||
<Item1 />
|
||||
</div>
|
||||
<div className={cls.rightTable}>
|
||||
<Item2 />
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
8
src/components/模块组件/总览/CenterTop/index.module.less
Normal file
8
src/components/模块组件/总览/CenterTop/index.module.less
Normal file
@@ -0,0 +1,8 @@
|
||||
.leftGrid {
|
||||
// width: 416px;
|
||||
height: 212px;
|
||||
}
|
||||
.rightTable {
|
||||
width: 410px;
|
||||
height: 240px;
|
||||
}
|
||||
21
src/components/模块组件/总览/LeftSide/index.jsx
Normal file
21
src/components/模块组件/总览/LeftSide/index.jsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import React from 'react';
|
||||
import Kiln from '../../../公共组件/窑炉信息/Kiln';
|
||||
import GoodProduction from '../../../公共组件/本日生产良品率/GoodProduction';
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
import cls from './index.module.less';
|
||||
|
||||
export default function index() {
|
||||
return (
|
||||
<motion.div
|
||||
className={cls.leftBar}
|
||||
initial={{ opacity: 0, position: 'absolute' }}
|
||||
animate={{ opacity: 1, position: 'relative' }}
|
||||
exit={{ opacity: 0, position: 'relative' }}
|
||||
transition={{ type: 'tween' }}
|
||||
>
|
||||
<Kiln />
|
||||
<GoodProduction />
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
9
src/components/模块组件/总览/LeftSide/index.module.less
Normal file
9
src/components/模块组件/总览/LeftSide/index.module.less
Normal file
@@ -0,0 +1,9 @@
|
||||
.leftBar {
|
||||
width: 625px;
|
||||
height: 966px;
|
||||
// margin-left: 40px;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
14
src/components/模块组件/总览/RightSide/index.jsx
Normal file
14
src/components/模块组件/总览/RightSide/index.jsx
Normal file
@@ -0,0 +1,14 @@
|
||||
import React from 'react';
|
||||
import SmokeHandle from '../../../公共组件/烟气处理';
|
||||
import EnergyCost from '../../../公共组件/能耗';
|
||||
|
||||
import cls from './index.module.less';
|
||||
|
||||
export default function index() {
|
||||
return (
|
||||
<div className={`${cls.rightBar} flex flex-col`}>
|
||||
<EnergyCost />
|
||||
<SmokeHandle />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
14
src/components/模块组件/总览/RightSide/index.module.less
Normal file
14
src/components/模块组件/总览/RightSide/index.module.less
Normal file
@@ -0,0 +1,14 @@
|
||||
.rightBar {
|
||||
> div {
|
||||
&:first-child {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.demoFloat {
|
||||
position: fixed;
|
||||
top: 100px;
|
||||
right: 600px;
|
||||
z-index: 10000;
|
||||
}
|
||||
104
src/components/模块组件/窑炉内部/Center/VideoContainer.jsx
Normal file
104
src/components/模块组件/窑炉内部/Center/VideoContainer.jsx
Normal file
@@ -0,0 +1,104 @@
|
||||
import EnterVideo from './videoComponents/EnterVideo';
|
||||
import EnterToFloorOne from './videoComponents/EnterToFloor1';
|
||||
import EnterToFloorTwo from './videoComponents/EnterToFloor2';
|
||||
import FloorOneToTwo from './videoComponents/Floor1To2';
|
||||
import FloorTwoToOne from './videoComponents/Floor2To1';
|
||||
import { useRef, useEffect, useReducer } from 'react';
|
||||
import { AnimatePresence } from 'framer-motion';
|
||||
|
||||
const initOpacity = {
|
||||
enterVideo: 1,
|
||||
enterToFloorOne: 0,
|
||||
enterToFloorTwo: 0,
|
||||
floorOneToTwo: 0,
|
||||
floorTwoToOne: 0,
|
||||
};
|
||||
const opacityReducer = (state, action) => {
|
||||
switch (action.type) {
|
||||
case 'enter-to-1': {
|
||||
return {
|
||||
...initOpacity,
|
||||
enterToFloorOne: 1,
|
||||
enterVideo: 0,
|
||||
};
|
||||
}
|
||||
case 'enter-to-2': {
|
||||
return {
|
||||
...initOpacity,
|
||||
enterToFloorTwo: 1,
|
||||
enterVideo: 0,
|
||||
};
|
||||
}
|
||||
case 'floor-1-to-2': {
|
||||
return {
|
||||
...initOpacity,
|
||||
floorOneToTwo: 1,
|
||||
enterToFloorOne: 0,
|
||||
enterVideo: 0,
|
||||
floorTwoToOne: 0,
|
||||
};
|
||||
}
|
||||
case 'floor-2-to-1': {
|
||||
return {
|
||||
...initOpacity,
|
||||
floorTwoToOne: 1,
|
||||
enterToFloorTwo: 0,
|
||||
floorOneToTwo: 0,
|
||||
enterVideo: 0,
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function VideoContainer(props) {
|
||||
const floor = props.floor || null;
|
||||
const lastFloor = useRef(null);
|
||||
const [opacity, dispatch] = useReducer(opacityReducer, initOpacity);
|
||||
|
||||
useEffect(() => {
|
||||
if (floor) {
|
||||
if (floor == 1) {
|
||||
if (lastFloor.current == 2) {
|
||||
dispatch({ type: 'floor-2-to-1' });
|
||||
} else {
|
||||
dispatch({ type: 'enter-to-1' });
|
||||
}
|
||||
} else if (floor == 2) {
|
||||
if (lastFloor.current == 1) {
|
||||
dispatch({ type: 'floor-1-to-2' });
|
||||
} else {
|
||||
dispatch({ type: 'enter-to-2' });
|
||||
}
|
||||
}
|
||||
lastFloor.current = floor;
|
||||
}
|
||||
}, [floor]);
|
||||
|
||||
const enterToFloorOne = () => {
|
||||
// 更新层数
|
||||
props.onFloorUpdate(1);
|
||||
// floor1 one 立即显示,enter 延迟点消失
|
||||
dispatch({ type: 'enter-to-1' });
|
||||
};
|
||||
|
||||
function handleEnterVideoEnd() {
|
||||
console.log('video end');
|
||||
enterToFloorOne();
|
||||
}
|
||||
|
||||
return (
|
||||
<AnimatePresence>
|
||||
<EnterVideo
|
||||
key="enter"
|
||||
onVideoEnd={handleEnterVideoEnd}
|
||||
opacity={opacity.enterVideo}
|
||||
/>
|
||||
<EnterToFloorOne key="enter-to-1" opacity={opacity.enterToFloorOne} />
|
||||
<EnterToFloorTwo key="enter-to-2" opacity={opacity.enterToFloorTwo} />
|
||||
<FloorOneToTwo key="1-to-2" opacity={opacity.floorOneToTwo} />
|
||||
<FloorTwoToOne key="2-to-1" opacity={opacity.floorTwoToOne} />
|
||||
</AnimatePresence>
|
||||
);
|
||||
}
|
||||
|
||||
export default VideoContainer;
|
||||
125
src/components/模块组件/窑炉内部/Center/index.jsx
Normal file
125
src/components/模块组件/窑炉内部/Center/index.jsx
Normal file
@@ -0,0 +1,125 @@
|
||||
import { useState } from 'react';
|
||||
import cls from './index.module.css';
|
||||
import Chart2 from '../../../公共组件/时间火向数据';
|
||||
import VideoContainer from './VideoContainer';
|
||||
|
||||
function KilnCenter() {
|
||||
const [floor, setFloor] = useState(0);
|
||||
|
||||
function onFloorUpdate(flr) {
|
||||
setFloor(flr);
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className="bgKilnInner"
|
||||
style={{
|
||||
width: '100%',
|
||||
position: 'absolute',
|
||||
top: '12%',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
}}
|
||||
>
|
||||
{/* 时间火向数据 */}
|
||||
<div
|
||||
className="fireAndTime"
|
||||
style={{ position: 'absolute', top: '-112px', height: '212px' }}
|
||||
>
|
||||
<Chart2 />
|
||||
</div>
|
||||
|
||||
{/* menu */}
|
||||
<div
|
||||
className="subMenu"
|
||||
style={{
|
||||
display: 'flex',
|
||||
marginBottom: '24px',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className={
|
||||
'flr flr1 ' + cls.menuItem + ' ' + (floor == 1 ? cls.active : '')
|
||||
}
|
||||
onClick={() => onFloorUpdate(1)}
|
||||
>
|
||||
一层
|
||||
</div>
|
||||
<div
|
||||
className={
|
||||
'flr flr2 ' + cls.menuItem + ' ' + (floor == 2 ? cls.active : '')
|
||||
}
|
||||
onClick={() => onFloorUpdate(2)}
|
||||
>
|
||||
二层
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* video */}
|
||||
<VideoContainer onFloorUpdate={onFloorUpdate} floor={floor} />
|
||||
|
||||
{/* <div className={cls.videoLayer2}></div> */}
|
||||
|
||||
{/* left side */}
|
||||
{/* <div
|
||||
className="leftSide"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
left: '88px',
|
||||
top: '24%',
|
||||
display: 'grid',
|
||||
gridTemplateColumns: '100px 100px',
|
||||
gap: '20px 18px',
|
||||
gridAutoRows: '64px',
|
||||
}}
|
||||
>
|
||||
{data.map((item) => (
|
||||
<div
|
||||
className="leftSideItem"
|
||||
style={{
|
||||
background: '#fff3',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
background: '#32535d',
|
||||
}}
|
||||
>
|
||||
<span style={{ fontSize: '18px', lineHeight: 1, color: '#2EE4E6' }}>
|
||||
{item.name}
|
||||
</span>
|
||||
<span
|
||||
style={{ fontSize: '24px', lineHeight: '32px', color: '#fff' }}
|
||||
>
|
||||
{item.value} ℃
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="toolbox"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
bottom: '32px',
|
||||
left: '64px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '24px',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className="tlj tlj1"
|
||||
style={{ background: '#ccc', width: '200px', height: '100px' }}
|
||||
></div>
|
||||
<div
|
||||
className="tlj tlj2"
|
||||
style={{ background: '#ccc', width: '200px', height: '100px' }}
|
||||
></div>
|
||||
</div> */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default KilnCenter;
|
||||
46
src/components/模块组件/窑炉内部/Center/index.module.css
Normal file
46
src/components/模块组件/窑炉内部/Center/index.module.css
Normal file
@@ -0,0 +1,46 @@
|
||||
.menuItem {
|
||||
transition: all 0.3s ease-out;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
padding: 10px 50px;
|
||||
font-size: 32px;
|
||||
line-height: 48px;
|
||||
letter-spacing: 6px;
|
||||
background: url(../../../../assets/bg_center_menu.png) no-repeat;
|
||||
background-size: 100% 50%;
|
||||
background-position: bottom;
|
||||
color: #00fff788;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue',
|
||||
'PingFang SC', 'Microsoft YaHei', '微软雅黑', 'Microsoft YaHei UI',
|
||||
'Source Han Sans SC', 'Noto Sans CJK SC', 'WenQuanYi Micro Hei', sans-serif;
|
||||
}
|
||||
|
||||
.menuItem.active,
|
||||
.menuItem:hover {
|
||||
color: #00fff7;
|
||||
}
|
||||
|
||||
.menuItem:not(:first-child) {
|
||||
margin-left: 50px;
|
||||
}
|
||||
|
||||
.videoLayer2 {
|
||||
width: 2440px;
|
||||
height: 720px;
|
||||
background: url(../../../../assets/video-layer-2.png) no-repeat;
|
||||
background-size: 100% 100%;
|
||||
background-position: 0 0;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
.videoLayer1 {
|
||||
width: 2440px;
|
||||
height: 720px;
|
||||
background: url(../../../../assets/floor1-status.png) no-repeat;
|
||||
background-size: 100% 100%;
|
||||
background-position: 0 0;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
import { useRef, useEffect, useMemo, useCallback, useState } from "react";
|
||||
import cls from "../index.module.css";
|
||||
// import SocketContext from '../../../../../store/socket-data-provider';
|
||||
import { useContext } from "react";
|
||||
|
||||
function EnterToFloorOne(props) {
|
||||
// const ctx = useContext(SocketContext);
|
||||
const ctx = null;
|
||||
|
||||
const fireDir = ctx?.runState?.fireDirection || null;
|
||||
const [fireCanPlay, setFireCanPlay] = useState(false);
|
||||
const vd = useRef(null);
|
||||
const show = props.opacity || 0;
|
||||
|
||||
useEffect(() => {
|
||||
if (show) {
|
||||
vd.current.play();
|
||||
setTimeout(() => {
|
||||
console.log("开启enter的火播放");
|
||||
setFireCanPlay(true);
|
||||
}, 5000);
|
||||
}
|
||||
return () => {
|
||||
console.log("关闭enter的火播放");
|
||||
setFireCanPlay(false);
|
||||
};
|
||||
}, [show]);
|
||||
|
||||
return (
|
||||
<AnimatePresence>
|
||||
{show && (
|
||||
<motion.div
|
||||
className="video-wrapper"
|
||||
style={{
|
||||
position: "fixed",
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
zIndex: -999,
|
||||
overflow: "hidden",
|
||||
}}
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: [1, 1, 0], transition: { duration: 0.5 } }}
|
||||
>
|
||||
<video ref={vd} muted width={"100%"}>
|
||||
<source src="/video/floor1.webm" type="video/mp4" />
|
||||
</video>
|
||||
|
||||
{fireCanPlay && fireDir == "东火" && (
|
||||
<video
|
||||
src="/video/fire_top.webm"
|
||||
muted
|
||||
autoPlay
|
||||
loop
|
||||
width={3900}
|
||||
style={{ position: "absolute", top: "-20px", left: "-20px" }}
|
||||
></video>
|
||||
)}
|
||||
{fireCanPlay && fireDir == "西火" && (
|
||||
<video
|
||||
src="/video/fire_down.webm"
|
||||
muted
|
||||
autoPlay
|
||||
loop
|
||||
width={3900}
|
||||
style={{ position: "absolute", top: "-20px", left: "-20px" }}
|
||||
></video>
|
||||
)}
|
||||
|
||||
<motion.div
|
||||
className={cls.videoLayer1}
|
||||
key="eto1div"
|
||||
style={{
|
||||
top: "336px",
|
||||
left: "730px",
|
||||
width: "2380px",
|
||||
}}
|
||||
animate={{
|
||||
opacity: [0, 0, 0, 0.6, 1],
|
||||
transition: { duration: 0.3, delay: 2 },
|
||||
}}
|
||||
></motion.div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
);
|
||||
}
|
||||
|
||||
export default EnterToFloorOne;
|
||||
@@ -0,0 +1,44 @@
|
||||
import { motion } from 'framer-motion';
|
||||
import { useRef, useEffect } from 'react';
|
||||
|
||||
function EnterToFloorTwo(props) {
|
||||
const vd = useRef(null);
|
||||
const opacity = props.opacity || 0;
|
||||
|
||||
if (opacity == 1) {
|
||||
setTimeout(() => {
|
||||
vd.current.play();
|
||||
}, 100);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
vd.current.addEventListener('ended', () => {
|
||||
setTimeout(() => {
|
||||
vd.current.currentTime = 0;
|
||||
}, 1000);
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
className="video-wrapper"
|
||||
style={{
|
||||
position: 'fixed',
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
zIndex: -1000,
|
||||
opacity: opacity,
|
||||
zIndex: -999,
|
||||
}}
|
||||
transition={{ type: 'tween', duration: 1 }}
|
||||
>
|
||||
<video ref={vd} muted width={'100%'}>
|
||||
<source src="/video/floor2.webm" type="video/mp4" />
|
||||
</video>
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
||||
export default EnterToFloorTwo;
|
||||
@@ -0,0 +1,38 @@
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
import { useEffect, useRef, useMemo } from 'react';
|
||||
|
||||
function EnterVideo(props) {
|
||||
const show = props.opacity || 0;
|
||||
const vd = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
vd.current.addEventListener('ended', props.onVideoEnd);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<AnimatePresence>
|
||||
{show && (
|
||||
<motion.div
|
||||
className="video-wrapper"
|
||||
style={{
|
||||
position: 'fixed',
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
zIndex: -1000,
|
||||
}}
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: [1, 1, 0], transition: { duration: 0.5 } }}
|
||||
>
|
||||
<video ref={vd} muted autoPlay={true} width={'100%'}>
|
||||
<source src="/video/enter.webm" type="video/mp4" />
|
||||
</video>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
);
|
||||
}
|
||||
|
||||
export default EnterVideo;
|
||||
@@ -0,0 +1,97 @@
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
import { useRef, useEffect, useMemo, useState } from "react";
|
||||
import cls from "../index.module.css";
|
||||
// import SocketContext from '../../../../../store/socket-data-provider';
|
||||
import { useContext } from "react";
|
||||
|
||||
function FloorOneToTwo(props) {
|
||||
// const ctx = useContext(SocketContext);
|
||||
|
||||
const ctx = null;
|
||||
|
||||
const fireDir = ctx?.runState?.fireDirection || null;
|
||||
const [fireCanPlay, setFireCanPlay] = useState(false);
|
||||
|
||||
const vd = useRef(null);
|
||||
const show = props.opacity || 0;
|
||||
|
||||
useEffect(() => {
|
||||
if (show) {
|
||||
vd.current.play();
|
||||
setTimeout(() => {
|
||||
console.log("开启1-2的火播放");
|
||||
setFireCanPlay(true);
|
||||
}, 3000);
|
||||
}
|
||||
if (!show) setFireCanPlay(false);
|
||||
return () => {
|
||||
console.log("关闭1-2的火播放");
|
||||
setFireCanPlay(false);
|
||||
};
|
||||
}, [show]);
|
||||
|
||||
return (
|
||||
<AnimatePresence>
|
||||
{show && (
|
||||
<motion.div
|
||||
className="video-wrapper"
|
||||
style={{
|
||||
position: "fixed",
|
||||
top: "7px",
|
||||
left: "50px",
|
||||
width: "calc(100% - 50px)",
|
||||
height: "calc(100% - 7px)",
|
||||
zIndex: -998,
|
||||
overflow: "clip",
|
||||
}}
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0, transition: { duration: 0, delay: 0.1 } }}
|
||||
>
|
||||
<video ref={vd} muted>
|
||||
<source src="/video/1to2.webm" type="video/mp4" />
|
||||
</video>
|
||||
|
||||
{fireCanPlay && fireDir == "东火" && (
|
||||
<video
|
||||
src="/video/fire_top.webm"
|
||||
muted
|
||||
autoPlay
|
||||
loop
|
||||
width={3700}
|
||||
style={{ position: "absolute", top: "18px", left: "56px" }}
|
||||
></video>
|
||||
)}
|
||||
{fireCanPlay && fireDir == "西火" && (
|
||||
// {fireCanPlay && (
|
||||
<video
|
||||
src="/video/fire_down.webm"
|
||||
muted
|
||||
autoPlay
|
||||
loop
|
||||
width={3780}
|
||||
style={{ position: "absolute", top: "-24px", left: "12px" }}
|
||||
></video>
|
||||
)}
|
||||
|
||||
<motion.div
|
||||
className={cls.videoLayer2}
|
||||
key="1to2div"
|
||||
style={{
|
||||
top: "360px",
|
||||
left: "740px",
|
||||
width: "2415px",
|
||||
height: "690px",
|
||||
}}
|
||||
animate={{
|
||||
opacity: [0, 0, 0, 0.6, 1],
|
||||
transition: { duration: 0.3, delay: 2 },
|
||||
}}
|
||||
></motion.div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
);
|
||||
}
|
||||
|
||||
export default FloorOneToTwo;
|
||||
@@ -0,0 +1,97 @@
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
import { useRef, useEffect, useMemo, useState } from "react";
|
||||
import cls from "../index.module.css";
|
||||
// import SocketContext from '../../../../../store/socket-data-provider';
|
||||
import { useContext } from "react";
|
||||
|
||||
function FloorTwoToOne(props) {
|
||||
// const ctx = useContext(SocketContext);
|
||||
|
||||
const ctx = null;
|
||||
|
||||
const fireDir = ctx?.runState?.fireDirection || null;
|
||||
const [fireCanPlay, setFireCanPlay] = useState(false);
|
||||
|
||||
const vd = useRef(null);
|
||||
const show = props.opacity || 0;
|
||||
|
||||
useEffect(() => {
|
||||
if (show) {
|
||||
vd.current.play();
|
||||
setTimeout(() => {
|
||||
console.log("开启2-1的火播放");
|
||||
setFireCanPlay(true);
|
||||
}, 3000);
|
||||
}
|
||||
if (!show) setFireCanPlay(false);
|
||||
return () => {
|
||||
console.log("关闭2-1的火播放");
|
||||
setFireCanPlay(false);
|
||||
};
|
||||
}, [show]);
|
||||
|
||||
return (
|
||||
<AnimatePresence>
|
||||
{show && (
|
||||
<motion.div
|
||||
className="video-wrapper"
|
||||
style={{
|
||||
position: "fixed",
|
||||
top: "7px",
|
||||
left: "50px",
|
||||
width: "calc(100% - 50px)",
|
||||
height: "calc(100% - 7px)",
|
||||
zIndex: -998,
|
||||
overflow: "clip",
|
||||
}}
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0, transition: { duration: 0.2, delay: 0.2 } }}
|
||||
>
|
||||
<video ref={vd} muted>
|
||||
<source src="/video/2to1.webm" type="video/mp4" />
|
||||
</video>
|
||||
|
||||
{fireCanPlay && fireDir == "东火" && (
|
||||
// {fireCanPlay && (
|
||||
<video
|
||||
src="/video/fire_top.webm"
|
||||
muted
|
||||
autoPlay
|
||||
loop
|
||||
width={3800}
|
||||
style={{ position: "absolute", top: "10px", left: "-26px" }}
|
||||
></video>
|
||||
)}
|
||||
{fireCanPlay && fireDir == "西火" && (
|
||||
// {fireCanPlay && (
|
||||
<video
|
||||
src="/video/fire_down.webm"
|
||||
muted
|
||||
autoPlay
|
||||
loop
|
||||
width={3800}
|
||||
style={{ position: "absolute", top: "-12px", left: "-26px" }}
|
||||
></video>
|
||||
)}
|
||||
|
||||
<motion.div
|
||||
className={cls.videoLayer1}
|
||||
key="eto1div"
|
||||
style={{
|
||||
top: "336px",
|
||||
left: "730px",
|
||||
width: "2380px",
|
||||
}}
|
||||
animate={{
|
||||
opacity: [0, 0, 0, 0.6, 1],
|
||||
transition: { duration: 0.3, delay: 2 },
|
||||
}}
|
||||
></motion.div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
);
|
||||
}
|
||||
|
||||
export default FloorTwoToOne;
|
||||
24
src/components/模块组件/窑炉内部/LeftSide/index.jsx
Normal file
24
src/components/模块组件/窑炉内部/LeftSide/index.jsx
Normal file
@@ -0,0 +1,24 @@
|
||||
import React from 'react';
|
||||
import Kiln from '../../../公共组件/窑炉信息/Kiln';
|
||||
import GasFlow from '../../../公共组件/天然气流量';
|
||||
import WindFlow from '../../../公共组件/助燃风流量';
|
||||
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
import cls from './index.module.less';
|
||||
|
||||
export default function index() {
|
||||
return (
|
||||
<motion.div
|
||||
className={cls.leftBar}
|
||||
initial={{ opacity: 0, position: 'absolute' }}
|
||||
animate={{ opacity: 1, position: 'relative' }}
|
||||
exit={{ opacity: 0, position: 'relative' }}
|
||||
transition={{ type: 'tween' }}
|
||||
>
|
||||
<Kiln />
|
||||
<GasFlow style={{ flex: 1, width: '100%', marginTop: '24px' }} />
|
||||
<WindFlow style={{ flex: 1, width: '100%', marginTop: '24px' }} />
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
9
src/components/模块组件/窑炉内部/LeftSide/index.module.less
Normal file
9
src/components/模块组件/窑炉内部/LeftSide/index.module.less
Normal file
@@ -0,0 +1,9 @@
|
||||
.leftBar {
|
||||
width: 625px;
|
||||
height: 966px;
|
||||
// margin-left: 40px;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
31
src/components/模块组件/窑炉内部/RightSide/index.jsx
Normal file
31
src/components/模块组件/窑炉内部/RightSide/index.jsx
Normal file
@@ -0,0 +1,31 @@
|
||||
import React from 'react';
|
||||
import FanInfo from '../../../公共组件/风机信息';
|
||||
import WindFrequence from '../../../公共组件/风机运行频率';
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
import cls from './index.module.less';
|
||||
|
||||
export default function index() {
|
||||
return (
|
||||
<motion.div
|
||||
style={{
|
||||
width: '625px',
|
||||
height: '966px',
|
||||
// background: '#fff3',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
}}
|
||||
initial={{ opacity: 0, position: 'absolute' }}
|
||||
animate={{ opacity: 1, position: 'relative' }}
|
||||
exit={{ opacity: 0, position: 'absolute' }}
|
||||
transition={{ type: 'tween' }}
|
||||
>
|
||||
<div style={{ height: '380px' }}>
|
||||
<FanInfo />
|
||||
</div>
|
||||
<div style={{ flex: 1, marginTop: '24px' }}>
|
||||
<WindFrequence />
|
||||
</div>
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
44
src/components/模块组件/能耗分析/一氧化氮/index.jsx
Normal file
44
src/components/模块组件/能耗分析/一氧化氮/index.jsx
Normal file
@@ -0,0 +1,44 @@
|
||||
import GraphBase from '../../../公共组件/GraphBase';
|
||||
import ReactECharts from 'echarts-for-react';
|
||||
import getOptions from '../../../../hooks/getChartOption';
|
||||
|
||||
function NO(props) {
|
||||
function handleSwitch(v) {
|
||||
console.log('switched ', v);
|
||||
}
|
||||
|
||||
function handleDateChange(v) {
|
||||
console.log('date ', v);
|
||||
}
|
||||
|
||||
return (
|
||||
<GraphBase
|
||||
icon="battery"
|
||||
title="一氧化氮"
|
||||
desc="能耗趋势图"
|
||||
switchOptions={true}
|
||||
onSwitch={handleSwitch}
|
||||
dateOptions={['日', '周', '月', '年']}
|
||||
legend={['总量', '白班', '夜班']}
|
||||
onDateChange={handleDateChange}
|
||||
size={['long', 'middle']}
|
||||
>
|
||||
{/* real echarts here */}
|
||||
<ReactECharts
|
||||
key={Math.random()}
|
||||
option={getOptions(
|
||||
[
|
||||
[148, 110, 140, 122, 84, 153, 89],
|
||||
[88, 79, 75, 73, 33, 54, 31],
|
||||
[60, 31, 65, 49, 51, 99, 58],
|
||||
],
|
||||
'氧气',
|
||||
)}
|
||||
style={{ height: '100%' }}
|
||||
/>
|
||||
{/* real table data here */}
|
||||
</GraphBase>
|
||||
);
|
||||
}
|
||||
|
||||
export default NO;
|
||||
0
src/components/模块组件/能耗分析/一氧化氮/index.module.css
Normal file
0
src/components/模块组件/能耗分析/一氧化氮/index.module.css
Normal file
44
src/components/模块组件/能耗分析/二氧化氮/index.jsx
Normal file
44
src/components/模块组件/能耗分析/二氧化氮/index.jsx
Normal file
@@ -0,0 +1,44 @@
|
||||
import GraphBase from '../../../公共组件/GraphBase';
|
||||
import ReactECharts from 'echarts-for-react';
|
||||
import getOptions from '../../../../hooks/getChartOption';
|
||||
|
||||
function NO2(props) {
|
||||
function handleSwitch(v) {
|
||||
console.log('switched ', v);
|
||||
}
|
||||
|
||||
function handleDateChange(v) {
|
||||
console.log('date ', v);
|
||||
}
|
||||
|
||||
return (
|
||||
<GraphBase
|
||||
icon="battery"
|
||||
title="二氧化氮"
|
||||
desc="能耗趋势图"
|
||||
switchOptions={true}
|
||||
onSwitch={handleSwitch}
|
||||
dateOptions={['日', '周', '月', '年']}
|
||||
legend={['总量', '白班', '夜班']}
|
||||
onDateChange={handleDateChange}
|
||||
size={['long', 'middle']}
|
||||
>
|
||||
{/* real echarts here */}
|
||||
<ReactECharts
|
||||
key={Math.random()}
|
||||
option={getOptions(
|
||||
[
|
||||
[91, 164, 88, 120, 167, 158, 43],
|
||||
[30, 75, 52, 43, 73, 66, 36],
|
||||
[61, 89, 36, 77, 94, 92, 7],
|
||||
],
|
||||
'氧气',
|
||||
)}
|
||||
style={{ height: '100%' }}
|
||||
/>
|
||||
{/* real table data here */}
|
||||
</GraphBase>
|
||||
);
|
||||
}
|
||||
|
||||
export default NO2;
|
||||
0
src/components/模块组件/能耗分析/二氧化氮/index.module.css
Normal file
0
src/components/模块组件/能耗分析/二氧化氮/index.module.css
Normal file
44
src/components/模块组件/能耗分析/二氧化硫/index.jsx
Normal file
44
src/components/模块组件/能耗分析/二氧化硫/index.jsx
Normal file
@@ -0,0 +1,44 @@
|
||||
import GraphBase from '../../../公共组件/GraphBase';
|
||||
import ReactECharts from 'echarts-for-react';
|
||||
import getOptions from '../../../../hooks/getChartOption';
|
||||
|
||||
function SO2(props) {
|
||||
function handleSwitch(v) {
|
||||
console.log('switched ', v);
|
||||
}
|
||||
|
||||
function handleDateChange(v) {
|
||||
console.log('date ', v);
|
||||
}
|
||||
|
||||
return (
|
||||
<GraphBase
|
||||
icon="battery"
|
||||
title="二氧化硫"
|
||||
desc="能耗趋势图"
|
||||
switchOptions={true}
|
||||
onSwitch={handleSwitch}
|
||||
dateOptions={['日', '周', '月', '年']}
|
||||
legend={['总量', '白班', '夜班']}
|
||||
onDateChange={handleDateChange}
|
||||
size={['long', 'middle']}
|
||||
>
|
||||
{/* real echarts here */}
|
||||
<ReactECharts
|
||||
key={Math.random()}
|
||||
option={getOptions(
|
||||
[
|
||||
[132, 155, 140, 83, 180, 67, 136],
|
||||
[83, 58, 60, 22, 80, 64, 43],
|
||||
[49, 97, 80, 61, 100, 3, 93],
|
||||
],
|
||||
'氧气',
|
||||
)}
|
||||
style={{ height: '100%' }}
|
||||
/>
|
||||
{/* real table data here */}
|
||||
</GraphBase>
|
||||
);
|
||||
}
|
||||
|
||||
export default SO2;
|
||||
0
src/components/模块组件/能耗分析/二氧化硫/index.module.css
Normal file
0
src/components/模块组件/能耗分析/二氧化硫/index.module.css
Normal file
44
src/components/模块组件/能耗分析/余热发电/index.jsx
Normal file
44
src/components/模块组件/能耗分析/余热发电/index.jsx
Normal file
@@ -0,0 +1,44 @@
|
||||
import GraphBase from '../../../公共组件/GraphBase';
|
||||
import ReactECharts from 'echarts-for-react';
|
||||
import getOptions from '../../../../hooks/getChartOption';
|
||||
|
||||
function RestHeat(props) {
|
||||
function handleSwitch(v) {
|
||||
console.log('switched ', v);
|
||||
}
|
||||
|
||||
function handleDateChange(v) {
|
||||
console.log('date ', v);
|
||||
}
|
||||
|
||||
return (
|
||||
<GraphBase
|
||||
icon="battery"
|
||||
title="余热发电"
|
||||
desc="能耗趋势图"
|
||||
switchOptions={true}
|
||||
onSwitch={handleSwitch}
|
||||
dateOptions={['日', '周', '月', '年']}
|
||||
legend={['总量', '白班', '夜班']}
|
||||
onDateChange={handleDateChange}
|
||||
size={['long', 'middle']}
|
||||
>
|
||||
{/* real echarts here */}
|
||||
<ReactECharts
|
||||
key={Math.random()}
|
||||
option={getOptions(
|
||||
[
|
||||
[138, 136, 29, 104, 101, 93, 128],
|
||||
[69, 52, 18, 57, 22, 88, 46],
|
||||
[69, 84, 11, 47, 79, 5, 82],
|
||||
],
|
||||
'氧气',
|
||||
)}
|
||||
style={{ height: '100%' }}
|
||||
/>
|
||||
{/* real table data here */}
|
||||
</GraphBase>
|
||||
);
|
||||
}
|
||||
|
||||
export default RestHeat;
|
||||
0
src/components/模块组件/能耗分析/余热发电/index.module.css
Normal file
0
src/components/模块组件/能耗分析/余热发电/index.module.css
Normal file
37
src/components/模块组件/能耗分析/天然气/index.jsx
Normal file
37
src/components/模块组件/能耗分析/天然气/index.jsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import GraphBase from '../../../公共组件/GraphBase';
|
||||
import ReactECharts from 'echarts-for-react';
|
||||
import getOptions from '../../../../hooks/getChartOption';
|
||||
|
||||
function NatGas(props) {
|
||||
function handleSwitch(v) {
|
||||
console.log('switched ', v);
|
||||
}
|
||||
|
||||
function handleDateChange(v) {
|
||||
console.log('date ', v);
|
||||
}
|
||||
|
||||
return (
|
||||
<GraphBase
|
||||
icon="battery"
|
||||
title="天然气"
|
||||
desc="能耗趋势图"
|
||||
switchOptions={true}
|
||||
onSwitch={handleSwitch}
|
||||
dateOptions={['日', '周', '月', '年']}
|
||||
legend={['总量']}
|
||||
onDateChange={handleDateChange}
|
||||
size={['long', 'short']}
|
||||
>
|
||||
{/* real echarts here */}
|
||||
<ReactECharts
|
||||
key={Math.random()}
|
||||
option={getOptions([[91, 69, 5, 10, 21, 46, 24]], '氧气')}
|
||||
style={{ height: '100%' }}
|
||||
/>
|
||||
{/* real table data here */}
|
||||
</GraphBase>
|
||||
);
|
||||
}
|
||||
|
||||
export default NatGas;
|
||||
0
src/components/模块组件/能耗分析/天然气/index.module.css
Normal file
0
src/components/模块组件/能耗分析/天然气/index.module.css
Normal file
65
src/components/模块组件/能耗分析/氧气含量/index.jsx
Normal file
65
src/components/模块组件/能耗分析/氧气含量/index.jsx
Normal file
@@ -0,0 +1,65 @@
|
||||
import GraphBase from '../../../公共组件/GraphBase';
|
||||
import ReactECharts from 'echarts-for-react';
|
||||
import getOptions from '../../../../hooks/getChartOption';
|
||||
|
||||
// function rand(max) {
|
||||
// return Math.ceil(Math.random() * max);
|
||||
// }
|
||||
// function getArr(len) {
|
||||
// return Array(len).fill(1).map(() => rand(100))
|
||||
// }
|
||||
// function getArrs(len) {
|
||||
// return Array(len).fill(1).map(() => getArr(7))
|
||||
// }
|
||||
// function fan4(...arrs) {
|
||||
// const total = arrs[0].map((_, i) =>
|
||||
// arrs.reduce((sum, arr) => sum + arr[i], 0),
|
||||
// );
|
||||
// arrs.unshift(total);
|
||||
// return arrs;
|
||||
// }
|
||||
// function main() {
|
||||
// // console.log(JSON.stringify(fan(getArrs(3))))
|
||||
// console.log(fan(getArrs(3)))
|
||||
// }
|
||||
|
||||
function Oxygen(props) {
|
||||
function handleSwitch(v) {
|
||||
console.log('switched ', v);
|
||||
}
|
||||
|
||||
function handleDateChange(v) {
|
||||
console.log('date ', v);
|
||||
}
|
||||
|
||||
return (
|
||||
<GraphBase
|
||||
icon="battery"
|
||||
title="氧气含量"
|
||||
desc="能耗趋势图"
|
||||
switchOptions={true}
|
||||
onSwitch={handleSwitch}
|
||||
dateOptions={['日', '周', '月', '年']}
|
||||
legend={['总量', '白班', '夜班']}
|
||||
onDateChange={handleDateChange}
|
||||
size={['long', 'middle']}
|
||||
>
|
||||
{/* real echarts here */}
|
||||
<ReactECharts
|
||||
key={Math.random()}
|
||||
option={getOptions(
|
||||
[
|
||||
[172, 165, 135, 35, 101, 53, 68], // 总量
|
||||
[87, 68, 81, 33, 35, 44, 38], // 白班
|
||||
[85, 97, 54, 2, 66, 9, 30], // 夜班
|
||||
],
|
||||
'氧气',
|
||||
)}
|
||||
style={{ height: '100%' }}
|
||||
/>
|
||||
{/* real table data here */}
|
||||
</GraphBase>
|
||||
);
|
||||
}
|
||||
|
||||
export default Oxygen;
|
||||
0
src/components/模块组件/能耗分析/氧气含量/index.module.css
Normal file
0
src/components/模块组件/能耗分析/氧气含量/index.module.css
Normal file
44
src/components/模块组件/能耗分析/水耗能/index.jsx
Normal file
44
src/components/模块组件/能耗分析/水耗能/index.jsx
Normal file
@@ -0,0 +1,44 @@
|
||||
import GraphBase from '../../../公共组件/GraphBase';
|
||||
import ReactECharts from 'echarts-for-react';
|
||||
import getOptions from '../../../../hooks/getChartOption';
|
||||
|
||||
function WaterCost(props) {
|
||||
function handleSwitch(v) {
|
||||
console.log('switched ', v);
|
||||
}
|
||||
|
||||
function handleDateChange(v) {
|
||||
console.log('date ', v);
|
||||
}
|
||||
|
||||
return (
|
||||
<GraphBase
|
||||
icon="battery"
|
||||
title="水耗能"
|
||||
desc="能耗趋势图"
|
||||
switchOptions={true}
|
||||
onSwitch={handleSwitch}
|
||||
dateOptions={['日', '周', '月', '年']}
|
||||
legend={['总量', '白班', '夜班']}
|
||||
onDateChange={handleDateChange}
|
||||
size={['long', 'middle']}
|
||||
>
|
||||
{/* real echarts here */}
|
||||
<ReactECharts
|
||||
key={Math.random()}
|
||||
option={getOptions(
|
||||
[
|
||||
[9, 119, 56, 80, 75, 145, 66],
|
||||
[7, 100, 14, 54, 63, 62, 11],
|
||||
[2, 19, 42, 26, 12, 83, 55],
|
||||
],
|
||||
'氧气',
|
||||
)}
|
||||
style={{ height: '100%' }}
|
||||
/>
|
||||
{/* real table data here */}
|
||||
</GraphBase>
|
||||
);
|
||||
}
|
||||
|
||||
export default WaterCost;
|
||||
0
src/components/模块组件/能耗分析/水耗能/index.module.css
Normal file
0
src/components/模块组件/能耗分析/水耗能/index.module.css
Normal file
37
src/components/模块组件/能耗分析/烟气处理/index.jsx
Normal file
37
src/components/模块组件/能耗分析/烟气处理/index.jsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import cls from './index.module.css';
|
||||
import GradientText from '../../../公共组件/GradientText';
|
||||
|
||||
function SmokeHandle(props) {
|
||||
return (
|
||||
<div className={' ' + cls.smoke} style={{ color: '#fff' }}>
|
||||
<span
|
||||
className={cls.shadowBorder}
|
||||
style={{
|
||||
gridRow: '1 / 3',
|
||||
paddingTop: '38px',
|
||||
paddingLeft: '32px',
|
||||
userSelect: 'none',
|
||||
}}
|
||||
>
|
||||
<GradientText text="烟气处理" />
|
||||
</span>
|
||||
<span
|
||||
className={cls.shadowBorder + ' ' + cls.infoText}
|
||||
style={{ letterSpacing: '12px' }}
|
||||
>
|
||||
氧气含量: <span style={{ letterSpacing: '1px' }}>80%</span>
|
||||
</span>
|
||||
<span className={cls.shadowBorder + ' ' + cls.infoText}>
|
||||
一氧化氮排放浓度: 20mg/m³
|
||||
</span>
|
||||
<span className={cls.shadowBorder + ' ' + cls.infoText}>
|
||||
二氧化硫排放浓度: 20mg/m³
|
||||
</span>
|
||||
<span className={cls.shadowBorder + ' ' + cls.infoText}>
|
||||
二氧化氮排放浓度: 20mg/m³
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default SmokeHandle;
|
||||
21
src/components/模块组件/能耗分析/烟气处理/index.module.css
Normal file
21
src/components/模块组件/能耗分析/烟气处理/index.module.css
Normal file
@@ -0,0 +1,21 @@
|
||||
.smoke {
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
grid-template-columns: 187px 347px 347px ;
|
||||
grid-template-rows: 60px 60px;
|
||||
}
|
||||
|
||||
.shadowBorder {
|
||||
box-shadow: inset 0 0 12px 3px #fff3;
|
||||
border-radius: 4px;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.infoText {
|
||||
text-align: center;
|
||||
font-size: 24px;
|
||||
line-height: 2.2;
|
||||
/* line-height: 20px; */
|
||||
letter-spacing: 1px;
|
||||
user-select: none;
|
||||
}
|
||||
37
src/components/模块组件/能耗分析/焦炉煤气/index.jsx
Normal file
37
src/components/模块组件/能耗分析/焦炉煤气/index.jsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import GraphBase from '../../../公共组件/GraphBase';
|
||||
import ReactECharts from 'echarts-for-react';
|
||||
import getOptions from '../../../../hooks/getChartOption';
|
||||
|
||||
function Gas(props) {
|
||||
function handleSwitch(v) {
|
||||
console.log('switched ', v);
|
||||
}
|
||||
|
||||
function handleDateChange(v) {
|
||||
console.log('date ', v);
|
||||
}
|
||||
|
||||
return (
|
||||
<GraphBase
|
||||
icon="battery"
|
||||
title="焦炉煤气"
|
||||
desc="能耗趋势图"
|
||||
switchOptions={true}
|
||||
onSwitch={handleSwitch}
|
||||
dateOptions={['日', '周', '月', '年']}
|
||||
legend={['总量']}
|
||||
onDateChange={handleDateChange}
|
||||
size={['long', 'short']}
|
||||
>
|
||||
{/* real echarts here */}
|
||||
<ReactECharts
|
||||
key={Math.random()}
|
||||
option={getOptions([[21, 4, 74, 72, 9, 59, 63]], '氧气')}
|
||||
style={{ height: '100%' }}
|
||||
/>
|
||||
{/* real table data here */}
|
||||
</GraphBase>
|
||||
);
|
||||
}
|
||||
|
||||
export default Gas;
|
||||
0
src/components/模块组件/能耗分析/焦炉煤气/index.module.css
Normal file
0
src/components/模块组件/能耗分析/焦炉煤气/index.module.css
Normal file
37
src/components/模块组件/能耗分析/电耗能/index.jsx
Normal file
37
src/components/模块组件/能耗分析/电耗能/index.jsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import GraphBase from '../../../公共组件/GraphBase';
|
||||
import ReactECharts from 'echarts-for-react';
|
||||
import getOptions from '../../../../hooks/getChartOption';
|
||||
|
||||
function ElecCost(props) {
|
||||
function handleSwitch(v) {
|
||||
console.log('switched ', v);
|
||||
}
|
||||
|
||||
function handleDateChange(v) {
|
||||
console.log('date ', v);
|
||||
}
|
||||
|
||||
return (
|
||||
<GraphBase
|
||||
icon="battery"
|
||||
title="电耗能"
|
||||
desc="能耗趋势图"
|
||||
switchOptions={true}
|
||||
onSwitch={handleSwitch}
|
||||
dateOptions={['日', '周', '月', '年']}
|
||||
legend={['总量']}
|
||||
onDateChange={handleDateChange}
|
||||
size={['long', 'short']}
|
||||
>
|
||||
{/* real echarts here */}
|
||||
<ReactECharts
|
||||
key={Math.random()}
|
||||
option={getOptions([[112, 73, 79, 82, 30, 105, 87]], '氧气')}
|
||||
style={{ height: '100%' }}
|
||||
/>
|
||||
{/* real table data here */}
|
||||
</GraphBase>
|
||||
);
|
||||
}
|
||||
|
||||
export default ElecCost;
|
||||
0
src/components/模块组件/能耗分析/电耗能/index.module.css
Normal file
0
src/components/模块组件/能耗分析/电耗能/index.module.css
Normal file
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user