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", "version": "0.1.0",
"private": true, "private": true,
"dependencies": { "dependencies": {
"@ant-design/icons": "^5.2.6",
"@babel/core": "^7.16.0", "@babel/core": "^7.16.0",
"@jiaminghi/data-view-react": "^1.2.5", "@jiaminghi/data-view-react": "^1.2.5",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.3", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.3",
@ -23,7 +22,6 @@
"case-sensitive-paths-webpack-plugin": "^2.4.0", "case-sensitive-paths-webpack-plugin": "^2.4.0",
"css-loader": "^6.5.1", "css-loader": "^6.5.1",
"css-minimizer-webpack-plugin": "^3.2.0", "css-minimizer-webpack-plugin": "^3.2.0",
"dayjs": "^1.11.10",
"dotenv": "^10.0.0", "dotenv": "^10.0.0",
"dotenv-expand": "^5.1.0", "dotenv-expand": "^5.1.0",
"echarts": "^5.4.3", "echarts": "^5.4.3",
@ -61,7 +59,6 @@
"style-loader": "^3.3.1", "style-loader": "^3.3.1",
"tailwindcss": "^3.0.2", "tailwindcss": "^3.0.2",
"terser-webpack-plugin": "^5.2.5", "terser-webpack-plugin": "^5.2.5",
"uuid": "^9.0.1",
"webpack": "^5.64.4", "webpack": "^5.64.4",
"webpack-dev-server": "^4.6.0", "webpack-dev-server": "^4.6.0",
"webpack-manifest-plugin": "^4.0.2", "webpack-manifest-plugin": "^4.0.2",
@ -92,10 +89,8 @@
}, },
"devDependencies": { "devDependencies": {
"@babel/plugin-proposal-private-property-in-object": "^7.21.11", "@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"@types/uuid": "^9.0.7",
"less": "^4.2.0", "less": "^4.2.0",
"less-loader": "^11.1.3", "less-loader": "^11.1.3"
"typescript": "^5.3.3"
}, },
"jest": { "jest": {
"roots": [ "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 "./global.css";
import "./index.css"; import "./index.css";
import Head from "./components/Common/Company"; import Head from "./components/Common/Company";
// import { SocketContextProvider } from "../store/socket-data-provider";
import useSlider, { Slider } from "./hooks/useSlider"; import useSlider, { Slider } from "./hooks/useSlider";
import NavMenu from "./components/Common/NavMenu"; import NavMenu from "./components/Common/NavMenu";
import { useEffect, useState } from "react"; import { useState } from "react";
import Home from "./pages/Home"; import Home from "./pages/Home";
import EnergyAnalysis from "./pages/EnergyCostAnalysis"; import EnergyAnalysis from "./pages/EnergyCostAnalysis";
import RulerContainer from "./components/Tools/Ruler"; import RulerContainer from "./components/Tools/Ruler";
import { Switch } from "antd";
import { createPortal } from "react-dom"; import { createPortal } from "react-dom";
const Menus = ["窑炉总览", "窑炉内部", "退火监测", "质检统计", "能耗分析"];
function App() { function App() {
const { styles, value, setValue } = useSlider(100); const { styles, value, setValue } = useSlider(100);
const [navActive, setNavActive] = useState("窑炉总览"); 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 ( return (
<> <>
<div id="FullScreen" style={{ ...styles, overflow: "hidden" }}> <div id="FullScreen" style={styles}>
<NavMenu active={navActive} onChangeActive={handleMenuChange} /> <NavMenu active={navActive} onChangeActive={(v) => setNavActive(v)} />
<Head /> <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 == "能耗分析" && <EnergyAnalysis />}
{navActive == "能耗分析" && <div className="bgDitu"></div>}
{navActive != "能耗分析" && <Home active={navActive} />} {navActive != "能耗分析" && <Home active={navActive} />}
</div> </div>
<Slider value={value} setValue={setValue} /> <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 <Container
icon={props.icon} icon={props.icon}
title={props.title} title={props.title}
desc={props.desc}
className={`${cls.bottomBarItem} ${props.className}`} className={`${cls.bottomBarItem} ${props.className}`}
style={props.style} style={props.style}
> >

View File

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

View File

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

View File

@ -1,36 +1,60 @@
import BottomBarItem from "../BottomItemBackground"; import BottomBarItem from "../BottomItemBackground";
import React, { Component } from "react";
import cls from "./righttable.module.scss"; import cls from "./righttable.module.scss";
import { useSelector } from "react-redux";
import { ScrollBoard } from "@jiaminghi/data-view-react"; import { ScrollBoard } from "@jiaminghi/data-view-react";
function Chart1(props) { let data = [
const rawData = useSelector((state) => state.cutting.productData); ["产线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 = { let header = ["产线名", "原板宽度", "净板宽", "玻璃厚度"];
// headerBGC: "rgba(4, 44, 76, 0.3)",
headerBGC: "#044A8460", let config = {
headerBGC: "rgba(4, 44, 76, 0.3)",
header: [ header: [
'<span style="color:#fff; padding-left: 8px;">产线名<span/>', '<span style="color:#fff">产线名<span/>',
'<span style="color:#fff; padding-left: 8px;">玻璃长度<span/>', '<span style="color:#fff">原板宽度<span/>',
'<span style="color:#fff; padding-left: 8px;">玻璃宽度<span/>', '<span style="color:#fff">净板宽<span/>',
'<span style="color:#fff; padding-left: 8px;">玻璃厚度<span/>', '<span style="color:#fff">玻璃厚度<span/>',
], ],
// oddRowBGC: "#042444", oddRowBGC: "#042444",
// evenRowBGC: "#042c4c", evenRowBGC: "#042c4c",
oddRowBGC: "#044A8460",
evenRowBGC: "#0b549970",
columnWidth: [128], columnWidth: [128],
headerHeight: 40, headerHeight: 40,
hoverPause: true, hoverPause: false,
data: replaceStyle(filterData(rawData), 0.7), 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 ( return (
<BottomBarItem <BottomBarItem
icon="pause" icon="pause"
title="当前产线生产规格" title="当前产线生产规格"
className={props.className} className={this.props.className}
style={props.style} style={this.props.style}
> >
<div <div
className={cls.CenterChart1itemDetailBorder} className={cls.CenterChart1itemDetailBorder}
@ -39,115 +63,11 @@ function Chart1(props) {
<span className={cls.CenterFormitemDetailBorderLine1}></span> <span className={cls.CenterFormitemDetailBorderLine1}></span>
<span className={cls.CenterFormitemDetailBorderLine2}></span> <span className={cls.CenterFormitemDetailBorderLine2}></span>
<span className={cls.CenterFormitemDetailBorderLine3}></span> <span className={cls.CenterFormitemDetailBorderLine3}></span>
{config.data.length !== 0 && <ScrollBoard config={config} style={{}} />} <ScrollBoard config={config} style={{}} />
{config.data.length === 0 && (
<p
style={{
color: "#cccf",
fontSize: "24px",
userSelect: "none",
textAlign: "center",
paddingTop: "72px",
}}
>
暂无数据
</p>
)}
</div> </div>
</BottomBarItem> </BottomBarItem>
); );
}
} }
export default Chart1; 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; flex-direction: column;
justify-content: flex-start; justify-content: flex-start;
// background-color: rgba(4, 44, 76, 0.2); background-color: rgba(4, 44, 76, 0.2);
.CenterChart1itemTXT { .CenterChart1itemTXT {
width: 100%; width: 100%;
height: 10%; 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 BottomBarItem from '../BottomItemBackground';
import "./font.css"; import GraphBase from '../GraphBase';
import cls from "./index.module.css"; import { Radio } from 'antd';
import { useEffect, useState } from "react"; import cls from './index.module.css';
import { Tooltip, Button } from "antd"; import { useState } from 'react';
import { InfoCircleOutlined } from "@ant-design/icons";
import { useSelector } from "react-redux";
const SmallBox = (props) => { const SmallBox = (props) => {
return ( return (
<div <div
className="small-box" className="small-box"
style={{ style={{
boxShadow: "inset 0 0 18px 10px #fff1", boxShadow: 'inset 0 0 18px 10px #fff1',
borderRadius: "3px", borderRadius: '3px',
padding: "6px", padding: '6px',
display: "flex", display: 'flex',
alignItems: "center", alignItems: 'center',
justifyContent: "center", justifyContent: 'center',
color: "#fff", color: '#fff',
position: "relative", position: 'relative',
userSelect: "none", userSelect: 'none',
}} }}
> >
{props.split !== false && ( {props.split !== false && (
<span <span
className="vertical-line" className="vertical-line"
style={{ style={{
position: "absolute", position: 'absolute',
display: "inline-block", display: 'inline-block',
width: "2px", width: '2px',
height: "80%", height: '80%',
top: "10%", top: '10%',
left: "45%", left: '50%',
background: background:
"linear-gradient(to bottom, transparent, #fff3, #fffa, #fff3, transparent)", 'linear-gradient(to bottom, transparent, #fff3, #fffa, #fff3, transparent)',
}} }}
></span> ></span>
)} )}
@ -43,212 +41,93 @@ const SmallBox = (props) => {
}; };
function WindFrequence(props) { function WindFrequence(props) {
const [dataSource, setDataSource] = useState("Y61"); const [dataSource, setDataSource] = useState('风机');
const [currentLineTemp, setCurrentLineTemp] = useState([]);
const currentTempList = useSelector((state) => state.annealTemperature?.data);
const lines = ["Y61", "Y62", "Y63", "Y64", "Y65"];
function handleSourceChange(line) {
setDataSource(line);
}
useEffect(() => { function handleSourceChange(v) {
setCurrentLineTemp( console.log('val', v);
(currentTempList && }
currentTempList[1 + lines.indexOf(dataSource) + "#"]) ||
[]
);
}, [dataSource]);
return ( return (
<GraphBase <GraphBase
icon="temp" icon="pause"
title="当前温度" title="当前温度"
dateOptions={["Y61", "Y62", "Y63", "Y64", "Y65"]} dateOptions={['风机', '风阀', '电加热']}
selectWidth={70}
defaultSelect={dataSource}
onDateChange={handleSourceChange} onDateChange={handleSourceChange}
size={["middle", "long"]} size={['middle', 'long']}
> >
<div className={cls.mainContent + " " + cls.grid}> <div className={cls.mainContent + ' ' + cls.grid}>
<SmallBox> <SmallBox>
<h1 className={cls.areaName}>A1区板上</h1> <h1 className={cls.areaName}>A1区板上</h1>
<div className={cls.areaContent}> <div className={cls.areaContent}>
<span className={cls.areaValue}> <span className={cls.areaValue}>123.8</span>
{(+currentLineTemp[0]).toFixed(2) || 0} <span className={cls.areaValue}>123.8</span>
</span> <span className={cls.areaValue}>123.8</span>
<span className={cls.areaValue}>
{(+currentLineTemp[1]).toFixed(2) || 0}
</span>
<span className={cls.areaValue}>
{(+currentLineTemp[2]).toFixed(2) || 0}
</span>
</div> </div>
</SmallBox> </SmallBox>
<SmallBox> <SmallBox>
<h1 className={cls.areaName}>A2区板上</h1> <h1 className={cls.areaName}>A1区板上</h1>
<div className={cls.areaContent}> <div className={cls.areaContent}>
<span className={cls.areaValue}> <span className={cls.areaValue}>123.8</span>
{(+currentLineTemp[6]).toFixed(2) || 0} <span className={cls.areaValue}>123.8</span>
</span> <span className={cls.areaValue}>123.8</span>
<span className={cls.areaValue}>
{(+currentLineTemp[7]).toFixed(2) || 0}
</span>
<span className={cls.areaValue}>
{(+currentLineTemp[8]).toFixed(2) || 0}
</span>
</div> </div>
</SmallBox> </SmallBox>
<SmallBox> <SmallBox>
<h1 className={cls.areaName}>B区板上</h1> <h1 className={cls.areaName}>A1区板上</h1>
<div className={cls.areaContent}> <div className={cls.areaContent}>
<span className={cls.areaValue}> <span className={cls.areaValue}>123.8</span>
{(+currentLineTemp[12]).toFixed(2) || 0} <span className={cls.areaValue}>123.8</span>
</span> <span className={cls.areaValue}>123.8</span>
<span className={cls.areaValue}>
{(+currentLineTemp[13]).toFixed(2) || 0}
</span>
<span className={cls.areaValue}>
{(+currentLineTemp[14]).toFixed(2) || 0}
</span>
</div> </div>
</SmallBox> </SmallBox>
<SmallBox> <SmallBox>
<h1 className={cls.areaName}>C区板上</h1> <h1 className={cls.areaName}>A1区板上</h1>
<div className={cls.areaContent}> <div className={cls.areaContent}>
<span className={cls.areaValue}> <span className={cls.areaValue}>123.8</span>
{(+currentLineTemp[18]).toFixed(2) || 0} <span className={cls.areaValue}>123.8</span>
</span> <span className={cls.areaValue}>123.8</span>
<span className={cls.areaValue}>
{(+currentLineTemp[19]).toFixed(2) || 0}
</span>
<span className={cls.areaValue}>
{(+currentLineTemp[20]).toFixed(2) || 0}
</span>
</div> </div>
</SmallBox> </SmallBox>
<SmallBox> <SmallBox>
<h1 className={cls.areaName}>A1区板</h1> <h1 className={cls.areaName}>A1区板上</h1>
<div className={cls.areaContent}> <div className={cls.areaContent}>
<span className={cls.areaValue}> <span className={cls.areaValue}>123.8</span>
{(+currentLineTemp[3]).toFixed(2) || 0} <span className={cls.areaValue}>123.8</span>
</span> <span className={cls.areaValue}>123.8</span>
<span className={cls.areaValue}>
{(+currentLineTemp[4]).toFixed(2) || 0}
</span>
<span className={cls.areaValue}>
{(+currentLineTemp[5]).toFixed(2) || 0}
</span>
</div> </div>
</SmallBox> </SmallBox>
<SmallBox> <SmallBox split={false}>
<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" }}>
<div className={cls.areaPureContent}> <div className={cls.areaPureContent}>
<div <span className={cls.areaPureValue}>123.8</span>
className="hint" <span className={cls.areaPureValue}>123.8</span>
style={{ position: "absolute", top: "3px", right: "3px" }} <span className={cls.areaPureValue}>123.8</span>
>
<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>
</div> </div>
</SmallBox> </SmallBox>
<SmallBox>
<SmallBox split={false} style={{ position: "relative" }}> <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={cls.areaPureContent}>
<div <span className={cls.areaPureValue}>123.8</span>
className="hint" <span className={cls.areaPureValue}>123.8</span>
style={{ position: "absolute", top: "3px", right: "3px" }} <span className={cls.areaPureValue}>123.8</span>
>
<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>
</div> </div>
</SmallBox> </SmallBox>
<SmallBox> <SmallBox>
<h1 className={cls.areaName}>RET1区</h1> <h1 className={cls.areaName}>A1区板上</h1>
<div className={cls.areaContent}> <div className={cls.areaContent}>
<span className={cls.areaValue}> <span className={cls.areaValue}>123.8</span>
{(+currentLineTemp[24]).toFixed(2) || 0}
</span>
</div> </div>
</SmallBox> </SmallBox>
<SmallBox> <SmallBox>
<h1 className={cls.areaName}>RET2区</h1> <h1 className={cls.areaName}>A1区板上</h1>
<div className={cls.areaContent}> <div className={cls.areaContent}>
<span className={cls.areaValue}> <span className={cls.areaValue}>123.8</span>
{(+currentLineTemp[25]).toFixed(2) || 0}
</span>
</div> </div>
</SmallBox> </SmallBox>
</div> </div>

View File

@ -50,7 +50,7 @@
.areaName { .areaName {
color: #fff; color: #fff;
font-size: 18px; font-size: 20px;
line-height: 1; line-height: 1;
letter-spacing: 1.5px; letter-spacing: 1.5px;
margin: 0; margin: 0;
@ -66,7 +66,7 @@
padding: 0 8px; padding: 0 8px;
} }
span.areaPureValue:not(:first-of-type) { .areaPureValue:not(:first-child) {
border-left: 2px solid #fff6; border-left: 2px solid #fff6;
} }
@ -80,11 +80,9 @@ span.areaPureValue:not(:first-of-type) {
.areaPureValue, .areaPureValue,
.areaValue { .areaValue {
display: inline-block; display: inline-block;
font-size: 14px; font-size: 17px;
line-height: 16px; line-height: 22px;
letter-spacing: 1.2px; letter-spacing: 1.2px;
font-family: "HelloFont WenYiHei", sans-serif;
color: #53c2d4;
} }
.switchLabel { .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 cls from './index.module.css';
import { Radio, Select } from "antd"; import { randomInt } from '../../../../utils';
import ReactECharts from "echarts-for-react"; import * as echarts from 'echarts';
import { useState } from "react"; import { Switch, Radio } from 'antd';
import { useSelector } from "react-redux"; import ReactECharts from 'echarts-for-react';
import { getOptions } from "../../../../utils/energeChartOption";
import triangle from "../../../../assets/Icon/triangle.svg";
import dayjs from "dayjs";
const EnergyCostChart = (props) => { const EnergyCostChart = (props) => {
const elecTrend = useSelector((state) => state.energy.trend.elec); const options = {
const gasITrend = useSelector((state) => state.energy.trend.natGas1); color: ['#FFD160', '#12FFF5', '#2760FF'],
const gasIITrend = useSelector((state) => state.energy.trend.natGas2); grid: { top: 32, right: 12, bottom: 20, left: 48 },
const [source, setSource] = useState("elec"); xAxis: {
const [period, setPeriod] = useState("week"); type: 'category',
data: Array(7)
const [timestr, setTimestr] = useState( .fill(1)
dayjs().subtract(7, "day").format("YYYY.MM.DD") + .map((_, index) => {
" - " + const today = new Date();
dayjs().subtract(1, "day").format("YYYY.MM.DD") const dtimestamp = today - index * 24 * 60 * 60 * 1000;
); return `${new Date(dtimestamp).getMonth() + 1}.${new Date(
dtimestamp,
const currentTrend = ).getDate()}`;
source == "elec" ? elecTrend : source == "gasi" ? gasITrend : gasIITrend; })
.reverse(),
const options = getOptions( axisLabel: {
period, color: '#fff',
source, fontSize: 12,
currentTrend ?? { week: [], month: [], year: [] } },
); axisTick: { show: false },
axisLine: {
function handleDateChange(value) { lineStyle: {
setPeriod( 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", data: Array(7)
: "month", .fill(1)
: "year", .map((_) => {
}[value] return randomInt(60, 100);
); }),
setTimestr( type: 'line',
{ areaStyle: {
: color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
dayjs().subtract(1, "year").endOf("year").format("YYYY.MM.") + { offset: 0, color: '#FFD16040' },
"29 - " + { offset: 0.5, color: '#FFD16020' },
dayjs().endOf("year").format("YYYY.MM.") + { offset: 1, color: '#FFD16010' },
"28", ]),
: },
dayjs().subtract(7, "day").format("YYYY.MM.DD") + // smooth: true,
" - " + },
dayjs().subtract(1, "day").format("YYYY.MM.DD"), ],
: tooltip: {
dayjs().subtract(1, "month").format("YYYY.MM.") + trigger: 'axis',
"29 - " + },
dayjs().format("YYYY.MM.") + };
"28",
}[value] function handleSwitchChange(val) {
); // val: boolean
console.log('switch change', val);
} }
return ( return (
<div className={cls.energyCostChart}> <div className={cls.energyCostChart}>
<div className={cls.titleBar}> <div className={cls.titleBar}>
<h2>能耗趋势图</h2> <h2>能耗趋势图</h2>
<Switch defaultChecked onChange={handleSwitchChange} />
<div className={cls.legend}>
<span className="legend__title">班次详情</span>
<ul className="legend__list">
<li>总量</li>
</ul>
</div> </div>
<div className={`${cls.choiceBar} flex items-center justify-between`}>
<Radio.Group <Radio.Group
value={source} defaultValue="week"
buttonStyle="solid" 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} className={cls.radioGroup}
> >
<Radio.Button value="day" className="radio-group__item">
</Radio.Button>
<Radio.Button value="week" className="radio-group__item"> <Radio.Button value="week" className="radio-group__item">
</Radio.Button> </Radio.Button>
@ -96,53 +116,10 @@ const EnergyCostChart = (props) => {
<Radio.Button value="year" className="radio-group__item"> <Radio.Button value="year" className="radio-group__item">
</Radio.Button> </Radio.Button>
</Radio.Group> */} </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)}
/>
</div> </div>
<div className="flex-1">
<div className="flex-1" style={{ marginTop: "8px" }}> <ReactECharts option={options} style={{ height: '180px' }} />
{options && (
<ReactECharts option={options} style={{ height: "180px" }} />
)}
{!options && (
<p
style={{
color: "#cccf",
fontSize: "20px",
userSelect: "none",
textAlign: "center",
paddingTop: "32px",
}}
>
暂无数据
</p>
)}
</div> </div>
</div> </div>
); );

View File

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

View File

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

View File

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

View File

@ -1,20 +1,46 @@
import GraphBase from "../../Common/GraphBase"; import GraphBase from "../../Common/GraphBase";
import "./index.module.scss"; import "./index.module.scss";
import { useSelector } from "react-redux";
import { ScrollBoard } from "@jiaminghi/data-view-react"; 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) { function attachStyle(data) {
return data.map((arr) => { return data.map((arr) => {
return arr.map((item, index) => { return arr.map((item, index) => {
if (index == arr.length - 1) { if (index == arr.length - 1) {
return `<div style="display: flex; align-items: center"> return `<div style="display: flex; align-items: center">
<span style="box-shadow: 0 0 4px 4px ${ <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: ${ }; margin-right: 8px; width: 8px; height: 8px; border-radius: 8px; background: ${
item == 1 ? "#2760ff" : item == 0 ? "#a81b26" : "#E6A23C" item == 1 ? "#2760ff" : "#a81b26"
}"></span><span style="color: ${ }"></span><span style="color: ${item == 1 ? "#2760ff" : "#a81b26"}">${
item == 1 ? "#2760ff" : item == 0 ? "#a81b26" : "#E6A23C" item == 1 ? "正常" : "故障"
}">${item == 1 ? "运行" : item == 0 ? "故障" : "未运行"}</span></div>`; }</span></div>`;
} }
return `<span style='color: #fffa'>${item}</span>`; return `<span style='color: #fffa'>${item}</span>`;
}); });
@ -23,17 +49,7 @@ function attachStyle(data) {
function FanInfo(props) { function FanInfo(props) {
const rowNum = props.rows || 8; const rowNum = props.rows || 8;
// 使使 source 使 annealFanInfo let data = getRandomRows(100);
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 config = { let config = {
headerBGC: "rgba(4, 44, 76, 0.3)", headerBGC: "rgba(4, 44, 76, 0.3)",
@ -44,10 +60,11 @@ function FanInfo(props) {
], ],
oddRowBGC: "#042444", oddRowBGC: "#042444",
evenRowBGC: "#042c4c", evenRowBGC: "#042c4c",
// columnWidth: data.length > 12 ? [50, 136] : [88, 256], columnWidth: [70, 96],
columnWidth: [50, 136],
rowNum, rowNum,
hoverPause: true, // headerHeight: 40,
hoverPause: false,
// data: replaceStyle(data, 0.7),
data: attachStyle(data), data: attachStyle(data),
}; };
@ -61,9 +78,7 @@ function FanInfo(props) {
className="flex" className="flex"
style={{ style={{
display: "flex", display: "flex",
flex: 1,
gap: "20px", gap: "20px",
// gap: data.length > 12 ? "20px" : 0,
height: "100%", height: "100%",
position: "relative", position: "relative",
}} }}
@ -71,15 +86,9 @@ function FanInfo(props) {
<div className="flex-1" style={{ flex: 1 }}> <div className="flex-1" style={{ flex: 1 }}>
<ScrollBoard <ScrollBoard
config={config} config={config}
style={{ style={{ width: "280px", height: "100%" }}
width: "280px",
// width: data.length > 12 ? "280px" : "100%",
height: "100%",
}}
/> />
</div> </div>
{/* {data.length > 12 && (
<> */}
<div <div
className="verticalLine" className="verticalLine"
style={{ style={{
@ -94,12 +103,10 @@ function FanInfo(props) {
></div> ></div>
<div className="flex-1" style={{ flex: 1 }}> <div className="flex-1" style={{ flex: 1 }}>
<ScrollBoard <ScrollBoard
config={{ ...config, data: attachStyle(dataRight) }} config={config}
style={{ width: "280px", height: "100%" }} style={{ width: "280px", height: "100%" }}
/> />
</div> </div>
{/* </>
)} */}
</div> </div>
</GraphBase> </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 // FanRunFrequence
import cls from "./index.module.css"; import cls from "./index.module.css";
import ReactECharts from "echarts-for-react";
import * as echarts from "echarts"; import * as echarts from "echarts";
import { Switch } from "antd";
import GraphBase from "../../Common/GraphBase"; import GraphBase from "../../Common/GraphBase";
import { useState } from "react"; import { useState, useContext } from "react";
import { useSelector } from "react-redux"; // import SocketContext from '../../../store/socket-data-provider';
function WindFrequence(props) { function WindFrequence(props) {
const [showChart, setShowChart] = useState(false); const [showChart, setShowChart] = useState(true);
const runState = useSelector((state) => state.fanFrequence.runtime); // const { runState, hisState } = useContext(SocketContext);
const hisState = useSelector((state) => state.fanFrequence.history);
const [options, dataList] = getOptions(showChart, hisState, runState); const runState = null;
const hisState = null;
function handleSwitchChange(val) { let dataList = [];
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 seriesData = []; let seriesData = [];
const colors = [ const colors = [
"#12FFF5", "#12FFF5",
@ -80,15 +29,20 @@ function getOptions(showChart, hisState, runState) {
let options = null; let options = null;
if (showChart) { if (showChart) {
// keys() sort() // keys() sort()
seriesData = seriesData = hisState?.combustionAir
hisState != null ? Object.keys(hisState.combustionAir)
? Object.keys(hisState)
.sort() .sort()
.map((key) => hisState[key]) .map((key) => hisState.combustionAir[key])
: Array(8) : Array(8)
.fill(1) .fill(1)
.map((_) => Array(7).fill(0)); .map((_) => Array(7).fill(0));
// debug
console.log(
"助燃风 chart series data",
hisState?.combustionAir,
seriesData
);
options = { options = {
color: colors, color: colors,
grid: { top: 32, right: 12, bottom: 20, left: 48 }, grid: { top: 32, right: 12, bottom: 20, left: 48 },
@ -150,10 +104,9 @@ function getOptions(showChart, hisState, runState) {
symbol: "circle", symbol: "circle",
areaStyle: { areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
// i % 8 8 { offset: 0, color: colors[i] + "40" },
{ offset: 0, color: colors[i % 8] + "40" }, { offset: 0.5, color: colors[i] + "20" },
{ offset: 0.5, color: colors[i % 8] + "20" }, { offset: 1, color: colors[i] + "00" },
{ offset: 1, color: colors[i % 8] + "00" },
]), ]),
}, },
})), })),
@ -162,12 +115,27 @@ function getOptions(showChart, hisState, runState) {
}, },
}; };
} else { } else {
dataList = dataList = runState?.combustionAirPressureArr
runState != null ? [
? Object.keys(runState).map((fan) => ({ { id: 1, name: "1#风机", value: "0m³/h" },
id: Math.random(), { id: 2, name: "2#风机", value: "0m³/h" },
name: fan, { id: 3, name: "3#风机", value: "0m³/h" },
value: (+runState[fan])?.toFixed(2), { id: 4, name: "4#风机", value: "0m³/h" },
{ id: 5, name: "5#风机", value: "0m³/h" },
{ id: 6, name: "6#风机", value: "0m³/h" },
{ id: 7, name: "7#风机", value: "0m³/h" },
{ id: 8, name: "8#风机", value: "0m³/h" },
{ id: 9, name: "9#风机", value: "0m³/h" },
{ id: 10, name: "10#风机", value: "0m³/h" },
{ id: 11, name: "11#风机", value: "0m³/h" },
{ id: 12, name: "12#风机", value: "0m³/h" },
{ id: 13, name: "13#风机", value: "0m³/h" },
{ id: 14, name: "14#风机", value: "0m³/h" },
{ id: 15, name: "15#风机", value: "0m³/h" },
{ id: 16, name: "16#风机", value: "0m³/h" },
].map((item, index) => ({
...item,
value: runState.combustionAirPressureArr[index] ?? "/",
})) }))
: [ : [
{ id: 1, name: "1#风机", value: "0m³/h" }, { id: 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 { .listItem {
border-radius: 2px; border-radius: 2px;
padding: 10px 0; padding: 9px 0;
text-align: center; text-align: center;
color: #fff; color: #fff;
box-shadow: inset 0 0 16px 4px rgba(255, 255, 255, 0.197); box-shadow: inset 0 0 16px 4px rgba(255, 255, 255, 0.197);
display: flex;
align-items: center;
gap: 12px;
} }
.headWidget { .headWidget {
position: absolute; position: absolute;
top: 22px; top: 22px;
@ -35,18 +31,3 @@
.relative { .relative {
position: 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 cls from './index.module.css';
import BottomBarItem from "../BottomItemBackground"; import BottomBarItem from '../BottomItemBackground';
import ReactECharts from "echarts-for-react"; import ReactECharts from 'echarts-for-react';
import * as echarts from "echarts"; import * as echarts from 'echarts';
import { Switch } from "antd"; import { randomInt } from '../../../utils';
import { useState, useEffect } from "react"; import { Switch } from 'antd';
import { useSelector, useDispatch } from "react-redux"; import { useState, useContext } from 'react';
import dayjs from "dayjs"; // import SocketContext from '../../../store/socket-data-provider';
/** 助燃风流量 */
function GasI(props) { function GasI(props) {
const [showChart, setShowChart] = useState(true); const [showChart, setShowChart] = useState(true);
const runState = useSelector((state) => state.combustionAir.runtime); // const { runState, hisState } = useContext(SocketContext);
const hisState = useSelector((state) => state.combustionAir.history);
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) { function handleSwitchChange(val) {
if (val) { if (val) {
@ -23,17 +151,10 @@ function GasI(props) {
setShowChart(false); setShowChart(false);
} }
} }
const desc =
dayjs().subtract(7, "day").format("YYYY.MM.DD") +
" - " +
dayjs().subtract(1, "day").format("YYYY.MM.DD");
return ( return (
<BottomBarItem <BottomBarItem
icon="pause" icon="pause"
title="助燃风流量" title="助燃风流量"
desc={desc}
className={cls.gas} className={cls.gas}
style={props.style} style={props.style}
> >
@ -47,15 +168,13 @@ function GasI(props) {
<div className={cls.chart}> <div className={cls.chart}>
{showChart && ( {showChart && (
<ReactECharts option={options} style={{ height: "100%" }} /> <ReactECharts option={options} style={{ height: '100%' }} />
)} )}
{!showChart && ( {!showChart && (
<div className={cls.gridList}> <div className={cls.gridList}>
{dataList.map((item) => ( {dataList.map((item) => (
<div key={item.id} className={cls.listItem}> <div key={item.id} className={cls.listItem}>
<span className={cls.item_label}>{item.name}</span> {item.name}: {item.value}
<span className={cls.item_value}>{item.value}</span>
{/* {item.name}: {item.value} */}
</div> </div>
))} ))}
</div> </div>
@ -66,158 +185,3 @@ function GasI(props) {
} }
export default GasI; 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; position: absolute;
/* background: #00ee33; */ /* background: #00ee33; */
top: 20px; top: 20px;
left: 180px;
right: 24px; right: 24px;
height: 32px; height: 32px;
width: 128px; width: 190px;
text-align: right; text-align: right;
} }
@ -63,21 +62,7 @@
padding: 12px 0; padding: 12px 0;
text-align: center; text-align: center;
color: #fff; color: #fff;
box-shadow: inset 0 0 12px 2px rgba(255, 255, 255, 0.197); 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: 4;
text-align: left;
} }
.headWidget { .headWidget {

View File

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

View File

@ -63,7 +63,7 @@
} }
.graphBaseTitle > img { .graphBaseTitle > img {
width: 24px; width: 20px;
} }
.graphBaseTitle > h2 { .graphBaseTitle > h2 {
@ -72,7 +72,7 @@
'Source Han Sans SC', 'Noto Sans CJK SC', 'WenQuanYi Micro Hei', sans-serif; 'Source Han Sans SC', 'Noto Sans CJK SC', 'WenQuanYi Micro Hei', sans-serif;
margin: 0; margin: 0;
margin-left: 6px; margin-left: 6px;
font-size: 22px; font-size: 20px;
color: #fff; color: #fff;
letter-spacing: 2px; letter-spacing: 2px;
font-weight: 500; font-weight: 500;
@ -85,10 +85,9 @@
} }
.graphBaseDesc { .graphBaseDesc {
margin-left: 8px; position: absolute;
/* position: absolute;
top: 25px; top: 25px;
left: 150px; */ left: 150px;
font-size: 19px; font-size: 19px;
color: #76fff9; color: #76fff9;
} }
@ -115,7 +114,7 @@
.radioGroup * { .radioGroup * {
border: none !important; border: none !important;
border-radius: 6px !important; border-radius: 0 !important;
} }
.radioGroup *:focus-within { .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 cls from "./kiln.module.scss";
import Container from "../../Container"; 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"; import { stateNameMap } from "../../../store/features/kilnSlice";
export default function Kiln() { export default function Kiln() {
const kilnInfo = useSelector((state) => state.kiln); const kilnInfo = useSelector((state) => state.kiln);
const dispatch = useDispatch();
console.log("state: ", kilnInfo, stateNameMap);
const infos = Object.keys(kilnInfo).map((key) => ({ const infos = Object.keys(kilnInfo).map((key) => ({
label: stateNameMap[key], label: stateNameMap[key],
value: kilnInfo[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 ( return (
<Container title="窑炉信息" icon="kiln" className={cls.leftBar__top}> <Container title="窑炉信息" icon="kiln" className={cls.leftBar__top}>
<div className={cls.leftBar__top__content}> <div className={cls.leftBar__top__content}>
{infos.map((item) => ( {infos.map((item) => (
<div key={item.label} className={cls.info__item}> <div key={item.label} className={cls.info__item}>
<span className={cls.label}>{item.label}</span> {item.label}: {item.value}
<span className={cls.value}>{item.value}</span>
{/* {item.label}: {item.value} */}
</div> </div>
))} ))}
</div> </div>

View File

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

View File

@ -1,28 +1,34 @@
import cls from "./index.module.css"; import cls from './index.module.css';
import ReactECharts from "echarts-for-react"; import ReactECharts from 'echarts-for-react';
import getOptions from "./chart.config"; import getOptions from './chart.config';
import { useSelector, useDispatch } from "react-redux"; // import SocketContext from '../../../../store/socket-data-provider';
import { useContext } from 'react';
function GasChart(props) { function GasChart(props) {
const { dataSource } = props; const { dataSource } = props;
const hisState = useSelector((state) => state.natGas.history); // const { hisState } = useContext(SocketContext);
const dataName = dataSource == "gas-i" ? "gasIHistory" : "gasIIHistory"; const hisState = null;
const dataName = dataSource == 'gas-i' ? 'kilnGasT1' : 'kilnGasT2';
// keys() sort()
const seriesData = hisState?.[dataName] const seriesData = hisState?.[dataName]
? Object.keys(hisState?.[dataName]) ? Object.keys(hisState?.[dataName])
.sort() .sort()
.map((key, index) => hisState?.[dataName][key]) .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 ( return (
<div className={cls.gasChart}> <div className={cls.gasChart}>
<ReactECharts <ReactECharts
key={dataSource} key={Math.random()}
option={getOptions( option={getOptions(
seriesData, seriesData,
dataSource == "gas-i" ? "天然气I" : "天然气II" dataSource == 'gas-i' ? '天然气I' : '天然气II',
)} )}
style={{ height: "100%" }} style={{ height: '100%' }}
/> />
</div> </div>
); );

View File

@ -1,27 +1,28 @@
import cls from "./index.module.css"; import cls from './index.module.css';
import { useSelector } from "react-redux"; import { useContext, useEffect, useState } from 'react';
// import SocketContext from '../../../../store/socket-data-provider';
function getData(type) { function getData(type) {
let data = []; let data = [];
switch (type) { switch (type) {
case "gas-i": case 'gas-i':
data = [ data = [
{ id: 1, name: "1#天然气I", value: "0m³/h" }, { id: 1, name: '1#天然气I', value: '0m³/h' },
{ id: 2, name: "2#天然气I", value: "0m³/h" }, { id: 2, name: '2#天然气I', value: '0m³/h' },
{ id: 3, name: "3#天然气I", value: "0m³/h" }, { id: 3, name: '3#天然气I', value: '0m³/h' },
{ id: 4, name: "4#天然气I", value: "0m³/h" }, { id: 4, name: '4#天然气I', value: '0m³/h' },
{ id: 5, name: "5#天然气I", value: "0m³/h" }, { id: 5, name: '5#天然气I', value: '0m³/h' },
{ id: 6, name: "6#天然气I", value: "0m³/h" }, { id: 6, name: '6#天然气I', value: '0m³/h' },
{ id: 7, name: "7#天然气I", value: "0m³/h" }, { id: 7, name: '7#天然气I', value: '0m³/h' },
{ id: 8, name: "8#天然气I", value: "0m³/h" }, { id: 8, name: '8#天然气I', value: '0m³/h' },
]; ];
break; break;
case "gas-ii": case 'gas-ii':
data = [ data = [
{ id: 11, name: "1#天然气II", value: "0m³/h" }, { id: 11, name: '1#天然气II', value: '0m³/h' },
{ id: 12, name: "2#天然气II", value: "0m³/h" }, { id: 12, name: '2#天然气II', value: '0m³/h' },
{ id: 13, name: "3#天然气II", value: "0m³/h" }, { id: 13, name: '3#天然气II', value: '0m³/h' },
{ id: 14, name: "4#天然气II", value: "0m³/h" }, { id: 14, name: '4#天然气II', value: '0m³/h' },
// { id: 15, name: '5#II', value: '0m³/h' }, // { id: 15, name: '5#II', value: '0m³/h' },
]; ];
break; break;
@ -30,25 +31,21 @@ function getData(type) {
} }
function GridList(props) { 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); let dataList = getData(props.dataSource);
dataList = runState?.[key] dataList = runState?.[key]
? dataList.map((v, i) => ({ ? dataList.map((v, i) => ({ ...v, value: runState[key][i] ?? '/' }))
...v,
value: (runState[key][i] || 0) + "m³/h",
}))
: dataList; : dataList;
return ( return (
<div className={cls.gridList}> <div className={cls.gridList}>
{dataList.map((item) => ( {dataList.map((item) => (
<div key={item.id} className={cls.listItem}> <div key={item.id} className={cls.listItem}>
<span className={cls.item_label}>{item.name}</span> {item.name}: {item.value}
<span className={cls.item_value}>{item.value}</span>
{/* {item.name}: {item.value} */}
</div> </div>
))} ))}
</div> </div>

View File

@ -11,17 +11,4 @@
text-align: center; text-align: center;
color: #fff; color: #fff;
box-shadow: inset 0 0 16px 4px rgba(255, 255, 255, 0.197); 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 cls from './index.module.css';
import BottomBarItem from "../BottomItemBackground"; import BottomBarItem from '../BottomItemBackground';
import triangle from "../../../assets/Icon/triangle.svg";
import { Switch, Select, Radio } from "antd"; import { Switch, Radio } from 'antd';
import { useState } from "react"; import { useState } from 'react';
import GridList from "./gridList"; import GridList from './gridList';
import GasChart from "./gasChart"; import GasChart from './gasChart';
import dayjs from "dayjs";
function GasII(props) { 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); const [showChart, setShowChart] = useState(true);
function handleSwitchChange(val) { function handleSwitchChange(val) {
@ -20,33 +19,21 @@ function GasII(props) {
} }
} }
// function handleSourceChange(e) { function handleSourceChange(e) {
// if (e.target.value == "ii") { console.log('val', e.target.value);
// // II if (e.target.value == 'ii') {
// setDataSource("gas-ii"); // II
// } else if (e.target.value == "i") { setDataSource('gas-ii');
// // I } else if (e.target.value == 'i') {
// setDataSource("gas-i"); // I
// } setDataSource('gas-i');
// }
function handleDateChange(value) {
if (value == "天然气I") {
setDataSource("gas-i");
} else {
setDataSource("gas-ii");
} }
} }
const desc =
dayjs().subtract(7, "day").format("YYYY.MM.DD") +
" - " +
dayjs().subtract(1, "day").format("YYYY.MM.DD");
return ( return (
<BottomBarItem <BottomBarItem
icon="pause" icon="pause"
title="天然气流量" title="天然气流量"
desc={desc}
className={`${cls.gas} ${props.className}`} className={`${cls.gas} ${props.className}`}
style={props.style} style={props.style}
> >
@ -58,32 +45,7 @@ function GasII(props) {
{!showChart && <span className={cls.switchLabel}>实时流量</span>} {!showChart && <span className={cls.switchLabel}>实时流量</span>}
</div> </div>
<Select <Radio.Group
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
defaultValue="i" defaultValue="i"
buttonStyle="solid" buttonStyle="solid"
className={cls.radioGroup} className={cls.radioGroup}
@ -95,7 +57,7 @@ function GasII(props) {
<Radio.Button value="ii" className="radio-group__item"> <Radio.Button value="ii" className="radio-group__item">
天然气 II 天然气 II
</Radio.Button> </Radio.Button>
</Radio.Group> */} </Radio.Group>
</div> </div>
<div className={cls.chart}> <div className={cls.chart}>

View File

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

View File

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

View File

@ -1,8 +1,7 @@
.centerMenu { .centerMenu {
position: fixed; position: fixed;
top: 120px; top: 120px;
// left: 1340px; left: 1340px;
left: 1460px;
color: white; color: white;
z-index: 10000; 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 cls from './index.module.css';
import * as echarts from "echarts"; import { randomInt } from '../../../../utils';
import { Select } from "antd";
import ReactECharts from "echarts-for-react"; import * as echarts from 'echarts';
import { useEffect, useState } from "react"; import { Switch, Radio } from 'antd';
import { useSelector } from "react-redux"; import ReactECharts from 'echarts-for-react';
import triangle from "../../../../assets/Icon/triangle.svg";
import dayjs from "dayjs";
const SmokeTrendChart = (props) => { const SmokeTrendChart = (props) => {
const dayTrend = useSelector((state) => state.smoke?.dayTrend); const options = {
const weekTrend = useSelector((state) => state.smoke?.weekTrend); color: ['#FFD160', '#12FFF5', '#2760FF'],
const monthTrend = useSelector((state) => state.smoke?.monthTrend); grid: { top: 38, right: 12, bottom: 20, left: 48 },
const yearTrend = useSelector((state) => state.smoke?.yearTrend); xAxis: {
type: 'category',
const [source, setSource] = useState("O2_float"); data: Array(7)
const [period, setPeriod] = useState("day"); .fill(1)
.map((_, index) => {
const currentTrend = const today = new Date();
period === "day" const dtimestamp = today - index * 24 * 60 * 60 * 1000;
? dayTrend return `${new Date(dtimestamp).getMonth() + 1}.${new Date(
: period === "week" dtimestamp,
? weekTrend ).getDate()}`;
: period === "month" })
? monthTrend .reverse(),
: yearTrend; axisLabel: {
color: '#fff',
const options = getOptions(source, period, currentTrend); fontSize: 12,
},
const [desc, setDesc] = useState(""); axisTick: { show: false },
axisLine: {
useEffect(() => { lineStyle: {
switch (period) { width: 1,
case "day": color: '#213259',
setDesc( },
dayjs().subtract(1, "day").format("YYYY.MM.DD") + },
" 7点 - " + },
dayjs().format("YYYY.MM.DD") + yAxis: {
" 7点" name: '单位m³/h',
); nameTextStyle: {
break; color: '#fff',
case "month": fontSize: 10,
setDesc( align: 'right',
dayjs().subtract(1, "month").format("YYYY.MM.") + },
"29 - " + type: 'value',
dayjs().format("YYYY.MM.") + axisLabel: {
"28" color: '#fff',
); fontSize: 12,
break; formatter: '{value} %',
case "week": },
setDesc( axisLine: {
dayjs().subtract(7, "day").format("YYYY.MM.DD") + show: true,
" - " + lineStyle: {
dayjs().subtract(1, "day").format("YYYY.MM.DD") color: '#213259',
); },
break; },
case "year": splitLine: {
setDesc( lineStyle: {
dayjs().subtract(1, "year").endOf("year").format("YYYY.MM.") + color: '#213259a0',
"29 - " + },
dayjs().endOf("year").format("YYYY.MM.") + },
"28" interval: 10,
); min: 0,
break; max: 100,
} },
}, [period]); series: [
function handleDateChange(value) {
setPeriod(
{ {
: "day", data: Array(7)
: "week", .fill(1)
: "month", .map((_) => {
: "year", return randomInt(60, 100);
}[value] }),
); type: 'line',
} areaStyle: {
function handleSourceChange(value) { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
setSource( { offset: 0, color: '#FFD16040' },
{ offset: 0.5, color: '#FFD16020' },
{ offset: 1, color: '#FFD16010' },
]),
},
// smooth: true,
},
{ {
氧气: "O2_float", data: Array(7)
氮氧化物: "NOX_float", .fill(1)
二氧化硫: "SO2_float", .map((_) => {
颗粒物: "dust_float", return randomInt(60, 100);
}[value] }),
); 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 ( return (
<div className={cls.energyCostChart}> <div className={cls.energyCostChart}>
<div className={cls.titleBar}> <div className={cls.titleBar}>
<h2>烟气趋势图</h2> <h2>烟气趋势图</h2>
{/* <Switch defaultChecked onChange={handleSwitchChange} /> */} <Switch defaultChecked onChange={handleSwitchChange} />
{/* <div className={cls.legend}> <div className={cls.legend}>
<span className="legend__title">班次详情</span> <span className="legend__title">班次详情</span>
<ul className="legend__list"> <ul className="legend__list">
<li>总量</li> <li>总量</li>
<li>白班</li> <li>白班</li>
<li>夜班</li> <li>夜班</li>
</ul> </ul>
</div> */} </div>
</div> </div>
<div className={`${cls.choiceBar} flex items-center justify-between`}> <div className={`${cls.choiceBar} flex items-center justify-between`}>
{/* <Radio.Group <Radio.Group
value={source} defaultValue="oxygen"
onChange={(e) => setSource(e.target.value)}
buttonStyle="solid" buttonStyle="solid"
className={`${cls.radioGroup} flex items-center justify-between`} 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>
<Radio.Button value="NOX_float" className="radio-group__item"> <Radio.Button value="so2" className="radio-group__item">
氮氧化物
</Radio.Button>
<Radio.Button value="SO2_float" className="radio-group__item">
二氧化硫 二氧化硫
</Radio.Button> </Radio.Button>
<Radio.Button value="dust_float" className="radio-group__item"> <Radio.Button value="no" className="radio-group__item">
颗粒物 一氧化氮
</Radio.Button> </Radio.Button>
</Radio.Group> */} <Radio.Button value="no2" className="radio-group__item">
<Select 二氧化氮
defaultValue={"氧气"} </Radio.Button>
style={{ width: 100 }} </Radio.Group>
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)}
/>
<div className={cls.graphBaseDesc}>{desc}</div> <Radio.Group
defaultValue="week"
{/* <Radio.Group
value={period}
onChange={(e) => setPeriod(e.target.value)}
buttonStyle="solid" buttonStyle="solid"
className={cls.radioGroup} className={cls.radioGroup}
> >
@ -166,174 +173,11 @@ const SmokeTrendChart = (props) => {
<Radio.Button value="year" className="radio-group__item"> <Radio.Button value="year" className="radio-group__item">
</Radio.Button> </Radio.Button>
</Radio.Group> */} </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)}
/>
</div> </div>
{options && <ReactECharts option={options} style={{ height: "220px" }} />} <ReactECharts option={options} style={{ height: '240px' }} />
{!options && (
<p
style={{
color: "#cccf",
fontSize: "24px",
userSelect: "none",
textAlign: "center",
paddingTop: "96px",
}}
>
暂无数据
</p>
)}
</div> </div>
); );
}; };
export default SmokeTrendChart; 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; padding-left: 16px;
} }
.energyCostChart .titleBar .legend ul li::before { .energyCostChart .titleBar .legend ul li::before {
content: ""; content: '';
position: absolute; position: absolute;
left: 2px; left: 2px;
top: 2px; top: 2px;
@ -73,10 +73,6 @@
border: none !important; border: none !important;
border-radius: 0 !important; border-radius: 0 !important;
} }
.radioGroupShort * {
border: none !important;
border-radius: 6px !important;
}
.radioGroup *:focus-within { .radioGroup *:focus-within {
box-shadow: none !important; box-shadow: none !important;
} }
@ -93,10 +89,3 @@
.radioGroup_button_wrapper.ant-radio-button-wrapper-checked { .radioGroup_button_wrapper.ant-radio-button-wrapper-checked {
background: #02457e !important; 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 cls from './index.module.scss';
import Container from "../../Container"; import Container from '../../Container';
import TechSplitline from "../TechSplitline"; import TechSplitline from '../TechSplitline';
import SmokeTrendChart from "./SmokeTrendChart"; import SmokeTrendChart from './SmokeTrendChart';
import SmokeHandleTable from "./SmokeHandleTable";
function SmokeHandle(props) { function SmokeHandle(props) {
return ( return (
<Container title="烟气处理" icon="smoke" className={cls.smokeHandle}> <Container title="烟气处理" icon="smoke" className={cls.smokeHandle}>
<div className={`${cls.smokeHandle__content} flex flex-col`}> <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 /> <TechSplitline />
<SmokeTrendChart /> <SmokeTrendChart />
</div> </div>

View File

@ -3,7 +3,7 @@
background: url(../../../assets/smoke.png) no-repeat; background: url(../../../assets/smoke.png) no-repeat;
background-size: 100% 100%; background-size: 100% 100%;
width: 626px; width: 626px;
height: 490px; height: 540px;
.smokeHandle__content { .smokeHandle__content {
margin-top: 8px; margin-top: 8px;
} }
@ -13,17 +13,19 @@
border-radius: 2px; border-radius: 2px;
color: hsl(0, 0%, 100%, 0.9); color: hsl(0, 0%, 100%, 0.9);
box-shadow: inset 0 0 17px 0px hsla(0, 0%, 100%, 0.15); box-shadow: inset 0 0 17px 0px hsla(0, 0%, 100%, 0.15);
height: 32px; // width: 288px;
font-size: 16px; height: 56px;
font-size: 20px;
letter-spacing: 1.43px; letter-spacing: 1.43px;
line-height: 32px; line-height: 56px;
text-align: center; text-align: center;
user-select: none; user-select: none;
} }
.info__item_groups { .info__item_groups {
margin-bottom: 12px; margin-bottom: 12px;
margin-left: 8px;
display: grid; display: grid;
grid-template-columns: 1fr 1fr; 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"; import useTimeCounter from "../../../hooks/useTimeCounter";
const FireInfo = () => { const FireInfo = () => {
// const dispatch = useDispatch(); const dispatch = useDispatch();
const fireInfo = useSelector((state) => state.fireInfo); const fireInfo = useSelector((state) => state.fireInfo);
const time = fireInfo.lastFireChangeTime || "0分0秒"; const time = fireInfo.lastFireChangeTime || "0分0秒";
const minsec = useTimeCounter(time); const [min, sec] = useTimeCounter(time);
let [min, sec] = [0, 0];
if (minsec) {
min = minsec[0];
sec = minsec[1];
}
// useEffect(() => { // useEffect(() => {
// const restTime = ctx?.runState?.lastFireChangeTime; // const restTime = ctx?.runState?.lastFireChangeTime;
// if (restTime == null) return; // if (restTime == null) return;
@ -80,22 +76,22 @@ const FireInfo = () => {
// }; // };
// }, [ctx?.runState?.lastFireChangeTime]); // }, [ctx?.runState?.lastFireChangeTime]);
// useEffect(() => { useEffect(() => {
// setInterval(() => { setInterval(() => {
// dispatch({ dispatch({
// type: "fireInfo/setFireInfo", type: "fireInfo/setFireInfo",
// payload: { payload: {
// fireChangeTime: `${Math.ceil(Math.random() * 10)}:${Math.ceil( fireChangeTime: `${Math.ceil(Math.random() * 10)}:${Math.ceil(
// Math.random() * 10 Math.random() * 10
// )}`, )}`,
// fireDirection: Math.random * 10 < 5 ? "" : "西", fireDirection: Math.random * 10 < 5 ? "东火" : "西火",
// lastFireChangeTime: `${Math.ceil(Math.random() * 60)}${Math.ceil( lastFireChangeTime: `${Math.ceil(Math.random() * 60)}${Math.ceil(
// Math.random() * 50 Math.random() * 50
// )}`, )}`,
// }, },
// }); });
// }, 10000); }, 10000);
// }, []); }, []);
const data = [ const data = [
{ {

View File

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

View File

@ -1,213 +1,163 @@
import cls from "./index.module.css"; import cls from './index.module.css';
import GraphBase from "../GraphBase"; import GraphBase from '../GraphBase';
import ReactECharts from "echarts-for-react"; import ReactECharts from 'echarts-for-react';
import { useSelector } from "react-redux";
import { useState } from "react";
import dayjs from 'dayjs'
function FaultTotal(props) { function FaultTotal(props) {
const [currentSelect, setCurrentSelect] = useState("日"); const options = {
const isra = useSelector((state) => state.isra); color: [
'#2760FF',
const currentStatistic = '#5B9BFF',
currentSelect == "日" '#FFD160',
? isra.dayStatistic '#8167F6',
: currentSelect == "周" '#99D66C',
? isra.weekStatistic '#FF8A40',
: currentSelect == "月" '#12FFF5',
? isra.monthStatistic ],
: currentSelect == "月" grid: { top: 42, right: 12, bottom: 20, left: 48 },
? 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,
},
legend: { legend: {
top: 10, top: 10,
left: 60,
padding: 5, padding: 5,
itemWidth: 12, itemWidth: 12,
itemHeight: 12, itemHeight: 12,
itemGap: 12, itemGap: 12,
height: 12, height: 12,
textStyle: { textStyle: {
color: "#DFF1FE", color: '#DFF1FE',
fontSize: 12, fontSize: 12,
}, },
data: isra.checkType,
}, },
xAxis: { xAxis: {
type: "category", type: 'category',
data: currentStatistic.map((item) => item.name), data: Array(5)
.fill(1)
.map((_, index) => {
return '产线' + (index + 1);
}),
axisLabel: { axisLabel: {
color: "#fffc", color: '#fff',
fontSize: 12, fontSize: 12,
}, },
axisTick: { show: false }, axisTick: { show: false },
axisLine: { axisLine: {
lineStyle: { lineStyle: {
width: 1, width: 1,
color: "#213259", color: '#213259',
}, },
}, },
}, },
yAxis: { yAxis: {
name: "单位/个", name: '单位/个',
nameTextStyle: { nameTextStyle: {
color: "#fff", color: '#fff',
fontSize: 10, fontSize: 10,
align: "right", align: 'right',
}, },
type: "value", type: 'value',
axisLabel: { axisLabel: {
color: "#fff", color: '#fff',
fontSize: 12, fontSize: 12,
formatter: "{value}", formatter: '{value}',
}, },
axisLine: { axisLine: {
show: true, show: true,
lineStyle: { lineStyle: {
color: "#213259", color: '#213259',
}, },
}, },
splitLine: { splitLine: {
lineStyle: { 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: { tooltip: {
trigger: "axis", trigger: 'axis',
axisPointer: {
type: "shadow",
},
className: "xc-chart-tooltip",
// backgroundColor: ''
}, },
}; };
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 cls from './index.module.css';
import GraphBase from "../GraphBase"; import GraphBase from '../GraphBase';
import ReactECharts from "echarts-for-react"; import ReactECharts from 'echarts-for-react';
import { useSelector } from "react-redux"; import { useState } from 'react';
import { useEffect, useState } from "react";
import { randomInt } from "../../../utils";
import * as echarts from "echarts";
function FaultType(props) { function FaultType(props) {
const [init, setInit] = useState(true); const options = {
const [currentLine, setCurrentLine] = useState("Y61"); colors: [
const isra = useSelector((state) => state.isra); '#2760FF',
const currentStatistic = isra.dayStatistic || []; '#5B9BFF',
const currentLineStatistic = '#FFD160',
currentLine != "" '#8167F6',
? currentStatistic.find((item) => item.name === currentLine)?.data || [] '#99D66C',
: []; '#FF8A40',
const lines = currentStatistic.map((item) => item.name); '#12FFF5',
const CHART_TYPE = "line"; // "pie" | "line"; ],
grid: {
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 = {
left: 24, left: 24,
top: 10, top: 10,
bottom: 10, bottom: 10,
right: 24, right: 24,
}; },
const legend_common = { legend: {
icon: "circle", icon: 'circle',
top: 32, top: 32,
right: 0, right: 0,
bottom: 32, bottom: 32,
width: 296, width: 296,
height: 130, height: 130,
itemGap: 30, itemGap: 30,
formatter: function (name) {
return `${name} {sub|${
options.series[0].data.find((o) => o.name == name).value
}}`;
},
textStyle: { textStyle: {
color: "#DFF1FE", color: '#DFF1FE',
fontSize: 18, fontSize: 18,
rich: { rich: {
sub: { sub: {
color: "#fff9", color: '#fff9',
fontSize: 18, 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: [ series: [
{ {
type: "bar", type: 'pie',
barWidth: 14, center: ['26%', '54%'],
itemStyle: { radius: ['55%', '75%'],
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%"],
avoidLabelOverlap: false, avoidLabelOverlap: false,
label: { label: {
show: true, show: true,
formatter: "{d}%", formatter: '{d}%',
fontSize: 14, fontSize: 14,
color: "inherit", color: 'inherit',
}, },
labelLine: { labelLine: {
length: 0, length: 0,
}, },
data: currentItem.data.map((item) => ({ data: [
value: item.checkNum, { value: 1048, name: '缺陷1' },
name: item.checkType, { 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 cls from './good.module.scss';
import Container from "../../Container"; import Container from '../../Container';
import TodayTableData from "./components/TodayTableData"; import TodayTableData from './components/TodayTableData';
import GoodRateChart from "./components/GoodRateChart"; import GoodRateChart from './components/GoodRateChart';
import TechSplitline from "../TechSplitline"; import TechSplitline from '../TechSplitline';
const GoodProduction = () => { const GoodProduction = () => {
return ( return (

View File

@ -1,132 +1,137 @@
import cls from "./index.module.css"; import cls from './index.module.css';
import "./overwrite.css"; // antd import './overwrite.css'; // antd
import ReactECharts from "echarts-for-react"; import ReactECharts from 'echarts-for-react';
import * as echarts from "echarts"; import * as echarts from 'echarts';
import { Switch, Select, Radio } from "antd"; import { Switch, Radio } from 'antd';
import { useEffect, useState } from "react"; import { randomInt } from '../../../../../utils';
import { useSelector } from "react-redux";
import triangle from "../../../../../assets/Icon/triangle.svg";
import dayjs from "dayjs";
const dateOptions = { day: "日", week: "周", month: "月", year: "年" };
const GoodRateChart = (props) => { const GoodRateChart = (props) => {
// const options = {
const [showMore, setShowMore] = useState(false); color: ['#FFD160', '#12FFF5', '#2760FF'],
// key grid: { top: 28, right: 12, bottom: 32, left: 48 },
const [updateKey, setUpdateKey] = useState(Date.now()); xAxis: {
// type: 'category',
const [dateType, setDateType] = useState("day"); data: Array(7)
const [defaultSelect, setDefaultSelect] = useState(dateOptions[dateType]); .fill(1)
const cutting = useSelector((state) => state.cutting); .map((_, index) => {
useEffect(() => { const today = new Date();
setUpdateKey(Date.now()); const dtimestamp = today - index * 24 * 60 * 60 * 1000;
}, [showMore]); 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) { function handleSwitchChange(val) {
// val: boolean // 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 ( return (
<div className={cls.GoodRateChart}> <div className={cls.GoodRateChart}>
<div className={cls.titleBar}> <div className={cls.titleBar}>
<h2>生产良品率</h2> <h2>生产良品率</h2>
<Switch defaultChecked={showMore} onChange={handleSwitchChange} /> <Switch defaultChecked onChange={handleSwitchChange} />
<div className={cls.legend}> <div className={cls.legend}>
<span className="legend__title">班次详情</span> <span className="legend__title">班次详情</span>
<ul className="legend__list"> <ul className="legend__list">
<li>总量</li> <li>总量</li>
{showMore && (
<>
<li>白班</li> <li>白班</li>
<li>夜班</li> <li>夜班</li>
</>
)}
</ul> </ul>
</div> </div>
<div className={cls.graphBaseDesc}>{timestr}</div> <Radio.Group
<Select defaultValue="week"
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"
buttonStyle="solid" buttonStyle="solid"
onChange={handleDateChange}
className={cls.radioGroup} className={cls.radioGroup}
style={{ flex: 1, textAlign: "right" }}
> >
<Radio.Button value="day" className="radio-group__item"> <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 value="year" className="radio-group__item">
</Radio.Button> </Radio.Button>
</Radio.Group> */} </Radio.Group>
</div> </div>
{options && <ReactECharts key={updateKey} option={options} />} <ReactECharts option={options} />
{!options && (
<p
style={{
paddingTop: "88px",
color: "#fffc",
textAlign: "center",
fontSize: "24px",
userSelect: "none",
}}
>
暂无数据
</p>
)}
</div> </div>
); );
}; };
export default GoodRateChart; 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 { .GoodRateChart .titleBar {
display: flex; display: flex;
justify-content: flex-start; justify-content: space-between;
align-items: center; align-items: center;
gap: 5px;
color: white; color: white;
} }
.GoodRateChart .titleBar h2 { .GoodRateChart .titleBar h2 {
margin: 0; margin: 0;
font-size: 16px; font-size: 18px;
line-height: 32px; line-height: 32px;
letter-spacing: 1px; letter-spacing: 1.2px;
color: #52fff8; color: #52fff8;
} }
@ -29,17 +28,10 @@
color: #dff1fe; color: #dff1fe;
} }
.graphBaseDesc {
margin: 0 6px;
font-size: 16px;
color: #76fff9;
flex: 1;
}
.GoodRateChart .titleBar .legend ul { .GoodRateChart .titleBar .legend ul {
display: flex; display: flex;
margin: 0; margin: 0;
margin-left: 5px; margin-left: 8px;
padding: 0; padding: 0;
list-style: none; list-style: none;
align-items: center; align-items: center;
@ -50,7 +42,7 @@
padding-left: 16px; padding-left: 16px;
} }
.GoodRateChart .titleBar .legend ul li::before { .GoodRateChart .titleBar .legend ul li::before {
content: ""; content: '';
position: absolute; position: absolute;
left: 2px; left: 2px;
top: 2px; top: 2px;
@ -74,8 +66,7 @@
.radioGroup * { .radioGroup * {
border: none !important; border: none !important;
border-radius: 6px !important; border-radius: 0 !important;
/* transform: translateX(224px) !important; */
} }
.radioGroup *:focus-within { .radioGroup *:focus-within {
box-shadow: none !important; box-shadow: none !important;

View File

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

View File

@ -1,42 +1,21 @@
import { useEffect, useRef } from "react"; import { useEffect, useRef } from 'react';
import useIcon from "../hooks/useIcon"; import useIcon from '../hooks/useIcon';
import cls from "./container.module.scss"; import cls from './container.module.scss';
const Container = (props) => { const Container = (props) => {
let icon = useIcon(props.icon); let icon = useIcon(props.icon);
const desc = props.desc;
return ( return (
<div <div className={`${cls.container} ${props.className}`} style={props.style}>
className={`${cls.container} ${props.className}`}
style={props.pending ? { filter: "grayscale(100%)" } : props.style}
>
<div className={cls.container__head}> <div className={cls.container__head}>
<img <img
src={icon} src={icon}
alt="#" alt="#"
className={props.icon == "kiln" ? cls.bigger : ""} className={props.icon == 'kiln' ? cls.bigger : ''}
/> />
<h2>{props.title}</h2> <h2>{props.title}</h2>
{desc && <div className={cls.graphBaseDesc}>{desc}</div>}
</div> </div>
<div className={cls.container__content}>{props.children}</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> </div>
); );
}; };

View File

@ -1,222 +1,37 @@
import GraphBase from "../../../Common/GraphBase"; import GraphBase from '../../../Common/GraphBase';
import ReactECharts from "echarts-for-react"; import ReactECharts from 'echarts-for-react';
// import getOptions from "../../../../hooks/getChartOption"; 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";
function Gas(props) { 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) { function handleSwitch(v) {
// console.log('switched ', v); console.log('switched ', v);
} }
function handleDateChange(v) {
function handleDateChange(value) { console.log('date ', v);
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]
);
} }
return ( return (
<GraphBase <GraphBase
icon="battery" icon="battery"
title="天然气II" title="焦炉煤气"
desc={`能耗趋势图 ${timestr}`} desc="能耗趋势图"
switchOptions={false} switchOptions={true}
onSwitch={handleSwitch} onSwitch={handleSwitch}
defaultSelect={period} dateOptions={['日', '周', '月', '年']}
dateOptions={["周", "月", "年"]} legend={['总量']}
// legend={[""]}
onDateChange={handleDateChange} onDateChange={handleDateChange}
size={["long", "middle"]} size={['long', 'short']}
> >
{/* real echarts here */} {/* real echarts here */}
{options && (
<ReactECharts <ReactECharts
key={Math.random()} key={Math.random()}
option={options} option={getOptions([[21, 4, 74, 72, 9, 59, 63]], '氧气')}
// option={getOptions([[21, 4, 74, 72, 9, 59, 63]], "")} style={{ height: '100%' }}
style={{ height: "100%" }}
/> />
)}
{!options && (
<p
style={{
color: "#cccf",
fontSize: "24px",
userSelect: "none",
textAlign: "center",
paddingTop: "88px",
}}
>
暂无数据
</p>
)}
{/* real table data here */} {/* real table data here */}
</GraphBase> </GraphBase>
); );
} }
export default Gas; 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 GraphBase from '../../../Common/GraphBase';
import ReactECharts from "echarts-for-react"; import ReactECharts from 'echarts-for-react';
import { useSelector } from "react-redux"; import getOptions from '../../../../hooks/getChartOption';
import { useState } from "react";
import * as echarts from "echarts";
import dayjs from "dayjs";
function ElecCost(props) { 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) { function handleSwitch(v) {
// console.log('switched ', v); console.log('switched ', v);
} }
function handleDateChange(value) { function handleDateChange(v) {
setPeriod(value); console.log('date ', v);
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]
);
} }
return ( return (
<GraphBase <GraphBase
icon="battery" icon="battery"
title="电耗能" title="电耗能"
desc={`能耗趋势图 ${timestr}`} desc="能耗趋势图"
switchOptions={false} switchOptions={true}
onSwitch={handleSwitch} onSwitch={handleSwitch}
defaultSelect={period} dateOptions={['日', '周', '月', '年']}
dateOptions={["周", "月", "年"]} legend={['总量']}
// legend={[""]}
onDateChange={handleDateChange} onDateChange={handleDateChange}
size={["long", "middle"]} size={['long', 'short']}
> >
{/* real echarts here */} {/* real echarts here */}
{options && (
<ReactECharts <ReactECharts
key={Math.random()} key={Math.random()}
option={options} option={getOptions([[112, 73, 79, 82, 30, 105, 87]], '氧气')}
// option={getOptions([[112, 73, 79, 82, 30, 105, 87]], "")} style={{ height: '100%' }}
style={{ height: "100%" }}
/> />
)}
{!options && (
<p
style={{
color: "#cccf",
fontSize: "24px",
userSelect: "none",
textAlign: "center",
paddingTop: "48px",
}}
>
暂无数据
</p>
)}
{/* real table data here */} {/* real table data here */}
</GraphBase> </GraphBase>
); );
} }
export default ElecCost; 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 cls from './index.module.css';
import GradientText from "../../../Common/GradientText"; import GradientText from '../../../Common/GradientText';
import { useSelector } from "react-redux";
import { useEffect, useState } from "react";
function Energy(props) { 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 ( return (
<div className={" " + cls.layout} style={{ color: "#fff" }}> <div className={' ' + cls.layout} style={{ color: '#fff' }}>
<span <span
className={cls.shadowBorder} className={cls.shadowBorder}
style={{ style={{
gridRow: "1 / 3", gridRow: '1 / 3',
paddingTop: "104px", paddingTop: '38px',
paddingLeft: "32px", paddingLeft: '32px',
userSelect: "none", userSelect: 'none',
}} }}
> >
<GradientText text="能源" /> <GradientText text="能源" />
</span> </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 <span
className={cls.shadowBorder + ' ' + cls.infoText}
style={{ style={{
lineHeight: 1.5, gridRow: '1 / 3',
width: "180px",
wordWrap: "break-word",
}} }}
> >
{(+energyInfo?.elecQty6)?.toFixed(2) || 0} <span style={{ lineHeight: 2.5 }}>余热发电</span>
<span style={{ lineHeight: 2.5 }}>992Kwh</span>
</span> </span>
</div>
<div className={cls.shadowBorder + " " + cls.infoText}> <span className={cls.shadowBorder + ' ' + cls.infoText}>
<span style={{ lineHeight: 1.5 }}>许昌安彩光伏发电(昨日)/kWh</span> 水耗量: 32Km³
<span
style={{
lineHeight: 1.5,
width: "180px",
wordWrap: "break-word",
}}
>
{(+energyInfo?.elecQty7)?.toFixed(2) || 0}
</span> </span>
</div> <span className={cls.shadowBorder + ' ' + cls.infoText}>
<div className={cls.shadowBorder + " " + cls.infoText}> 天然气I: 92
<span style={{ lineHeight: 1.5 }}>智慧能源光伏发电(总量)/kWh</span>
<span
style={{
lineHeight: 1.5,
width: "180px",
wordWrap: "break-word",
}}
>
{(+energyInfo?.elecQty4)?.toFixed(2) || 0}
</span> </span>
</div> <span className={cls.shadowBorder + ' ' + cls.infoText}>
<div className={cls.shadowBorder + " " + cls.infoText}> 电耗量: 92Km³
<span style={{ lineHeight: 1.5 }}>许昌安彩光伏发电(总量)/kWh</span>
<span
style={{
lineHeight: 1.5,
width: "180px",
wordWrap: "break-word",
}}
>
{(+energyInfo?.elecQty5)?.toFixed(2) || 0}
</span> </span>
</div> <span className={cls.shadowBorder + ' ' + cls.infoText}>
</div> 天然气II: 92
)}
{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> </span>
</div> </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 { .layout {
display: grid; display: grid;
gap: 6px; gap: 6px;
/* grid-template-columns: 133px 158px 292px 292px; */ grid-template-columns: 133px 158px 292px 292px ;
grid-template-columns: 125px 250px 250px 250px; grid-template-rows: 60px 60px;
/* grid-template-rows: 60px 60px; */
grid-template-rows: 129px 129px;
} }
.shadowBorder { .shadowBorder {
box-shadow: inset 0 0 12px 3px #fff2; box-shadow: inset 0 0 12px 3px #fff3;
border-radius: 4px; border-radius: 4px;
padding: 4px; padding: 4px;
} }
.infoText { .infoText {
text-align: center; text-align: center;
font-size: 22px; font-size: 24px;
line-height: 2.5; line-height: 2.2;
/* line-height: 20px; */ /* line-height: 20px; */
letter-spacing: 1px; letter-spacing: 1px;
user-select: none; 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 GraphBase from '../../../Common/GraphBase';
import ReactECharts from "echarts-for-react"; import ReactECharts from 'echarts-for-react';
// import getOptions from "../../../../hooks/getChartOption"; import getOptions from '../../../../hooks/getChartOption';
import { useSelector } from "react-redux";
import { useState } from "react";
import * as echarts from "echarts";
import dayjs from "dayjs";
function NO(props) { function NO(props) {
const dayTrend = useSelector((state) => state.smoke?.dayTrend); function handleSwitch(v) {
const weekTrend = useSelector((state) => state.smoke?.weekTrend); console.log('switched ', v);
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 handleDateChange(v) {
console.log('date ', v);
}
return ( return (
<GraphBase <GraphBase
icon="smoke" icon="battery"
title="氮氧化物" title="一氧化氮"
desc={`能耗趋势图 ${timestr}`} desc="能耗趋势图"
switchOptions={false} switchOptions={true}
defaultSelect={period}
onSwitch={handleSwitch} onSwitch={handleSwitch}
dateOptions={["日", "周", "月", "年"]} dateOptions={['日', '周', '月', '年']}
legend={['总量', '白班', '夜班']}
onDateChange={handleDateChange} onDateChange={handleDateChange}
size={["long", "middle"]} size={['long', 'middle']}
> >
{options && ( {/* real echarts here */}
<ReactECharts <ReactECharts
key={Math.random()} key={Math.random()}
option={options} option={getOptions(
style={{ height: "100%" }} [
[148, 110, 140, 122, 84, 153, 89],
[88, 79, 75, 73, 33, 54, 31],
[60, 31, 65, 49, 51, 99, 58],
],
'氧气',
)}
style={{ height: '100%' }}
/> />
)} {/* real table data here */}
{!options && (
<p
style={{
color: "#cccf",
fontSize: "24px",
userSelect: "none",
textAlign: "center",
paddingTop: "96px",
}}
>
暂无数据
</p>
)}
</GraphBase> </GraphBase>
); );
} }
export default NO; 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 GraphBase from '../../../Common/GraphBase';
import ReactECharts from "echarts-for-react"; import ReactECharts from 'echarts-for-react';
// import getOptions from "../../../../hooks/getChartOption"; import getOptions from '../../../../hooks/getChartOption';
import { useSelector } from "react-redux";
import { useState } from "react";
import * as echarts from "echarts";
import dayjs from "dayjs";
function Dust(props) { function NO2(props) {
const dayTrend = useSelector((state) => state.smoke?.dayTrend); function handleSwitch(v) {
const weekTrend = useSelector((state) => state.smoke?.weekTrend); console.log('switched ', v);
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("dust_float", period, currentTrend); function handleDateChange(v) {
console.log('date ', v);
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]
);
} }
return ( return (
<GraphBase <GraphBase
icon="smoke" icon="battery"
title="颗粒物" title="二氧化氮"
desc={`能耗趋势图 ${timestr}`} desc="能耗趋势图"
switchOptions={false} switchOptions={true}
defaultSelect={period}
onSwitch={handleSwitch} onSwitch={handleSwitch}
dateOptions={["日", "周", "月", "年"]} dateOptions={['日', '周', '月', '年']}
legend={['总量', '白班', '夜班']}
onDateChange={handleDateChange} onDateChange={handleDateChange}
size={["long", "middle"]} size={['long', 'middle']}
> >
{options && ( {/* real echarts here */}
<ReactECharts <ReactECharts
key={Math.random()} key={Math.random()}
option={options} option={getOptions(
style={{ height: "100%" }} [
[91, 164, 88, 120, 167, 158, 43],
[30, 75, 52, 43, 73, 66, 36],
[61, 89, 36, 77, 94, 92, 7],
],
'氧气',
)}
style={{ height: '100%' }}
/> />
)} {/* real table data here */}
{!options && (
<p
style={{
color: "#cccf",
fontSize: "24px",
userSelect: "none",
textAlign: "center",
paddingTop: "96px",
}}
>
暂无数据
</p>
)}
</GraphBase> </GraphBase>
); );
} }
export default Dust; export default NO2;
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,224 +1,37 @@
import GraphBase from "../../../Common/GraphBase"; import GraphBase from '../../../Common/GraphBase';
import ReactECharts from "echarts-for-react"; import ReactECharts from 'echarts-for-react';
// import getOptions from "../../../../hooks/getChartOption"; 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";
function NatGas(props) { 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) { function handleSwitch(v) {
// console.log('switched ', v); console.log('switched ', v);
} }
function handleDateChange(value) { function handleDateChange(v) {
setPeriod(value); console.log('date ', v);
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]
);
} }
return ( return (
<GraphBase <GraphBase
icon="battery" icon="battery"
title="天然气I" title="天然气"
desc={`能耗趋势图 ${timestr}`} desc="能耗趋势图"
switchOptions={false} switchOptions={true}
onSwitch={handleSwitch} onSwitch={handleSwitch}
defaultSelect={period} dateOptions={['日', '周', '月', '年']}
dateOptions={["周", "月", "年"]} legend={['总量']}
// legend={[""]}
onDateChange={handleDateChange} onDateChange={handleDateChange}
size={["long", "middle"]} size={['long', 'short']}
> >
{/* real echarts here */} {/* real echarts here */}
{options && (
<ReactECharts <ReactECharts
key={Math.random()} key={Math.random()}
option={options} option={getOptions([[91, 69, 5, 10, 21, 46, 24]], '氧气')}
// option={getOptions([[91, 69, 5, 10, 21, 46, 24]], "")} style={{ height: '100%' }}
style={{ height: "100%" }}
/> />
)}
{!options && (
<p
style={{
color: "#cccf",
fontSize: "24px",
userSelect: "none",
textAlign: "center",
paddingTop: "88px",
}}
>
暂无数据
</p>
)}
{/* real table data here */} {/* real table data here */}
</GraphBase> </GraphBase>
); );
} }
export default NatGas; 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 GraphBase from '../../../Common/GraphBase';
import ReactECharts from "echarts-for-react"; import ReactECharts from 'echarts-for-react';
// import getOptions from "../../../../hooks/getChartOption"; import getOptions from '../../../../hooks/getChartOption';
import { useSelector } from "react-redux";
import { useState } from "react"; // function rand(max) {
import * as echarts from "echarts"; // return Math.ceil(Math.random() * max);
import dayjs from "dayjs"; // }
// function getArr(len) {
// return Array(len).fill(1).map(() => rand(100))
// }
// function getArrs(len) {
// return Array(len).fill(1).map(() => getArr(7))
// }
// function fan4(...arrs) {
// const total = arrs[0].map((_, i) =>
// arrs.reduce((sum, arr) => sum + arr[i], 0),
// );
// arrs.unshift(total);
// return arrs;
// }
// function main() {
// // console.log(JSON.stringify(fan(getArrs(3))))
// console.log(fan(getArrs(3)))
// }
function Oxygen(props) { function Oxygen(props) {
const dayTrend = useSelector((state) => state.smoke?.dayTrend); function handleSwitch(v) {
const weekTrend = useSelector((state) => state.smoke?.weekTrend); console.log('switched ', v);
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 handleDateChange(v) {
console.log('date ', v);
}
return ( return (
<GraphBase <GraphBase
icon="smoke" icon="battery"
title="氧气含量" title="氧气含量"
desc={`能耗趋势图 ${timestr}`} desc="能耗趋势图"
switchOptions={false} switchOptions={true}
defaultSelect={period}
onSwitch={handleSwitch} onSwitch={handleSwitch}
dateOptions={["日", "周", "月", "年"]} dateOptions={['日', '周', '月', '年']}
legend={['总量', '白班', '夜班']}
onDateChange={handleDateChange} onDateChange={handleDateChange}
size={["long", "middle"]} size={['long', 'middle']}
> >
{options && ( {/* real echarts here */}
<ReactECharts <ReactECharts
key={Math.random()} key={Math.random()}
option={options} option={getOptions(
style={{ height: "100%" }} [
[172, 165, 135, 35, 101, 53, 68], //
[87, 68, 81, 33, 35, 44, 38], //
[85, 97, 54, 2, 66, 9, 30], //
],
'氧气',
)}
style={{ height: '100%' }}
/> />
)} {/* real table data here */}
{!options && (
<p
style={{
color: "#cccf",
fontSize: "24px",
userSelect: "none",
textAlign: "center",
paddingTop: "160px",
}}
>
暂无数据
</p>
)}
</GraphBase> </GraphBase>
); );
} }
export default Oxygen; 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 RestHeat(props) {
function handleSwitch(v) { function handleSwitch(v) {
// console.log('switched ', v); console.log('switched ', v);
} }
function handleDateChange(v) { function handleDateChange(v) {
// console.log('date ', v); console.log('date ', v);
} }
return ( return (

View File

@ -1,174 +1,44 @@
import GraphBase from "../../../Common/GraphBase"; import GraphBase from '../../../Common/GraphBase';
import ReactECharts from "echarts-for-react"; import ReactECharts from 'echarts-for-react';
// import getOptions from "../../../../hooks/getChartOption"; import getOptions from '../../../../hooks/getChartOption';
import { useSelector } from "react-redux";
import { useState } from "react";
import * as echarts from "echarts";
import dayjs from "dayjs";
function SO2(props) { function SO2(props) {
const dayTrend = useSelector((state) => state.smoke?.dayTrend); function handleSwitch(v) {
const weekTrend = useSelector((state) => state.smoke?.weekTrend); console.log('switched ', v);
const monthTrend = useSelector((state) => state.smoke?.monthTrend); }
const yearTrend = useSelector((state) => state.smoke?.yearTrend);
const [period, setPeriod] = useState("日");
const currentTrend = function handleDateChange(v) {
period === "日" console.log('date ', v);
? 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]
);
} }
return ( return (
<GraphBase <GraphBase
icon="smoke" icon="battery"
title="二氧化硫" title="二氧化硫"
desc={`能耗趋势图 ${timestr}`} desc="能耗趋势图"
switchOptions={false} switchOptions={true}
defaultSelect={period}
onSwitch={handleSwitch} onSwitch={handleSwitch}
dateOptions={["日", "周", "月", "年"]} dateOptions={['日', '周', '月', '年']}
legend={['总量', '白班', '夜班']}
onDateChange={handleDateChange} onDateChange={handleDateChange}
size={["long", "middle"]} size={['long', 'middle']}
> >
{options && ( {/* real echarts here */}
<ReactECharts <ReactECharts
key={Math.random()} key={Math.random()}
option={options} option={getOptions(
style={{ height: "100%" }} [
[132, 155, 140, 83, 180, 67, 136],
[83, 58, 60, 22, 80, 64, 43],
[49, 97, 80, 61, 100, 3, 93],
],
'氧气',
)}
style={{ height: '100%' }}
/> />
)} {/* real table data here */}
{!options && (
<p
style={{
color: "#cccf",
fontSize: "24px",
userSelect: "none",
textAlign: "center",
paddingTop: "96px",
}}
>
暂无数据
</p>
)}
</GraphBase> </GraphBase>
); );
} }
export default SO2; 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 cls from './index.module.css';
import GradientText from "../../../Common/GradientText"; import GradientText from '../../../Common/GradientText';
import { useSelector } from "react-redux";
function SmokeHandle(props) { function SmokeHandle(props) {
const smokeInfo = useSelector((state) => state.smoke?.info);
return ( return (
<div className={" " + cls.smoke} style={{ color: "#fff" }}> <div className={' ' + cls.smoke} style={{ color: '#fff' }}>
<span <span
className={cls.shadowBorder} className={cls.shadowBorder}
style={{ style={{
gridRow: "1 / 3", gridRow: '1 / 3',
paddingTop: "96px", paddingTop: '38px',
paddingLeft: "32px", paddingLeft: '32px',
userSelect: "none", userSelect: 'none',
}} }}
> >
<GradientText text="烟气处理" /> <GradientText text="烟气处理" />
</span> </span>
<span <span
className={cls.shadowBorder + " " + cls.infoText} className={cls.shadowBorder + ' ' + cls.infoText}
style={{ letterSpacing: "2px" }} style={{ letterSpacing: '12px' }}
> >
<span style={{ lineHeight: 1.5 }}>氧气含量 %</span> 氧气含量: <span style={{ letterSpacing: '1px' }}>80%</span>
<span style={{ lineHeight: 1.5 }}>
{(+smokeInfo?.O2_float)?.toFixed(2) || 0}
</span> </span>
<span className={cls.shadowBorder + ' ' + cls.infoText}>
一氧化氮排放浓度: 20mg/
</span> </span>
<span className={cls.shadowBorder + " " + cls.infoText}> <span className={cls.shadowBorder + ' ' + cls.infoText}>
<span style={{ lineHeight: 1.5 }}>氮氧化物浓度 mg/</span> 二氧化硫排放浓度: 20mg/
<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> </span>
<span className={cls.shadowBorder + ' ' + cls.infoText}>
二氧化氮排放浓度: 20mg/
</span> </span>
</div> </div>
); );

View File

@ -1,14 +1,12 @@
.smoke { .smoke {
display: grid; display: grid;
gap: 6px; gap: 6px;
grid-template-columns: 187px 347px 347px; grid-template-columns: 187px 347px 347px ;
/* grid-template-rows: 60px 60px; */ grid-template-rows: 60px 60px;
grid-template-rows: 129px 129px;
height: 100%;
} }
.shadowBorder { .shadowBorder {
box-shadow: inset 0 0 12px 3px #fff2; box-shadow: inset 0 0 12px 3px #fff3;
border-radius: 4px; border-radius: 4px;
padding: 4px; padding: 4px;
} }
@ -16,17 +14,8 @@
.infoText { .infoText {
text-align: center; text-align: center;
font-size: 24px; font-size: 24px;
line-height: 2.5; line-height: 2.2;
/* line-height: 20px; */ /* line-height: 20px; */
letter-spacing: 1px; letter-spacing: 1px;
user-select: none; 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 WaterCost(props) {
function handleSwitch(v) { function handleSwitch(v) {
// console.log('switched ', v); console.log('switched ', v);
} }
function handleDateChange(v) { function handleDateChange(v) {
// console.log('date ', v); console.log('date ', v);
} }
return ( return (

View File

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

View File

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

View File

@ -1,118 +1,32 @@
import cls from "./righttable.module.scss"; import React, { Component } from "react";
import { ScrollBoard } from "@jiaminghi/data-view-react"; import "./righttable.module.scss";
import { useSelector } from "react-redux";
function CurrentSpec(props) { // import { ScrollBoard } from '@jiaminghi/data-view-react';
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),
};
return ( let data = [
<div className={cls.CenterChart1itemDetailBorder} style={{ opacity: 0.75 }}> ["产线0", "10mm", "10mm", "10mm"],
<h2 className={cls.CenterChart1itemTXT}>当前产线生产规格</h2> ["产线2", "8mm", "8mm", "8mm"],
<div className={cls.TableContainer}> ["产线3", "15mm", "15mm", "15mm"],
{config.data.length !== 0 && <ScrollBoard config={config} style={{}} />} ["产线4", "15mm", "15mm", "15mm"],
{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,
},
]; ];
function filterData(rawData) { let header = ["产线名", "原板宽度", "净板宽", "玻璃厚度"];
return (rawData ?? []).map((item) => [
// 线 let config = {
item.productionLine, headerBGC: "rgba(4, 44, 76, 0.3)",
// header: [
item.length, '<span style="color:#fff">产线名<span/>',
// '<span style="color:#fff">原板宽度<span/>',
item.wide, '<span style="color:#fff">净板宽<span/>',
// '<span style="color:#fff">玻璃厚度<span/>',
item.thick, ],
]); oddRowBGC: "#042444",
} evenRowBGC: "#042c4c",
columnWidth: [90],
headerHeight: 40,
hoverPause: false,
data: replaceStyle(data, 0.7),
};
function replaceStyle(Arr, opencity) { function replaceStyle(Arr, opencity) {
let temp = []; let temp = [];
@ -120,11 +34,32 @@ function replaceStyle(Arr, opencity) {
for (let i = 0; i < Arr.length; i++) { for (let i = 0; i < Arr.length; i++) {
temp[i] = []; temp[i] = [];
for (let j = 0; j < Arr[i].length; j++) { for (let j = 0; j < Arr[i].length; j++) {
temp[i][j] = `<span style="color:rgba(255, 255, 255,${opencity})">${ temp[i][
Arr[i][j] j
} ${j == 0 ? "" : "mm"}<span/>`; ] = ` <span style="color:rgba(255, 255, 255,${opencity})">${Arr[i][j]}<span/>`;
} }
} }
return temp; 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 { .CenterChart1itemDetailBorder {
width: 100%; width: 100%;
height: 200px; height: 240px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: flex-start; justify-content: flex-start;
color: #fff;
background-color: rgba(4, 44, 76, 0.2); background-color: rgba(4, 44, 76, 0.2);
.CenterChart1itemTXT { .CenterChart1itemTXT {
user-select: none; width: 100%;
padding: 8px 0; height: 10%;
font-size: 18px; font-size: 20px;
font-weight: 400; color: rgba(255, 255, 255, 0.8);
letter-spacing: 1px;
color: rgba(255, 255, 255, 0.9);
text-align: center; text-align: center;
margin-top: 2%;
} }
.CenterChart1itemContainer {
width: 95%;
height: 100px;
position: relative;
.TableContainer { .CenterFormitemDetailBorderLine1 {
flex: 1; 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() { function handleEnterVideoEnd() {
// console.log('video end'); console.log('video end');
enterToFloorOne(); enterToFloorOne();
} }

View File

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

View File

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

View File

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

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