Compare commits

..

No commits in common. "master" and "testing-redux" have entirely different histories.

140 changed files with 9496 additions and 14477 deletions

12381
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,6 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@ant-design/icons": "^5.2.6",
"@babel/core": "^7.16.0",
"@jiaminghi/data-view-react": "^1.2.5",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.3",
@ -23,7 +22,6 @@
"case-sensitive-paths-webpack-plugin": "^2.4.0",
"css-loader": "^6.5.1",
"css-minimizer-webpack-plugin": "^3.2.0",
"dayjs": "^1.11.10",
"dotenv": "^10.0.0",
"dotenv-expand": "^5.1.0",
"echarts": "^5.4.3",
@ -61,7 +59,6 @@
"style-loader": "^3.3.1",
"tailwindcss": "^3.0.2",
"terser-webpack-plugin": "^5.2.5",
"uuid": "^9.0.1",
"webpack": "^5.64.4",
"webpack-dev-server": "^4.6.0",
"webpack-manifest-plugin": "^4.0.2",
@ -92,10 +89,8 @@
},
"devDependencies": {
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"@types/uuid": "^9.0.7",
"less": "^4.2.0",
"less-loader": "^11.1.3",
"typescript": "^5.3.3"
"less-loader": "^11.1.3"
},
"jest": {
"roots": [

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,68 +1,27 @@
// import "./App.css";
import "./global.css";
import "./index.css";
import Head from "./components/Common/Company";
// import { SocketContextProvider } from "../store/socket-data-provider";
import useSlider, { Slider } from "./hooks/useSlider";
import NavMenu from "./components/Common/NavMenu";
import { useEffect, useState } from "react";
import { useState } from "react";
import Home from "./pages/Home";
import EnergyAnalysis from "./pages/EnergyCostAnalysis";
import RulerContainer from "./components/Tools/Ruler";
import { Switch } from "antd";
import { createPortal } from "react-dom";
const Menus = ["窑炉总览", "窑炉内部", "退火监测", "质检统计", "能耗分析"];
function App() {
const { styles, value, setValue } = useSlider(100);
const [navActive, setNavActive] = useState("窑炉总览");
const [lunbo, setlunbo] = useState(false);
useEffect(() => {
let timer;
if (lunbo) {
timer = setInterval(() => {
handleMenuChange(Menus[(Menus.indexOf(navActive) + 1) % Menus.length]);
}, 5000);
}
return () => {
clearInterval(timer);
};
}, [lunbo, navActive]);
function handleSwitchChange(val) {
setlunbo(val);
}
function handleMenuChange(value) {
setNavActive(value);
}
return (
<>
<div id="FullScreen" style={{ ...styles, overflow: "hidden" }}>
<NavMenu active={navActive} onChangeActive={handleMenuChange} />
<div id="FullScreen" style={styles}>
<NavMenu active={navActive} onChangeActive={(v) => setNavActive(v)} />
<Head />
<div
className="lunbo-setting"
style={{
position: "fixed",
top: "48px",
right: "680px",
display: "flex",
alignItems: "center",
gap: "16px",
}}
>
<span style={{ fontSize: "20px", color: "#00fff7" }}>模块轮播</span>
<Switch
className="lunbo-btn"
size="small"
value={lunbo}
onChange={handleSwitchChange}
/>
</div>
{navActive == "能耗分析" && <EnergyAnalysis />}
{navActive == "能耗分析" && <div className="bgDitu"></div>}
{navActive != "能耗分析" && <Home active={navActive} />}
</div>
<Slider value={value} setValue={setValue} />

View File

@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>温度</title>
<g id="退火监测" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g transform="translate(-64.000000, -134.000000)" fill-rule="nonzero" id="编组-8备份">
<g transform="translate(40.000000, 112.000000)">
<g id="温度" transform="translate(24.000000, 22.000000)">
<rect id="矩形" fill="#000000" opacity="0" x="0" y="0" width="24" height="24"></rect>
<path d="M18.6,15 C18.15,14.25 17.4,13.5 16.5,13.05 L16.5,3 C16.5,1.35 15.3,0 13.65,0 C12,0 10.8,1.35 10.8,3 L10.8,13.2 C9.9,13.5 9.3,14.25 8.7,15 C8.1,15.9 7.8,16.95 7.8,18.15 C7.8,19.65 8.4,21.15 9.45,22.2 C10.5,23.25 12.15,24 13.65,24 C15.15,24 16.65,23.4 17.7,22.35 C18.75,21.3 19.35,19.8 19.35,18.3 C19.5,17.1 19.2,16.05 18.6,15 Z M13.65,22.95 C10.95,22.95 8.85,20.7 8.85,18.15 C8.85,16.35 9.9,14.7 11.55,13.8 L11.85,13.65 L11.85,3 C11.85,1.95 12.75,1.05 13.8,1.05 C14.85,1.05 15.75,1.95 15.75,3 L15.75,13.8 L16.05,13.95 C17.7,14.85 18.75,16.5 18.75,18.3 C18.6,20.85 16.35,22.95 13.65,22.95 Z M14.55,15.6 L14.55,6.15 C14.55,5.7 14.1,5.25 13.65,5.25 C13.2,5.25 12.75,5.7 12.75,6.15 L12.75,15.6 C11.7,15.9 11.1,16.95 11.1,18 C11.1,19.35 12.3,20.55 13.65,20.55 C15,20.55 16.2,19.35 16.2,18 C16.2,16.95 15.6,15.9 14.55,15.6 Z M8.25,4.35 L3.6,4.35 C3,4.35 2.7,4.05 2.7,3.45 C2.7,3 3,2.55 3.6,2.55 L8.4,2.55 C8.85,2.55 9.3,3 9.3,3.45 C9.15,4.05 8.85,4.35 8.25,4.35 L8.25,4.35 Z M8.25,7.2 L5.25,7.2 C4.8,7.2 4.35,6.75 4.35,6.3 C4.35,5.85 4.8,5.4 5.25,5.4 L8.25,5.4 C8.7,5.4 9.15,5.85 9.15,6.3 C9.15,6.9 8.85,7.2 8.25,7.2 Z M8.25,10.2 L7.35,10.2 C6.9,10.2 6.45,9.75 6.45,9.3 C6.45,8.85 6.9,8.4 7.35,8.4 L8.4,8.4 C8.85,8.4 9.3,8.85 9.3,9.3 C9.15,9.75 8.85,10.2 8.25,10.2 Z" id="形状" fill="#59D0E2"></path>
</g>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组 13</title>
<g id="·窑炉总览" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="总览" transform="translate(-1823.000000, -772.000000)">
<g id="编组-20备份-5" transform="translate(1786.000000, 764.000000)">
<g id="编组-13" transform="translate(45.000000, 16.000000) scale(1, -1) rotate(-180.000000) translate(-45.000000, -16.000000) translate(37.000000, 8.000000)">
<rect id="矩形" stroke="#979797" fill="#D8D8D8" opacity="0" x="0.5" y="0.5" width="15" height="15"></rect>
<path d="M3.67840479,4.47768215 L12.3215952,4.47768215 C12.87388,4.47768215 13.3215952,4.9253974 13.3215952,5.47768215 C13.3215952,5.70423387 13.2446673,5.92407165 13.1034098,6.1011931 L8.78181462,11.5200015 C8.43745903,11.9517857 7.80827335,12.0226607 7.37648905,11.6783051 C7.31796217,11.6316289 7.2648616,11.5785283 7.21818538,11.5200015 L2.89659016,6.1011931 C2.55223458,5.6694088 2.62310955,5.04022312 3.05489384,4.69586753 C3.23201529,4.55461005 3.45185307,4.47768215 3.67840479,4.47768215 Z" id="路径-2" fill="#03233C"></path>
</g>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 MiB

After

Width:  |  Height:  |  Size: 2.7 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

View File

@ -1,5 +0,0 @@
function AmenSelector() {
return <div className="amen-selector"></div>;
}
export default AmenSelector;

View File

@ -1,212 +0,0 @@
// AnnealFanRunFrequence
import cls from "./index.module.css";
import * as echarts from "echarts";
import GraphBase from "../GraphBase";
import { useEffect, useState } from "react";
import { useSelector } from "react-redux";
function WindFrequence(props) {
const [currLine, setCurrLine] = useState('Y61')
const [showChart, setShowChart] = useState(false);
const [currentLine, setCurrentLine] = useState([]);
const runState = useSelector((state) => state.annealFanFrequence.runtime);
const hisState = useSelector((state) => state.annealFanFrequence.history);
let dataList = [];
let seriesData = [];
const colors = [
"#12FFF5",
"#2760FF",
"#FFD160",
"#E80091",
"#8064ff",
"#ff8a3b",
"#8cd26d",
"#2aa1ff",
];
let options = null;
if (showChart) {
// keys() sort()
seriesData =
hisState != null
? Object.keys(hisState)
.sort()
.map((key) => hisState[key])
: Array(8)
.fill(1)
.map((_) => Array(7).fill(0));
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, [
// i % 8 8
{ offset: 0, color: colors[i % 8] + "40" },
{ offset: 0.5, color: colors[i % 8] + "20" },
{ offset: 1, color: colors[i % 8] + "00" },
]),
},
})),
tooltip: {
trigger: "axis",
},
};
} else {
dataList =
runState != null
? Object.keys(runState).map((fan) => ({
id: Math.random(),
name: fan,
value: runState[fan],
}))
: [
{ id: 1, name: "1#风机#1", value: "0m³/h" },
// { id: 133, name: "1##1", value: "0m³/h" },
// { id: 134, name: "1##1", value: "0m³/h" },
// { id: 1344, name: "1##1", value: "0m³/h" },
// { id: 51, name: "1##1", value: "0m³/h" },
// { id: 1534, name: "1##1", value: "0m³/h" },
// { id: 154, name: "1##1", value: "0m³/h" },
// { id: 153, name: "1##1", value: "0m³/h" },
// { id: 111, name: "1##1", value: "0m³/h" },
{ id: 2, name: "2#风机#1", value: "0m³/h" },
{ id: 3, name: "3#风机#1", value: "0m³/h" },
{ id: 4, name: "4#风机#1", value: "0m³/h" },
{ id: 5, name: "5#风机#1", value: "0m³/h" },
{ id: 11, name: "1#风机#2", value: "0m³/h" },
{ id: 12, name: "2#风机#2", value: "0m³/h" },
{ id: 13, name: "3#风机#2", value: "0m³/h" },
{ id: 14, name: "4#风机#2", value: "0m³/h" },
{ id: 15, name: "5#风机#2", value: "0m³/h" },
];
}
function handleSwitchChange(val) {
if (val) {
setShowChart(true);
} else {
setShowChart(false);
}
}
useEffect(() => {
if (!showChart) {
setCurrentLine((old) =>
dataList.filter((item) => item?.name.startsWith("1#"))
);
}
}, [showChart]);
function handleLineChange(line) {
const lineNum = line[2];
setCurrLine(line);
setCurrentLine((old) =>
dataList.filter((item) => item?.name.startsWith(`${lineNum}#`))
);
}
return (
<GraphBase
icon="kiln"
title="风机运行频率"
size={["middle", "long"]}
switchOptions={false}
switchPosition={[null, 200]} // [top, left]
onSwitch={handleSwitchChange}
dateOptions={["Y61", "Y62", "Y63", "Y64", "Y65"]}
selectWidth={70}
defaultSelect={currLine}
onDateChange={handleLineChange}
>
<div className={cls.chart} style={{ marginTop: "24px" }}>
{/* {showChart && (
<ReactECharts option={options} style={{ height: "100%" }} />
)} */}
{!showChart && (
<div className={cls.gridList}>
{currentLine.map((item) => (
<div
key={item.id}
className={cls.listItem}
style={{ padding: props.stretch ? "20px 0" : "" }}
>
<span className={cls.fanName}>{item.name}</span>
<span
className={cls.fanValue}
style={{
fontWeight: 700,
letterSpacing: 1,
fontSize: 16,
// color: "#e03537",
color: "#24aebb",
}}
>
{item.value}
</span>
</div>
))}
</div>
)}
</div>
</GraphBase>
);
}
export default WindFrequence;

View File

@ -1,52 +0,0 @@
.chart {
height: 100%;
}
.gridList {
margin-top: 12px;
display: grid;
grid-template-columns: 1fr 1fr;
/* grid-auto-row: ; */
gap: 8px;
}
.listItem {
border-radius: 2px;
padding: 10px 0;
text-align: center;
color: #fff;
box-shadow: inset 0 0 16px 4px rgba(255, 255, 255, 0.197);
display: flex;
align-items: center;
gap: 12px;
}
.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;
}
.flex {
display: flex;
align-items: center;
}
.fanName {
text-align: right;
flex: 7;
}
.fanValue {
flex: 3;
text-align: left;
}

View File

@ -1,28 +0,0 @@
import cls from "./index.module.css";
const Arrow = ({ direction, disabled, onClick }) => {
function handleClick() {
onClick(direction)
}
return (
<button
className={`${cls["arrow"]} ${
direction == "right" ? cls["arrow__right"] : ""
} ${true ? "disabled" : ""}`}
onClick={handleClick}
>
<div
className={`${cls["arrow-top"]} ${
direction == "right" ? cls["arrow-top__right"] : ""
}`}
></div>
<div
className={`${cls["arrow-bottom"]} ${
direction == "right" ? cls["arrow-bottom__right"] : ""
}`}
></div>
</button>
);
};
export default Arrow;

View File

@ -1,60 +0,0 @@
.arrow {
appearance: none;
outline: none;
border: none;
background: transparent;
width: 16px;
height: 48px;
position: absolute;
top: 112px;
left: 5px;
cursor: pointer;
z-index: 10;
}
.arrow.disabled > div {
background: #3d4a56;
}
.arrow__right {
left: unset;
right: 5px;
}
.arrow:hover > div {
background: #00f3ed;
}
.arrow-top {
transition: background 0.1s ease-out;
background: #1eaba9;
width: 8px;
height: 24px;
position: absolute;
top: 0;
left: 0;
border-radius: 12px;
transform: rotateZ(20deg) translateY(2px) translateX(4px);
}
.arrow-bottom {
transition: background 0.1s ease-out;
background: #1eaba9;
width: 8px;
height: 24px;
position: absolute;
bottom: 0;
left: 0;
border-radius: 12px;
transform: rotateZ(-20deg) translateY(-2px) translateX(4px);
}
.arrow-top__right {
transform: rotateZ(-20deg) translateY(4px) translateX(4px);
}
.arrow-bottom__right {
transform: rotateZ(20deg) translateY(-4px) translateX(4px);
}

View File

@ -1,32 +0,0 @@
import cls from "./index.module.css";
function BlueRect(props) {
const title = props.title || "DEFAULT";
const value = props.value || "0℃";
return (
<div
className={`${cls.blueRect} ${cls[title]}`}
style={{
background: props.blue ? "#0a4268ee" : "#0a426860",
}}
>
<span
className="title"
style={{
fontSize: "18px",
lineHeight: "24px",
color: props.blue ? "#40afb8" : "#fff",
fontWeight: 600,
userSelect: "none",
}}
>
{title}
</span>
<span className="value" style={{ userSelect: "none", fontSize: "22px" }}>
{value}
</span>
</div>
);
}
export default BlueRect;

View File

@ -1,544 +0,0 @@
.blueRect {
display: inline-block;
width: 106px;
height: 68px;
position: absolute;
top: 0;
left: 0;
padding: 6px 0;
display: flex;
flex-direction: column;
align-items: center;
color: #fff;
background: #0a426820;
border-radius: 4px;
}
.blueRect::before {
content: "";
display: inline-block;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 3px;
background: linear-gradient(
to right,
transparent 0%,
transparent 50%,
#24aebb 100%
);
border-radius: 3px;
}
.blueRect::after {
content: "";
display: inline-block;
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 3px;
background: linear-gradient(
to right,
#24aebb 0%,
transparent 50%,
transparent 100%
);
border-radius: 3px;
}
/** left **/
.TE271 {
top: 160px;
left: 70px;
}
.TE272 {
top: 254px; /* +94px */
left: 70px;
}
.TE273 {
top: 348px; /* +94px */
left: 70px;
}
.TE274 {
top: 442px;
left: 70px;
}
.TE279 {
top: 536px;
left: 70px;
}
.TE275 {
top: 160px;
left: 206px;
}
.TE276 {
top: 254px;
left: 206px; /* +136px */
}
.TE277 {
top: 348px; /* +94px */
left: 206px; /* +136px */
}
.TE278 {
top: 442px; /* +94px */
left: 206px; /* +136px */
}
.TE280 {
top: 536px; /* +94px */
left: 206px; /* +136px */
}
/** center top **/
.TE227 {
top: 128px;
left: 630px;
}
.TE229 {
top: 128px;
left: 746px; /* +120px */
}
.TE231 {
top: 128px;
left: 866px;
}
.TE233 {
top: 128px;
left: 980px;
}
.TE235 {
top: 128px;
left: 1100px;
}
.TE237 {
top: 128px;
left: 1220px;
}
.TE239 {
top: 128px;
left: 1330px;
}
.TE241 {
top: 128px;
left: 1450px;
}
/** center bottom **/
.TE228 {
top: 620px;
left: 600px;
}
.TE230 {
top: 620px;
left: 720px;
}
.TE232 {
top: 620px;
left: 850px;
}
.TE234 {
top: 620px;
left: 970px;
}
.TE236 {
top: 620px;
left: 1100px;
}
.TE238 {
top: 620px;
left: 1225px;
}
.TE240 {
top: 620px;
left: 1350px;
}
.TE242 {
top: 620px;
left: 1470px;
}
/** center middle **/
.TE201 {
top: 410px;
/* transform: rotate(-1deg); */
left: 480px;
}
.TE202 {
top: 410px;
/* transform: rotate(-1deg); */
left: 610px;
}
.TE203 {
top: 410px;
/* transform: rotate(-1deg); */
left: 740px;
}
.TE204 {
top: 410px;
/* transform: rotate(-1deg); */
left: 870px;
}
.TE205 {
top: 410px;
/* transform: rotate(-1deg); */
left: 1000px;
}
.TE206 {
top: 410px;
/* transform: rotate(-1deg); */
left: 1130px;
}
.TE207 {
top: 330px;
/* transform: rotate(-1deg); */
left: 1260px;
}
.TE208 {
top: 410px;
/* transform: rotate(-1deg); */
left: 1260px;
}
.TE209 {
top: 485px;
/* transform: rotate(-1deg); */
left: 1260px;
}
.TE210 {
top: 410px;
/* transform: rotate(-1deg); */
left: 1390px;
}
.TE211 {
top: 410px;
/* transform: rotate(-1deg); */
left: 1520px;
}
.TE212 {
top: 410px;
/* transform: rotate(-1deg); */
left: 1650px;
}
.TE213 {
top: 410px;
/* transform: rotate(-1deg); */
left: 1780px;
}
/** right **/
.TE214 {
top: 168px;
left: 2000px;
}
.TE215 {
top: 265px;
left: 2030px;
}
.TE216 {
top: 400px;
left: 2050px;
}
.TE217 {
top: 520px;
left: 2070px;
}
.TE218 {
top: 660px;
left: 2090px;
}
.TE219 {
top: 168px;
left: 2120px;
}
.TE220 {
top: 265px;
left: 2135px;
}
.TE221 {
top: 400px;
left: 2170px;
}
.TE222 {
top: 520px;
left: 2180px;
}
.TE223 {
top: 660px;
left: 2200px;
}
.TE224 {
top: 265px;
left: 2240px;
}
.TE225 {
top: 400px;
left: 2290px;
}
.TE226 {
top: 520px;
left: 2290px;
}
/** 一层 --- 窑底 **/
.TE401 {
top: 420px;
left: 20px;
}
.TE402 {
top: 420px;
left: 140px;
}
.TE403 {
top: 420px;
left: 260px;
}
.PE401 {
top: 320px;
left: 20px;
}
.PE402 {
top: 320px;
left: 140px;
}
.PE403 {
top: 320px;
left: 260px;
}
/** center top **/
.TE333 {
top: 128px;
left: 660px;
}
.TE335 {
top: 128px;
left: 775px;
}
.TE337 {
top: 128px;
left: 880px;
}
.TE339 {
top: 128px;
left: 1000px;
}
.TE341 {
top: 128px;
left: 1110px;
}
.TE343 {
top: 128px;
left: 1225px;
}
.TE345 {
top: 128px;
left: 1335px;
}
.TE347 {
top: 128px;
left: 1440px;
}
/** center bottom **/
.TE334 {
top: 620px;
left: 610px;
}
.TE336 {
top: 620px;
left: 730px;
}
.TE338 {
top: 620px;
left: 860px;
}
.TE340 {
top: 620px;
left: 980px;
}
.TE342 {
top: 620px;
left: 1110px;
}
.TE344 {
top: 620px;
left: 1235px;
}
.TE346 {
top: 620px;
left: 1360px;
}
.TE348 {
top: 620px;
left: 1480px;
}
/** center middle **/
.TE301 {
top: 340px;
transform: scaleY(0.8);
left: 450px;
}
.TE302 {
top: 400px;
transform: scaleY(0.8);
left: 450px;
}
.TE303 {
top: 460px;
transform: scaleY(0.8);
left: 450px;
}
.TE304 {
top: 400px;
/* transform: scaleY(0.8) skewX(-2deg); */
transform: scaleY(0.8);
left: 580px;
}
.TE305 {
top: 340px;
/* transform: scaleY(0.8) skewX(-2deg); */
transform: scaleY(0.8);
left: 720px;
}
.TE306 {
top: 400px;
/* transform: scaleY(0.8) skewX(-2deg); */
/* transform: scaleY(0.8) rotate(-1deg); */
transform: scaleY(0.8);
left: 720px;
}
.TE307 {
top: 460px;
/* transform: scaleY(0.8) rotate(-1deg); */
transform: scaleY(0.8);
left: 720px;
}
.TE308 {
top: 400px;
transform: scaleY(0.8);
left: 860px;
}
.TE309 {
top: 400px;
transform: scaleY(0.8);
left: 1000px;
}
.TE310 {
top: 400px;
transform: scaleY(0.8);
left: 1140px;
}
.TE311 {
top: 340px;
transform: scaleY(0.8);
left: 1280px;
}
.TE312 {
top: 400px;
transform: scaleY(0.8);
left: 1280px;
}
.TE313 {
top: 460px;
transform: scaleY(0.8);
left: 1280px;
}
.TE314 {
top: 400px;
transform: scaleY(0.8);
left: 1420px;
}
.TE315 {
top: 400px;
transform: scaleY(0.8);
left: 1560px;
}
.TE316 {
top: 400px;
transform: scaleY(0.8);
left: 1700px;
}
.TE317 {
top: 340px;
transform: scaleY(0.8);
left: 1840px;
}
.TE318 {
top: 400px;
transform: scaleY(0.8);
left: 1840px;
}
.TE319 {
top: 460px;
transform: scaleY(0.8);
left: 1840px;
}
/** right **/
.TE327 {
top: 152px;
left: 2000px;
transform: scale(0.8) skewX(5deg);
}
.TE320 {
top: 252px;
left: 2020px;
transform: scale(0.8) skewX(7deg);
}
.TE321 {
top: 400px;
left: 2040px;
transform: scale(0.8) skewX(7deg);
}
.TE322 {
top: 532px;
left: 2060px;
transform: scale(0.8) skewX(7deg);
}
.TE330 {
top: 656px;
left: 2080px;
transform: scale(0.8) skewX(7deg);
}
.TE323 {
top: 152px;
left: 2100px;
transform: scale(0.8) skewX(7deg);
}
.TE328 {
top: 252px;
left: 2120px;
transform: scale(0.8) skewX(7deg);
}
.TE331 {
top: 400px;
left: 2140px;
transform: scale(0.8) skewX(7deg);
}
.TE329 {
top: 532px;
left: 2160px;
transform: scale(0.8) skewX(7deg);
}
.TE326 {
top: 656px;
left: 2180px;
transform: scale(0.8) skewX(7deg);
}
.TE324 {
top: 252px;
left: 2220px;
transform: scale(0.8) skewX(7deg);
}
.TE332 {
top: 400px;
left: 2260px;
transform: scale(0.8) skewX(7deg);
}
.TE325 {
top: 532px;
left: 2260px;
transform: scale(0.8) skewX(7deg);
}

View File

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

View File

@ -32,7 +32,7 @@ export default function CompanyName() {
<img src={TopSide} alt="图片丢失" className={cls.TopSideLeft}/>
<div className={cls.TopSideLeftLine}>
<img src={LeftLine} alt="图片丢失" className={cls.TopSideLeftLineicon}/>
<h2 className={cls.TopSideLeftTxt}>单位河南汇融数字科技有限公司</h2>
<h2 className={cls.TopSideLeftTxt}>单位河南汇融科技服务有限公司</h2>
</div>
<div>
<h2 className={cls.TopTitleText}>

View File

@ -38,10 +38,9 @@
.TopSideLeftTxt {
margin-right: 120px;
margin-top: 15px;
color: rgb(255, 255, 255, 0.6);
color: rgb(255, 255, 255, 0.8);
font-size: 20px;
font-weight: 300px;
letter-spacing: 1px;
line-height: 22.174976px;
}
}
@ -78,9 +77,9 @@
}
.TopTitleText {
margin-top: 40px;
margin-top: 16px;
letter-spacing: 8px;
font-size: 34px;
font-size: 32px;
color: #00fff7;
text-align: center;
letter-spacing: 2px;

View File

@ -1,36 +1,60 @@
import BottomBarItem from "../BottomItemBackground";
import React, { Component } from "react";
import cls from "./righttable.module.scss";
import { useSelector } from "react-redux";
import { ScrollBoard } from "@jiaminghi/data-view-react";
function Chart1(props) {
const rawData = useSelector((state) => state.cutting.productData);
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 config = {
// headerBGC: "rgba(4, 44, 76, 0.3)",
headerBGC: "#044A8460",
let header = ["产线名", "原板宽度", "净板宽", "玻璃厚度"];
let config = {
headerBGC: "rgba(4, 44, 76, 0.3)",
header: [
'<span style="color:#fff; padding-left: 8px;">产线名<span/>',
'<span style="color:#fff; padding-left: 8px;">玻璃长度<span/>',
'<span style="color:#fff; padding-left: 8px;">玻璃宽度<span/>',
'<span style="color:#fff; padding-left: 8px;">玻璃厚度<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",
oddRowBGC: "#044A8460",
evenRowBGC: "#0b549970",
oddRowBGC: "#042444",
evenRowBGC: "#042c4c",
columnWidth: [128],
headerHeight: 40,
hoverPause: true,
data: replaceStyle(filterData(rawData), 0.7),
};
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={props.className}
style={props.style}
className={this.props.className}
style={this.props.style}
>
<div
className={cls.CenterChart1itemDetailBorder}
@ -39,115 +63,11 @@ function Chart1(props) {
<span className={cls.CenterFormitemDetailBorderLine1}></span>
<span className={cls.CenterFormitemDetailBorderLine2}></span>
<span className={cls.CenterFormitemDetailBorderLine3}></span>
{config.data.length !== 0 && <ScrollBoard config={config} style={{}} />}
{config.data.length === 0 && (
<p
style={{
color: "#cccf",
fontSize: "24px",
userSelect: "none",
textAlign: "center",
paddingTop: "72px",
}}
>
暂无数据
</p>
)}
<ScrollBoard config={config} style={{}} />
</div>
</BottomBarItem>
);
}
}
export default Chart1;
//
var rawData = [
{
id: 1,
length: 1209,
productionLine: "Y61",
square: 123.3,
thick: 2,
wide: 1089,
},
{
id: 2,
length: 1119,
productionLine: "Y62",
square: 103.3,
thick: 2,
wide: 1339,
},
{
id: 3,
length: 1019,
productionLine: "Y63",
square: 233,
thick: 1,
wide: 1111,
},
{
id: 4,
length: 2000,
productionLine: "Y64",
square: 233,
thick: 1,
wide: 1232,
},
{
id: 5,
length: 1560,
productionLine: "Y65",
square: 233,
thick: 1,
wide: 996,
},
{
id: 6,
length: 1990,
productionLine: "Y66",
square: 233,
thick: 1,
wide: 416,
},
];
function filterData(rawData) {
return (rawData ?? []).map((item) => [
// 线
item.productionLine,
//
item.length,
//
item.wide,
//
item.thick,
]);
}
// 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 = ["线", "", "", ""];
function replaceStyle(Arr, opacity) {
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,${opacity})">${
Arr[i][j]
} ${j == 0 ? "" : "mm"}<span/>`;
}
}
return temp;
}

View File

@ -5,7 +5,7 @@
flex-direction: column;
justify-content: flex-start;
// background-color: rgba(4, 44, 76, 0.2);
background-color: rgba(4, 44, 76, 0.2);
.CenterChart1itemTXT {
width: 100%;
height: 10%;

View File

@ -1,7 +0,0 @@
@font-face {
font-family: "HelloFont WenYiHei";
/* font-style: normal;
font-weight: 400; */
src: url("./ziyou.ttf");
/* font-display: swap; */
}

View File

@ -1,39 +1,37 @@
import GraphBase from "../GraphBase";
import "./font.css";
import cls from "./index.module.css";
import { useEffect, useState } from "react";
import { Tooltip, Button } from "antd";
import { InfoCircleOutlined } from "@ant-design/icons";
import { useSelector } from "react-redux";
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",
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: "45%",
position: 'absolute',
display: 'inline-block',
width: '2px',
height: '80%',
top: '10%',
left: '50%',
background:
"linear-gradient(to bottom, transparent, #fff3, #fffa, #fff3, transparent)",
'linear-gradient(to bottom, transparent, #fff3, #fffa, #fff3, transparent)',
}}
></span>
)}
@ -43,212 +41,93 @@ const SmallBox = (props) => {
};
function WindFrequence(props) {
const [dataSource, setDataSource] = useState("Y61");
const [currentLineTemp, setCurrentLineTemp] = useState([]);
const currentTempList = useSelector((state) => state.annealTemperature?.data);
const lines = ["Y61", "Y62", "Y63", "Y64", "Y65"];
function handleSourceChange(line) {
setDataSource(line);
}
const [dataSource, setDataSource] = useState('风机');
useEffect(() => {
setCurrentLineTemp(
(currentTempList &&
currentTempList[1 + lines.indexOf(dataSource) + "#"]) ||
[]
);
}, [dataSource]);
function handleSourceChange(v) {
console.log('val', v);
}
return (
<GraphBase
icon="temp"
icon="pause"
title="当前温度"
dateOptions={["Y61", "Y62", "Y63", "Y64", "Y65"]}
selectWidth={70}
defaultSelect={dataSource}
dateOptions={['风机', '风阀', '电加热']}
onDateChange={handleSourceChange}
size={["middle", "long"]}
size={['middle', 'long']}
>
<div className={cls.mainContent + " " + cls.grid}>
<div className={cls.mainContent + ' ' + cls.grid}>
<SmallBox>
<h1 className={cls.areaName}>A1区板上</h1>
<div className={cls.areaContent}>
<span className={cls.areaValue}>
{(+currentLineTemp[0]).toFixed(2) || 0}
</span>
<span className={cls.areaValue}>
{(+currentLineTemp[1]).toFixed(2) || 0}
</span>
<span className={cls.areaValue}>
{(+currentLineTemp[2]).toFixed(2) || 0}
</span>
<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}>A2区板上</h1>
<h1 className={cls.areaName}>A1区板上</h1>
<div className={cls.areaContent}>
<span className={cls.areaValue}>
{(+currentLineTemp[6]).toFixed(2) || 0}
</span>
<span className={cls.areaValue}>
{(+currentLineTemp[7]).toFixed(2) || 0}
</span>
<span className={cls.areaValue}>
{(+currentLineTemp[8]).toFixed(2) || 0}
</span>
<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}>B区板上</h1>
<h1 className={cls.areaName}>A1区板上</h1>
<div className={cls.areaContent}>
<span className={cls.areaValue}>
{(+currentLineTemp[12]).toFixed(2) || 0}
</span>
<span className={cls.areaValue}>
{(+currentLineTemp[13]).toFixed(2) || 0}
</span>
<span className={cls.areaValue}>
{(+currentLineTemp[14]).toFixed(2) || 0}
</span>
<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}>C区板上</h1>
<h1 className={cls.areaName}>A1区板上</h1>
<div className={cls.areaContent}>
<span className={cls.areaValue}>
{(+currentLineTemp[18]).toFixed(2) || 0}
</span>
<span className={cls.areaValue}>
{(+currentLineTemp[19]).toFixed(2) || 0}
</span>
<span className={cls.areaValue}>
{(+currentLineTemp[20]).toFixed(2) || 0}
</span>
<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>
<h1 className={cls.areaName}>A1区板上</h1>
<div className={cls.areaContent}>
<span className={cls.areaValue}>
{(+currentLineTemp[3]).toFixed(2) || 0}
</span>
<span className={cls.areaValue}>
{(+currentLineTemp[4]).toFixed(2) || 0}
</span>
<span className={cls.areaValue}>
{(+currentLineTemp[5]).toFixed(2) || 0}
</span>
<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}>A2区板下</h1>
<div className={cls.areaContent}>
<span className={cls.areaValue}>
{(+currentLineTemp[9]).toFixed(2) || 0}
</span>
<span className={cls.areaValue}>
{(+currentLineTemp[10]).toFixed(2) || 0}
</span>
<span className={cls.areaValue}>
{(+currentLineTemp[11]).toFixed(2) || 0}
</span>
</div>
</SmallBox>
<SmallBox>
<h1 className={cls.areaName}>B区板下</h1>
<div className={cls.areaContent}>
<span className={cls.areaValue}>
{(+currentLineTemp[15]).toFixed(2) || 0}
</span>
<span className={cls.areaValue}>
{(+currentLineTemp[16]).toFixed(2) || 0}
</span>
<span className={cls.areaValue}>
{(+currentLineTemp[17]).toFixed(2) || 0}
</span>
</div>
</SmallBox>
<SmallBox>
<h1 className={cls.areaName}>C区板下</h1>
<div className={cls.areaContent}>
<span className={cls.areaValue}>
{(+currentLineTemp[21]).toFixed(2) || 0}
</span>
<span className={cls.areaValue}>
{(+currentLineTemp[22]).toFixed(2) || 0}
</span>
<span className={cls.areaValue}>
{(+currentLineTemp[23]).toFixed(2) || 0}
</span>
</div>
</SmallBox>
<SmallBox split={false} style={{ position: "relative" }}>
<SmallBox split={false}>
<div className={cls.areaPureContent}>
<div
className="hint"
style={{ position: "absolute", top: "3px", right: "3px" }}
>
<Tooltip title="红外温度">
<Button
shape="circle"
type="text"
style={{ color: "#cccc" }}
icon={<InfoCircleOutlined />}
></Button>
</Tooltip>
</div>
<span className={cls.areaPureValue} style={{ fontSize: "12px" }}>
{(+currentLineTemp[26]).toFixed(2) || 0}
</span>
<span className={cls.areaPureValue} style={{ fontSize: "12px" }}>
{(+currentLineTemp[27]).toFixed(2) || 0}
</span>
<span className={cls.areaPureValue} style={{ fontSize: "12px" }}>
{(+currentLineTemp[28]).toFixed(2) || 0}
</span>
<span className={cls.areaPureValue}>123.8</span>
<span className={cls.areaPureValue}>123.8</span>
<span className={cls.areaPureValue}>123.8</span>
</div>
</SmallBox>
<SmallBox split={false} style={{ position: "relative" }}>
<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}>
<div
className="hint"
style={{ position: "absolute", top: "3px", right: "3px" }}
>
<Tooltip title="压延机冷却水温度 | 过度辊台冷却水温度 | 唇砖冷却水温度">
<Button
shape="circle"
type="text"
style={{ color: "#cccc" }}
icon={<InfoCircleOutlined />}
></Button>
</Tooltip>
</div>
<span className={cls.areaPureValue} style={{ fontSize: "12px" }}>
{(+currentLineTemp[29]).toFixed(2) || 0}
</span>
<span className={cls.areaPureValue} style={{ fontSize: "12px" }}>
{(+currentLineTemp[30]).toFixed(2) || 0}
</span>
<span className={cls.areaPureValue} style={{ fontSize: "12px" }}>
{(+currentLineTemp[31]).toFixed(2) || 0}
</span>
<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}>RET1区</h1>
<h1 className={cls.areaName}>A1区板上</h1>
<div className={cls.areaContent}>
<span className={cls.areaValue}>
{(+currentLineTemp[24]).toFixed(2) || 0}
</span>
<span className={cls.areaValue}>123.8</span>
</div>
</SmallBox>
<SmallBox>
<h1 className={cls.areaName}>RET2区</h1>
<h1 className={cls.areaName}>A1区板上</h1>
<div className={cls.areaContent}>
<span className={cls.areaValue}>
{(+currentLineTemp[25]).toFixed(2) || 0}
</span>
<span className={cls.areaValue}>123.8</span>
</div>
</SmallBox>
</div>

View File

@ -50,7 +50,7 @@
.areaName {
color: #fff;
font-size: 18px;
font-size: 20px;
line-height: 1;
letter-spacing: 1.5px;
margin: 0;
@ -66,7 +66,7 @@
padding: 0 8px;
}
span.areaPureValue:not(:first-of-type) {
.areaPureValue:not(:first-child) {
border-left: 2px solid #fff6;
}
@ -80,11 +80,9 @@ span.areaPureValue:not(:first-of-type) {
.areaPureValue,
.areaValue {
display: inline-block;
font-size: 14px;
line-height: 16px;
font-size: 17px;
line-height: 22px;
letter-spacing: 1.2px;
font-family: "HelloFont WenYiHei", sans-serif;
color: #53c2d4;
}
.switchLabel {

View File

@ -1,184 +0,0 @@
import { useEffect, useState } from "react";
import cls from "./index.module.scss";
import { useSelector } from "react-redux";
import Arrow from "../../Arrow";
const EnergyCostRealtime = () => {
const [isPage1, setIsPage1] = useState(false);
const energyInfo = useSelector((state) => state.energy?.info);
// function handleClick() {
// setIsPage1((pre) => !pre);
// }
useEffect(() => {
const timer = setInterval(() => {
setIsPage1(pre => !pre);
}, 10000);
return () => {
clearInterval(timer);
}
}, []);
return (
<>
{/* <Arrow key="left" direction="left" onClick={handleClick} />
<Arrow key="right" direction="right" onClick={handleClick} /> */}
{isPage1 && (
<div className={`${cls.cost__info} flex`}>
<div className={`${cls.info__item_groups_col1}`}>
<div className={cls.info__item}>
<i
style={{
fontSize: "18px",
fontStyle: "normal",
paddingRight: "6px",
}}
>
余热发电(实时)
</i>
<span style={{ fontSize: "17px", color: "#3ce8ff" }}>
{(+energyInfo?.elecQty2)?.toFixed(2) || 0}kWh
</span>
</div>
<div className={cls.info__item}>
<i
style={{
fontSize: "18px",
fontStyle: "normal",
paddingRight: "6px",
}}
>
余热发电(总量)
</i>
<span style={{ fontSize: "17px", color: "#3ce8ff" }}>
{(+energyInfo?.elecQty3)?.toFixed(2) || 0}kWh
</span>
</div>
</div>
<div className={cls.info__item_groups}>
<div className={cls.info__item}>
<i
style={{
fontSize: "18px",
fontStyle: "normal",
paddingRight: "6px",
}}
>
水耗量
</i>
<span style={{ fontSize: "17px", color: "#3ce8ff" }}>
{(+energyInfo?.waterQty)?.toFixed(2) || 0}Km³
</span>
</div>
<div className={cls.info__item}>
<i
style={{
fontSize: "18px",
fontStyle: "normal",
paddingRight: "6px",
}}
>
天然气I
</i>
<span style={{ fontSize: "17px", color: "#3ce8ff" }}>
{energyInfo?.ngQty1 || "0Nm³"}
</span>
</div>
<div className={cls.info__item}>
<i
style={{
fontSize: "18px",
fontStyle: "normal",
paddingRight: "6px",
}}
>
电耗量
</i>
<span style={{ fontSize: "17px", color: "#3ce8ff" }}>
{(+energyInfo?.elecQty2)?.toFixed(2) || 0}kWh
</span>
</div>
<div className={cls.info__item}>
<i
style={{
fontSize: "18px",
fontStyle: "normal",
paddingRight: "6px",
}}
>
天然气II
</i>
<span style={{ fontSize: "17px", color: "#3ce8ff" }}>
{energyInfo?.ngQty2 || "0Nm³"}
</span>
</div>
</div>
</div>
)}
{!isPage1 && (
<div className={cls.energy_info_new}>
<div className="energy_info_new--item">
<i
style={{
fontSize: "18px",
fontStyle: "normal",
paddingRight: "6px",
}}
>
智慧能源光伏发电(昨日)/kwh
</i>
<span style={{ fontSize: "17px", color: "#3ce8ff" }}>
{(+energyInfo?.elecQty6)?.toFixed(2) || 0}kWh
</span>
</div>
<div className="energy_info_new--item">
<i
style={{
fontSize: "18px",
fontStyle: "normal",
paddingRight: "6px",
}}
>
许昌安彩光伏发电(昨日)/kwh
</i>
<span style={{ fontSize: "17px", color: "#3ce8ff" }}>
{(+energyInfo?.elecQty7)?.toFixed(2) || 0}kWh
</span>
</div>
<div className="energy_info_new--item">
<i
style={{
fontSize: "18px",
fontStyle: "normal",
paddingRight: "6px",
}}
>
智慧能源光伏发电(总量)/kwh
</i>
<span style={{ fontSize: "17px", color: "#3ce8ff" }}>
{(+energyInfo?.elecQty4)?.toFixed(2) || 0}kWh
</span>
</div>
<div className="energy_info_new--item">
<i
style={{
fontSize: "18px",
fontStyle: "normal",
paddingRight: "6px",
}}
>
许昌安彩光伏发电(总量)/kwh
</i>
<span style={{ fontSize: "17px", color: "#3ce8ff" }}>
{(+energyInfo?.elecQty5)?.toFixed(2) || 0}kWh
</span>
</div>
</div>
)}
</>
);
};
export default EnergyCostRealtime;

View File

@ -1,60 +0,0 @@
.cost__info {
margin-top: 4px;
margin-bottom: 6px;
// margin-bottom: 12px;
}
.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);
font-size: 14px;
line-height: 28px;
padding-left: 12px;
padding: 8px 0;
user-select: none;
display: flex;
flex-direction: column;
align-items: center;
}
.hAuto {
height: auto;
}
.info__item_groups {
flex: 2;
margin-left: 8px;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 8px;
}
.info__item_groups_col1 {
flex: 1;
display: grid;
grid-template-rows: 1fr 1fr;
gap: 8px;
}
.energy_info_new {
color: #fff;
display: grid;
gap: 8px;
grid-template-rows: 1fr 1fr;
grid-template-columns: 1fr 1fr;
height: 162px;
padding: 4px 0;
}
.energy_info_new > div {
border-radius: 2px;
box-shadow: inset 0 0 17px 0px hsla(0, 0%, 100%, 0.15);
font-size: 14px;
line-height: 28px;
color: hsl(0, 0%, 100%, 0.9);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}

View File

@ -1,92 +1,112 @@
import cls from "./index.module.css";
import { Radio, Select } from "antd";
import ReactECharts from "echarts-for-react";
import { useState } from "react";
import { useSelector } from "react-redux";
import { getOptions } from "../../../../utils/energeChartOption";
import triangle from "../../../../assets/Icon/triangle.svg";
import dayjs from "dayjs";
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 elecTrend = useSelector((state) => state.energy.trend.elec);
const gasITrend = useSelector((state) => state.energy.trend.natGas1);
const gasIITrend = useSelector((state) => state.energy.trend.natGas2);
const [source, setSource] = useState("elec");
const [period, setPeriod] = useState("week");
const [timestr, setTimestr] = useState(
dayjs().subtract(7, "day").format("YYYY.MM.DD") +
" - " +
dayjs().subtract(1, "day").format("YYYY.MM.DD")
);
const currentTrend =
source == "elec" ? elecTrend : source == "gasi" ? gasITrend : gasIITrend;
const options = getOptions(
period,
source,
currentTrend ?? { week: [], month: [], year: [] }
);
function handleDateChange(value) {
setPeriod(
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: [
{
: "week",
: "month",
: "year",
}[value]
);
setTimestr(
{
:
dayjs().subtract(1, "year").endOf("year").format("YYYY.MM.") +
"29 - " +
dayjs().endOf("year").format("YYYY.MM.") +
"28",
:
dayjs().subtract(7, "day").format("YYYY.MM.DD") +
" - " +
dayjs().subtract(1, "day").format("YYYY.MM.DD"),
:
dayjs().subtract(1, "month").format("YYYY.MM.") +
"29 - " +
dayjs().format("YYYY.MM.") +
"28",
}[value]
);
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>
<div className={`${cls.choiceBar} flex items-center justify-between`}>
<Radio.Group
value={source}
defaultValue="week"
buttonStyle="solid"
onChange={(v) => setSource(v.target.value)}
className={`${cls.radioGroup} flex items-center justify-between`}
>
<Radio.Button value="elec" className="radio-group__item">
</Radio.Button>
<Radio.Button value="gasi" className="radio-group__item">
天然气I
</Radio.Button>
<Radio.Button value="gasii" className="radio-group__item">
天然气II
</Radio.Button>
</Radio.Group>
{/* <Radio.Group
value={period}
buttonStyle="solid"
onChange={(v) => setPeriod(v.target.value)}
className={cls.radioGroup}
>
<Radio.Button value="day" className="radio-group__item">
</Radio.Button>
<Radio.Button value="week" className="radio-group__item">
</Radio.Button>
@ -96,53 +116,10 @@ const EnergyCostChart = (props) => {
<Radio.Button value="year" className="radio-group__item">
</Radio.Button>
</Radio.Group> */}
<div className={cls.graphBaseDesc}>{timestr}</div>
<Select
defaultValue={"周"}
style={{ width: 60 }}
popupClassName="xc-date-selector-menu"
className={cls.radioGroupShort}
options={["周", "月", "年"].map((item) => ({
label: item,
value: item,
}))}
suffixIcon={<img src={triangle} alt="#" />}
notFoundContent={
<span
style={{
color: "#fff",
fontSize: "14px",
lineHeight: 1,
paddingLeft: "12px",
}}
>
- -
</span>
}
onChange={(value, option) => handleDateChange(value)}
/>
</Radio.Group>
</div>
<div className="flex-1" style={{ marginTop: "8px" }}>
{options && (
<ReactECharts option={options} style={{ height: "180px" }} />
)}
{!options && (
<p
style={{
color: "#cccf",
fontSize: "20px",
userSelect: "none",
textAlign: "center",
paddingTop: "32px",
}}
>
暂无数据
</p>
)}
<div className="flex-1">
<ReactECharts option={options} style={{ height: '180px' }} />
</div>
</div>
);

View File

@ -16,12 +16,6 @@
letter-spacing: 1.2px;
color: #52fff8;
}
.graphBaseDesc {
margin: 0 12px;
line-height: 1;
color: #76fff9;
flex: 1;
}
.energyCostChart .titleBar .legend {
display: flex;
@ -47,7 +41,7 @@
padding-left: 16px;
}
.energyCostChart .titleBar .legend ul li::before {
content: "";
content: '';
position: absolute;
left: 2px;
top: 2px;
@ -73,10 +67,6 @@
border: none !important;
border-radius: 0 !important;
}
.radioGroupShort * {
border: none !important;
border-radius: 6px !important;
}
.radioGroup *:focus-within {
box-shadow: none !important;
}

View File

@ -1,15 +1,26 @@
import cls from "./index.module.scss";
import Container from "../../Container";
import TechSplitline from "../TechSplitline";
import EnergyCostChart from "./EnergyCostChart";
import EnergyCostRealtime from "./EnergeCostRealtime";
import cls from './index.module.scss';
import Container from '../../Container';
import TechSplitline from '../TechSplitline';
import EnergyCostChart from './EnergyCostChart';
function EnergyCost(props) {
return (
<Container title="能耗" icon="battery" className={cls.energyCost}>
<Container title="能耗" icon="charger" className={cls.energyCost}>
<div className={`flex flex-col`}>
<EnergyCostRealtime />
<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 : 83</div>
<div className={cls.info__item}> : 52kWh</div>
<div className={cls.info__item}> II: 32</div>
</div>
</div>
<TechSplitline />

View File

@ -2,7 +2,7 @@
background: url(../../../assets/energy.png) no-repeat;
background-size: 100% 100%;
width: 626px;
height: 460px;
height: 400px;
}
.cost__info {
@ -18,9 +18,12 @@
border-radius: 2px;
color: hsl(0, 0%, 100%, 0.9);
box-shadow: inset 0 0 17px 0px hsla(0, 0%, 100%, 0.15);
font-size: 14px;
// width: 288px;
height: 43px;
font-size: 20px;
letter-spacing: 1.43px;
line-height: 40px;
padding-left: 12px;
text-align: center;
user-select: none;
}

View File

@ -1,20 +1,46 @@
import GraphBase from "../../Common/GraphBase";
import "./index.module.scss";
import { useSelector } from "react-redux";
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" : item == 0 ? "#a81b2655" : "#E6A23C55"
item == 1 ? "#2760ff55" : "#a81b2655"
}; margin-right: 8px; width: 8px; height: 8px; border-radius: 8px; background: ${
item == 1 ? "#2760ff" : item == 0 ? "#a81b26" : "#E6A23C"
}"></span><span style="color: ${
item == 1 ? "#2760ff" : item == 0 ? "#a81b26" : "#E6A23C"
}">${item == 1 ? "运行" : item == 0 ? "故障" : "未运行"}</span></div>`;
item == 1 ? "#2760ff" : "#a81b26"
}"></span><span style="color: ${item == 1 ? "#2760ff" : "#a81b26"}">${
item == 1 ? "正常" : "故障"
}</span></div>`;
}
return `<span style='color: #fffa'>${item}</span>`;
});
@ -23,17 +49,7 @@ function attachStyle(data) {
function FanInfo(props) {
const rowNum = props.rows || 8;
// 使使 source 使 annealFanInfo
const fanInfo = useSelector((state) => state[props.source ?? "fanInfo"].data);
const data = Object.keys(fanInfo).map((key, index) => {
return [
index + 1,
key,
fanInfo[key] == "运行" ? 1 : fanInfo[key] == "故障" ? 0 : 2,
];
});
const dataRight = [...data.slice(rowNum), ...data.slice(0, rowNum)];
let data = getRandomRows(100);
let config = {
headerBGC: "rgba(4, 44, 76, 0.3)",
@ -44,10 +60,11 @@ function FanInfo(props) {
],
oddRowBGC: "#042444",
evenRowBGC: "#042c4c",
// columnWidth: data.length > 12 ? [50, 136] : [88, 256],
columnWidth: [50, 136],
columnWidth: [70, 96],
rowNum,
hoverPause: true,
// headerHeight: 40,
hoverPause: false,
// data: replaceStyle(data, 0.7),
data: attachStyle(data),
};
@ -61,9 +78,7 @@ function FanInfo(props) {
className="flex"
style={{
display: "flex",
flex: 1,
gap: "20px",
// gap: data.length > 12 ? "20px" : 0,
height: "100%",
position: "relative",
}}
@ -71,15 +86,9 @@ function FanInfo(props) {
<div className="flex-1" style={{ flex: 1 }}>
<ScrollBoard
config={config}
style={{
width: "280px",
// width: data.length > 12 ? "280px" : "100%",
height: "100%",
}}
style={{ width: "280px", height: "100%" }}
/>
</div>
{/* {data.length > 12 && (
<> */}
<div
className="verticalLine"
style={{
@ -94,12 +103,10 @@ function FanInfo(props) {
></div>
<div className="flex-1" style={{ flex: 1 }}>
<ScrollBoard
config={{ ...config, data: attachStyle(dataRight) }}
config={config}
style={{ width: "280px", height: "100%" }}
/>
</div>
{/* </>
)} */}
</div>
</GraphBase>
);

View File

@ -1,248 +0,0 @@
import GraphBase from "../GraphBase";
import "./index.module.scss";
import { useSelector } from "react-redux";
import { ScrollBoard } from "@jiaminghi/data-view-react";
import { useMemo } from "react";
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" : item == 0 ? "#a81b2655" : "#E6A23C55"
}; margin-right: 8px; width: 8px; height: 8px; border-radius: 8px; background: ${
item == 1 ? "#2760ff" : item == 0 ? "#a81b26" : "#E6A23C"
}"></span><span style="color: ${
item == 1 ? "#2760ff" : item == 0 ? "#a81b26" : "#E6A23C"
}">${item == 1 ? "运行" : item == 0 ? "故障" : "未运行"}</span></div>`;
}
return `<span style='color: #fffa'>${item}</span>`;
});
});
}
function FanInfo(props) {
// 使使 source 使 annealFanInfo
const fanInfo = useSelector((state) => state[props.source ?? "fanInfo"].data);
const data = Object.keys(fanInfo).map((key, index) => {
return [
index + 1,
key,
fanInfo[key] == "运行" ? 1 : fanInfo[key] == "故障" ? 0 : 2,
];
});
const y61 = useMemo(
() => data.filter((item) => item[1].startsWith("1#")) || [],
[data]
);
const y62 = useMemo(
() => data.filter((item) => item[1].startsWith("2#")) || [],
[data]
);
const y63 = useMemo(
() => data.filter((item) => item[1].startsWith("3#")) || [],
[data]
);
const y64 = useMemo(
() => data.filter((item) => item[1].startsWith("4#")) || [],
[data]
);
const y65 = useMemo(
() => data.filter((item) => item[1].startsWith("5#")) || [],
[data]
);
const y66 = useMemo(() => [...y65.slice(5), ...y65.slice(0, 5)], [y65]);
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: data.length > 12 ? [50, 136] : [88, 256],
columnWidth: [50, 136],
rowNum: 6,
hoverPause: true,
data: [],
};
return (
<GraphBase
icon="kiln"
title="风机信息"
size={props.longBg ? ["middle", "full"] : ["middle", "short"]}
>
<div
style={{
display: "grid",
gridTemplateRows: "auto 2px auto 2px auto",
gap: "4px",
// height: "100%",
position: "relative",
}}
>
<div className="" style={{ display: "flex", gap: "8px" }}>
<div>
<h1
style={{
fontSize: "16px",
fontWeight: 400,
textAlign: "center",
letterSpacing: "2px",
color: "#fff",
background: "#012041",
padding: "4px 0",
}}
>
产线Y61
</h1>
<ScrollBoard
key="y61"
config={{ ...config, data: attachStyle(y61) }}
style={{
width: "280px",
height: "280px",
}}
/>
</div>
<div>
<h1
style={{
fontSize: "16px",
fontWeight: 400,
textAlign: "center",
letterSpacing: "2px",
color: "#fff",
background: "#012041",
padding: "4px 0",
}}
>
产线Y62
</h1>
<ScrollBoard
key="y62"
config={{ ...config, data: attachStyle(y62) }}
style={{
width: "280px",
height: "280px",
}}
/>
</div>
</div>
<div
className="horizontalLine"
style={{
height: "2px",
background:
"radial-gradient(ellipse, #15E8F563, #15E8F599, transparent, transparent)",
}}
></div>
<div className="" style={{ display: "flex", gap: "8px" }}>
<div>
<h1
style={{
fontSize: "16px",
fontWeight: 400,
textAlign: "center",
letterSpacing: "2px",
color: "#fff",
background: "#012041",
padding: "4px 0",
}}
>
产线Y63
</h1>
<ScrollBoard
key="y63"
config={{ ...config, data: attachStyle(y63) }}
style={{
width: "280px",
height: "280px",
}}
/>
</div>
<div>
{/* <div style={{ display: "flex", flexDirection: "column" }}> */}
<h1
style={{
fontSize: "16px",
fontWeight: 400,
textAlign: "center",
letterSpacing: "2px",
color: "#fff",
background: "#012041",
padding: "4px 0",
}}
>
产线Y64
</h1>
<ScrollBoard
key="y64"
config={{ ...config, data: attachStyle(y64) }}
style={{
width: "280px",
height: "280px",
}}
/>
</div>
</div>
<div
className="horizontalLine"
style={{
height: "2px",
background:
"radial-gradient(ellipse, #15E8F563, #15E8F599, transparent, transparent)",
}}
></div>
<div
className=""
style={{ height: "240px", display: "flex", flexDirection: "column" }}
>
<h1
style={{
fontSize: "16px",
fontWeight: 400,
textAlign: "center",
letterSpacing: "2px",
color: "#fff",
background: "#012041",
padding: "4px 0",
}}
>
产线Y65
</h1>
<div style={{ flex: 1, height: "1px", display: "flex", gap: "4px" }}>
<ScrollBoard
key="y65"
config={{ ...config, data: attachStyle(y65), rowNum: 5 }}
style={{
width: "280px",
height: "220px",
}}
/>
<ScrollBoard
key="y66"
config={{ ...config, data: attachStyle(y66), rowNum: 5 }}
style={{
width: "280px",
height: "220px",
}}
/>
</div>
</div>
</div>
</GraphBase>
);
}
export default FanInfo;

View File

@ -1,50 +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,71 +1,20 @@
// FanRunFrequence
import cls from "./index.module.css";
import ReactECharts from "echarts-for-react";
import * as echarts from "echarts";
import { Switch } from "antd";
import GraphBase from "../../Common/GraphBase";
import { useState } from "react";
import { useSelector } from "react-redux";
import { useState, useContext } from "react";
// import SocketContext from '../../../store/socket-data-provider';
function WindFrequence(props) {
const [showChart, setShowChart] = useState(false);
const runState = useSelector((state) => state.fanFrequence.runtime);
const hisState = useSelector((state) => state.fanFrequence.history);
const [showChart, setShowChart] = useState(true);
// const { runState, hisState } = useContext(SocketContext);
const [options, dataList] = getOptions(showChart, hisState, runState);
const runState = null;
const hisState = null;
function handleSwitchChange(val) {
if (val) {
setShowChart(true);
} else {
setShowChart(false);
}
}
return (
<GraphBase
icon="smoke"
title="风机运行频率"
size={["middle", "long"]}
switchOptions={false}
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}
style={{ padding: props.stretch ? "16px 0" : "" }}
>
<span className={cls.fanName}>{item.name}</span>
<span
className={cls.fanValue}
style={{
fontWeight: 700,
letterSpacing: 1,
fontSize: 16,
// color: "#e03537",
color: "#24aebb",
}}
>
{item.value}
</span>
</div>
))}
</div>
)}
</div>
</GraphBase>
);
}
export default WindFrequence;
function getOptions(showChart, hisState, runState) {
let dataList = null;
let dataList = [];
let seriesData = [];
const colors = [
"#12FFF5",
@ -80,15 +29,20 @@ function getOptions(showChart, hisState, runState) {
let options = null;
if (showChart) {
// keys() sort()
seriesData =
hisState != null
? Object.keys(hisState)
seriesData = hisState?.combustionAir
? Object.keys(hisState.combustionAir)
.sort()
.map((key) => hisState[key])
.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 },
@ -150,10 +104,9 @@ function getOptions(showChart, hisState, runState) {
symbol: "circle",
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
// i % 8 8
{ offset: 0, color: colors[i % 8] + "40" },
{ offset: 0.5, color: colors[i % 8] + "20" },
{ offset: 1, color: colors[i % 8] + "00" },
{ offset: 0, color: colors[i] + "40" },
{ offset: 0.5, color: colors[i] + "20" },
{ offset: 1, color: colors[i] + "00" },
]),
},
})),
@ -162,12 +115,27 @@ function getOptions(showChart, hisState, runState) {
},
};
} else {
dataList =
runState != null
? Object.keys(runState).map((fan) => ({
id: Math.random(),
name: fan,
value: (+runState[fan])?.toFixed(2),
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" },
@ -189,5 +157,38 @@ function getOptions(showChart, hisState, runState) {
];
}
return [options, dataList];
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;

View File

@ -12,15 +12,11 @@
.listItem {
border-radius: 2px;
padding: 10px 0;
padding: 9px 0;
text-align: center;
color: #fff;
box-shadow: inset 0 0 16px 4px rgba(255, 255, 255, 0.197);
display: flex;
align-items: center;
gap: 12px;
}
.headWidget {
position: absolute;
top: 22px;
@ -35,18 +31,3 @@
.relative {
position: relative;
}
.flex {
display: flex;
align-items: center;
}
.fanName {
text-align: right;
flex: 7;
}
.fanValue {
flex: 3;
text-align: left;
}

View File

@ -1,16 +0,0 @@
.feeder {
flex: 1;
}
.feeder-running {
background: url(../../../assets/online.png);
background-size: 100% 100%;
}
.feeder-stop {
background: url(../../../assets/offline.png);
background-size: 100% 100%;
}
.feeder-error {
background: url(../../../assets/offline.png);
background-size: 100% 100%;
}

View File

@ -1,104 +0,0 @@
import { useSelector } from "react-redux";
import { motion } from "framer-motion";
import "./feeder.css";
function FeederStatus(props) {
const feeder = useSelector((state) => state.feeder);
const rightFeeder = feeder.rightFeeder;
const leftFeeder = feeder.leftFeeder;
return (
<motion.div
className="feeder"
style={{
position: "absolute",
bottom: "56px",
left: "740px",
width: "400px",
height: "128px",
zIndex: "-1",
display: "flex",
gap: "8px",
paddingTop: "12px",
justifyContent: "center",
...props.style,
}}
animate={{
opacity: [0, 0, 0, 0.6, 1],
transition: { duration: 0.3, delay: 2 },
}}
>
<span
style={{
position: "absolute",
color: "#6be1e1",
top: "-32px",
left: "20px",
fontSize: "22px",
}}
>
1#投料{" "}
<b
style={{
fontWeight: 400,
color:
leftFeeder == "故障"
? "#f83a35"
: leftFeeder == "运行"
? "#9af72b"
: "#ccc",
}}
>
{leftFeeder}
</b>
</span>
<span
style={{
position: "absolute",
color: "#6be1e1",
top: "-32px",
left: "230px",
fontSize: "22px",
}}
>
2#投料{" "}
<b
style={{
fontWeight: 400,
color:
rightFeeder == "故障"
? "#f83a35"
: rightFeeder == "运行"
? "#9af72b"
: "#ccc",
}}
>
{rightFeeder}
</b>
</span>
<span
className={`
feeder ${
leftFeeder == "运行"
? "feeder-running"
: leftFeeder == "故障"
? "feeder-error"
: "feeder-stop"
}
`}
></span>
<span
className={`
feeder ${
rightFeeder == "运行"
? "feeder-running"
: rightFeeder == "故障"
? "feeder-error"
: "feeder-stop"
}
`}
></span>
</motion.div>
);
}
export default FeederStatus;

View File

@ -1,20 +1,148 @@
//
import cls from "./index.module.css";
import BottomBarItem from "../BottomItemBackground";
import ReactECharts from "echarts-for-react";
import * as echarts from "echarts";
import { Switch } from "antd";
import { useState, useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import dayjs from "dayjs";
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 = useSelector((state) => state.combustionAir.runtime);
const hisState = useSelector((state) => state.combustionAir.history);
// const { runState, hisState } = useContext(SocketContext);
let [options, dataList] = getOptions(showChart, hisState, runState);
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) {
@ -23,17 +151,10 @@ function GasI(props) {
setShowChart(false);
}
}
const desc =
dayjs().subtract(7, "day").format("YYYY.MM.DD") +
" - " +
dayjs().subtract(1, "day").format("YYYY.MM.DD");
return (
<BottomBarItem
icon="pause"
title="助燃风流量"
desc={desc}
className={cls.gas}
style={props.style}
>
@ -47,15 +168,13 @@ function GasI(props) {
<div className={cls.chart}>
{showChart && (
<ReactECharts option={options} style={{ height: "100%" }} />
<ReactECharts option={options} style={{ height: '100%' }} />
)}
{!showChart && (
<div className={cls.gridList}>
{dataList.map((item) => (
<div key={item.id} className={cls.listItem}>
<span className={cls.item_label}>{item.name}</span>
<span className={cls.item_value}>{item.value}</span>
{/* {item.name}: {item.value} */}
{item.name}: {item.value}
</div>
))}
</div>
@ -66,158 +185,3 @@ function GasI(props) {
}
export default GasI;
function getOptions(showChart, hisState, runState) {
const colors = [
"#12FFF5",
"#2760FF",
"#FFD160",
"#E80091",
"#8064ff",
"#ff8a3b",
"#8cd26d",
"#2aa1ff",
];
let seriesData = null;
let dataList = null;
let options = null;
if (showChart) {
// keys() sort()
seriesData =
hisState != null
? Object.keys(hisState)
.sort()
.map((key) => hisState[key])
: Array(8)
.fill(1)
.map((_) => Array(7).fill(0));
options = {
color: colors,
grid: { top: 36, 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 + 1) * 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,
},
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",
symbolSize: 6,
// label: {
// show: true,
// position: "top",
// distance: 10,
// color: "#fffc",
// },
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: colors[i % colors.length] + "40" },
{ offset: 0.5, color: colors[i % colors.length] + "20" },
{ offset: 1, color: colors[i % colors.length] + "00" },
]),
},
})),
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow",
},
className: "xc-chart-tooltip",
// backgroundColor: ''
},
};
} else {
dataList =
runState != null
? [
{ 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[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" },
];
}
return [options, dataList];
}

View File

@ -26,10 +26,9 @@
position: absolute;
/* background: #00ee33; */
top: 20px;
left: 180px;
right: 24px;
height: 32px;
width: 128px;
width: 190px;
text-align: right;
}
@ -63,21 +62,7 @@
padding: 12px 0;
text-align: center;
color: #fff;
box-shadow: inset 0 0 12px 2px rgba(255, 255, 255, 0.197);
display: flex;
align-items: center;
gap: 12px;
}
.item_label {
flex: 5;
text-align: right;
}
.item_value {
flex: 4;
text-align: left;
box-shadow: inset 0 0 16px 4px rgba(255, 255, 255, 0.197);
}
.headWidget {

View File

@ -1,36 +1,34 @@
// TODO: -
import useIcon from "../../../hooks/useIcon";
import cls from "./index.module.css";
import { useMemo, useState } from "react";
import { Switch, Select } from "antd";
import "./selector.style.overwrite.css";
import triangle from "../../../assets/Icon/triangle.svg";
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";
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 size = props.size || ['middle', 'middle'];
const bgClass = choseBg(size);
const {
icon,
@ -40,12 +38,10 @@ function GraphBase(props) {
onSwitch,
dateOptions,
onDateChange,
defaultSelect,
selectWidth,
legend,
} = props;
const iconSrc = useIcon(icon);
const colors = useMemo(() => ["#ffd160", "#2760ff", "#15e8f5"], []);
const colors = useMemo(() => ['#ffd160', '#2760ff', '#15e8f5'], []);
const [showChart, setShowChart] = useState(true);
let dto = null;
@ -54,35 +50,16 @@ function GraphBase(props) {
if (props.switchPosition) {
props.switchPosition.forEach((item, index) => {
if (item != null) {
switchStyle[index == 0 ? "top" : "left"] = item + "px";
switchStyle[index == 0 ? 'top' : 'left'] = item + 'px';
}
});
}
if (dateOptions) {
dto = (
<Select
defaultValue={defaultSelect || dateOptions[0]}
style={{ width: selectWidth || 60 }}
popupClassName="xc-date-selector-menu"
className={cls.graphBaseDate + " " + cls.radioGroup}
options={dateOptions.map((item) => ({ label: item, value: item }))}
suffixIcon={<img src={triangle} alt="#" />}
notFoundContent={
<span
style={{
color: "#fff",
fontSize: "14px",
lineHeight: 1,
paddingLeft: "12px",
}}
>
- -
</span>
}
onChange={(value, option) => onDateChange(value)}
/>
);
dto = dateOptions.map((item) => (
<Radio.Button value={item} key={item} className="radio-group__item">
{item}
</Radio.Button>
));
}
function handleSwitchChange(v) {
@ -93,11 +70,11 @@ function GraphBase(props) {
return (
<div
className={
"graph-base " +
'graph-base ' +
cls[bgClass] +
" " +
' ' +
cls.graphBase +
" " +
' ' +
props.className
}
style={{ ...props.style }}
@ -105,9 +82,9 @@ function GraphBase(props) {
<div className={cls.graphBaseTitle}>
<img src={iconSrc} alt="#" />
<h2>{title}</h2>
{desc && <div className={cls.graphBaseDesc}>{desc}</div>}
</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} />
@ -128,7 +105,16 @@ function GraphBase(props) {
))}
</div>
)}
{dateOptions && dto}
{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>

View File

@ -63,7 +63,7 @@
}
.graphBaseTitle > img {
width: 24px;
width: 20px;
}
.graphBaseTitle > h2 {
@ -72,7 +72,7 @@
'Source Han Sans SC', 'Noto Sans CJK SC', 'WenQuanYi Micro Hei', sans-serif;
margin: 0;
margin-left: 6px;
font-size: 22px;
font-size: 20px;
color: #fff;
letter-spacing: 2px;
font-weight: 500;
@ -85,10 +85,9 @@
}
.graphBaseDesc {
margin-left: 8px;
/* position: absolute;
position: absolute;
top: 25px;
left: 150px; */
left: 150px;
font-size: 19px;
color: #76fff9;
}
@ -115,7 +114,7 @@
.radioGroup * {
border: none !important;
border-radius: 6px !important;
border-radius: 0 !important;
}
.radioGroup *:focus-within {

View File

@ -1,31 +0,0 @@
.xc-date-selector-menu {
background-color: #04233c !important;
}
.xc-date-selector-menu .ant-select-item {
color: #fff;
background: transparent;
}
.xc-date-selector-menu .ant-select-item-option-content {
text-align: center;
}
.xc-date-selector-menu .ant-select-item-option-selected {
color: #fff !important;
background-color: #02457E !important;
}
.ant-select-selector {
background-color: #02457E !important;
color: #fff !important;
}
/*
.ant-select-selector::after {
content: '\25BC' !important;
visibility: visible !important;
position: absolute;
top: 2px;
right: 22px;
color: #04233c;
} */

View File

@ -1,24 +1,60 @@
import cls from "./kiln.module.scss";
import Container from "../../Container";
import { useSelector } from "react-redux";
import { useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import { stateNameMap } from "../../../store/features/kilnSlice";
export default function Kiln() {
const kilnInfo = useSelector((state) => state.kiln);
const dispatch = useDispatch();
console.log("state: ", kilnInfo, stateNameMap);
const infos = Object.keys(kilnInfo).map((key) => ({
label: stateNameMap[key],
value: kilnInfo[key],
}));
useEffect(() => {
setInterval(() => {
dispatch({
type: "kiln/setKilnInfo",
payload: {
kilnPressure: Math.ceil(Math.random() * 100) + "Pa",
waterTemp: Math.ceil(Math.random() * 100) + "℃",
waterFlow: Math.ceil(Math.random() * 100) + "m³/h",
waterPressure: Math.ceil(Math.random() * 100) + "Pa",
combustionAirPressure: Math.ceil(Math.random() * 100) + "Pa",
topTemp: Math.ceil(Math.random() * 100) + "℃",
compressedAirPressure: Math.ceil(Math.random() * 100) + "Pa",
meltTemp: Math.ceil(Math.random() * 100) + "℃",
},
});
}, 30000);
}, []);
// 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}>
<span className={cls.label}>{item.label}</span>
<span className={cls.value}>{item.value}</span>
{/* {item.label}: {item.value} */}
{item.label}: {item.value}
</div>
))}
</div>

View File

@ -24,19 +24,6 @@
line-height: 40px;
text-align: center;
user-select: none;
display: flex;
align-items: center;
gap: 12px;
.label {
flex: 6;
text-align: right;
}
.value {
flex: 4;
text-align: left;
}
}
}
}

View File

@ -1,23 +1,23 @@
import * as echarts from "echarts";
import { randomInt } from "../../../../utils";
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",
'#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",
icon: 'roundRect',
top: 10,
right: 10,
padding: 0,
@ -26,80 +26,73 @@ export default function getOptions(seriesData, name) {
itemGap: 3,
height: 8,
textStyle: {
color: "#DFF1FE",
color: '#DFF1FE',
fontSize: 10,
},
},
xAxis: {
type: "category",
type: 'category',
data: Array(7)
.fill(1)
.map((_, index) => {
const today = new Date();
const dtimestamp = today - (index+1) * 24 * 60 * 60 * 1000;
const dtimestamp = today - index * 24 * 60 * 60 * 1000;
return `${new Date(dtimestamp).getMonth() + 1}.${new Date(
dtimestamp
dtimestamp,
).getDate()}`;
})
.reverse(),
axisLabel: {
color: "#fff",
color: '#fff',
fontSize: 12,
},
axisTick: { show: false },
axisLine: {
lineStyle: {
width: 1,
color: "#213259",
color: '#213259',
},
},
},
yAxis: {
name: "单位m³/h",
name: '单位m³/h',
nameTextStyle: {
color: "#fff",
color: '#fff',
fontSize: 10,
align: "right",
align: 'right',
},
type: "value",
type: 'value',
axisLabel: {
color: "#fff",
color: '#fff',
fontSize: 12,
formatter: "{value}",
formatter: '{value}',
},
axisLine: {
show: true,
lineStyle: {
color: "#213259",
color: '#213259',
},
},
splitLine: {
lineStyle: {
color: "#213259a0",
color: '#213259a0',
},
},
},
series: seriesData.map((arr, index) => ({
name: index + 1 + "#" + name,
name: index + 1 + '#' + name,
data: arr,
type: "line",
symbol: 'circle',
symbolSize: 6,
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" },
{ offset: 0, color: colors[index] + '40' },
{ offset: 0.5, color: colors[index] + '20' },
{ offset: 1, color: colors[index] + '00' },
]),
},
})),
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow",
},
className: "xc-chart-tooltip",
// backgroundColor: ''
trigger: 'axis',
},
};
}

View File

@ -1,28 +1,34 @@
import cls from "./index.module.css";
import ReactECharts from "echarts-for-react";
import getOptions from "./chart.config";
import { useSelector, useDispatch } from "react-redux";
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 = useSelector((state) => state.natGas.history);
const dataName = dataSource == "gas-i" ? "gasIHistory" : "gasIIHistory";
// 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));
: 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={dataSource}
key={Math.random()}
option={getOptions(
seriesData,
dataSource == "gas-i" ? "天然气I" : "天然气II"
dataSource == 'gas-i' ? '天然气I' : '天然气II',
)}
style={{ height: "100%" }}
style={{ height: '100%' }}
/>
</div>
);

View File

@ -1,27 +1,28 @@
import cls from "./index.module.css";
import { useSelector } from "react-redux";
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":
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" },
{ 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":
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: 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;
@ -30,25 +31,21 @@ function getData(type) {
}
function GridList(props) {
const runState = useSelector((state) => state.natGas.runtime);
// const { runState } = useContext(SocketContext);
const runState = null;
const key = props.dataSource == "gas-i" ? "gasIRuntime" : "gasIIRuntime";
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] || 0) + "m³/h",
}))
? 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}>
<span className={cls.item_label}>{item.name}</span>
<span className={cls.item_value}>{item.value}</span>
{/* {item.name}: {item.value} */}
{item.name}: {item.value}
</div>
))}
</div>

View File

@ -11,17 +11,4 @@
text-align: center;
color: #fff;
box-shadow: inset 0 0 16px 4px rgba(255, 255, 255, 0.197);
display: flex;
align-items: center;
gap: 12px;
}
.item_label {
flex: 5;
text-align: right;
}
.item_value {
flex: 6;
text-align: left;
}

View File

@ -1,15 +1,14 @@
//
import cls from "./index.module.css";
import BottomBarItem from "../BottomItemBackground";
import triangle from "../../../assets/Icon/triangle.svg";
import { Switch, Select, Radio } from "antd";
import { useState } from "react";
import GridList from "./gridList";
import GasChart from "./gasChart";
import dayjs from "dayjs";
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 [dataSource, setDataSource] = useState('gas-i'); // gas-i , gas-ii
const [showChart, setShowChart] = useState(true);
function handleSwitchChange(val) {
@ -20,33 +19,21 @@ function GasII(props) {
}
}
// function handleSourceChange(e) {
// if (e.target.value == "ii") {
// // II
// setDataSource("gas-ii");
// } else if (e.target.value == "i") {
// // I
// setDataSource("gas-i");
// }
// }
function handleDateChange(value) {
if (value == "天然气I") {
setDataSource("gas-i");
} else {
setDataSource("gas-ii");
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');
}
}
const desc =
dayjs().subtract(7, "day").format("YYYY.MM.DD") +
" - " +
dayjs().subtract(1, "day").format("YYYY.MM.DD");
return (
<BottomBarItem
icon="pause"
title="天然气流量"
desc={desc}
className={`${cls.gas} ${props.className}`}
style={props.style}
>
@ -58,32 +45,7 @@ function GasII(props) {
{!showChart && <span className={cls.switchLabel}>实时流量</span>}
</div>
<Select
defaultValue={"天然气I"}
style={{ width: 90 }}
popupClassName="xc-date-selector-menu"
className={cls.radioGroup}
options={["天然气I", "天然气II"].map((item) => ({
label: item,
value: item,
}))}
suffixIcon={<img src={triangle} alt="#" />}
notFoundContent={
<span
style={{
color: "#fff",
fontSize: "14px",
lineHeight: 1,
paddingLeft: "12px",
}}
>
- -
</span>
}
onChange={(value, option) => handleDateChange(value)}
/>
{/* <Radio.Group
<Radio.Group
defaultValue="i"
buttonStyle="solid"
className={cls.radioGroup}
@ -95,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

@ -24,10 +24,9 @@
.headWidget {
position: absolute;
top: 22px;
left: 178px;
right: 24px;
height: 32px;
width: calc(100% - 200px);
/* background: #12fff5; */
width: 410px;
display: flex;
align-items: center;
justify-content: space-between;
@ -70,7 +69,7 @@
.radioGroup * {
border: none !important;
border-radius: 6px !important;
border-radius: 0 !important;
}
.radioGroup *:focus-within {

View File

@ -1,20 +1,20 @@
import { useCallback, useEffect, useState } from "react";
import cls from "./index.module.scss";
import { useCallback, useState } from 'react';
import cls from './index.module.scss';
export default function CenterMenu({ active, onChangeActive }) {
const menuList = [
["窑炉总览", "/kilnSummary"],
["窑炉内部", "/kilnInner"],
["退火监测", "/stopFire"],
["质检统计", "/quailtyCheck"],
["能耗分析", "/energyCost"],
['窑炉总览', '/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 : ""}`}
className={`${cls.menuItem} ${active == menu[0] ? cls.active : ''}`}
onClick={() => onChangeActive(menu[0])}
>
{menu[0]}

View File

@ -1,8 +1,7 @@
.centerMenu {
position: fixed;
top: 120px;
// left: 1340px;
left: 1460px;
left: 1340px;
color: white;
z-index: 10000;
}

View File

@ -1,24 +0,0 @@
import { useSelector } from "react-redux";
import cls from "../index.module.scss";
const SmokeHandleTable = () => {
const smokeInfo = useSelector((state) => state.smoke?.info);
return (
<div className={cls.info__item_groups}>
<div className={cls.info__item}>
: {(+smokeInfo?.O2_float)?.toFixed(2) || 0}%
</div>
<div className={cls.info__item}>
氮氧化物浓度: {(+smokeInfo?.NOX_float)?.toFixed(2) || 0}mg/
</div>
<div className={cls.info__item}>
二氧化硫浓度: {(+smokeInfo?.SO2_float)?.toFixed(2) || 0}mg/
</div>
<div className={cls.info__item}>
颗粒物浓度: {(+smokeInfo?.dust_float)?.toFixed(2) || 0}mg/
</div>
</div>
);
};
export default SmokeHandleTable;

View File

@ -1,156 +1,163 @@
import cls from "./index.module.css";
import * as echarts from "echarts";
import { Select } from "antd";
import ReactECharts from "echarts-for-react";
import { useEffect, useState } from "react";
import { useSelector } from "react-redux";
import triangle from "../../../../assets/Icon/triangle.svg";
import dayjs from "dayjs";
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 dayTrend = useSelector((state) => state.smoke?.dayTrend);
const weekTrend = useSelector((state) => state.smoke?.weekTrend);
const monthTrend = useSelector((state) => state.smoke?.monthTrend);
const yearTrend = useSelector((state) => state.smoke?.yearTrend);
const [source, setSource] = useState("O2_float");
const [period, setPeriod] = useState("day");
const currentTrend =
period === "day"
? dayTrend
: period === "week"
? weekTrend
: period === "month"
? monthTrend
: yearTrend;
const options = getOptions(source, period, currentTrend);
const [desc, setDesc] = useState("");
useEffect(() => {
switch (period) {
case "day":
setDesc(
dayjs().subtract(1, "day").format("YYYY.MM.DD") +
" 7点 - " +
dayjs().format("YYYY.MM.DD") +
" 7点"
);
break;
case "month":
setDesc(
dayjs().subtract(1, "month").format("YYYY.MM.") +
"29 - " +
dayjs().format("YYYY.MM.") +
"28"
);
break;
case "week":
setDesc(
dayjs().subtract(7, "day").format("YYYY.MM.DD") +
" - " +
dayjs().subtract(1, "day").format("YYYY.MM.DD")
);
break;
case "year":
setDesc(
dayjs().subtract(1, "year").endOf("year").format("YYYY.MM.") +
"29 - " +
dayjs().endOf("year").format("YYYY.MM.") +
"28"
);
break;
}
}, [period]);
function handleDateChange(value) {
setPeriod(
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: [
{
: "day",
: "week",
: "month",
: "year",
}[value]
);
}
function handleSourceChange(value) {
setSource(
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,
},
{
氧气: "O2_float",
氮氧化物: "NOX_float",
二氧化硫: "SO2_float",
颗粒物: "dust_float",
}[value]
);
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}>
<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>
<div className={`${cls.choiceBar} flex items-center justify-between`}>
{/* <Radio.Group
value={source}
onChange={(e) => setSource(e.target.value)}
<Radio.Group
defaultValue="oxygen"
buttonStyle="solid"
className={`${cls.radioGroup} flex items-center justify-between`}
>
<Radio.Button value="O2_float" className="radio-group__item">
氧气
<Radio.Button value="oxygen" className="radio-group__item">
氧气含量
</Radio.Button>
<Radio.Button value="NOX_float" className="radio-group__item">
氮氧化物
</Radio.Button>
<Radio.Button value="SO2_float" className="radio-group__item">
<Radio.Button value="so2" className="radio-group__item">
二氧化硫
</Radio.Button>
<Radio.Button value="dust_float" className="radio-group__item">
颗粒物
<Radio.Button value="no" className="radio-group__item">
一氧化氮
</Radio.Button>
</Radio.Group> */}
<Select
defaultValue={"氧气"}
style={{ width: 100 }}
popupClassName="xc-date-selector-menu"
className={cls.radioGroupShort}
options={["氧气", "氮氧化物", "二氧化硫", "颗粒物"].map((item) => ({
label: item,
value: item,
}))}
suffixIcon={<img src={triangle} alt="#" />}
notFoundContent={
<span
style={{
color: "#fff",
fontSize: "14px",
lineHeight: 1,
paddingLeft: "12px",
}}
>
- -
</span>
}
onChange={(value, option) => handleSourceChange(value)}
/>
<Radio.Button value="no2" className="radio-group__item">
二氧化氮
</Radio.Button>
</Radio.Group>
<div className={cls.graphBaseDesc}>{desc}</div>
{/* <Radio.Group
value={period}
onChange={(e) => setPeriod(e.target.value)}
<Radio.Group
defaultValue="week"
buttonStyle="solid"
className={cls.radioGroup}
>
@ -166,174 +173,11 @@ const SmokeTrendChart = (props) => {
<Radio.Button value="year" className="radio-group__item">
</Radio.Button>
</Radio.Group> */}
<Select
defaultValue={"日"}
style={{ width: 60 }}
popupClassName="xc-date-selector-menu"
className={cls.radioGroupShort}
options={["日", "周", "月", "年"].map((item) => ({
label: item,
value: item,
}))}
suffixIcon={<img src={triangle} alt="#" />}
notFoundContent={
<span
style={{
color: "#fff",
fontSize: "14px",
lineHeight: 1,
paddingLeft: "12px",
}}
>
- -
</span>
}
onChange={(value, option) => handleDateChange(value)}
/>
</Radio.Group>
</div>
{options && <ReactECharts option={options} style={{ height: "220px" }} />}
{!options && (
<p
style={{
color: "#cccf",
fontSize: "24px",
userSelect: "none",
textAlign: "center",
paddingTop: "96px",
}}
>
暂无数据
</p>
)}
<ReactECharts option={options} style={{ height: '240px' }} />
</div>
);
};
export default SmokeTrendChart;
function getOptions(source, period, trend) {
if (
trend[source].length === 0 ||
trend[source].filter((item) => item.value).length == 0
)
return null;
return {
color: ["#FFD160", "#12FFF5", "#2760FF"],
grid: {
top: 40,
right: 12,
bottom: 20,
left: source == "O2_float" ? 56 : 72,
},
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(),
data: trend[source].map((item) => item.time),
axisLabel: {
color: "#fff",
fontSize: 12,
},
axisTick: { show: false },
axisLine: {
lineStyle: {
width: 1,
color: "#213259",
},
},
},
yAxis: {
name: source == "O2_float" ? "单位:%" : "单位mg/m³",
nameTextStyle: {
color: "#fff",
fontSize: 13,
align: "right",
},
type: "value",
axisLabel: {
color: "#fff",
fontSize: 14,
formatter: "{value}",
},
axisLine: {
show: true,
lineStyle: {
color: "#213259",
},
},
splitLine: {
lineStyle: {
color: "#213259a0",
},
},
},
series: [
{
data: trend[source].map((item) =>
!(item.value == null || isNaN(+item.value))
? (+item.value).toFixed(2)
: null
),
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",
axisPointer: {
type: "shadow",
},
className: "xc-chart-tooltip",
},
};
}

View File

@ -43,7 +43,7 @@
padding-left: 16px;
}
.energyCostChart .titleBar .legend ul li::before {
content: "";
content: '';
position: absolute;
left: 2px;
top: 2px;
@ -73,10 +73,6 @@
border: none !important;
border-radius: 0 !important;
}
.radioGroupShort * {
border: none !important;
border-radius: 6px !important;
}
.radioGroup *:focus-within {
box-shadow: none !important;
}
@ -93,10 +89,3 @@
.radioGroup_button_wrapper.ant-radio-button-wrapper-checked {
background: #02457e !important;
}
.graphBaseDesc {
margin: 0 12px;
line-height: 1;
color: #76fff9;
flex: 1;
}

View File

@ -1,14 +1,18 @@
import cls from "./index.module.scss";
import Container from "../../Container";
import TechSplitline from "../TechSplitline";
import SmokeTrendChart from "./SmokeTrendChart";
import SmokeHandleTable from "./SmokeHandleTable";
import cls from './index.module.scss';
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`}>
<SmokeHandleTable />
<div className={cls.info__item_groups}>
<div className={cls.info__item}> : 72%</div>
<div className={cls.info__item}>一氧化氮排放浓度:59mg/</div>
<div className={cls.info__item}>二氧化硫排放浓度:59mg/</div>
<div className={cls.info__item}>二氧化氮排放浓度:59mg/</div>
</div>
<TechSplitline />
<SmokeTrendChart />
</div>

View File

@ -3,7 +3,7 @@
background: url(../../../assets/smoke.png) no-repeat;
background-size: 100% 100%;
width: 626px;
height: 490px;
height: 540px;
.smokeHandle__content {
margin-top: 8px;
}
@ -13,17 +13,19 @@
border-radius: 2px;
color: hsl(0, 0%, 100%, 0.9);
box-shadow: inset 0 0 17px 0px hsla(0, 0%, 100%, 0.15);
height: 32px;
font-size: 16px;
// width: 288px;
height: 56px;
font-size: 20px;
letter-spacing: 1.43px;
line-height: 32px;
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: 4px;
gap: 8px;
}

View File

@ -1,41 +0,0 @@
import BlueRect from "../BlueRect";
import { useSelector } from "react-redux";
import { motion, AnimatePresence } from "framer-motion";
const blueTe = [
"TE401",
"TE402",
"TE403",
"PE401",
"PE402",
"PE403",
];
function TemperatureBottom(props) {
const tempBottom = useSelector((state) => state.temperature.bottom);
return (
<motion.div
className="temperature-bottom"
style={{
position: "absolute",
top: "0",
left: "0",
width: "100%",
height: "80vh",
zIndex: "-1",
...props.style
}}
animate={{
opacity: [0, 0, 0, 0.6, 1],
transition: { duration: 0.3, delay: 2 },
}}
>
{Object.keys(tempBottom).map((d) => (
<BlueRect title={d} key={d + Math.random()} value={tempBottom[d]} blue={blueTe.includes(d)} />
))}
</motion.div>
);
}
export default TemperatureBottom;

View File

@ -1,45 +0,0 @@
import BlueRect from "../BlueRect";
import { useSelector } from "react-redux";
import { motion, AnimatePresence } from "framer-motion";
const blueTe = [
"TE271",
"TE272",
"TE273",
"TE274",
"TE275",
"TE276",
"TE277",
"TE278",
"TE279",
"TE280",
];
function TemperatureTop(props) {
const tempTop = useSelector((state) => state.temperature.top);
return (
<motion.div
className="temperature-top"
style={{
position: "absolute",
top: "0",
left: "0",
width: "100%",
height: "80vh",
zIndex: "-1",
...props.style
}}
animate={{
opacity: [0, 0, 0, 0.6, 1],
transition: { duration: 0.3, delay: 2 },
}}
>
{Object.keys(tempTop).map((d) => (
<BlueRect title={d} key={d + Math.random()} value={tempTop[d]} blue={blueTe.includes(d)} />
))}
</motion.div>
);
}
export default TemperatureTop;

View File

@ -10,15 +10,11 @@ import icon3 from "../../../assets/CenterChart2icon3.svg";
import useTimeCounter from "../../../hooks/useTimeCounter";
const FireInfo = () => {
// const dispatch = useDispatch();
const dispatch = useDispatch();
const fireInfo = useSelector((state) => state.fireInfo);
const time = fireInfo.lastFireChangeTime || "0分0秒";
const minsec = useTimeCounter(time);
let [min, sec] = [0, 0];
if (minsec) {
min = minsec[0];
sec = minsec[1];
}
const [min, sec] = useTimeCounter(time);
// useEffect(() => {
// const restTime = ctx?.runState?.lastFireChangeTime;
// if (restTime == null) return;
@ -80,22 +76,22 @@ const FireInfo = () => {
// };
// }, [ctx?.runState?.lastFireChangeTime]);
// useEffect(() => {
// setInterval(() => {
// dispatch({
// type: "fireInfo/setFireInfo",
// payload: {
// fireChangeTime: `${Math.ceil(Math.random() * 10)}:${Math.ceil(
// Math.random() * 10
// )}`,
// fireDirection: Math.random * 10 < 5 ? "" : "西",
// lastFireChangeTime: `${Math.ceil(Math.random() * 60)}${Math.ceil(
// Math.random() * 50
// )}`,
// },
// });
// }, 10000);
// }, []);
useEffect(() => {
setInterval(() => {
dispatch({
type: "fireInfo/setFireInfo",
payload: {
fireChangeTime: `${Math.ceil(Math.random() * 10)}:${Math.ceil(
Math.random() * 10
)}`,
fireDirection: Math.random * 10 < 5 ? "东火" : "西火",
lastFireChangeTime: `${Math.ceil(Math.random() * 60)}${Math.ceil(
Math.random() * 50
)}`,
},
});
}, 10000);
}, []);
const data = [
{

View File

@ -1 +0,0 @@
1.json

View File

@ -1,213 +1,163 @@
import cls from "./index.module.css";
import GraphBase from "../GraphBase";
import ReactECharts from "echarts-for-react";
import { useSelector } from "react-redux";
import { useState } from "react";
import dayjs from 'dayjs'
import cls from './index.module.css';
import GraphBase from '../GraphBase';
import ReactECharts from 'echarts-for-react';
function FaultTotal(props) {
const [currentSelect, setCurrentSelect] = useState("日");
const isra = useSelector((state) => state.isra);
const currentStatistic =
currentSelect == "日"
? isra.dayStatistic
: currentSelect == "周"
? isra.weekStatistic
: currentSelect == "月"
? isra.monthStatistic
: currentSelect == "月"
? isra.yearStatistic
: [];
const series = preHandleStatisticData(currentStatistic, isra.checkType ?? []);
const options = getOptions(series, isra, currentStatistic);
function handleDateChange(v) {
setCurrentSelect(v);
}
// 使
const bgSize =
props.page == "home" ? ["middle", "short"] : ["middle", "long"];
// time hint
let timeDesc = "";
const now = new Date();
switch (currentSelect) {
case "日":
timeDesc = dayjs().subtract(1, 'day').format('YYYY.MM.DD') + " 7点 - " + dayjs().format('YYYY.MM.DD') + " 7点";
break;
case "周":
timeDesc = dayjs().subtract(7, 'day').format('YYYY.MM.DD') + " - " + dayjs().subtract(1, 'day').format('YYYY.MM.DD') ;
break;
case "月":
timeDesc = dayjs().subtract(1, 'month').format('YYYY.MM.') + "29 - " + dayjs().format('YYYY.MM.') + '28' ;
break;
case "年":
timeDesc = dayjs().subtract(1, 'year').endOf('year').format('YYYY.MM.') + "29 - " + dayjs().endOf('year').format('YYYY.MM.') + '28' ;
break;
}
return (
<GraphBase
icon="chart"
title="产线缺陷统计"
dateOptions={["日", "周", "月", "年"]}
defaultSelect={currentSelect}
onDateChange={handleDateChange}
size={bgSize}
desc={timeDesc}
style={{ width: "600px" }}
>
<div className={cls.chart}>
{currentStatistic.length != 0 && (
<ReactECharts option={options} style={{ height: "100%" }} />
)}
{currentStatistic.length == 0 && (
<p
style={{
paddingTop: "72px",
color: "#fff6",
textAlign: "center",
fontSize: "24px",
}}
>
暂无数据
</p>
)}
</div>
</GraphBase>
);
}
export default FaultTotal;
function preHandleStatisticData(data, legend) {
const obj = {};
if (!data || !Array.isArray(data)) data = [];
data.forEach((item) => {
obj[item.name] = {};
item.data.forEach((d) => {
obj[item.name][d.checkType] = d.checkNum;
});
});
const series = Array(legend.length)
.fill(1)
.map((_) => ({
name: "",
type: "bar",
stack: "true",
barWidth: 12,
emphasis: {
focus: "series",
},
data: [],
}));
legend.forEach((item, index) => {
series[index].name = item;
data.forEach((d, idx) => {
if (index == legend.length - 1) {
series[index].label = {
show: true,
position: "top",
distance: 10,
color: "#fffc",
formatter: (params) => data[params.dataIndex].sum,
};
}
// const sum = d.sum;
// console.log("d", d, sum);
// series[index].label = ((fff) => {
// console.log("===>", fff);
// return {
// show: true,
// position: "top",
// distance: 10,
// color: "#fffc",
// formatter: "asdf" + fff,
// };
// })(sum);
series[index].data.push(obj[d.name][item] || 0);
});
});
return series;
}
function getOptions(series, isra, currentStatistic) {
return {
color: ["#2760FF", "#8167F6", "#5B9BFF", "#99D66C", "#FFD160", "#FF8A40"],
grid: {
top: (isra.checkType || []).length <= 10 ? 80 : 100,
right: 12,
bottom: 20,
left: 48,
},
const options = {
color: [
'#2760FF',
'#5B9BFF',
'#FFD160',
'#8167F6',
'#99D66C',
'#FF8A40',
'#12FFF5',
],
grid: { top: 42, right: 12, bottom: 20, left: 48 },
legend: {
top: 10,
left: 60,
padding: 5,
itemWidth: 12,
itemHeight: 12,
itemGap: 12,
height: 12,
textStyle: {
color: "#DFF1FE",
color: '#DFF1FE',
fontSize: 12,
},
data: isra.checkType,
},
xAxis: {
type: "category",
data: currentStatistic.map((item) => item.name),
type: 'category',
data: Array(5)
.fill(1)
.map((_, index) => {
return '产线' + (index + 1);
}),
axisLabel: {
color: "#fffc",
color: '#fff',
fontSize: 12,
},
axisTick: { show: false },
axisLine: {
lineStyle: {
width: 1,
color: "#213259",
color: '#213259',
},
},
},
yAxis: {
name: "单位/个",
name: '单位/个',
nameTextStyle: {
color: "#fff",
color: '#fff',
fontSize: 10,
align: "right",
align: 'right',
},
type: "value",
type: 'value',
axisLabel: {
color: "#fff",
color: '#fff',
fontSize: 12,
formatter: "{value}",
formatter: '{value}',
},
axisLine: {
show: true,
lineStyle: {
color: "#213259",
color: '#213259',
},
},
splitLine: {
lineStyle: {
color: "#213259a0",
color: '#213259a0',
},
},
// interval: 10,
// min: 0,
// max: 100,
},
series,
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",
axisPointer: {
type: "shadow",
},
className: "xc-chart-tooltip",
// backgroundColor: ''
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;

View File

@ -1,244 +1,107 @@
import cls from "./index.module.css";
import GraphBase from "../GraphBase";
import ReactECharts from "echarts-for-react";
import { useSelector } from "react-redux";
import { useEffect, useState } from "react";
import { randomInt } from "../../../utils";
import * as echarts from "echarts";
import cls from './index.module.css';
import GraphBase from '../GraphBase';
import ReactECharts from 'echarts-for-react';
import { useState } from 'react';
function FaultType(props) {
const [init, setInit] = useState(true);
const [currentLine, setCurrentLine] = useState("Y61");
const isra = useSelector((state) => state.isra);
const currentStatistic = isra.dayStatistic || [];
const currentLineStatistic =
currentLine != ""
? currentStatistic.find((item) => item.name === currentLine)?.data || []
: [];
const lines = currentStatistic.map((item) => item.name);
const CHART_TYPE = "line"; // "pie" | "line";
useEffect(() => {
if (init == false) return;
if (lines.length) {
setInit(false);
setCurrentLine(lines[0]);
}
}, [lines]);
const options = init
? {}
: getOptions(
CHART_TYPE == "pie"
? getSeries(currentStatistic, currentLine)
: currentLineStatistic,
CHART_TYPE
);
function handleLineChange(line) {
setCurrentLine(line);
}
// 使
const bgSize =
props.page == "home" ? ["middle", "short"] : ["middle", "short"];
return (
<GraphBase
icon="default"
title="产线当日缺陷分类"
dateOptions={[...lines]}
defaultSelect={currentLine}
onDateChange={handleLineChange}
size={bgSize}
selectWidth={64}
style={{ width: "600px" }}
>
<div className={cls.chart}>
{currentStatistic.length == 0 && (
<p
style={{
paddingTop: "72px",
color: "#fff6",
textAlign: "center",
fontSize: "24px",
}}
>
暂无数据
</p>
)}
{currentStatistic.length != 0 && (
<ReactECharts option={options} style={{ height: "100%" }} />
)}
</div>
</GraphBase>
);
}
export default FaultType;
function getOptions(data, chart_type) {
const color = [
"#2760FF",
"#8167F6",
"#5B9BFF",
"#99D66C",
"#FFD160",
"#FF8A40",
];
const grid = {
const options = {
colors: [
'#2760FF',
'#5B9BFF',
'#FFD160',
'#8167F6',
'#99D66C',
'#FF8A40',
'#12FFF5',
],
grid: {
left: 24,
top: 10,
bottom: 10,
right: 24,
};
const legend_common = {
icon: "circle",
},
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",
color: '#DFF1FE',
fontSize: 18,
rich: {
sub: {
color: "#fff9",
color: '#fff9',
fontSize: 18,
},
},
},
};
if (chart_type == "pie") {
return {
color,
grid,
legend: {
...legend_common,
formatter: function (name) {
return `${name} {sub|${
data[0].data.find((o) => o.name == name).value
}}`;
},
},
series: data,
};
} else if (chart_type == "line") {
const dataList = data.map((item) => ({
category: item.checkType,
value: item.checkNum,
}));
return {
grid: {
top: 48,
left: 48,
bottom: 40,
right: 18,
},
legend: {
...legend_common,
},
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow",
},
symbol: 'rect',
className: "xc-chart-tooltip",
// backgroundColor: ''
},
xAxis: {
type: "category",
data: (dataList || []).map((item) => item.category),
axisLabel: {
color: "#fff",
fontSize: 10,
rotate: 20,
},
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",
},
},
},
series: [
{
type: "bar",
barWidth: 14,
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
// i % 8 8
{ offset: 0, color: "#5CB7FF" },
{ offset: 1, color: "#364BFE" },
]),
},
label: {
show: true,
position: "top",
distance: 10,
fontSize: 10,
color: "#fffc",
},
data: (dataList || []).map((item) =>
item.value == null || isNaN(+item.value) ? null : (+item.value).toFixed(0)
),
},
],
};
}
}
function getSeries(currentStatistic, currentLine) {
const currentItem = currentStatistic.find((item) => item.name == currentLine);
return [
{
type: "pie",
center: ["26%", "54%"],
radius: ["55%", "75%"],
type: 'pie',
center: ['26%', '54%'],
radius: ['55%', '75%'],
avoidLabelOverlap: false,
label: {
show: true,
formatter: "{d}%",
formatter: '{d}%',
fontSize: 14,
color: "inherit",
color: 'inherit',
},
labelLine: {
length: 0,
},
data: currentItem.data.map((item) => ({
value: item.checkNum,
name: item.checkType,
})),
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;

View File

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

View File

@ -1,132 +1,137 @@
import cls from "./index.module.css";
import "./overwrite.css"; // antd
import ReactECharts from "echarts-for-react";
import * as echarts from "echarts";
import { Switch, Select, Radio } from "antd";
import { useEffect, useState } from "react";
import { useSelector } from "react-redux";
import triangle from "../../../../../assets/Icon/triangle.svg";
import dayjs from "dayjs";
const dateOptions = { day: "日", week: "周", month: "月", year: "年" };
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 [showMore, setShowMore] = useState(false);
// key
const [updateKey, setUpdateKey] = useState(Date.now());
//
const [dateType, setDateType] = useState("day");
const [defaultSelect, setDefaultSelect] = useState(dateOptions[dateType]);
const cutting = useSelector((state) => state.cutting);
useEffect(() => {
setUpdateKey(Date.now());
}, [showMore]);
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
setShowMore(val);
console.log('switch change', val);
}
const [timestr, setTimestr] = useState(
dayjs().subtract(1, "day").format("YYYY.MM.DD") +
" 7点 - " +
dayjs().format("YYYY.MM.DD") +
" 7点"
);
function handleDateChange(value) {
// e: Event
let v = "day";
switch (value) {
case "日":
setTimestr(
dayjs().subtract(1, "day").format("YYYY.MM.DD") +
" 7点 - " +
dayjs().format("YYYY.MM.DD") +
" 7点"
);
break;
case "月":
v = "month";
setTimestr(
dayjs().subtract(1, "month").format("YYYY.MM.") +
"29 - " +
dayjs().format("YYYY.MM.") +
"28"
);
break;
case "周":
v = "week";
setTimestr(
dayjs().subtract(7, "day").format("YYYY.MM.DD") +
" - " +
dayjs().subtract(1, "day").format("YYYY.MM.DD")
);
break;
case "年":
v = "year";
setTimestr(
dayjs().subtract(1, "year").endOf("year").format("YYYY.MM.") +
"29 - " +
dayjs().endOf("year").format("YYYY.MM.") +
"28"
);
break;
}
setDateType(v);
}
// options
const options = getOptions(cutting.chart[dateType], showMore, dateType);
return (
<div className={cls.GoodRateChart}>
<div className={cls.titleBar}>
<h2>生产良品率</h2>
<Switch defaultChecked={showMore} onChange={handleSwitchChange} />
<Switch defaultChecked onChange={handleSwitchChange} />
<div className={cls.legend}>
<span className="legend__title">班次详情</span>
<ul className="legend__list">
<li>总量</li>
{showMore && (
<>
<li>白班</li>
<li>夜班</li>
</>
)}
</ul>
</div>
<div className={cls.graphBaseDesc}>{timestr}</div>
<Select
defaultValue={defaultSelect}
style={{ width: 60 }}
popupClassName="xc-date-selector-menu"
className={cls.radioGroup}
options={["日", "周", "月", "年"].map((item) => ({
label: item,
value: item,
}))}
suffixIcon={<img src={triangle} alt="#" />}
notFoundContent={
<span
style={{
color: "#fff",
fontSize: "14px",
lineHeight: 1,
paddingLeft: "12px",
}}
>
- -
</span>
}
onChange={(value, option) => handleDateChange(value)}
/>
{/* <Radio.Group
defaultValue="day"
<Radio.Group
defaultValue="week"
buttonStyle="solid"
onChange={handleDateChange}
className={cls.radioGroup}
style={{ flex: 1, textAlign: "right" }}
>
<Radio.Button value="day" className="radio-group__item">
@ -140,174 +145,11 @@ const GoodRateChart = (props) => {
<Radio.Button value="year" className="radio-group__item">
</Radio.Button>
</Radio.Group> */}
</Radio.Group>
</div>
{options && <ReactECharts key={updateKey} option={options} />}
{!options && (
<p
style={{
paddingTop: "88px",
color: "#fffc",
textAlign: "center",
fontSize: "24px",
userSelect: "none",
}}
>
暂无数据
</p>
)}
<ReactECharts option={options} />
</div>
);
};
export default GoodRateChart;
function getOptions(dataList, showMore, dateType) {
const list = [...dataList].sort((a, b) => a.dataTime - b.dataTime);
console.log(
"list ",
list.filter((item) => item.sum)
);
if (list.length === 0 || list.filter((item) => item.sum).length == 0)
return null;
const color = ["#FFD160", "#12FFF5", "#2760FF"];
const grid = { top: 28, right: 12, bottom: showMore ? 72 : 64, left: 48 };
const xAxis = {
type: "category",
data: list.map((item) =>
dateType == "day"
? item.dataTime.split("T")[1]
: item.dataTime.split("T")[0]
),
axisLabel: {
color: "#fff",
fontSize: 10,
rotate: 25,
margin: 13,
},
axisTick: { show: false },
axisLine: {
lineStyle: {
width: 1,
color: "#213259",
},
},
};
const 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,
};
const seriesTeam = [
{
name: "白班",
data: list.map((item) => (item.day * 100).toFixed(2)),
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" },
]),
},
},
{
name: "夜班",
data: list.map((item) => (item.night * 100).toFixed(2)),
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" },
]),
},
},
];
return {
grid,
color,
xAxis,
yAxis,
tooltip: {
trigger: "axis",
color: "#fff",
formatter: showMore
? "{a0} {c0}%<br />{a1} {c1}%<br />{a2} {c2}%"
: "{b} {c}%",
axisPointer: {
type: "shadow",
},
textStyle: {
color: "#fffc",
},
className: "xc-chart-tooltip",
},
series: [
{
name: "总量",
data: list.map((item) =>
item.sum != null ? (item.sum * 100).toFixed(2) : "-- "
),
type: "line",
symbol: "circle",
symbolSize: 6,
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,
},
...(showMore ? seriesTeam : []),
],
};
}
// {
// 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((_, index) => {
// const today = new Date();
// const dtimestamp = today - index * 24 * 60 * 60 * 1000;
// return `${new Date(dtimestamp).getMonth() + 1}.${new Date(
// dtimestamp
// ).getDate()}`;
// })
// .reverse(),

View File

@ -6,16 +6,15 @@
}
.GoodRateChart .titleBar {
display: flex;
justify-content: flex-start;
justify-content: space-between;
align-items: center;
gap: 5px;
color: white;
}
.GoodRateChart .titleBar h2 {
margin: 0;
font-size: 16px;
font-size: 18px;
line-height: 32px;
letter-spacing: 1px;
letter-spacing: 1.2px;
color: #52fff8;
}
@ -29,17 +28,10 @@
color: #dff1fe;
}
.graphBaseDesc {
margin: 0 6px;
font-size: 16px;
color: #76fff9;
flex: 1;
}
.GoodRateChart .titleBar .legend ul {
display: flex;
margin: 0;
margin-left: 5px;
margin-left: 8px;
padding: 0;
list-style: none;
align-items: center;
@ -50,7 +42,7 @@
padding-left: 16px;
}
.GoodRateChart .titleBar .legend ul li::before {
content: "";
content: '';
position: absolute;
left: 2px;
top: 2px;
@ -74,8 +66,7 @@
.radioGroup * {
border: none !important;
border-radius: 6px !important;
/* transform: translateX(224px) !important; */
border-radius: 0 !important;
}
.radioGroup *:focus-within {
box-shadow: none !important;

View File

@ -1,82 +1,34 @@
import { useState } from "react";
import cls from "./index.module.scss";
import { ScrollBoard } from "@jiaminghi/data-view-react";
import { useSelector } from "react-redux";
function getRate(decimal) {
return decimal != null ? (decimal * 100).toFixed(2) + "%" : undefined;
}
const TodayTableData = (props) => {
const cutting = useSelector((state) => state.cutting);
// let cutting = {
// table: [
// {
// lineName: "Y61",
// first: 0.37,
// second: 0.03,
// product: 0.99,
// waste: 0.01,
// },
// ],
// chart: {},
// };
const config = {
const [config, setConfig] = useState({
// headerBGC: 'rgba(4, 44, 76, 0.3)',
// headerBGC: "rgba(4, 44, 76, .8)",
headerBGC: "#044A8460",
headerBGC: "rgba(4, 44, 76, .8)",
header: [
'<span style="color:#fff; padding-left: 12px;">产线<span/>',
'<span style="color:#fff; padding-left: 12px;">一等率<span/>',
'<span style="color:#fff; padding-left: 12px;">二等率<span/>',
'<span style="color:#fff; padding-left: 12px;">成品率<span/>',
'<span style="color:#fff; padding-left: 12px;">废品率<span/>',
'<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",
oddRowBGC: "#044A8460",
evenRowBGC: "#0b549970",
oddRowBGC: "#042444",
evenRowBGC: "#042c4c",
columnWidth: [90],
headerHeight: 40,
hoverPause: false,
data: cutting.table.map((line) => [
line.lineName,
getRate(line.first),
getRate(line.second),
getRate(line.product),
getRate(line.waste),
]),
// data: [
// ["Y61", "37%", "62%", "97%", "7%"],
// ["Y62", "95%", "10%", "99%", "3%"],
// ["Y63", "68%", "1%", "92%", "4%"],
// ["Y64", "94%", "21%", "97%", "2%"],
// ["Y65", "99%", "30%", "95%", "5%"],
// ],
};
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}>
{config.data.length != 0 && (
<ScrollBoard
className={cls.paddingCeil}
config={config}
style={{ width: "100%", color: "#fffc" }}
/>
)}
{config.data.length == 0 && (
<p
style={{
color: "#cccf",
fontSize: "24px",
userSelect: "none",
textAlign: "center",
paddingTop: "48px",
}}
>
暂无数据
</p>
)}
<ScrollBoard config={config} style={{ width: "100%" }} />
</div>
);
};

View File

@ -1,42 +1,21 @@
import { useEffect, useRef } from "react";
import useIcon from "../hooks/useIcon";
import cls from "./container.module.scss";
import { useEffect, useRef } from 'react';
import useIcon from '../hooks/useIcon';
import cls from './container.module.scss';
const Container = (props) => {
let icon = useIcon(props.icon);
const desc = props.desc;
return (
<div
className={`${cls.container} ${props.className}`}
style={props.pending ? { filter: "grayscale(100%)" } : props.style}
>
<div className={`${cls.container} ${props.className}`} style={props.style}>
<div className={cls.container__head}>
<img
src={icon}
alt="#"
className={props.icon == "kiln" ? cls.bigger : ""}
className={props.icon == 'kiln' ? cls.bigger : ''}
/>
<h2>{props.title}</h2>
{desc && <div className={cls.graphBaseDesc}>{desc}</div>}
</div>
<div className={cls.container__content}>{props.children}</div>
{props.pending && (
<div
className={`${cls.container__content} pending-modal`}
style={{
position: "absolute",
top: 0,
left: 0,
width: "100%",
height: "100%",
borderRadius: "20px",
userSelect: "none",
cursor: "not-allowed",
}}
></div>
)}
</div>
);
};

View File

@ -1,222 +1,37 @@
import GraphBase from "../../../Common/GraphBase";
import ReactECharts from "echarts-for-react";
// import getOptions from "../../../../hooks/getChartOption";
import { useSelector } from "react-redux";
import { useState } from "react";
import * as echarts from "echarts";
import { lunarYear } from "../../../../utils/energeChartOption";
import dayjs from "dayjs";
import GraphBase from '../../../Common/GraphBase';
import ReactECharts from 'echarts-for-react';
import getOptions from '../../../../hooks/getChartOption';
function Gas(props) {
const elecTrend = useSelector((state) => state.energy.trend.natGas2);
const [period, setPeriod] = useState("周");
const [timestr, setTimestr] = useState(
dayjs().subtract(7, "day").format("YYYY.MM.DD") +
" - " +
dayjs().subtract(1, "day").format("YYYY.MM.DD")
);
const options = getOptions(
{ : "week", : "month", : "year" }[period],
elecTrend ?? { week: [], month: [], year: [] }
);
function handleSwitch(v) {
// console.log('switched ', v);
console.log('switched ', v);
}
function handleDateChange(value) {
setPeriod(value);
setTimestr(
{
:
dayjs().subtract(1, "year").endOf("year").format("YYYY.MM.") +
"29 - " +
dayjs().endOf("year").format("YYYY.MM.") +
"28",
:
dayjs().subtract(7, "day").format("YYYY.MM.DD") +
" - " +
dayjs().subtract(1, "day").format("YYYY.MM.DD"),
:
dayjs().subtract(1, "month").format("YYYY.MM.") +
"29 - " +
dayjs().format("YYYY.MM.") +
"28",
}[value]
);
function handleDateChange(v) {
console.log('date ', v);
}
return (
<GraphBase
icon="battery"
title="天然气II"
desc={`能耗趋势图 ${timestr}`}
switchOptions={false}
title="焦炉煤气"
desc="能耗趋势图"
switchOptions={true}
onSwitch={handleSwitch}
defaultSelect={period}
dateOptions={["周", "月", "年"]}
// legend={[""]}
dateOptions={['日', '周', '月', '年']}
legend={['总量']}
onDateChange={handleDateChange}
size={["long", "middle"]}
size={['long', 'short']}
>
{/* real echarts here */}
{options && (
<ReactECharts
key={Math.random()}
option={options}
// option={getOptions([[21, 4, 74, 72, 9, 59, 63]], "")}
style={{ height: "100%" }}
option={getOptions([[21, 4, 74, 72, 9, 59, 63]], '氧气')}
style={{ height: '100%' }}
/>
)}
{!options && (
<p
style={{
color: "#cccf",
fontSize: "24px",
userSelect: "none",
textAlign: "center",
paddingTop: "88px",
}}
>
暂无数据
</p>
)}
{/* real table data here */}
</GraphBase>
);
}
export default Gas;
function getOptions(period, trend) {
if (trend[period].length === 0) return null;
// export default function getOptions(seriesData, name) {
const today = new Date();
const currentYear = today.getFullYear();
const currentMonth = today.getMonth() + 1;
let days = 30;
if (period == "month") {
if (currentMonth in [1, 3, 5, 7, 8, 10, 12]) {
days = 31;
} else if (currentMonth == 2) {
days = lunarYear(currentYear) ? 29 : 28;
}
}
const colors = [
"#FFD160",
"#12FFF5",
"#2760FF",
"#E80091",
"#8064ff",
"#ff8a3b",
"#8cd26d",
"#2aa1ff",
];
return {
color: colors,
grid: { top: 40, right: 12, bottom: 20, left: 80 },
legend: {
show: false,
icon: "roundRect",
top: 10,
right: 10,
padding: 0,
itemWidth: 8,
itemHeight: 8,
itemGap: 3,
height: 8,
textStyle: {
color: "#DFF1FE",
fontSize: 12,
},
},
xAxis: {
type: "category",
data: Array(period == "week" ? 7 : period == "year" ? 12 : days)
.fill(1)
.map((_, index) => {
if (period == "week") {
const dtimestamp = today - (index + 1) * 24 * 60 * 60 * 1000;
return `${new Date(dtimestamp).getMonth() + 1}.${new Date(
dtimestamp
).getDate()}`;
} else if (period == "month") {
return `${currentMonth}.${days - index}`;
} else {
return `${currentYear}.${12 - index}`;
}
})
.reverse(),
axisLabel: {
color: "#fff",
fontSize: 14,
},
axisTick: { show: false },
axisLine: {
lineStyle: {
width: 1,
color: "#213259",
},
},
},
yAxis: {
name: "单位/Nm³",
nameTextStyle: {
color: "#fff",
fontSize: 16,
align: "right",
},
type: "value",
axisLabel: {
color: "#fff",
fontSize: 14,
formatter: "{value}",
},
axisLine: {
show: true,
lineStyle: {
color: "#213259",
},
},
splitLine: {
lineStyle: {
color: "#213259a0",
},
},
},
series: {
data: trend[period].map(item => item != null ? (+item).toFixed(2) : null),
type: "line",
symbol: "circle",
symbolSize: 6,
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: colors[0] + "40" },
{ offset: 0.5, color: colors[0] + "20" },
{ offset: 1, color: colors[0] + "00" },
]),
},
},
// 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",
axisPointer: {
type: "shadow",
},
className: "xc-chart-tooltip",
// backgroundColor: ''
},
};
}

View File

@ -1,204 +1,37 @@
import GraphBase from "../../../Common/GraphBase";
import ReactECharts from "echarts-for-react";
import { useSelector } from "react-redux";
import { useState } from "react";
import * as echarts from "echarts";
import dayjs from "dayjs";
import GraphBase from '../../../Common/GraphBase';
import ReactECharts from 'echarts-for-react';
import getOptions from '../../../../hooks/getChartOption';
function ElecCost(props) {
const elecTrend = useSelector((state) => state.energy.trend.elec);
const [period, setPeriod] = useState("周");
const [timestr, setTimestr] = useState(
dayjs().subtract(7, "day").format("YYYY.MM.DD") +
" - " +
dayjs().subtract(1, "day").format("YYYY.MM.DD")
);
const options = getOptions(
{ : "week", : "month", : "year" }[period],
elecTrend ?? { week: [], month: [], year: [] }
);
function handleSwitch(v) {
// console.log('switched ', v);
console.log('switched ', v);
}
function handleDateChange(value) {
setPeriod(value);
setTimestr(
{
:
dayjs().subtract(1, "year").endOf("year").format("YYYY.MM.") +
"29 - " +
dayjs().endOf("year").format("YYYY.MM.") +
"28",
:
dayjs().subtract(7, "day").format("YYYY.MM.DD") +
" - " +
dayjs().subtract(1, "day").format("YYYY.MM.DD"),
:
dayjs().subtract(1, "month").format("YYYY.MM.") +
"29 - " +
dayjs().format("YYYY.MM.") +
"28",
}[value]
);
function handleDateChange(v) {
console.log('date ', v);
}
return (
<GraphBase
icon="battery"
title="电耗能"
desc={`能耗趋势图 ${timestr}`}
switchOptions={false}
desc="能耗趋势图"
switchOptions={true}
onSwitch={handleSwitch}
defaultSelect={period}
dateOptions={["周", "月", "年"]}
// legend={[""]}
dateOptions={['日', '周', '月', '年']}
legend={['总量']}
onDateChange={handleDateChange}
size={["long", "middle"]}
size={['long', 'short']}
>
{/* real echarts here */}
{options && (
<ReactECharts
key={Math.random()}
option={options}
// option={getOptions([[112, 73, 79, 82, 30, 105, 87]], "")}
style={{ height: "100%" }}
option={getOptions([[112, 73, 79, 82, 30, 105, 87]], '氧气')}
style={{ height: '100%' }}
/>
)}
{!options && (
<p
style={{
color: "#cccf",
fontSize: "24px",
userSelect: "none",
textAlign: "center",
paddingTop: "48px",
}}
>
暂无数据
</p>
)}
{/* real table data here */}
</GraphBase>
);
}
export default ElecCost;
function getOptions(period, trend) {
if (trend[period].length === 0) return null;
const colors = [
"#FFD160",
"#12FFF5",
"#2760FF",
"#E80091",
"#8064ff",
"#ff8a3b",
"#8cd26d",
"#2aa1ff",
];
return {
color: colors,
grid: { top: 40, right: 12, bottom: 20, left: 80 },
legend: {
show: false,
icon: "roundRect",
top: 10,
right: 10,
padding: 0,
itemWidth: 8,
itemHeight: 8,
itemGap: 3,
height: 8,
textStyle: {
color: "#DFF1FE",
fontSize: 12,
},
},
xAxis: {
type: "category",
data: trend[period].map((item) => item.time),
// 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: 14,
},
axisTick: { show: false },
axisLine: {
lineStyle: {
width: 1,
color: "#213259",
},
},
},
yAxis: {
name: "单位/kWh",
nameTextStyle: {
color: "#fff",
fontSize: 16,
align: "right",
},
type: "value",
axisLabel: {
color: "#fff",
fontSize: 14,
formatter: "{value}",
},
axisLine: {
show: true,
lineStyle: {
color: "#213259",
},
},
splitLine: {
lineStyle: {
color: "#213259a0",
},
},
},
series: {
// !(item.value == null || isNaN(+item.value)) ? (+item.value).toFixed(2) : null
data: trend[period].map((item) =>
item.qty == null || isNaN(+item.qty) ? null : (+item.qty).toFixed(2)
),
type: "line",
symbol: "circle",
symbolSize: 6,
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: colors[0] + "40" },
{ offset: 0.5, color: colors[0] + "20" },
{ offset: 1, color: colors[0] + "00" },
]),
},
},
// 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",
axisPointer: {
type: "shadow",
},
className: "xc-chart-tooltip",
},
};
}

View File

@ -1,164 +1,43 @@
import cls from "./index.module.css";
import GradientText from "../../../Common/GradientText";
import { useSelector } from "react-redux";
import { useEffect, useState } from "react";
import cls from './index.module.css';
import GradientText from '../../../Common/GradientText';
function Energy(props) {
const [isPage1, setIsPage1] = useState(true);
const energyInfo = useSelector((state) => state.energy?.info);
useEffect(() => {
const timer = setInterval(() => {
setIsPage1((pre) => !pre);
}, 10000);
return () => {
clearInterval(timer);
}
}, []);
return (
<div className={" " + cls.layout} style={{ color: "#fff" }}>
<div className={' ' + cls.layout} style={{ color: '#fff' }}>
<span
className={cls.shadowBorder}
style={{
gridRow: "1 / 3",
paddingTop: "104px",
paddingLeft: "32px",
userSelect: "none",
gridRow: '1 / 3',
paddingTop: '38px',
paddingLeft: '32px',
userSelect: 'none',
}}
>
<GradientText text="能源" />
</span>
{!isPage1 && (
<div
style={{
gridRow: "1 / 3",
gridColumn: "2 / 5",
display: "grid",
gridTemplateRows: "1fr 1fr",
gridTemplateColumns: "1fr 1fr",
gap: "6px",
}}
>
<div className={cls.shadowBorder + " " + cls.infoText}>
<span style={{ lineHeight: 1.5 }}>智慧能源光伏发电(昨日)/kWh</span>
<span
className={cls.shadowBorder + ' ' + cls.infoText}
style={{
lineHeight: 1.5,
width: "180px",
wordWrap: "break-word",
gridRow: '1 / 3',
}}
>
{(+energyInfo?.elecQty6)?.toFixed(2) || 0}
<span style={{ lineHeight: 2.5 }}>余热发电</span>
<span style={{ lineHeight: 2.5 }}>992Kwh</span>
</span>
</div>
<div className={cls.shadowBorder + " " + cls.infoText}>
<span style={{ lineHeight: 1.5 }}>许昌安彩光伏发电(昨日)/kWh</span>
<span
style={{
lineHeight: 1.5,
width: "180px",
wordWrap: "break-word",
}}
>
{(+energyInfo?.elecQty7)?.toFixed(2) || 0}
<span className={cls.shadowBorder + ' ' + cls.infoText}>
水耗量: 32Km³
</span>
</div>
<div className={cls.shadowBorder + " " + cls.infoText}>
<span style={{ lineHeight: 1.5 }}>智慧能源光伏发电(总量)/kWh</span>
<span
style={{
lineHeight: 1.5,
width: "180px",
wordWrap: "break-word",
}}
>
{(+energyInfo?.elecQty4)?.toFixed(2) || 0}
<span className={cls.shadowBorder + ' ' + cls.infoText}>
天然气I: 92
</span>
</div>
<div className={cls.shadowBorder + " " + cls.infoText}>
<span style={{ lineHeight: 1.5 }}>许昌安彩光伏发电(总量)/kWh</span>
<span
style={{
lineHeight: 1.5,
width: "180px",
wordWrap: "break-word",
}}
>
{(+energyInfo?.elecQty5)?.toFixed(2) || 0}
<span className={cls.shadowBorder + ' ' + cls.infoText}>
电耗量: 92Km³
</span>
</div>
</div>
)}
{isPage1 && (
<>
<div
style={{
display: "flex",
flexDirection: "column",
gap: "6px",
gridRow: "1 / 3",
}}
>
<div
style={{ flex: 1 }}
className={cls.shadowBorder + " " + cls.infoText}
>
<span style={{ lineHeight: 1.5 }}>余热发电(实时)/kWh</span>
<span
style={{
lineHeight: 1.5,
width: "180px",
wordWrap: "break-word",
}}
>
{(+energyInfo?.elecQty1)?.toFixed(2) || 0}
<span className={cls.shadowBorder + ' ' + cls.infoText}>
天然气II: 92
</span>
</div>
<div
style={{ flex: 1 }}
className={cls.shadowBorder + " " + cls.infoText}
>
<span style={{ lineHeight: 1.5 }}>余热发电(总量)/kWh</span>
<span
style={{
lineHeight: 1.5,
width: "180px",
wordWrap: "break-word",
}}
>
{(+energyInfo?.elecQty3)?.toFixed(2) || 0}
</span>
</div>
</div>
<span className={cls.shadowBorder + " " + cls.infoText}>
<span style={{ lineHeight: 1.5 }}>水耗量/Km³</span>
<span style={{ lineHeight: 1.5 }}>
{(+energyInfo?.waterQty)?.toFixed(2) || 0}
</span>
</span>
<span className={cls.shadowBorder + " " + cls.infoText}>
<span style={{ lineHeight: 1.5 }}>天然气I/Nm³</span>
<span style={{ lineHeight: 1.5 }}>
{energyInfo?.ngQty1?.replace("Nm³", "") || "0Nm³"}
</span>
</span>
<span className={cls.shadowBorder + " " + cls.infoText}>
<span style={{ lineHeight: 1.5 }}>电耗量/kWh</span>
<span style={{ lineHeight: 1.5 }}>
{(+energyInfo?.elecQty2)?.toFixed(2) || 0}
</span>
</span>
<span className={cls.shadowBorder + " " + cls.infoText}>
<span style={{ lineHeight: 1.5 }}>天然气II/Nm³</span>
<span style={{ lineHeight: 1.5 }}>
{energyInfo?.ngQty2?.replace("Nm³", "") || "0Nm³"}
</span>
</span>
</>
)}
</div>
);
}

View File

@ -1,32 +1,21 @@
.layout {
display: grid;
gap: 6px;
/* grid-template-columns: 133px 158px 292px 292px; */
grid-template-columns: 125px 250px 250px 250px;
/* grid-template-rows: 60px 60px; */
grid-template-rows: 129px 129px;
grid-template-columns: 133px 158px 292px 292px ;
grid-template-rows: 60px 60px;
}
.shadowBorder {
box-shadow: inset 0 0 12px 3px #fff2;
box-shadow: inset 0 0 12px 3px #fff3;
border-radius: 4px;
padding: 4px;
}
.infoText {
text-align: center;
font-size: 22px;
line-height: 2.5;
font-size: 24px;
line-height: 2.2;
/* line-height: 20px; */
letter-spacing: 1px;
user-select: none;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.infoText > span:last-child {
color: #00FFF7;
font-size: 24px;
}

View File

@ -1,172 +1,44 @@
import GraphBase from "../../../Common/GraphBase";
import ReactECharts from "echarts-for-react";
// import getOptions from "../../../../hooks/getChartOption";
import { useSelector } from "react-redux";
import { useState } from "react";
import * as echarts from "echarts";
import dayjs from "dayjs";
import GraphBase from '../../../Common/GraphBase';
import ReactECharts from 'echarts-for-react';
import getOptions from '../../../../hooks/getChartOption';
function NO(props) {
const dayTrend = useSelector((state) => state.smoke?.dayTrend);
const weekTrend = useSelector((state) => state.smoke?.weekTrend);
const monthTrend = useSelector((state) => state.smoke?.monthTrend);
const yearTrend = useSelector((state) => state.smoke?.yearTrend);
const [period, setPeriod] = useState("日");
const [timestr, setTimestr] = useState(
dayjs().subtract(7, "day").format("YYYY.MM.DD") +
" - " +
dayjs().subtract(1, "day").format("YYYY.MM.DD")
);
const currentTrend =
period === "日"
? dayTrend
: period === "周"
? weekTrend
: period === "月"
? monthTrend
: yearTrend;
const options = getOptions("NOX_float", period, currentTrend);
function handleSwitch(v) {}
function handleDateChange(value) {
setPeriod(value);
setTimestr(
{
:
dayjs().subtract(1, "day").format("YYYY.MM.DD") +
" 7点 - " +
dayjs().format("YYYY.MM.DD") +
" 7点",
:
dayjs().subtract(1, "year").endOf("year").format("YYYY.MM.") +
"29 - " +
dayjs().endOf("year").format("YYYY.MM.") +
"28",
:
dayjs().subtract(7, "day").format("YYYY.MM.DD") +
" - " +
dayjs().subtract(1, "day").format("YYYY.MM.DD"),
:
dayjs().subtract(1, "month").format("YYYY.MM.") +
"29 - " +
dayjs().format("YYYY.MM.") +
"28",
}[value]
);
function handleSwitch(v) {
console.log('switched ', v);
}
function handleDateChange(v) {
console.log('date ', v);
}
return (
<GraphBase
icon="smoke"
title="氮氧化物"
desc={`能耗趋势图 ${timestr}`}
switchOptions={false}
defaultSelect={period}
icon="battery"
title="一氧化氮"
desc="能耗趋势图"
switchOptions={true}
onSwitch={handleSwitch}
dateOptions={["日", "周", "月", "年"]}
dateOptions={['日', '周', '月', '年']}
legend={['总量', '白班', '夜班']}
onDateChange={handleDateChange}
size={["long", "middle"]}
size={['long', 'middle']}
>
{options && (
{/* real echarts here */}
<ReactECharts
key={Math.random()}
option={options}
style={{ height: "100%" }}
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%' }}
/>
)}
{!options && (
<p
style={{
color: "#cccf",
fontSize: "24px",
userSelect: "none",
textAlign: "center",
paddingTop: "96px",
}}
>
暂无数据
</p>
)}
{/* real table data here */}
</GraphBase>
);
}
export default NO;
function getOptions(source, period, trend) {
if (
trend[source].length == 0 ||
trend[source].filter((item) => item.value).length == 0
)
return null;
return {
color: ["#FFD160", "#12FFF5", "#2760FF"],
grid: { top: 40, right: 12, bottom: 20, left: 64 },
xAxis: {
type: "category",
data: trend[source].map((item) => item.time),
axisLabel: {
color: "#fff",
fontSize: 12,
},
axisTick: { show: false },
axisLine: {
lineStyle: {
width: 1,
color: "#213259",
},
},
},
yAxis: {
name: "单位mg/m³",
nameTextStyle: {
color: "#fff",
fontSize: 12,
align: "right",
},
type: "value",
axisLabel: {
color: "#fff",
fontSize: 12,
formatter: "{value}",
},
axisLine: {
show: true,
lineStyle: {
color: "#213259",
},
},
splitLine: {
lineStyle: {
color: "#213259a0",
},
},
},
series: [
{
data: trend[source].map((item) =>
!(item.value == null || isNaN(+item.value))
? (+item.value).toFixed(2)
: null
),
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" },
]),
},
},
],
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow",
},
className: "xc-chart-tooltip",
},
};
}

View File

@ -1,174 +1,44 @@
import GraphBase from "../../../Common/GraphBase";
import ReactECharts from "echarts-for-react";
// import getOptions from "../../../../hooks/getChartOption";
import { useSelector } from "react-redux";
import { useState } from "react";
import * as echarts from "echarts";
import dayjs from "dayjs";
import GraphBase from '../../../Common/GraphBase';
import ReactECharts from 'echarts-for-react';
import getOptions from '../../../../hooks/getChartOption';
function Dust(props) {
const dayTrend = useSelector((state) => state.smoke?.dayTrend);
const weekTrend = useSelector((state) => state.smoke?.weekTrend);
const monthTrend = useSelector((state) => state.smoke?.monthTrend);
const yearTrend = useSelector((state) => state.smoke?.yearTrend);
const [period, setPeriod] = useState("日");
const [timestr, setTimestr] = useState(
dayjs().subtract(7, "day").format("YYYY.MM.DD") +
" - " +
dayjs().subtract(1, "day").format("YYYY.MM.DD")
);
const currentTrend =
period === "日"
? dayTrend
: period === "周"
? weekTrend
: period === "月"
? monthTrend
: yearTrend;
function NO2(props) {
function handleSwitch(v) {
console.log('switched ', v);
}
const options = getOptions("dust_float", period, currentTrend);
function handleSwitch(v) {}
function handleDateChange(value) {
setPeriod(value);
setTimestr(
{
:
dayjs().subtract(1, "day").format("YYYY.MM.DD") +
" 7点 - " +
dayjs().format("YYYY.MM.DD") +
" 7点",
:
dayjs().subtract(1, "year").endOf("year").format("YYYY.MM.") +
"29 - " +
dayjs().endOf("year").format("YYYY.MM.") +
"28",
:
dayjs().subtract(7, "day").format("YYYY.MM.DD") +
" - " +
dayjs().subtract(1, "day").format("YYYY.MM.DD"),
:
dayjs().subtract(1, "month").format("YYYY.MM.") +
"29 - " +
dayjs().format("YYYY.MM.") +
"28",
}[value]
);
function handleDateChange(v) {
console.log('date ', v);
}
return (
<GraphBase
icon="smoke"
title="颗粒物"
desc={`能耗趋势图 ${timestr}`}
switchOptions={false}
defaultSelect={period}
icon="battery"
title="二氧化氮"
desc="能耗趋势图"
switchOptions={true}
onSwitch={handleSwitch}
dateOptions={["日", "周", "月", "年"]}
dateOptions={['日', '周', '月', '年']}
legend={['总量', '白班', '夜班']}
onDateChange={handleDateChange}
size={["long", "middle"]}
size={['long', 'middle']}
>
{options && (
{/* real echarts here */}
<ReactECharts
key={Math.random()}
option={options}
style={{ height: "100%" }}
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%' }}
/>
)}
{!options && (
<p
style={{
color: "#cccf",
fontSize: "24px",
userSelect: "none",
textAlign: "center",
paddingTop: "96px",
}}
>
暂无数据
</p>
)}
{/* real table data here */}
</GraphBase>
);
}
export default Dust;
function getOptions(source, period, trend) {
if (
trend[source].length == 0 ||
trend[source].filter((item) => item.value).length == 0
)
return null;
return {
color: ["#FFD160", "#12FFF5", "#2760FF"],
grid: { top: 40, right: 12, bottom: 20, left: 64 },
xAxis: {
type: "category",
data: trend[source].map((item) => item.time),
axisLabel: {
color: "#fff",
fontSize: 12,
},
axisTick: { show: false },
axisLine: {
lineStyle: {
width: 1,
color: "#213259",
},
},
},
yAxis: {
name: "单位mg/m³",
nameTextStyle: {
color: "#fff",
fontSize: 12,
align: "right",
},
type: "value",
axisLabel: {
color: "#fff",
fontSize: 12,
formatter: "{value}",
},
axisLine: {
show: true,
lineStyle: {
color: "#213259",
},
},
splitLine: {
lineStyle: {
color: "#213259a0",
},
},
},
series: [
{
data: trend[source].map((item) =>
!(item.value == null || isNaN(+item.value))
? (+item.value).toFixed(2)
: null
),
type: "line",
symbol: "circle",
symbolSize: 6,
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: "#FFD16040" },
{ offset: 0.5, color: "#FFD16020" },
{ offset: 1, color: "#FFD16010" },
]),
},
},
],
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow",
},
className: "xc-chart-tooltip",
},
};
}
export default NO2;

View File

@ -1,224 +1,37 @@
import GraphBase from "../../../Common/GraphBase";
import ReactECharts from "echarts-for-react";
// import getOptions from "../../../../hooks/getChartOption";
import { useSelector } from "react-redux";
import { useState } from "react";
import * as echarts from "echarts";
import { lunarYear } from "../../../../utils/energeChartOption";
import dayjs from "dayjs";
import GraphBase from '../../../Common/GraphBase';
import ReactECharts from 'echarts-for-react';
import getOptions from '../../../../hooks/getChartOption';
function NatGas(props) {
const elecTrend = useSelector((state) => state.energy.trend.natGas1);
const [period, setPeriod] = useState("周");
const [timestr, setTimestr] = useState(
dayjs().subtract(7, "day").format("YYYY.MM.DD") +
" - " +
dayjs().subtract(1, "day").format("YYYY.MM.DD")
);
const options = getOptions(
{ : "week", : "month", : "year" }[period],
elecTrend ?? { week: [], month: [], year: [] }
);
function handleSwitch(v) {
// console.log('switched ', v);
console.log('switched ', v);
}
function handleDateChange(value) {
setPeriod(value);
setTimestr(
{
:
dayjs().subtract(1, "year").endOf("year").format("YYYY.MM.") +
"29 - " +
dayjs().endOf("year").format("YYYY.MM.") +
"28",
:
dayjs().subtract(7, "day").format("YYYY.MM.DD") +
" - " +
dayjs().subtract(1, "day").format("YYYY.MM.DD"),
:
dayjs().subtract(1, "month").format("YYYY.MM.") +
"29 - " +
dayjs().format("YYYY.MM.") +
"28",
}[value]
);
function handleDateChange(v) {
console.log('date ', v);
}
return (
<GraphBase
icon="battery"
title="天然气I"
desc={`能耗趋势图 ${timestr}`}
switchOptions={false}
title="天然气"
desc="能耗趋势图"
switchOptions={true}
onSwitch={handleSwitch}
defaultSelect={period}
dateOptions={["周", "月", "年"]}
// legend={[""]}
dateOptions={['日', '周', '月', '年']}
legend={['总量']}
onDateChange={handleDateChange}
size={["long", "middle"]}
size={['long', 'short']}
>
{/* real echarts here */}
{options && (
<ReactECharts
key={Math.random()}
option={options}
// option={getOptions([[91, 69, 5, 10, 21, 46, 24]], "")}
style={{ height: "100%" }}
option={getOptions([[91, 69, 5, 10, 21, 46, 24]], '氧气')}
style={{ height: '100%' }}
/>
)}
{!options && (
<p
style={{
color: "#cccf",
fontSize: "24px",
userSelect: "none",
textAlign: "center",
paddingTop: "88px",
}}
>
暂无数据
</p>
)}
{/* real table data here */}
</GraphBase>
);
}
export default NatGas;
function getOptions(period, trend) {
if (trend[period].length === 0) return null;
// export default function getOptions(seriesData, name) {
const today = new Date();
const currentYear = today.getFullYear();
const currentMonth = today.getMonth() + 1;
let days = 30;
if (period == "month") {
if (currentMonth in [1, 3, 5, 7, 8, 10, 12]) {
days = 31;
} else if (currentMonth == 2) {
days = lunarYear(currentYear) ? 29 : 28;
}
}
const colors = [
"#FFD160",
"#12FFF5",
"#2760FF",
"#E80091",
"#8064ff",
"#ff8a3b",
"#8cd26d",
"#2aa1ff",
];
return {
color: colors,
grid: { top: 40, right: 12, bottom: 20, left: 80 },
legend: {
show: false,
icon: "roundRect",
top: 10,
right: 10,
padding: 0,
itemWidth: 8,
itemHeight: 8,
itemGap: 3,
height: 8,
textStyle: {
color: "#DFF1FE",
fontSize: 12,
},
},
xAxis: {
type: "category",
data: Array(period == "week" ? 7 : period == "year" ? 12 : days)
.fill(1)
.map((_, index) => {
if (period == "week") {
const dtimestamp = today - (index + 1) * 24 * 60 * 60 * 1000;
return `${new Date(dtimestamp).getMonth() + 1}.${new Date(
dtimestamp
).getDate()}`;
} else if (period == "month") {
return `${currentMonth}.${days - index}`;
} else {
return `${currentYear}.${12 - index}`;
}
})
.reverse(),
axisLabel: {
color: "#fff",
fontSize: 14,
},
axisTick: { show: false },
axisLine: {
lineStyle: {
width: 1,
color: "#213259",
},
},
},
yAxis: {
name: "单位/Nm³",
nameTextStyle: {
color: "#fff",
fontSize: 16,
align: "right",
},
type: "value",
axisLabel: {
color: "#fff",
fontSize: 14,
formatter: "{value}",
},
axisLine: {
show: true,
lineStyle: {
color: "#213259",
},
},
splitLine: {
lineStyle: {
color: "#213259a0",
},
},
},
series: {
data: trend[period].map((item) =>
item != null ? (+item).toFixed(2) : null
),
type: "line",
symbol: "circle",
symbolSize: 6,
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: colors[0] + "40" },
{ offset: 0.5, color: colors[0] + "20" },
{ offset: 1, color: colors[0] + "00" },
]),
},
},
// 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",
axisPointer: {
type: "shadow",
},
className: "xc-chart-tooltip",
// backgroundColor: ''
},
};
}

View File

@ -1,186 +1,65 @@
import GraphBase from "../../../Common/GraphBase";
import ReactECharts from "echarts-for-react";
// import getOptions from "../../../../hooks/getChartOption";
import { useSelector } from "react-redux";
import { useState } from "react";
import * as echarts from "echarts";
import dayjs from "dayjs";
import GraphBase from '../../../Common/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) {
const dayTrend = useSelector((state) => state.smoke?.dayTrend);
const weekTrend = useSelector((state) => state.smoke?.weekTrend);
const monthTrend = useSelector((state) => state.smoke?.monthTrend);
const yearTrend = useSelector((state) => state.smoke?.yearTrend);
const [period, setPeriod] = useState("日");
const [timestr, setTimestr] = useState(
dayjs().subtract(7, "day").format("YYYY.MM.DD") +
" - " +
dayjs().subtract(1, "day").format("YYYY.MM.DD")
);
const currentTrend =
period === "日"
? dayTrend
: period === "周"
? weekTrend
: period === "月"
? monthTrend
: yearTrend;
const options = getOptions("O2_float", period, currentTrend);
function handleSwitch(v) {}
function handleDateChange(value) {
setPeriod(value);
setTimestr(
{
:
dayjs().subtract(1, "day").format("YYYY.MM.DD") +
" 7点 - " +
dayjs().format("YYYY.MM.DD") +
" 7点",
:
dayjs().subtract(1, "year").endOf("year").format("YYYY.MM.") +
"29 - " +
dayjs().endOf("year").format("YYYY.MM.") +
"28",
:
dayjs().subtract(7, "day").format("YYYY.MM.DD") +
" - " +
dayjs().subtract(1, "day").format("YYYY.MM.DD"),
:
dayjs().subtract(1, "month").format("YYYY.MM.") +
"29 - " +
dayjs().format("YYYY.MM.") +
"28",
}[value]
);
function handleSwitch(v) {
console.log('switched ', v);
}
function handleDateChange(v) {
console.log('date ', v);
}
return (
<GraphBase
icon="smoke"
icon="battery"
title="氧气含量"
desc={`能耗趋势图 ${timestr}`}
switchOptions={false}
defaultSelect={period}
desc="能耗趋势图"
switchOptions={true}
onSwitch={handleSwitch}
dateOptions={["日", "周", "月", "年"]}
dateOptions={['日', '周', '月', '年']}
legend={['总量', '白班', '夜班']}
onDateChange={handleDateChange}
size={["long", "middle"]}
size={['long', 'middle']}
>
{options && (
{/* real echarts here */}
<ReactECharts
key={Math.random()}
option={options}
style={{ height: "100%" }}
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%' }}
/>
)}
{!options && (
<p
style={{
color: "#cccf",
fontSize: "24px",
userSelect: "none",
textAlign: "center",
paddingTop: "160px",
}}
>
暂无数据
</p>
)}
{/* real table data here */}
</GraphBase>
);
}
export default Oxygen;
function getOptions(source, period, trend) {
if (
trend[source].length == 0 ||
trend[source].filter((item) => item.value).length == 0
)
return null;
return {
color: ["#FFD160", "#12FFF5", "#2760FF"],
grid: { top: 40, right: 12, bottom: 20, left: 80 },
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(),
data: trend[source].map((item) => item.time),
axisLabel: {
color: "#fff",
fontSize: 12,
},
axisTick: { show: false },
axisLine: {
lineStyle: {
width: 1,
color: "#213259",
},
},
},
yAxis: {
name: "单位/%",
nameTextStyle: {
color: "#fff",
fontSize: 16,
align: "right",
},
type: "value",
axisLabel: {
color: "#fff",
fontSize: 16,
formatter: "{value} %",
},
min: 0,
max: 100,
axisLine: {
show: true,
lineStyle: {
color: "#213259",
},
},
splitLine: {
lineStyle: {
color: "#213259a0",
},
},
},
series: [
{
data: trend[source].map((item) =>
!(item.value == null || isNaN(+item.value))
? (+item.value).toFixed(2)
: null
),
type: "line",
symbol: "circle",
symbolSize: 6,
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: "#FFD16040" },
{ offset: 0.5, color: "#FFD16020" },
{ offset: 1, color: "#FFD16010" },
]),
},
},
],
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow",
},
className: "xc-chart-tooltip",
},
};
}

View File

@ -4,11 +4,11 @@ import getOptions from '../../../../hooks/getChartOption';
function RestHeat(props) {
function handleSwitch(v) {
// console.log('switched ', v);
console.log('switched ', v);
}
function handleDateChange(v) {
// console.log('date ', v);
console.log('date ', v);
}
return (

View File

@ -1,174 +1,44 @@
import GraphBase from "../../../Common/GraphBase";
import ReactECharts from "echarts-for-react";
// import getOptions from "../../../../hooks/getChartOption";
import { useSelector } from "react-redux";
import { useState } from "react";
import * as echarts from "echarts";
import dayjs from "dayjs";
import GraphBase from '../../../Common/GraphBase';
import ReactECharts from 'echarts-for-react';
import getOptions from '../../../../hooks/getChartOption';
function SO2(props) {
const dayTrend = useSelector((state) => state.smoke?.dayTrend);
const weekTrend = useSelector((state) => state.smoke?.weekTrend);
const monthTrend = useSelector((state) => state.smoke?.monthTrend);
const yearTrend = useSelector((state) => state.smoke?.yearTrend);
const [period, setPeriod] = useState("日");
function handleSwitch(v) {
console.log('switched ', v);
}
const currentTrend =
period === "日"
? dayTrend
: period === "周"
? weekTrend
: period === "月"
? monthTrend
: yearTrend;
const [timestr, setTimestr] = useState(
dayjs().subtract(7, "day").format("YYYY.MM.DD") +
" - " +
dayjs().subtract(1, "day").format("YYYY.MM.DD")
);
const options = getOptions("SO2_float", period, currentTrend);
function handleSwitch(v) {}
function handleDateChange(value) {
setPeriod(value);
setTimestr(
{
:
dayjs().subtract(1, "day").format("YYYY.MM.DD") +
" 7点 - " +
dayjs().format("YYYY.MM.DD") +
" 7点",
:
dayjs().subtract(1, "year").endOf("year").format("YYYY.MM.") +
"29 - " +
dayjs().endOf("year").format("YYYY.MM.") +
"28",
:
dayjs().subtract(7, "day").format("YYYY.MM.DD") +
" - " +
dayjs().subtract(1, "day").format("YYYY.MM.DD"),
:
dayjs().subtract(1, "month").format("YYYY.MM.") +
"29 - " +
dayjs().format("YYYY.MM.") +
"28",
}[value]
);
function handleDateChange(v) {
console.log('date ', v);
}
return (
<GraphBase
icon="smoke"
icon="battery"
title="二氧化硫"
desc={`能耗趋势图 ${timestr}`}
switchOptions={false}
defaultSelect={period}
desc="能耗趋势图"
switchOptions={true}
onSwitch={handleSwitch}
dateOptions={["日", "周", "月", "年"]}
dateOptions={['日', '周', '月', '年']}
legend={['总量', '白班', '夜班']}
onDateChange={handleDateChange}
size={["long", "middle"]}
size={['long', 'middle']}
>
{options && (
{/* real echarts here */}
<ReactECharts
key={Math.random()}
option={options}
style={{ height: "100%" }}
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%' }}
/>
)}
{!options && (
<p
style={{
color: "#cccf",
fontSize: "24px",
userSelect: "none",
textAlign: "center",
paddingTop: "96px",
}}
>
暂无数据
</p>
)}
{/* real table data here */}
</GraphBase>
);
}
export default SO2;
function getOptions(source, period, trend) {
if (
trend[source].length == 0 ||
trend[source].filter((item) => item.value).length == 0
)
return null;
return {
color: ["#FFD160", "#12FFF5", "#2760FF"],
grid: { top: 40, right: 12, bottom: 20, left: 64 },
xAxis: {
type: "category",
data: trend[source].map((item) => item.time),
axisLabel: {
color: "#fff",
fontSize: 12,
},
axisTick: { show: false },
axisLine: {
lineStyle: {
width: 1,
color: "#213259",
},
},
},
yAxis: {
name: "单位mg/m³",
nameTextStyle: {
color: "#fff",
fontSize: 12,
align: "right",
},
type: "value",
axisLabel: {
color: "#fff",
fontSize: 12,
formatter: "{value}",
},
axisLine: {
show: true,
lineStyle: {
color: "#213259",
},
},
splitLine: {
lineStyle: {
color: "#213259a0",
},
},
},
series: [
{
data: trend[source].map((item) =>
!(item.value == null || isNaN(+item.value))
? (+item.value).toFixed(2)
: null
),
type: "line",
symbol: "circle",
symbolSize: 6,
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: "#FFD16040" },
{ offset: 0.5, color: "#FFD16020" },
{ offset: 1, color: "#FFD16010" },
]),
},
},
],
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow",
},
className: "xc-chart-tooltip",
},
};
}

View File

@ -1,48 +1,34 @@
import cls from "./index.module.css";
import GradientText from "../../../Common/GradientText";
import { useSelector } from "react-redux";
import cls from './index.module.css';
import GradientText from '../../../Common/GradientText';
function SmokeHandle(props) {
const smokeInfo = useSelector((state) => state.smoke?.info);
return (
<div className={" " + cls.smoke} style={{ color: "#fff" }}>
<div className={' ' + cls.smoke} style={{ color: '#fff' }}>
<span
className={cls.shadowBorder}
style={{
gridRow: "1 / 3",
paddingTop: "96px",
paddingLeft: "32px",
userSelect: "none",
gridRow: '1 / 3',
paddingTop: '38px',
paddingLeft: '32px',
userSelect: 'none',
}}
>
<GradientText text="烟气处理" />
</span>
<span
className={cls.shadowBorder + " " + cls.infoText}
style={{ letterSpacing: "2px" }}
className={cls.shadowBorder + ' ' + cls.infoText}
style={{ letterSpacing: '12px' }}
>
<span style={{ lineHeight: 1.5 }}>氧气含量 %</span>
<span style={{ lineHeight: 1.5 }}>
{(+smokeInfo?.O2_float)?.toFixed(2) || 0}
氧气含量: <span style={{ letterSpacing: '1px' }}>80%</span>
</span>
<span className={cls.shadowBorder + ' ' + cls.infoText}>
一氧化氮排放浓度: 20mg/
</span>
<span className={cls.shadowBorder + " " + cls.infoText}>
<span style={{ lineHeight: 1.5 }}>氮氧化物浓度 mg/</span>
<span style={{ lineHeight: 1.5 }}>
{(+smokeInfo?.NOX_float)?.toFixed(2) || 0}
</span>
</span>
<span className={cls.shadowBorder + " " + cls.infoText}>
<span style={{ lineHeight: 1.5 }}>二氧化硫浓度 mg/</span>
<span style={{ lineHeight: 1.5 }}>
{(+smokeInfo?.SO2_float)?.toFixed(2) || 0}
</span>
</span>
<span className={cls.shadowBorder + " " + cls.infoText}>
<span style={{ lineHeight: 1.5 }}>颗粒物浓度 mg/</span>
<span style={{ lineHeight: 1.5 }}>
{(+smokeInfo?.dust_float)?.toFixed(2) || 0}
<span className={cls.shadowBorder + ' ' + cls.infoText}>
二氧化硫排放浓度: 20mg/
</span>
<span className={cls.shadowBorder + ' ' + cls.infoText}>
二氧化氮排放浓度: 20mg/
</span>
</div>
);

View File

@ -1,14 +1,12 @@
.smoke {
display: grid;
gap: 6px;
grid-template-columns: 187px 347px 347px;
/* grid-template-rows: 60px 60px; */
grid-template-rows: 129px 129px;
height: 100%;
grid-template-columns: 187px 347px 347px ;
grid-template-rows: 60px 60px;
}
.shadowBorder {
box-shadow: inset 0 0 12px 3px #fff2;
box-shadow: inset 0 0 12px 3px #fff3;
border-radius: 4px;
padding: 4px;
}
@ -16,17 +14,8 @@
.infoText {
text-align: center;
font-size: 24px;
line-height: 2.5;
line-height: 2.2;
/* line-height: 20px; */
letter-spacing: 1px;
user-select: none;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.infoText > span:last-child {
color: #00fff7;
font-size: 28px;
}

View File

@ -4,11 +4,11 @@ import getOptions from '../../../../hooks/getChartOption';
function WaterCost(props) {
function handleSwitch(v) {
// console.log('switched ', v);
console.log('switched ', v);
}
function handleDateChange(v) {
// console.log('date ', v);
console.log('date ', v);
}
return (

View File

@ -1,6 +1,6 @@
import React from 'react';
import CurrentTemp from '../../../Common/CurrentTemp';
import WindFrequence from '../../../Common/AnnealFanRunFrequence';
import WindFrequence from '../../../Common/FanRunFrequence';
import { motion } from 'framer-motion';
@ -19,7 +19,7 @@ export default function index() {
<CurrentTemp style={{ width: '100%' }} />
</div>
<div style={{ flex: 1, marginTop: '24px', width: '100%' }}>
<WindFrequence stretch={true} />
<WindFrequence />
</div>
</motion.div>
);

View File

@ -1,5 +1,5 @@
import { motion } from 'framer-motion';
import FanInfo from '../../../Common/FanInfoStretch';
import FanInfo from '../../../Common/FanInfo';
import cls from './index.module.scss';
export default function index() {
@ -18,7 +18,7 @@ export default function index() {
transition={{ type: 'tween' }}
>
<div style={{ flex: 1 }}>
<FanInfo longBg={true} source="annealFanInfo" />
<FanInfo longBg={true} rows={24} />
</div>
</motion.div>
);

View File

@ -1,118 +1,32 @@
import cls from "./righttable.module.scss";
import { ScrollBoard } from "@jiaminghi/data-view-react";
import { useSelector } from "react-redux";
import React, { Component } from "react";
import "./righttable.module.scss";
function CurrentSpec(props) {
const rawData = useSelector((state) => state.cutting.productData);
let config = {
// headerBGC: "rgba(4, 44, 76, 0.3)",
headerBGC: "#044A8460",
header: [
'<span style="color:#fff; padding-left: 8px;">产线名<span/>',
'<span style="color:#fff; padding-left: 8px;">玻璃长度<span/>',
'<span style="color:#fff; padding-left: 8px;">玻璃宽度<span/>',
'<span style="color:#fff; padding-left: 8px;">玻璃厚度<span/>',
],
// oddRowBGC: "#042444",
// evenRowBGC: "#042c4c",
oddRowBGC: "#044A8460",
evenRowBGC: "#0b549970",
columnWidth: [90],
rowNum: 3,
hoverPause: true,
headerHeight: 40,
data: replaceStyle(filterData(rawData), 0.8),
};
// import { ScrollBoard } from '@jiaminghi/data-view-react';
return (
<div className={cls.CenterChart1itemDetailBorder} style={{ opacity: 0.75 }}>
<h2 className={cls.CenterChart1itemTXT}>当前产线生产规格</h2>
<div className={cls.TableContainer}>
{config.data.length !== 0 && <ScrollBoard config={config} style={{}} />}
{config.data.length === 0 && (
<p
style={{
color: "#cccf",
fontSize: "24px",
userSelect: "none",
textAlign: "center",
paddingTop: "36px",
}}
>
暂无数据
</p>
)}
</div>
</div>
);
}
export default CurrentSpec;
//
var rawData = [
{
id: 1,
length: 1209,
productionLine: "Y61",
square: 123.3,
thick: 2,
wide: 1089,
},
{
id: 2,
length: 1119,
productionLine: "Y62",
square: 103.3,
thick: 2,
wide: 1339,
},
{
id: 3,
length: 1019,
productionLine: "Y63",
square: 233,
thick: 1,
wide: 1111,
},
{
id: 4,
length: 2000,
productionLine: "Y64",
square: 233,
thick: 1,
wide: 1232,
},
{
id: 5,
length: 1560,
productionLine: "Y65",
square: 233,
thick: 1,
wide: 996,
},
{
id: 6,
length: 1990,
productionLine: "Y66",
square: 233,
thick: 1,
wide: 416,
},
let data = [
["产线0", "10mm", "10mm", "10mm"],
["产线2", "8mm", "8mm", "8mm"],
["产线3", "15mm", "15mm", "15mm"],
["产线4", "15mm", "15mm", "15mm"],
];
function filterData(rawData) {
return (rawData ?? []).map((item) => [
// 线
item.productionLine,
//
item.length,
//
item.wide,
//
item.thick,
]);
}
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 = [];
@ -120,11 +34,32 @@ function replaceStyle(Arr, opencity) {
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]
} ${j == 0 ? "" : "mm"}<span/>`;
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;

View File

@ -1,23 +1,50 @@
.CenterChart1itemDetailBorder {
width: 100%;
height: 200px;
height: 240px;
display: flex;
flex-direction: column;
justify-content: flex-start;
color: #fff;
background-color: rgba(4, 44, 76, 0.2);
.CenterChart1itemTXT {
user-select: none;
padding: 8px 0;
font-size: 18px;
font-weight: 400;
letter-spacing: 1px;
color: rgba(255, 255, 255, 0.9);
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;
.TableContainer {
flex: 1;
.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

@ -82,7 +82,7 @@ function VideoContainer(props) {
};
function handleEnterVideoEnd() {
// console.log('video end');
console.log('video end');
enterToFloorOne();
}

View File

@ -1,7 +1,7 @@
import { useState } from "react";
import cls from "./index.module.css";
import Chart2 from "../../../Common/TimeFireDir";
import VideoContainer from "./VideoContainer";
import { useState } from 'react';
import cls from './index.module.css';
import Chart2 from '../../../Common/TimeFireDir';
import VideoContainer from './VideoContainer';
function KilnCenter() {
const [floor, setFloor] = useState(0);
@ -14,17 +14,17 @@ function KilnCenter() {
<div
className="bgKilnInner"
style={{
width: "100%",
position: "absolute",
top: "12%",
display: "flex",
flexDirection: "column",
width: '100%',
position: 'absolute',
top: '12%',
display: 'flex',
flexDirection: 'column',
}}
>
{/* 时间火向数据 */}
<div
className="fireAndTime"
style={{ position: "absolute", top: "-112px", height: "212px" }}
style={{ position: 'absolute', top: '-112px', height: '212px' }}
>
<Chart2 />
</div>
@ -33,31 +33,91 @@ function KilnCenter() {
<div
className="subMenu"
style={{
display: "flex",
marginBottom: "24px",
justifyContent: "center",
display: 'flex',
marginBottom: '24px',
justifyContent: 'center',
}}
>
<div
className={
"flr flr1 " + cls.menuItem + " " + (floor == 1 ? cls.active : "")
'flr flr1 ' + cls.menuItem + ' ' + (floor == 1 ? cls.active : '')
}
onClick={() => onFloorUpdate(1)}
>
碹顶
一层
</div>
<div
className={
"flr flr2 " + cls.menuItem + " " + (floor == 2 ? cls.active : "")
'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>
);
}

View File

@ -1,14 +1,14 @@
import { motion, AnimatePresence } from "framer-motion";
import { useRef, useEffect, useMemo, useCallback, useState } from "react";
import FeederStatus from "../../../../Common/Feeder";
import TemperatureBottom from "../../../../Common/TemperatureBottom";
import TemperatureTop from "../../../../Common/TemperatureTop";
import { useSelector, useDispatch } from "react-redux";
import cls from "../index.module.css";
// import SocketContext from '../../../../../store/socket-data-provider';
import { useContext } from "react";
function EnterToFloorOne(props) {
const fireInfo = useSelector((state) => state.fireInfo);
const fireDir = fireInfo?.fireDirection || null;
// 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;
@ -17,12 +17,12 @@ function EnterToFloorOne(props) {
if (show) {
vd.current.play();
setTimeout(() => {
// console.log("enter");
console.log("开启enter的火播放");
setFireCanPlay(true);
}, 5000);
}
return () => {
// console.log("enter");
console.log("关闭enter的火播放");
setFireCanPlay(false);
};
}, [show]);
@ -49,7 +49,7 @@ function EnterToFloorOne(props) {
<source src="/video/floor1.webm" type="video/mp4" />
</video>
{/* {fireCanPlay && fireDir == "" && (
{fireCanPlay && fireDir == "东火" && (
<video
src="/video/fire_top.webm"
muted
@ -68,17 +68,21 @@ function EnterToFloorOne(props) {
width={3900}
style={{ position: "absolute", top: "-20px", left: "-20px" }}
></video>
)} */}
)}
<TemperatureTop
<motion.div
className={cls.videoLayer1}
key="eto1div"
style={{
top: "218px",
left: "678px",
top: "336px",
left: "730px",
width: "2380px",
zIndex: 0,
}}
/>
<FeederStatus />
animate={{
opacity: [0, 0, 0, 0.6, 1],
transition: { duration: 0.3, delay: 2 },
}}
></motion.div>
</motion.div>
)}
</AnimatePresence>

View File

@ -1,14 +1,15 @@
import { motion, AnimatePresence } from "framer-motion";
import { useRef, useEffect, useMemo, useState } from "react";
import FeederStatus from "../../../../Common/Feeder";
import TemperatureTop from "../../../../../components/Common/TemperatureTop";
import TemperatureBottom from "../../../../Common/TemperatureBottom";
import { useSelector, useDispatch } from "react-redux";
import cls from "../index.module.css";
// import SocketContext from '../../../../../store/socket-data-provider';
import { useContext } from "react";
function FloorOneToTwo(props) {
const fireInfo = useSelector((state) => state.fireInfo);
const fireDir = fireInfo?.fireDirection || null;
// const ctx = useContext(SocketContext);
const ctx = null;
const fireDir = ctx?.runState?.fireDirection || null;
const [fireCanPlay, setFireCanPlay] = useState(false);
const vd = useRef(null);
@ -18,13 +19,13 @@ function FloorOneToTwo(props) {
if (show) {
vd.current.play();
setTimeout(() => {
// console.log("1-2");
console.log("开启1-2的火播放");
setFireCanPlay(true);
}, 3000);
}
if (!show) setFireCanPlay(false);
return () => {
// console.log("1-2");
console.log("关闭1-2的火播放");
setFireCanPlay(false);
};
}, [show]);
@ -36,8 +37,8 @@ function FloorOneToTwo(props) {
className="video-wrapper"
style={{
position: "fixed",
top: "0px",
left: "0px",
top: "7px",
left: "50px",
width: "calc(100% - 50px)",
height: "calc(100% - 7px)",
zIndex: -998,
@ -58,7 +59,7 @@ function FloorOneToTwo(props) {
autoPlay
loop
width={3700}
style={{ position: "absolute", top: "18px", left: "72px" }}
style={{ position: "absolute", top: "18px", left: "56px" }}
></video>
)}
{fireCanPlay && fireDir == "西火" && (
@ -73,16 +74,20 @@ function FloorOneToTwo(props) {
></video>
)}
<TemperatureBottom
<motion.div
className={cls.videoLayer2}
key="1to2div"
style={{
top: "208px",
// left: "638px",
left: "690px",
width: "2380px",
zIndex: 0,
top: "360px",
left: "740px",
width: "2415px",
height: "690px",
}}
/>
<FeederStatus />
animate={{
opacity: [0, 0, 0, 0.6, 1],
transition: { duration: 0.3, delay: 2 },
}}
></motion.div>
</motion.div>
)}
</AnimatePresence>

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