49 Commits

Author SHA1 Message Date
lb
0b0ec8fd67 update 2023-11-08 16:49:34 +08:00
gtz
b502490e7a 'update' 2023-11-08 16:06:21 +08:00
lb
9a35afa58d update fire 2023-11-08 11:24:59 +08:00
lb
d0cdbb4901 update 2023-11-08 08:57:38 +08:00
lb
046b9dc305 update fire 2023-11-07 17:10:23 +08:00
lb
42b221c2fb update kiln inner 2023-11-07 15:19:37 +08:00
lb
74c58b570e update ruler 2023-11-07 14:37:00 +08:00
lb
00d9bdeaf1 update video order 2023-11-07 14:21:47 +08:00
lb
709008c3a3 update video play 2023-11-07 10:30:15 +08:00
lb
b0e492f066 update 2023-11-06 21:23:21 +08:00
lb
7faba81628 add 5 videos 2023-11-06 21:03:44 +08:00
lb
559f6fcd32 add videos 2023-11-06 17:20:44 +08:00
lb
6894aba781 update video 2023-11-06 17:00:35 +08:00
lb
3d80530ad6 update 2023-11-06 10:12:44 +08:00
lb
a93c6b37bc update 窑炉内部 2023-11-06 09:14:44 +08:00
Melete
4a8f81592c update 窑炉内部 2023-11-04 16:51:22 +08:00
Melete
1b25fa6eec update 窑炉内部 2023-11-04 15:59:18 +08:00
Melete
1f091a7fa5 update 2023-11-04 14:53:05 +08:00
Melete
b14a83ea8c add some pics 2023-11-04 14:25:41 +08:00
Melete
775fe04413 add bg 2023-11-04 12:52:19 +08:00
Melete
73d18b8eea done 左右侧边栏 2023-11-04 11:43:09 +08:00
lb
0fb251ba1b update 退火检测 2023-11-03 17:16:09 +08:00
lb
9470880de4 update 退火监测 2023-11-03 17:08:15 +08:00
lb
b7c2722aac update 风机信息 2023-11-03 16:50:00 +08:00
lb
66bb592405 update 窑炉内部right 2023-11-03 16:38:23 +08:00
lb
ec07109c2e update 风机信息 2023-11-03 16:26:07 +08:00
lb
21070337c5 done 能耗分析 2023-11-03 15:31:40 +08:00
lb
30a8a8e386 update 2023-11-03 13:54:52 +08:00
lb
32edb46215 update basic structrue of graphbase 2023-11-03 13:32:50 +08:00
lb
7bfa2cf9be add graphBase & update 能耗分析 2023-11-03 11:16:31 +08:00
lb
b1b439557f add 能源 2023-11-03 09:40:26 +08:00
lb
2a94f9050c update 能耗分析 2023-11-02 16:52:42 +08:00
lb
202cebdde4 add 能耗分析“ 2023-11-02 15:39:05 +08:00
lb
35de6f8b42 基本完成左侧边栏 2023-11-02 14:27:15 +08:00
lb
62d441496c update 2023-11-02 14:14:25 +08:00
lb
e11565ab7e add 退火监测左边栏 2023-11-02 10:38:04 +08:00
lb
c909129f41 update 2023-11-02 10:16:08 +08:00
lb
b9c1c97cab update 2023-11-01 17:07:59 +08:00
lb
75f8d75a7b update layout 2023-11-01 16:13:56 +08:00
lb
d56becaf05 update Home 2023-11-01 15:26:20 +08:00
lb
296a39c7f8 update 2023-11-01 14:56:41 +08:00
lb
4ce50704f3 update useSlider 2023-11-01 14:27:01 +08:00
lb
e244e35cad update useSlider 2023-11-01 14:21:47 +08:00
lb
1bba79ae3a fix errros 2023-11-01 14:06:07 +08:00
lb
3d34e5f685 add websocket fake server 2023-11-01 13:59:46 +08:00
lb
2efb67b25e add files 2023-11-01 13:57:31 +08:00
lb
db68914888 update file structure 2023-11-01 13:51:33 +08:00
lb
e50dfdb575 继续改变目录结构 2023-11-01 13:44:52 +08:00
lb
ec66a8bf59 变更目录结构 2023-11-01 11:08:42 +08:00
194 changed files with 3730 additions and 1393 deletions

View File

@@ -1,7 +1,6 @@
{
"private": true,
"scripts": {
"server": "nodemon --watch websocket/**/*.ts --exec ts-node websocket/server.ts",
"start": "umi dev",
"build": "umi build",
"postinstall": "umi generate tmp",
@@ -26,10 +25,9 @@
"antd": "^4.20.6",
"echarts": "^5.3.2",
"echarts-for-react": "^3.0.2",
"framer-motion": "^6.3.3",
"framer-motion": "^6.5.1",
"less": "^4.1.3",
"less-loader": "^11.0.0",
"moment": "^2.29.4",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"react-router-dom": "^6.3.0",
@@ -38,19 +36,16 @@
"umi": "^3.5.23"
},
"devDependencies": {
"@types/node": "^20.6.0",
"@types/ws": "^8.5.5",
"nodemon": "^3.0.1",
"ws": "^8.14.1",
"ts-node": "^10.9.1",
"@babel/runtime": "^7.18.0",
"@types/node": "^20.8.10",
"@types/react": "^17.0.0",
"@types/react-dom": "^17.0.0",
"@types/ws": "^8.5.8",
"@umijs/preset-react": "1.x",
"@umijs/test": "^3.5.23",
"lint-staged": "^10.0.7",
"prettier": "^2.2.0",
"typescript": "^5.2.2",
"typescript": "^4.9.5",
"yorkie": "^2.0.0"
}
}

BIN
public/video/1to2.webm Normal file

Binary file not shown.

BIN
public/video/2to1.webm Normal file

Binary file not shown.

BIN
public/video/enter.webm Normal file

Binary file not shown.

BIN
public/video/fire_down.webm Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
public/video/fire_top.webm Normal file

Binary file not shown.

BIN
public/video/floor1.webm Normal file

Binary file not shown.

BIN
public/video/floor2.webm Normal file

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 MiB

After

Width:  |  Height:  |  Size: 32 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 777 B

BIN
src/assets/TH.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

BIN
src/assets/ZL.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

BIN
src/assets/ditu.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 464 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 426 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 641 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 359 KiB

BIN
src/assets/line.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
src/assets/long-middle.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

BIN
src/assets/long-short.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

BIN
src/assets/middle-long.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

BIN
src/assets/middle-short.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

BIN
src/assets/moxing.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 561 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 394 KiB

BIN
src/assets/wave.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 714 KiB

View File

@@ -1,45 +0,0 @@
import { useState } from 'react';
import cls from './index.module.less';
import { ScrollBoard } from '@jiaminghi/data-view-react';
import BottomBarItem from '../BottomBarItem';
const TodayTableData = (props) => {
const [config, setConfig] = useState({
// headerBGC: 'rgba(4, 44, 76, 0.3)',
// headerBGC: 'rgba(4, 44, 76, .8)',
headerBGC: '#044A8425',
header: [
'<span style="color:#fff">产线名<span/>',
'<span style="color:#fff">原板宽度<span/>',
'<span style="color:#fff">净板宽度<span/>',
'<span style="color:#fff">玻璃厚度<span/>',
],
// oddRowBGC: '#042444',
oddRowBGC: '#044A8425',
// evenRowBGC: '#042c4c',
evenRowBGC: '#0B549945',
columnWidth: [90],
headerHeight: 40,
hoverPause: false,
data: [
['产线1', '1000mm', '1000mm', '3.2mm'],
['产线2', '100mm', '100mm', '2.2mm'],
['产线3', '100mm', '100mm', '2.0mm'],
['产线4', '100mm', '100mm', '2.1mm'],
['产线5', '100mm', '100mm', '2.2mm'],
],
});
return (
<BottomBarItem icon="signal" title="当前产线生产规格" className={cls.spec}>
<div className={cls.todayTableData}>
<ScrollBoard
config={config}
className={cls.tableClass}
style={{ height: '100%' }}
/>
</div>
</BottomBarItem>
);
};
export default TodayTableData;

View File

@@ -1,7 +0,0 @@
.spec {
height: 100%;
}
.todayTableData {
height: 100%;
}

View File

@@ -1,21 +0,0 @@
import React from 'react';
import { useEffect, useState } from 'react';
import GasI from './gasi';
import GasII from './gasii';
import FaultTotal from './FaultTotal';
import FaultType from './FaultType';
import './index.less';
import cls from './index.module.css';
export default function index() {
return (
<div className={`${cls.bottomBar} flex justify-between`}>
<FaultTotal />
<FaultType />
<GasII />
<GasI />
</div>
);
}

View File

@@ -1,52 +0,0 @@
.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;
}
}
}

View File

@@ -1,8 +0,0 @@
.leftGrid {
// width: 416px;
height: 212px;
}
.rightTable {
width: 410px;
height: 240px;
}

View File

@@ -1,51 +1,15 @@
import { useEffect, useRef } from 'react';
import useIcon from '../hooks/useIcon';
import cls from './container.module.less';
import IconStack from '../assets/Icon/icon-stack.png';
import IconGood from '../assets/Icon/icon-good.png';
import IconCharger from '../assets/Icon/icon-charge.png';
import IconSmoke from '../assets/Icon/icon-taiji.png';
import IconChart from '../assets/Icon/icon-chart.png';
import IconPuzzle from '../assets/Icon/icon-puzzle.png';
import IconPause from '../assets/Icon/icon-pause.png';
import IconSignal from '../assets/Icon/icon-signal.png';
const Container = (props) => {
let icon = useRef(null);
switch (props.icon) {
case 'kiln':
icon.current = IconStack;
break;
case 'good': // 良品率
icon.current = IconGood;
break;
case 'charger':
icon.current = IconCharger;
break;
case 'smoke':
icon.current = IconSmoke;
break;
case 'chart':
icon.current = IconChart;
break;
case 'puzzle':
icon.current = IconPuzzle;
break;
case 'pause':
icon.current = IconPause;
break;
case 'signal':
icon.current = IconSignal;
break;
}
let icon = useIcon(props.icon);
return (
<div className={`${cls.container} ${props.className}`}>
<div className={`${cls.container} ${props.className}`} style={props.style}>
<div className={cls.container__head}>
<img
src={icon.current}
src={icon}
alt="#"
className={props.icon == 'kiln' ? cls.bigger : ''}
/>

View File

@@ -1,88 +0,0 @@
.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;
}
}

View File

@@ -1,35 +0,0 @@
import React from 'react';
import { useState, useEffect, 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 infos = [
{ label: '窑炉压力', value: ctx.kilnInfo?.kilnPressure || '0Pa' },
{ label: '循环水温度', value: ctx.kilnInfo?.waterLoopTemperature || '0℃' },
{ label: '循环水流量', value: ctx.kilnInfo?.waterLoopFlow || '0㎡/h' },
{ label: '循环水压力', value: ctx.kilnInfo?.waterLoopPressure || '0Pa' },
{ label: '助燃风压力', value: ctx.kilnInfo?.windPressure || '0℃' },
{ label: '碹顶加权温度', value: ctx.kilnInfo?.topTemperature || '0℃' },
{
label: '压缩气压力',
value: ctx.kilnInfo?.gasPressure || '0Pa',
},
{ label: '熔化加权温度', value: ctx.kilnInfo?.meltTemperature || '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>
);
}

View File

@@ -1,10 +0,0 @@
.goodProd {
background: url(../../assets/good-bg.png) no-repeat;
background-size: 100% 100%;
height: 610px;
.goodProd__content {
display: flex;
flex-direction: column;
}
}

View File

@@ -1,14 +0,0 @@
import React from 'react';
import Kiln from './Kiln';
import GoodProduction from './GoodProduction';
import cls from './index.module.less';
export default function index() {
return (
<div className={cls.leftBar}>
<Kiln />
<GoodProduction />
</div>
);
}

View File

@@ -1,8 +0,0 @@
.leftBar {
width: 625px;
height: 100%;
margin-left: 40px;
display: flex;
flex-direction: column;
gap: 22px;
}

View File

@@ -1,50 +0,0 @@
import cls from './index.module.less';
import Container from '../../Container';
import TechSplitline from '../TechSplitline';
import EnergyCostChart from './EnergyCostChart';
import SocketContext from '../../../store/socket-data-provider';
import { useContext } from 'react';
function EnergyCost(props) {
const { energyState = {} } = useContext(SocketContext);
// console.log('energyState', energyState);
// let {
// restHeat = '0kWh',
// water = '0Km³',
// gasi = '0m³',
// gasii = '0m³',
// electricity = '0kWh',
// } = energyState;
let restHeat = energyState?.restHeat || '0kWh';
let water = energyState?.water || '0m³';
let gasi = energyState?.gasi || '0m³';
let gasii = energyState?.gasii || '0m³';
let electricity = energyState?.electricity || '0kWh';
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>{restHeat}</span>
</div>
<div className={cls.info__item_groups}>
<div className={cls.info__item}> : {water}</div>
<div className={cls.info__item}> : {gasi}</div>
<div className={cls.info__item}> : {electricity}</div>
{/* <div className={cls.info__item}>天 然 气 II: {gasii}</div> */}
</div>
</div>
<TechSplitline />
<EnergyCostChart />
</div>
</Container>
);
}
export default EnergyCost;

View File

@@ -1,7 +0,0 @@
import cls from './index.module.less';
const TechSplitline = (props) => {
return <div className={cls.techSplitline}></div>;
};
export default TechSplitline;

View File

@@ -1,5 +0,0 @@
.techSplitline {
height: 2px;
width: 100%;
background: radial-gradient(#3ce7ff, #3ce8ff92, #3ce8ff32, transparent);
}

View File

@@ -1,17 +0,0 @@
import './slider.css';
import { useState } from 'react';
const Slider = (props) => {
const [v, setV] = useState(100);
const handleInput = (e) => {
setV(e.target.value);
props.handleSlide(e.target.value);
};
return (
<div id="slider" className="slider">
<input type="range" value={v} onInput={handleInput} onChange={() => {}} />
</div>
);
};
export default Slider;

View File

@@ -10,7 +10,7 @@
align-items: center;
img {
width: 24px;
width: 20px;
&.bigger {
width: 24px;
@@ -24,7 +24,7 @@
sans-serif;
margin: 0;
margin-left: 6px;
font-size: 24px;
font-size: 18px;
color: #fff;
letter-spacing: 2px;
font-weight: 500;

View File

@@ -1,5 +0,0 @@
import './styles/bottom.module.css';
export default (props) => {
return <div className={`bottom ${props.className}`}>{props.children}</div>;
};

View File

@@ -1,26 +0,0 @@
import React, { useEffect, useState, useRef } from 'react';
import './styles/header.module.css';
import moment from 'moment';
export default (props) => {
let [today, setToday] = useState(new Date());
moment.locale('zh-cn');
setTimeout(() => {
setToday(new Date());
}, 1000);
return (
<header className="header">
<div>
<span className="header--logo"></span>
<h1>宜兴新能源生产线大数据指挥中心</h1>
</div>
<span className="header--wing absolute company">
设计单位中建材智能自动化研究院
</span>
<span className="header--wing absolute datetime">
{moment(today).format('YYYY.M.D dddd HH:mm:ss')}
</span>
</header>
);
};

View File

@@ -1,13 +0,0 @@
import './styles/left.module.css';
import Kiln from '../LeftBar/Kiln';
import GoodProduction from '../LeftBar/GoodProduction';
export default (props) => {
return (
<div className={`left-content ${props.className}`}>
<Kiln />
<GoodProduction />
</div>
);
};

View File

@@ -1,38 +0,0 @@
import Bottom from './Bottom';
import LeftContent from './LeftContent';
import RightContent from './RightContent';
import './styles/main.module.css';
import FaultTotal from '../BottomBar/FaultTotal';
import FaultType from '../BottomBar/FaultType';
import GasFlow from '../BottomBar/gasii';
import WindFlow from '../BottomBar/gasi';
import SpecPL from '../BottomBar/SpecPL';
import CenterTopBox from '../CenterTopData/LeftBoxes';
export default (props) => {
return (
<div className="main-container">
<LeftContent className="left"></LeftContent>
<div className="main-center">
<CenterTopBox />
</div>
<Bottom title="产线缺陷统计" className="bottom-1">
<FaultTotal />
</Bottom>
<Bottom title="产线当日缺陷分类" className="bottom-2">
<FaultType />
</Bottom>
<Bottom title="天然气流量" className="bottom-3">
<GasFlow />
</Bottom>
<Bottom title="助燃风流量" className="bottom-4">
<WindFlow />
</Bottom>
<Bottom title="当前产线生产风格" className="bottom-5">
<SpecPL />
</Bottom>
<RightContent className="right"></RightContent>
</div>
);
};

View File

@@ -1,13 +0,0 @@
import './styles/right.module.css';
import Energy from '../RightBar/EnergyCost';
import Smoke from '../RightBar/SmokeHandle';
export default (props) => {
return (
<div className={`right-content ${props.className}`}>
<Energy />
<Smoke />
</div>
);
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 252 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 294 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 309 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 218 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 284 KiB

View File

@@ -1,3 +0,0 @@
.bottom {
background: #f0f3;
}

View File

@@ -1,53 +0,0 @@
header {
height: 121px;
width: 100%;
position: absolute;
z-index: 10000;
background: url(../images/header.png) 100% 100% / contain no-repeat;
display: grid;
place-content: center;
}
header > div {
display: flex;
align-items: center;
margin-bottom: 0;
}
header > div .header--logo {
margin-top: 12px;
width: 48px;
height: 67px;
background: url(../images/logo.png) center/contain no-repeat;
}
header h1 {
margin-bottom: 0;
margin-left: 36px;
font-size: 52px;
/* line-height: 97px; */
user-select: none;
letter-spacing: 9px;
font-weight: 400;
color: #6bf2ff;
font-family: '微软雅黑', sans-serif;
}
.header--wing {
left: 0;
bottom: -12px;
height: 48px;
font-size: 28px;
line-height: 48px;
color: #51f0ff;
}
.company {
margin-left: 960px;
letter-spacing: 1px;
}
.datetime {
text-align: center;
left: unset;
right: 1100px;
letter-spacing: 1px;
}

View File

@@ -1,7 +0,0 @@
.left-content {
height: 100%;
display: flex;
flex-direction: column;
gap: 20px;
/* background: #fcc3; */
}

View File

@@ -1,54 +0,0 @@
.main-container {
height: 1px;
flex: 1;
/* background: #ccc4; */
display: grid;
grid-template-columns: 626px 576px 580px 626px 626px 450px 626px;
grid-template-rows: 600px 306px;
gap: 20px;
grid-template-areas:
'left main main main main main right'
'left bottom1 bottom2 bottom3 bottom4 bottom5 right';
place-content: end center;
margin-bottom: 20px;
}
.main-center {
grid-area: main;
background: url(../images/3d.png) 100% 80% / contain no-repeat;
display: flex;
justify-content: center;
}
.left {
grid-area: left;
}
.bottom-1 {
grid-area: bottom1;
background: url('../images/tongji-bg.png') 100% / contain no-repeat;
}
.bottom-2 {
grid-area: bottom2;
background: url('../images/fenlei-bg.png') 100% / contain no-repeat;
}
.bottom-3 {
grid-area: bottom3;
background: url('../images/gas-bg.png') 100% / contain no-repeat;
}
.bottom-4 {
grid-area: bottom4;
background: url('../images/gas-bg.png') 100% / contain no-repeat;
}
.bottom-5 {
grid-area: bottom5;
background: url('../images/spec-bg.png') 100% / contain no-repeat;
}
.right {
grid-area: right;
}

View File

@@ -1,7 +0,0 @@
.right-content {
height: 100%;
display: flex;
flex-direction: column;
gap: 20px;
/* background: #fcc3; */
}

View File

@@ -6,7 +6,8 @@ function BottomBarItem(props) {
<Container
icon={props.icon}
title={props.title}
className={`${props.className}`}
className={`${cls.bottomBarItem} ${props.className}`}
style={props.style}
>
{props.children}
</Container>

View File

@@ -0,0 +1,5 @@
.bottomBarItem {
background: url(../../../assets/bg-bottom-item.png) no-repeat;
background-size: 100% 100%;
width: 600px;
}

View 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;

View 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;

View 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;
}

View File

@@ -1,9 +1,6 @@
import cls from './index.module.css';
import BottomBarItem from '../BottomBarItem';
import { Switch, Radio } from 'antd';
import GraphBase from '../GraphBase';
import ReactECharts from 'echarts-for-react';
import * as echarts from 'echarts';
import { randomInt } from '../../../utils';
import { useState } from 'react';
function FaultType(props) {
@@ -18,10 +15,10 @@ function FaultType(props) {
'#12FFF5',
],
grid: {
left: 0,
top: 0,
bottom: 0,
right: 0,
left: 24,
top: 10,
bottom: 10,
right: 24,
},
legend: {
icon: 'circle',
@@ -38,11 +35,11 @@ function FaultType(props) {
},
textStyle: {
color: '#DFF1FE',
fontSize: 16,
fontSize: 18,
rich: {
sub: {
color: '#fff9',
fontSize: 16,
fontSize: 18,
},
},
},
@@ -62,16 +59,6 @@ function FaultType(props) {
labelLine: {
length: 0,
},
// emphasis: {
// label: {
// show: true,
// fontSize: 40,
// fontWeight: 'bold',
// },
// },
// labelLine: {
// show: false,
// },
data: [
{ value: 1048, name: '缺陷1' },
{ value: 735, name: '缺陷2' },
@@ -92,34 +79,28 @@ function FaultType(props) {
{ 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 (
<BottomBarItem
icon="puzzle"
<GraphBase
icon="battery"
title="产线当日缺陷分类"
className={cls.faultType}
dateOptions={lines.map((item) => item.label)}
onDateChange={handleDateChange}
size={bgSize}
style={{ width: '600px' }}
>
<div className={cls.headWidget}>
{/* 日周月年 */}
<Radio.Group
defaultValue="l1"
buttonStyle="solid"
className={cls.radioGroup}
>
{lines.map((l, index) => (
<Radio.Button
key={l.label}
value={l.value}
className={`radio-group__item ${cls['radio-group__item']}`}
>
{l.label}
</Radio.Button>
))}
</Radio.Group>
</div>
<div className={cls.chart}>
<ReactECharts option={options} style={{ height: '100%' }} />
</div>
</BottomBarItem>
</GraphBase>
);
}

View File

@@ -4,12 +4,11 @@
.faultType {
position: relative;
height: 100%;
}
.headWidget {
position: absolute;
top: 28px;
top: 20px;
right: 24px;
height: 32px;
width: 340px;
@@ -33,7 +32,3 @@
color: #fff !important;
background: #03233c !important;
}
.radio-group__item {
padding: 0 8px;
}

View File

@@ -1,9 +1,6 @@
import cls from './index.module.css';
import BottomBarItem from '../BottomBarItem';
import { Switch, Radio } from 'antd';
import GraphBase from '../GraphBase';
import ReactECharts from 'echarts-for-react';
import * as echarts from 'echarts';
import { randomInt } from '../../../utils';
function FaultTotal(props) {
const options = {
@@ -139,33 +136,27 @@ function FaultTotal(props) {
},
};
function handleDateChange(v) {
console.log('date ', v);
}
// 使
const bgSize =
props.page == 'home' ? ['middle', 'short'] : ['middle', 'long'];
return (
<BottomBarItem icon="chart" title="产线缺陷统计" className={cls.faultTotal}>
<div className={cls.headWidget}>
{/* 日周月年 */}
<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>
<GraphBase
icon="battery"
title="产线当日缺陷分类"
dateOptions={['日', '周', '月', '年']}
onDateChange={handleDateChange}
size={bgSize}
style={{ width: '600px' }}
>
<div className={cls.chart}>
<ReactECharts option={options} style={{ height: '100%' }} />
</div>
</BottomBarItem>
</GraphBase>
);
}

View File

@@ -4,14 +4,13 @@
}
.faultTotal {
height: 100%;
position: relative;
}
.headWidget {
position: absolute;
/* background: #00ee33; */
top: 28px;
top: 20px;
right: 24px;
height: 32px;
width: 190px;

View File

@@ -1,6 +1,6 @@
//
import cls from './index.module.css';
import BottomBarItem from '../BottomBarItem';
import BottomBarItem from '../BottomItemBackground';
import ReactECharts from 'echarts-for-react';
import * as echarts from 'echarts';
import { randomInt } from '../../../utils';
@@ -10,7 +10,7 @@ import SocketContext from '../../../store/socket-data-provider';
function GasI(props) {
const [showChart, setShowChart] = useState(true);
const { realtimeState, hisState } = useContext(SocketContext);
const { runState, hisState } = useContext(SocketContext);
let dataList = [];
let seriesData = [];
@@ -27,36 +27,23 @@ function GasI(props) {
let options = null;
if (showChart) {
// keys() sort()
seriesData = hisState?.wind
? Object.keys(hisState.wind)
seriesData = hisState?.combustionAir
? Object.keys(hisState.combustionAir)
.sort()
.map((key) => hisState.wind[key])
.map((key) => hisState.combustionAir[key])
: Array(8)
.fill(1)
.map((_) => Array(7).fill(0));
seriesData.unshift(hisState?.wind['FE_totalair'] || 1);
seriesData.splice(8, 1);
// debug
// console.log(' chart series data', hisState?.wind, seriesData);
console.log(
'助燃风 chart series data',
hisState?.combustionAir,
seriesData,
);
options = {
color: colors,
grid: { top: 32, 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)
@@ -77,13 +64,12 @@ function GasI(props) {
axisLine: {
lineStyle: {
width: 1,
color: '#4561AE',
// color: '#213259',
color: '#213259',
},
},
},
yAxis: {
name: '单位m³/h',
name: '单位/m³',
nameTextStyle: {
color: '#fff',
fontSize: 10,
@@ -97,14 +83,12 @@ function GasI(props) {
axisLine: {
show: true,
lineStyle: {
color: '#4561AE',
// color: '#213259',
color: '#213259',
},
},
splitLine: {
lineStyle: {
color: '#4561AEa0',
// color: '#213259a0',
color: '#213259a0',
},
},
// interval: 10,
@@ -112,7 +96,7 @@ function GasI(props) {
// max: 100,
},
series: seriesData.map((v, i) => ({
name: i ? i + '#助燃风' : '助燃风总流量',
name: i + 1 + '#助燃风',
data: v,
type: 'line',
symbol: 'circle',
@@ -129,9 +113,8 @@ function GasI(props) {
},
};
} else {
dataList = realtimeState?.wind
dataList = runState?.combustionAirPressureArr
? [
{ id: 0, name: '助燃风总流量', value: '0m³/h' },
{ id: 1, name: '1#助燃风', value: '0m³/h' },
{ id: 2, name: '2#助燃风', value: '0m³/h' },
{ id: 3, name: '3#助燃风', value: '0m³/h' },
@@ -139,12 +122,12 @@ function GasI(props) {
{ 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: realtimeState.wind[index] ?? '/',
value: runState.combustionAirPressureArr[index] ?? '/',
}))
: [
{ id: 0, name: '助燃风总流量', value: '0m³/h' },
{ id: 1, name: '1#助燃风', value: '0m³/h' },
{ id: 2, name: '2#助燃风', value: '0m³/h' },
{ id: 3, name: '3#助燃风', value: '0m³/h' },
@@ -152,7 +135,10 @@ function GasI(props) {
{ 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) {
@@ -163,7 +149,12 @@ function GasI(props) {
}
}
return (
<BottomBarItem icon="pause" title="助燃风流量" className={cls.gas}>
<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} />

View File

@@ -5,7 +5,6 @@
.gas {
position: relative;
height: 100%;
}
.currentFlow {
@@ -26,7 +25,7 @@
.headWidget {
position: absolute;
/* background: #00ee33; */
top: 28px;
top: 20px;
right: 24px;
height: 32px;
width: 190px;
@@ -69,7 +68,7 @@
.headWidget {
position: absolute;
/* background: #00ee33; */
top: 28px;
top: 22px;
right: 24px;
height: 32px;
width: 410px;

View File

@@ -50,13 +50,12 @@ export default function getOptions(seriesData, name) {
axisLine: {
lineStyle: {
width: 1,
// color: '#213259',
color: '#4561AE',
color: '#213259',
},
},
},
yAxis: {
name: '单位Nm³/h',
name: '单位m³/h',
nameTextStyle: {
color: '#fff',
fontSize: 10,
@@ -70,22 +69,18 @@ export default function getOptions(seriesData, name) {
},
axisLine: {
show: true,
// lineStyle: {
// color: '#213259',
// },
lineStyle: {
color: '#4561AE',
color: '#213259',
},
},
splitLine: {
lineStyle: {
// color: '#213259a0',
color: '#4561AEa0',
color: '#213259a0',
},
},
},
series: seriesData.map((arr, index) => ({
name: index !== 0 ? index + '#' + name : '天然气总流量',
name: index + 1 + '#' + name,
data: arr,
type: 'line',
areaStyle: {

View File

@@ -8,8 +8,8 @@ function GasChart(props) {
const { dataSource } = props;
const { hisState } = useContext(SocketContext);
// const dataName = dataSource == 'gas-i' ? 'kilnGasT1' : 'kilnGasT2';
const dataName = 'gas';
const dataName = dataSource == 'gas-i' ? 'kilnGasT1' : 'kilnGasT2';
// keys() sort()
const seriesData = hisState?.[dataName]
? Object.keys(hisState?.[dataName])
@@ -18,7 +18,7 @@ function GasChart(props) {
: Array(dataSource == 'gas-i' ? 8 : 4).fill(Array(7).fill(0));
// debug
// console.log(' series data', dataName, hisState?.[dataName], seriesData);
console.log('天然气 series data', dataName, hisState?.[dataName], seriesData);
return (
<div className={cls.gasChart}>
@@ -26,7 +26,7 @@ function GasChart(props) {
key={Math.random()}
option={getOptions(
seriesData,
dataSource == 'gas-i' ? '天然气' : '天然气II',
dataSource == 'gas-i' ? '天然气I' : '天然气II',
)}
style={{ height: '100%' }}
/>

View File

@@ -7,14 +7,14 @@ function getData(type) {
switch (type) {
case 'gas-i':
data = [
{ id: 0, name: '天然气总流量', value: '0Nm³/h' },
{ id: 1, name: '1#天然气', value: '0Nm³/h' },
{ id: 2, name: '2#天然气', value: '0Nm³/h' },
{ id: 3, name: '3#天然气', value: '0Nm³/h' },
{ id: 4, name: '4#天然气', value: '0Nm³/h' },
{ id: 5, name: '5#天然气', value: '0Nm³/h' },
{ id: 6, name: '6#天然气', value: '0Nm³/h' },
{ id: 7, name: '7#天然气', value: '0Nm³/h' },
{ 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':
@@ -31,16 +31,12 @@ function getData(type) {
}
function GridList(props) {
const { realtimeState } = useContext(SocketContext);
// const key = props.dataSource == 'gas-i' ? 'gasFlowArr' : 'furnaceGasFlowArr';
const { runState } = useContext(SocketContext);
const key = props.dataSource == 'gas-i' ? 'gasFlowArr' : 'furnaceGasFlowArr';
let dataList = getData(props.dataSource);
// dataList = realtimeState?.[key]
dataList = realtimeState?.['gasii']
? dataList.map((v, i) => ({
...v,
value: realtimeState['gasii'][i] ?? '/',
}))
dataList = runState?.[key]
? dataList.map((v, i) => ({ ...v, value: runState[key][i] ?? '/' }))
: dataList;
return (

View File

@@ -1,6 +1,6 @@
//
import cls from './index.module.css';
import BottomBarItem from '../BottomBarItem';
import BottomBarItem from '../BottomItemBackground';
import { Switch, Radio } from 'antd';
import { useState } from 'react';
@@ -19,19 +19,24 @@ function GasII(props) {
}
}
// 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');
// }
// }
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}>
<BottomBarItem
icon="pause"
title="天然气流量"
className={`${cls.gas} ${props.className}`}
style={props.style}
>
{/* legend */}
<div className={cls.headWidget}>
<div className="flex items-center">
@@ -40,7 +45,7 @@ function GasII(props) {
{!showChart && <span className={cls.switchLabel}>实时流量</span>}
</div>
{/* <Radio.Group
<Radio.Group
defaultValue="i"
buttonStyle="solid"
className={cls.radioGroup}
@@ -52,7 +57,7 @@ function GasII(props) {
<Radio.Button value="ii" className="radio-group__item">
天然气 II
</Radio.Button>
</Radio.Group> */}
</Radio.Group>
</div>
<div className={cls.chart}>

View File

@@ -4,12 +4,11 @@
.gas {
position: relative;
height: 100%;
}
.currentFlow {
position: absolute;
top: 28px;
top: 20px;
left: 50%;
transform: translateX(-50%);
padding: 8px 22px;
@@ -24,7 +23,7 @@
.headWidget {
position: absolute;
top: 28px;
top: 22px;
right: 24px;
height: 32px;
width: 410px;

View 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>
);
}

View 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;
}

View 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;

View 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;
}
}
}

View 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;

View 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;
}

View File

@@ -1,21 +1,18 @@
import React, { useState, useContext, useEffect, useMemo } from 'react';
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 icon4 from '@/assets/CenterChart2icon4.svg';
import cls from './leftbox.module.less';
const Chart2 = () => {
const { runState } = useContext(SocketContext);
const [time, setTime] = useState([0, 0]);
// console.clear();
// console.log('>>>>>>>> runstate (', runState, ')');
const ctx = useContext(SocketContext);
let [time, setTime] = useState([0, 0]);
useEffect(() => {
const restTime = runState?.lastFireChangeTime;
const restTime = ctx.runState?.lastFireChangeTime;
if (restTime == null) return;
console.log('restTime is:', restTime);
let timer = null;
@@ -74,38 +71,23 @@ const Chart2 = () => {
return () => {
clearInterval(timer);
};
}, [runState?.lastFireChangeTime, runState?.updateKey]);
const lastFireChangeTime = {
icon: icon3,
label: '剩余时间',
value: `${time[0]}${time[1]}`,
};
const fireChangeTime = useMemo(() => {
return runState?.fireChangeTime || '00:00';
}, [runState?.fireChangeTime]);
const fireDirection = useMemo(() => {
// let lastValue = null;
// if (runState?.fireDirection) {
// lastValue = runState?.fireDirection;
// }
// console.log(' <', runState?.fireDirection, '>')
return runState?.fireDirection || '南火';
}, [runState?.fireDirection]);
}, [ctx.runState?.lastFireChangeTime]);
const data = [
{
icon: icon1,
label: '换火时间',
value: fireChangeTime,
value: ctx.runState?.fireChangeTime || '00:00',
},
{
icon: icon3,
label: '剩余时间',
value: `${time[0]}${time[1]}`,
},
lastFireChangeTime,
{
icon: icon2,
label: '当前火向',
value: fireDirection,
value: ctx.runState?.fireDirection || '东火',
},
];

View File

@@ -1,7 +1,6 @@
.leftbox {
// width: 440px;
// background: rgb(127, 202, 42);
height: 98px;
.box {
margin-right: 16px;

View File

@@ -1,8 +1,8 @@
import cls from './good.module.less';
import Container from '../Container';
import TodayTableData from './substitutionCharts/TodayTableData';
import GoodRateChart from './substitutionCharts/GoodRateChart';
import TechSplitline from './substitutionCharts/TechSplitline';
import Container from '../../Container';
import TodayTableData from './components/TodayTableData';
import GoodRateChart from './components/GoodRateChart';
import TechSplitline from '../TechSplitline';
const GoodProduction = () => {
return (

View File

@@ -3,12 +3,12 @@ import './overwrite.css'; // 覆写 antd 默认样式,全局
import ReactECharts from 'echarts-for-react';
import * as echarts from 'echarts';
import { Switch, Radio } from 'antd';
import { randomInt } from '../../../../utils';
import { randomInt } from '../../../../../utils';
const GoodRateChart = (props) => {
const options = {
color: ['#FFD160', '#12FFF5', '#2760FF'],
grid: { top: 28, right: 12, bottom: 48, left: 48 },
grid: { top: 28, right: 12, bottom: 32, left: 48 },
xAxis: {
type: 'category',
data: Array(7)
@@ -29,7 +29,7 @@ const GoodRateChart = (props) => {
axisLine: {
lineStyle: {
width: 1,
color: '#4561AE',
color: '#213259',
},
},
},
@@ -43,12 +43,12 @@ const GoodRateChart = (props) => {
axisLine: {
show: true,
lineStyle: {
color: '#4561AE',
color: '#213259',
},
},
splitLine: {
lineStyle: {
color: '#4561AEa0',
color: '#213259a0',
},
},
interval: 10,
@@ -112,16 +112,16 @@ const GoodRateChart = (props) => {
function handleSwitchChange(val) {
// val: boolean
// console.log('switch change', val);
console.log('switch change', val);
}
return (
<div className={cls.GoodRateChart}>
<div className={cls.titleBar}>
<h2>生产良品率</h2>
{/* <Switch defaultChecked onChange={handleSwitchChange} /> */}
<Switch defaultChecked onChange={handleSwitchChange} />
<div className={cls.legend}>
{/* <span className="legend__title">班次详情</span> */}
<span className="legend__title">班次详情</span>
<ul className="legend__list">
<li>总量</li>
<li>白班</li>
@@ -147,7 +147,7 @@ const GoodRateChart = (props) => {
</Radio.Button>
</Radio.Group>
</div>
<ReactECharts option={options} style={{ height: '100%' }} />
<ReactECharts option={options} />
</div>
);
};

Some files were not shown because too many files have changed in this diff Show More