Compare commits

...

94 Commits

Author SHA1 Message Date
lb
19ea3287ae Merge branch 'bugfix#4.4' 2024-04-15 13:51:16 +08:00
lb
4f6e4cbcf8 bugfix4.4 2024-04-15 13:50:49 +08:00
lb
c9ccc6ebcb fire and kiln inner 2024-01-26 17:25:24 +08:00
lb
4374260acd update lunbo 2024-01-26 17:19:39 +08:00
lb
6cf533e718 add 轮播功能 2024-01-26 14:08:31 +08:00
lb
b0e7a7ca34 update kiln inner 2024-01-26 11:11:26 +08:00
lb
0b48f68078 add refresher 2024-01-26 09:24:26 +08:00
lb
c767a7fe2e update video playbackrate 2024-01-25 16:51:12 +08:00
lb
97409d61a9 1 2024-01-25 16:36:12 +08:00
lb
0da9ba434d update video 2024-01-25 16:15:53 +08:00
lb
0bd1f8dcac update energy cost page 2024-01-25 15:42:25 +08:00
lb
6e10a5aacd update energy 2024-01-25 15:19:27 +08:00
lb
2fb3d05f8c 1 2024-01-25 10:55:22 +08:00
lb
b27a20f3cf update rightbar 2024-01-25 10:24:08 +08:00
lb
be5fbe1c01 update 2024-01-25 09:10:00 +08:00
lb
d6f9744ded 1 2024-01-24 17:01:29 +08:00
lb
1ebda5cf6f 1 2024-01-24 16:13:45 +08:00
lb
b7b2ad2ee5 1 2024-01-24 15:39:42 +08:00
lb
446234c2aa update 2024-01-24 14:41:24 +08:00
lb
909bd92ee6 update 2024-01-11 16:50:55 +08:00
lb
b16ee86def bugfix 20240111 2024-01-11 16:03:33 +08:00
lb
c8d392ce51 update 2024-01-08 13:28:03 +08:00
lb
d1212c8729 update 2024-01-04 17:03:00 +08:00
lb
9d3c877628 update 2024-01-04 16:58:43 +08:00
lb
e1e73b341d update 2024-01-04 16:44:15 +08:00
lb
ac772e2caf fix ui 2024-01-04 10:58:20 +08:00
lb
0b1d3aa4b3 fix ui 2024-01-03 17:00:31 +08:00
lb
bee1aedda4 update 2024-01-03 15:21:43 +08:00
lb
678c1b86ed update 2024-01-03 15:09:59 +08:00
lb
0f56538c27 update websocket reconnect policy & fix some bugs 2024-01-03 15:07:43 +08:00
lb
6b838ce089 update 天然气历史 2024-01-03 11:28:26 +08:00
lb
e40e897882 update 2024-01-02 17:07:07 +08:00
lb
15d05c26d8 update energe layout 2024-01-02 17:01:27 +08:00
lb
c9829d4f5a update faninfostretch 2024-01-02 16:11:37 +08:00
lb
a32e6fb591 update 2024-01-02 14:34:35 +08:00
lb
4b043214ca update elec 2024-01-02 10:53:43 +08:00
lb
871efd2eb2 update 能耗 2023-12-29 12:47:30 +08:00
lb
0cd25a6972 update right table 2023-12-29 12:33:25 +08:00
lb
a73d61fad8 update 2023-12-29 11:06:07 +08:00
lb
3f44cb9e9a update 2023-12-29 09:31:33 +08:00
Melete
060616e845 fix error 2023-12-28 18:54:55 +08:00
lb
2722ca6122 update 2023-12-28 16:59:43 +08:00
lb
049a0804ac update烟气 2023-12-28 16:16:31 +08:00
lb
4e73410495 update 能源,规格: 2023-12-28 15:16:23 +08:00
lb
c2802627d6 update 当前产线生产规格 2023-12-28 10:44:13 +08:00
lb
b57b65ffd4 update 2023-12-27 16:44:24 +08:00
lb
b35cf01fc8 update 2023-12-21 17:41:54 +08:00
lb
f6cbc3a34a del test data 2023-12-20 09:15:12 +08:00
lb
373f990517 update table style 2023-12-19 16:36:53 +08:00
lb
94a713a803 Merge branch 'master' of http://git.picaiba.com/g7hoo/xuchang-new 2023-12-19 15:49:55 +08:00
lb
903a576cdc update 2023-12-19 15:49:24 +08:00
lb
4fc0cf19e9 update 2023-12-19 15:15:10 +08:00
gtz
6374fcdb6f 'add_cutting_newuser' 2023-12-18 18:10:18 +08:00
lb
31e065fa5a update 2023-12-18 09:51:28 +08:00
gtz
98ad9f590c 'update' 2023-12-15 18:42:45 +08:00
gtz
682cfc0407 Merge branch 'master' of git.picaiba.com:g7hoo/xuchang-new 2023-12-15 17:33:17 +08:00
gtz
f32306096f '1' 2023-12-15 17:33:15 +08:00
lb
a2349e6f26 update data 2023-12-15 17:31:33 +08:00
lb
5107dd8ce8 update isra 2023-12-15 15:20:20 +08:00
lb
0b91868b4f update 2023-12-15 11:16:54 +08:00
lb
bb541962dd update 2023-12-15 09:58:40 +08:00
lb
c3511e1bfe update 2023-12-14 13:57:49 +08:00
lb
e4a2af8458 update 2023-12-14 11:24:03 +08:00
lb
68065b612a update 缺陷分类 2023-12-14 11:06:19 +08:00
lb
ac711e6f2a update 2023-12-13 16:59:58 +08:00
lb
19825dcb5f before using typescript 2023-12-13 13:44:45 +08:00
lb
cb0de3b5d0 update 退火-风机信息 2023-12-11 16:04:46 +08:00
lb
85ed13d8f5 update 退火左侧组件 2023-12-11 15:33:34 +08:00
lb
aa2a730acc done 当前温度 2023-12-11 15:28:59 +08:00
lb
c549f38231 add AnnealFanFrequence 2023-12-11 13:52:44 +08:00
lb
9f51f2b3cb update 2023-12-07 09:56:21 +08:00
lb
d4a4e82aa6 update 能源数据对接 2023-12-07 09:20:32 +08:00
lb
dd5ce4d90d update 2023-12-07 09:19:12 +08:00
lb
eadbfcb982 update energy 2023-12-06 16:46:44 +08:00
lb
42e5bea184 update websocket 2023-12-06 16:37:53 +08:00
lb
5f92580c7e add energe slice 2023-12-06 16:24:34 +08:00
gtz
9a4f60a75a 'del_console' 2023-12-04 17:50:49 +08:00
gtz
9814c2b6e9 'update' 2023-12-04 17:47:13 +08:00
lb
49ac95fbbd update 风机信息 2023-12-01 16:30:04 +08:00
lb
6eb4102863 update 风机信息 2023-12-01 16:15:32 +08:00
lb
ad305f0c46 update firedir 2023-12-01 16:05:09 +08:00
lb
4a882104c8 update 投料机 2023-12-01 15:50:33 +08:00
lb
ca6a1c6ede update 2023-12-01 15:19:50 +08:00
lb
52f028d806 update一层温度 2023-12-01 15:15:10 +08:00
lb
69dcea7909 update 2023-12-01 14:40:19 +08:00
lb
04a15dc14c update 一层温度 2023-12-01 13:59:53 +08:00
lb
b601e9065a update 一层温度 2023-12-01 11:34:54 +08:00
lb
550da629c0 update 风机运行频率 2023-12-01 10:17:47 +08:00
lb
d1d47cf5ac update 天然气流量 2023-12-01 09:31:44 +08:00
lb
a880f62393 update 天然气数据 2023-11-30 17:01:30 +08:00
lb
d65fc0e3ed connect 助燃风流量 2023-11-30 16:40:02 +08:00
lb
af531456f4 connect KilnInfo 2023-11-30 16:07:41 +08:00
lb
bc03a717bb Merge branch 'testing-redux' 2023-11-10 10:10:18 +08:00
lb
3821121a6f add more slices 2023-11-10 10:09:50 +08:00
140 changed files with 14475 additions and 9494 deletions

12377
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

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

Binary file not shown.

BIN
public/video/1to2_old.webm Normal file

Binary file not shown.

Binary file not shown.

BIN
public/video/2to1_old.webm Normal file

Binary file not shown.

BIN
public/video/east_fire.webm Normal file

Binary file not shown.

Binary file not shown.

BIN
public/video/enter_old.webm Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
public/video/west_fire.webm Normal file

Binary file not shown.

View File

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

14
src/assets/Icon/temp.svg Normal file
View File

@ -0,0 +1,14 @@
<?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>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1,14 @@
<?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>

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 MiB

After

Width:  |  Height:  |  Size: 7.5 MiB

BIN
src/assets/offline.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
src/assets/online.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

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

View File

@ -0,0 +1,212 @@
// 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

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

@ -0,0 +1,28 @@
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

@ -0,0 +1,60 @@
.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

@ -0,0 +1,32 @@
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

@ -0,0 +1,544 @@
.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,6 +6,7 @@ function BottomBarItem(props) {
<Container
icon={props.icon}
title={props.title}
desc={props.desc}
className={`${cls.bottomBarItem} ${props.className}`}
style={props.style}
>

View File

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

View File

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

View File

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

View File

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

Binary file not shown.

View File

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

View File

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

View File

@ -1,139 +1,141 @@
.chart {
height: 100%;
height: 100%;
}
.gas {
position: relative;
position: relative;
}
.currentFlow {
position: absolute;
top: 20px;
left: 50%;
transform: translateX(-50%);
padding: 8px 22px;
border-radius: 2px;
letter-spacing: 2px;
box-shadow: inset 0 0 22px 0px hsla(0, 0%, 100%, 0.15);
line-height: 18px;
font-size: 18px;
text-align: center;
color: #12fff5;
position: absolute;
top: 20px;
left: 50%;
transform: translateX(-50%);
padding: 8px 22px;
border-radius: 2px;
letter-spacing: 2px;
box-shadow: inset 0 0 22px 0px hsla(0, 0%, 100%, 0.15);
line-height: 18px;
font-size: 18px;
text-align: center;
color: #12fff5;
}
.floatHead {
position: absolute;
top: 22px;
right: 24px;
height: 32px;
width: 410px;
display: flex;
align-items: center;
justify-content: flex-end;
position: absolute;
top: 22px;
right: 24px;
height: 32px;
width: 410px;
display: flex;
align-items: center;
justify-content: flex-end;
}
.mainContent {
padding-top: 16px;
padding-top: 16px;
}
.alignRight {
text-align: right;
justify-self: flex-end;
text-align: right;
justify-self: flex-end;
}
.grid {
display: grid;
gap: 6px;
grid-template-columns: repeat(2, minmax(100px, 1fr));
grid-auto-rows: minmax(64px, min-content);
display: grid;
gap: 6px;
grid-template-columns: repeat(2, minmax(100px, 1fr));
grid-auto-rows: minmax(64px, min-content);
}
.areaName {
color: #fff;
font-size: 20px;
line-height: 1;
letter-spacing: 1.5px;
margin: 0;
padding-left: 20px;
width: 50%;
color: #fff;
font-size: 18px;
line-height: 1;
letter-spacing: 1.5px;
margin: 0;
padding-left: 20px;
width: 50%;
}
.areaPureContent {
display: flex;
display: flex;
}
.areaPureValue {
padding: 0 8px;
padding: 0 8px;
}
.areaPureValue:not(:first-child) {
border-left: 2px solid #fff6;
span.areaPureValue:not(:first-of-type) {
border-left: 2px solid #fff6;
}
.areaContent {
width: 50%;
padding-left: 12px;
display: flex;
flex-direction: column;
width: 50%;
padding-left: 12px;
display: flex;
flex-direction: column;
}
.areaPureValue,
.areaValue {
display: inline-block;
font-size: 17px;
line-height: 22px;
letter-spacing: 1.2px;
display: inline-block;
font-size: 14px;
line-height: 16px;
letter-spacing: 1.2px;
font-family: "HelloFont WenYiHei", sans-serif;
color: #53c2d4;
}
.switchLabel {
color: white;
margin-left: 6px;
color: white;
margin-left: 6px;
}
.legend:last-child {
margin-left: 8px;
margin-left: 8px;
}
.legend > span {
display: inline-block;
color: #dff1fe;
font-size: 14px;
letter-spacing: 2px;
display: inline-block;
color: #dff1fe;
font-size: 14px;
letter-spacing: 2px;
}
.legend > span:first-child {
width: 12px;
height: 12px;
margin-right: 4px;
border-radius: 2px;
width: 12px;
height: 12px;
margin-right: 4px;
border-radius: 2px;
}
.gasIcon {
background: #12fff5;
background: #12fff5;
}
.gas2Icon {
background: #2760ff;
background: #2760ff;
}
.radioGroup {
user-select: none;
user-select: none;
}
.radioGroup * {
border: none !important;
border-radius: 0 !important;
border: none !important;
border-radius: 0 !important;
}
.radioGroup *:focus-within {
box-shadow: none !important;
box-shadow: none !important;
}
.radioGroup *::before {
width: 0 !important;
width: 0 !important;
}
.radioGroup_button_wrapper {
color: #fff !important;
background: #03233c !important;
color: #fff !important;
background: #03233c !important;
}

Binary file not shown.

View File

@ -0,0 +1,184 @@
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

@ -0,0 +1,60 @@
.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,128 +1,151 @@
import cls from './index.module.css';
import { randomInt } from '../../../../utils';
import * as echarts from 'echarts';
import { Switch, Radio } from 'antd';
import ReactECharts from 'echarts-for-react';
import cls from "./index.module.css";
import { Radio, Select } from "antd";
import ReactECharts from "echarts-for-react";
import { useState } from "react";
import { useSelector } from "react-redux";
import { getOptions } from "../../../../utils/energeChartOption";
import triangle from "../../../../assets/Icon/triangle.svg";
import dayjs from "dayjs";
const EnergyCostChart = (props) => {
const options = {
color: ['#FFD160', '#12FFF5', '#2760FF'],
grid: { top: 32, right: 12, bottom: 20, left: 48 },
xAxis: {
type: 'category',
data: Array(7)
.fill(1)
.map((_, index) => {
const today = new Date();
const dtimestamp = today - index * 24 * 60 * 60 * 1000;
return `${new Date(dtimestamp).getMonth() + 1}.${new Date(
dtimestamp,
).getDate()}`;
})
.reverse(),
axisLabel: {
color: '#fff',
fontSize: 12,
},
axisTick: { show: false },
axisLine: {
lineStyle: {
width: 1,
color: '#213259',
},
},
},
yAxis: {
name: '单位/m³',
nameTextStyle: {
color: '#fff',
fontSize: 10,
align: 'right',
},
type: 'value',
axisLabel: {
color: '#fff',
fontSize: 12,
formatter: '{value} %',
},
axisLine: {
show: true,
lineStyle: {
color: '#213259',
},
},
splitLine: {
lineStyle: {
color: '#213259a0',
},
},
interval: 10,
min: 0,
max: 100,
},
series: [
{
data: Array(7)
.fill(1)
.map((_) => {
return randomInt(60, 100);
}),
type: 'line',
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#FFD16040' },
{ offset: 0.5, color: '#FFD16020' },
{ offset: 1, color: '#FFD16010' },
]),
},
// smooth: true,
},
],
tooltip: {
trigger: 'axis',
},
};
const elecTrend = useSelector((state) => state.energy.trend.elec);
const gasITrend = useSelector((state) => state.energy.trend.natGas1);
const gasIITrend = useSelector((state) => state.energy.trend.natGas2);
const [source, setSource] = useState("elec");
const [period, setPeriod] = useState("week");
function handleSwitchChange(val) {
// val: boolean
console.log('switch change', val);
}
const [timestr, setTimestr] = useState(
dayjs().subtract(7, "day").format("YYYY.MM.DD") +
" - " +
dayjs().subtract(1, "day").format("YYYY.MM.DD")
);
return (
<div className={cls.energyCostChart}>
<div className={cls.titleBar}>
<h2>能耗趋势图</h2>
<Switch defaultChecked onChange={handleSwitchChange} />
<div className={cls.legend}>
<span className="legend__title">班次详情</span>
<ul className="legend__list">
<li>总量</li>
</ul>
</div>
<Radio.Group
defaultValue="week"
buttonStyle="solid"
className={cls.radioGroup}
>
<Radio.Button value="day" className="radio-group__item">
</Radio.Button>
<Radio.Button value="week" className="radio-group__item">
</Radio.Button>
<Radio.Button value="month" className="radio-group__item">
</Radio.Button>
<Radio.Button value="year" className="radio-group__item">
</Radio.Button>
</Radio.Group>
</div>
<div className="flex-1">
<ReactECharts option={options} style={{ height: '180px' }} />
</div>
</div>
);
const currentTrend =
source == "elec" ? elecTrend : source == "gasi" ? gasITrend : gasIITrend;
const options = getOptions(
period,
source,
currentTrend ?? { week: [], month: [], year: [] }
);
function handleDateChange(value) {
setPeriod(
{
: "week",
: "month",
: "year",
}[value]
);
setTimestr(
{
:
dayjs().subtract(1, "year").endOf("year").format("YYYY.MM.") +
"29 - " +
dayjs().endOf("year").format("YYYY.MM.") +
"28",
:
dayjs().subtract(7, "day").format("YYYY.MM.DD") +
" - " +
dayjs().subtract(1, "day").format("YYYY.MM.DD"),
:
dayjs().subtract(1, "month").format("YYYY.MM.") +
"29 - " +
dayjs().format("YYYY.MM.") +
"28",
}[value]
);
}
return (
<div className={cls.energyCostChart}>
<div className={cls.titleBar}>
<h2>能耗趋势图</h2>
</div>
<div className={`${cls.choiceBar} flex items-center justify-between`}>
<Radio.Group
value={source}
buttonStyle="solid"
onChange={(v) => setSource(v.target.value)}
className={`${cls.radioGroup} flex items-center justify-between`}
>
<Radio.Button value="elec" className="radio-group__item">
</Radio.Button>
<Radio.Button value="gasi" className="radio-group__item">
天然气I
</Radio.Button>
<Radio.Button value="gasii" className="radio-group__item">
天然气II
</Radio.Button>
</Radio.Group>
{/* <Radio.Group
value={period}
buttonStyle="solid"
onChange={(v) => setPeriod(v.target.value)}
className={cls.radioGroup}
>
<Radio.Button value="week" className="radio-group__item">
</Radio.Button>
<Radio.Button value="month" className="radio-group__item">
</Radio.Button>
<Radio.Button value="year" className="radio-group__item">
</Radio.Button>
</Radio.Group> */}
<div 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 className="flex-1" style={{ marginTop: "8px" }}>
{options && (
<ReactECharts option={options} style={{ height: "180px" }} />
)}
{!options && (
<p
style={{
color: "#cccf",
fontSize: "20px",
userSelect: "none",
textAlign: "center",
paddingTop: "32px",
}}
>
暂无数据
</p>
)}
</div>
</div>
);
};
export default EnergyCostChart;

View File

@ -1,85 +1,95 @@
.energyCostChart {
height: 1px;
flex: 1;
padding-top: 8px;
height: 1px;
flex: 1;
padding-top: 8px;
}
.energyCostChart .titleBar {
display: flex;
justify-content: space-between;
align-items: center;
color: white;
display: flex;
justify-content: space-between;
align-items: center;
color: white;
}
.energyCostChart .titleBar h2 {
margin: 0;
font-size: 18px;
line-height: 32px;
letter-spacing: 1.2px;
color: #52fff8;
margin: 0;
font-size: 18px;
line-height: 32px;
letter-spacing: 1.2px;
color: #52fff8;
}
.graphBaseDesc {
margin: 0 12px;
line-height: 1;
color: #76fff9;
flex: 1;
}
.energyCostChart .titleBar .legend {
display: flex;
align-items: center;
display: flex;
align-items: center;
}
.energyCostChart .titleBar .legend * {
font-size: 14px;
line-height: 14px;
color: #dff1fe;
font-size: 14px;
line-height: 14px;
color: #dff1fe;
}
.energyCostChart .titleBar .legend ul {
display: flex;
margin: 0;
margin-left: 8px;
padding: 0;
list-style: none;
align-items: center;
display: flex;
margin: 0;
margin-left: 8px;
padding: 0;
list-style: none;
align-items: center;
}
.energyCostChart .titleBar .legend ul li {
position: relative;
margin: 4px;
padding-left: 16px;
position: relative;
margin: 4px;
padding-left: 16px;
}
.energyCostChart .titleBar .legend ul li::before {
content: '';
position: absolute;
left: 2px;
top: 2px;
display: inline-block;
width: 12px;
height: 12px;
border-radius: 2px;
content: "";
position: absolute;
left: 2px;
top: 2px;
display: inline-block;
width: 12px;
height: 12px;
border-radius: 2px;
}
.energyCostChart .titleBar .legend ul li:first-child::before {
background-color: #ffd160;
background-color: #ffd160;
}
.energyCostChart .titleBar .legend ul li:nth-child(2)::before {
background-color: #12fff5;
background-color: #12fff5;
}
.energyCostChart .titleBar .legend ul li:nth-child(3)::before {
background-color: #2760ff;
background-color: #2760ff;
}
.radioGroup * {
border: none !important;
border-radius: 0 !important;
border: none !important;
border-radius: 0 !important;
}
.radioGroupShort * {
border: none !important;
border-radius: 6px !important;
}
.radioGroup *:focus-within {
box-shadow: none !important;
box-shadow: none !important;
}
.radioGroup *::before {
width: 0 !important;
width: 0 !important;
}
.radioGroup_button_wrapper {
color: #fff !important;
background: #03233c !important;
color: #fff !important;
background: #03233c !important;
}
.radioGroup_button_wrapper.ant-radio-button-wrapper-checked {
background: #02457e !important;
background: #02457e !important;
}

View File

@ -1,33 +1,22 @@
import cls from './index.module.scss';
import Container from '../../Container';
import TechSplitline from '../TechSplitline';
import EnergyCostChart from './EnergyCostChart';
import cls from "./index.module.scss";
import Container from "../../Container";
import TechSplitline from "../TechSplitline";
import EnergyCostChart from "./EnergyCostChart";
import EnergyCostRealtime from "./EnergeCostRealtime";
function EnergyCost(props) {
return (
<Container title="能耗" icon="charger" className={cls.energyCost}>
<div className={`flex flex-col`}>
<div className={`${cls.cost__info} flex`}>
<div
className={`${cls.info__item} ${cls.hAuto} flex flex-col justify-center items-center self-stretch`}
>
<span> </span>
<span>922kWh</span>
</div>
<div className={cls.info__item_groups}>
<div className={cls.info__item}> : 32Km³</div>
<div className={cls.info__item}> I : 83</div>
<div className={cls.info__item}> : 52kWh</div>
<div className={cls.info__item}> II: 32</div>
</div>
</div>
<TechSplitline />
return (
<Container title="能耗" icon="battery" className={cls.energyCost}>
<div className={`flex flex-col`}>
<EnergyCostRealtime />
<EnergyCostChart />
</div>
</Container>
);
<TechSplitline />
<EnergyCostChart />
</div>
</Container>
);
}
export default EnergyCost;

View File

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

View File

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

View File

@ -0,0 +1,248 @@
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

@ -0,0 +1,50 @@
.CenterChart1itemDetailBorder {
width: 100%;
height: 240px;
display: flex;
flex-direction: column;
justify-content: flex-start;
background-color: rgba(4, 44, 76, 0.2);
.CenterChart1itemTXT {
width: 100%;
height: 10%;
font-size: 20px;
color: rgba(255, 255, 255, 0.8);
text-align: center;
margin-top: 2%;
}
.CenterChart1itemContainer {
width: 95%;
height: 100px;
position: relative;
.CenterFormitemDetailBorderLine1 {
width: 1px;
height: 200px;
background-color: #041c2c;
float: left;
margin-left: 18%;
z-index: 10;
position: absolute;
}
.CenterFormitemDetailBorderLine2 {
width: 1px;
height: 200px;
background-color: #041c2c;
float: left;
margin-left: 46%;
z-index: 10;
position: absolute;
}
.CenterFormitemDetailBorderLine3 {
width: 1px;
height: 200px;
background-color: #041c2c;
float: left;
margin-left: 72%;
z-index: 10;
position: absolute;
}
}
}

View File

@ -1,20 +1,71 @@
// FanRunFrequence
import cls from "./index.module.css";
import ReactECharts from "echarts-for-react";
import * as echarts from "echarts";
import { Switch } from "antd";
import GraphBase from "../../Common/GraphBase";
import { useState, useContext } from "react";
// import SocketContext from '../../../store/socket-data-provider';
import { useState } from "react";
import { useSelector } from "react-redux";
function WindFrequence(props) {
const [showChart, setShowChart] = useState(true);
// const { runState, hisState } = useContext(SocketContext);
const [showChart, setShowChart] = useState(false);
const runState = useSelector((state) => state.fanFrequence.runtime);
const hisState = useSelector((state) => state.fanFrequence.history);
const runState = null;
const hisState = null;
const [options, dataList] = getOptions(showChart, hisState, runState);
let dataList = [];
function handleSwitchChange(val) {
if (val) {
setShowChart(true);
} else {
setShowChart(false);
}
}
return (
<GraphBase
icon="smoke"
title="风机运行频率"
size={["middle", "long"]}
switchOptions={false}
switchPosition={[null, 200]} // [top, left]
onSwitch={handleSwitchChange}
>
<div className={cls.chart}>
{/* {showChart && (
<ReactECharts option={options} style={{ height: "100%" }} />
)} */}
{!showChart && (
<div className={cls.gridList}>
{dataList.map((item) => (
<div
key={item.id}
className={cls.listItem}
style={{ padding: props.stretch ? "16px 0" : "" }}
>
<span className={cls.fanName}>{item.name}</span>
<span
className={cls.fanValue}
style={{
fontWeight: 700,
letterSpacing: 1,
fontSize: 16,
// color: "#e03537",
color: "#24aebb",
}}
>
{item.value}
</span>
</div>
))}
</div>
)}
</div>
</GraphBase>
);
}
export default WindFrequence;
function getOptions(showChart, hisState, runState) {
let dataList = null;
let seriesData = [];
const colors = [
"#12FFF5",
@ -29,20 +80,15 @@ function WindFrequence(props) {
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));
seriesData =
hisState != null
? Object.keys(hisState)
.sort()
.map((key) => hisState[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 },
@ -104,9 +150,10 @@ function WindFrequence(props) {
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" },
// 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" },
]),
},
})),
@ -115,80 +162,32 @@ function WindFrequence(props) {
},
};
} else {
dataList = runState?.combustionAirPressureArr
? [
{ id: 1, name: "1#风机", value: "0m³/h" },
{ id: 2, name: "2#风机", value: "0m³/h" },
{ id: 3, name: "3#风机", value: "0m³/h" },
{ id: 4, name: "4#风机", value: "0m³/h" },
{ id: 5, name: "5#风机", value: "0m³/h" },
{ id: 6, name: "6#风机", value: "0m³/h" },
{ id: 7, name: "7#风机", value: "0m³/h" },
{ id: 8, name: "8#风机", value: "0m³/h" },
{ id: 9, name: "9#风机", value: "0m³/h" },
{ id: 10, name: "10#风机", value: "0m³/h" },
{ id: 11, name: "11#风机", value: "0m³/h" },
{ id: 12, name: "12#风机", value: "0m³/h" },
{ id: 13, name: "13#风机", value: "0m³/h" },
{ id: 14, name: "14#风机", value: "0m³/h" },
{ id: 15, name: "15#风机", value: "0m³/h" },
{ id: 16, name: "16#风机", value: "0m³/h" },
].map((item, index) => ({
...item,
value: runState.combustionAirPressureArr[index] ?? "/",
}))
: [
{ id: 1, name: "1#风机", value: "0m³/h" },
{ id: 2, name: "2#风机", value: "0m³/h" },
{ id: 3, name: "3#风机", value: "0m³/h" },
{ id: 4, name: "4#风机", value: "0m³/h" },
{ id: 5, name: "5#风机", value: "0m³/h" },
{ id: 6, name: "6#风机", value: "0m³/h" },
{ id: 7, name: "7#风机", value: "0m³/h" },
{ id: 8, name: "8#风机", value: "0m³/h" },
{ id: 9, name: "9#风机", value: "0m³/h" },
{ id: 10, name: "10#风机", value: "0m³/h" },
{ id: 11, name: "11#风机", value: "0m³/h" },
{ id: 12, name: "12#风机", value: "0m³/h" },
{ id: 13, name: "13#风机", value: "0m³/h" },
{ id: 14, name: "14#风机", value: "0m³/h" },
{ id: 15, name: "15#风机", value: "0m³/h" },
{ id: 16, name: "16#风机", value: "0m³/h" },
];
dataList =
runState != null
? Object.keys(runState).map((fan) => ({
id: Math.random(),
name: fan,
value: (+runState[fan])?.toFixed(2),
}))
: [
{ id: 1, name: "1#风机", value: "0m³/h" },
{ id: 2, name: "2#风机", value: "0m³/h" },
{ id: 3, name: "3#风机", value: "0m³/h" },
{ id: 4, name: "4#风机", value: "0m³/h" },
{ id: 5, name: "5#风机", value: "0m³/h" },
{ id: 6, name: "6#风机", value: "0m³/h" },
{ id: 7, name: "7#风机", value: "0m³/h" },
{ id: 8, name: "8#风机", value: "0m³/h" },
{ id: 9, name: "9#风机", value: "0m³/h" },
{ id: 10, name: "10#风机", value: "0m³/h" },
{ id: 11, name: "11#风机", value: "0m³/h" },
{ id: 12, name: "12#风机", value: "0m³/h" },
{ id: 13, name: "13#风机", value: "0m³/h" },
{ id: 14, name: "14#风机", value: "0m³/h" },
{ id: 15, name: "15#风机", value: "0m³/h" },
{ id: 16, name: "16#风机", value: "0m³/h" },
];
}
function handleSwitchChange(val) {
if (val) {
setShowChart(true);
} else {
setShowChart(false);
}
}
return (
<GraphBase
icon="kiln"
title="风机运行频率"
size={["middle", "long"]}
switchOptions={true}
switchPosition={[null, 200]} // [top, left]
onSwitch={handleSwitchChange}
>
<div className={cls.chart}>
{showChart && (
<ReactECharts option={options} style={{ height: "100%" }} />
)}
{!showChart && (
<div className={cls.gridList}>
{dataList.map((item) => (
<div key={item.id} className={cls.listItem}>
{item.name}: {item.value}
</div>
))}
</div>
)}
</div>
</GraphBase>
);
return [options, dataList];
}
export default WindFrequence;

View File

@ -1,33 +1,52 @@
.chart {
height: 100%;
height: 100%;
}
.gridList {
margin-top: 12px;
display: grid;
grid-template-columns: 1fr 1fr;
/* grid-auto-row: ; */
gap: 6px;
margin-top: 12px;
display: grid;
grid-template-columns: 1fr 1fr;
/* grid-auto-row: ; */
gap: 6px;
}
.listItem {
border-radius: 2px;
padding: 9px 0;
text-align: center;
color: #fff;
box-shadow: inset 0 0 16px 4px rgba(255, 255, 255, 0.197);
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;
position: absolute;
top: 22px;
right: 24px;
height: 32px;
width: 410px;
display: flex;
align-items: center;
justify-content: flex-start;
color: #fff;
}
.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

@ -0,0 +1,16 @@
.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

@ -0,0 +1,104 @@
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,187 +1,223 @@
//
import cls from './index.module.css';
import BottomBarItem from '../BottomItemBackground';
import ReactECharts from 'echarts-for-react';
import * as echarts from 'echarts';
import { randomInt } from '../../../utils';
import { Switch } from 'antd';
import { useState, useContext } from 'react';
// import SocketContext from '../../../store/socket-data-provider';
import cls from "./index.module.css";
import BottomBarItem from "../BottomItemBackground";
import ReactECharts from "echarts-for-react";
import * as echarts from "echarts";
import { Switch } from "antd";
import { useState, useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import dayjs from "dayjs";
/** 助燃风流量 */
function GasI(props) {
const [showChart, setShowChart] = useState(true);
// const { runState, hisState } = useContext(SocketContext);
const [showChart, setShowChart] = useState(true);
const runState = useSelector((state) => state.combustionAir.runtime);
const hisState = useSelector((state) => state.combustionAir.history);
const runState = null;
const hisState = null;
let [options, dataList] = getOptions(showChart, hisState, runState);
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));
function handleSwitchChange(val) {
if (val) {
setShowChart(true);
} else {
setShowChart(false);
}
}
// 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);
}
const desc =
dayjs().subtract(7, "day").format("YYYY.MM.DD") +
" - " +
dayjs().subtract(1, "day").format("YYYY.MM.DD");
function handleSwitchChange(val) {
if (val) {
setShowChart(true);
} else {
setShowChart(false);
}
}
return (
<BottomBarItem
icon="pause"
title="助燃风流量"
className={cls.gas}
style={props.style}
>
<div className={cls.headWidget}>
<div className="flex items-center">
<Switch size="small" defaultChecked onChange={handleSwitchChange} />
{showChart && <span className={cls.switchLabel}>历史详情</span>}
{!showChart && <span className={cls.switchLabel}>实时流量</span>}
</div>
</div>
return (
<BottomBarItem
icon="pause"
title="助燃风流量"
desc={desc}
className={cls.gas}
style={props.style}
>
<div className={cls.headWidget}>
<div className="flex items-center">
<Switch size="small" defaultChecked onChange={handleSwitchChange} />
{showChart && <span className={cls.switchLabel}>历史详情</span>}
{!showChart && <span className={cls.switchLabel}>实时流量</span>}
</div>
</div>
<div className={cls.chart}>
{showChart && (
<ReactECharts option={options} style={{ height: '100%' }} />
)}
{!showChart && (
<div className={cls.gridList}>
{dataList.map((item) => (
<div key={item.id} className={cls.listItem}>
{item.name}: {item.value}
</div>
))}
</div>
)}
</div>
</BottomBarItem>
);
<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}>
<span className={cls.item_label}>{item.name}</span>
<span className={cls.item_value}>{item.value}</span>
{/* {item.name}: {item.value} */}
</div>
))}
</div>
)}
</div>
</BottomBarItem>
);
}
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,9 +26,10 @@
position: absolute;
/* background: #00ee33; */
top: 20px;
left: 180px;
right: 24px;
height: 32px;
width: 190px;
width: 128px;
text-align: right;
}
@ -62,7 +63,21 @@
padding: 12px 0;
text-align: center;
color: #fff;
box-shadow: inset 0 0 16px 4px rgba(255, 255, 255, 0.197);
box-shadow: inset 0 0 12px 2px rgba(255, 255, 255, 0.197);
display: flex;
align-items: center;
gap: 12px;
}
.item_label {
flex: 5;
text-align: right;
}
.item_value {
flex: 4;
text-align: left;
}
.headWidget {

View File

@ -1,124 +1,138 @@
// TODO: -
import useIcon from '../../../hooks/useIcon';
import cls from './index.module.css';
import { useMemo, useState } from 'react';
import { Switch, Radio } from 'antd';
import useIcon from "../../../hooks/useIcon";
import cls from "./index.module.css";
import { useMemo, useState } from "react";
import { Switch, Select } from "antd";
import "./selector.style.overwrite.css";
import triangle from "../../../assets/Icon/triangle.svg";
function choseBg(size) {
const [width, height] = size;
return width === 'long' && height === 'middle'
? 'long-middle'
: width === 'long' && height === 'short'
? 'long-short'
: width === 'short' && height === 'middle'
? 'short-middle'
: width === 'short' && height === 'short'
? 'short-short'
: width === 'short' && height === 'long'
? 'short-long'
: width === 'middle' && height === 'middle'
? 'middle-middle'
: width === 'middle' && height === 'short'
? 'middle-short'
: width === 'middle' && height === 'long'
? 'middle-long'
: width === 'middle' && height === 'full'
? 'middle-full'
: 'middle-middle';
const [width, height] = size;
return width === "long" && height === "middle"
? "long-middle"
: width === "long" && height === "short"
? "long-short"
: width === "short" && height === "middle"
? "short-middle"
: width === "short" && height === "short"
? "short-short"
: width === "short" && height === "long"
? "short-long"
: width === "middle" && height === "middle"
? "middle-middle"
: width === "middle" && height === "short"
? "middle-short"
: width === "middle" && height === "long"
? "middle-long"
: width === "middle" && height === "full"
? "middle-full"
: "middle-middle";
}
function GraphBase(props) {
const size = props.size || ['middle', 'middle'];
const bgClass = choseBg(size);
const {
icon,
title,
desc,
switchOptions,
onSwitch,
dateOptions,
onDateChange,
legend,
} = props;
const iconSrc = useIcon(icon);
const colors = useMemo(() => ['#ffd160', '#2760ff', '#15e8f5'], []);
const [showChart, setShowChart] = useState(true);
const size = props.size || ["middle", "middle"];
const bgClass = choseBg(size);
const {
icon,
title,
desc,
switchOptions,
onSwitch,
dateOptions,
onDateChange,
defaultSelect,
selectWidth,
legend,
} = props;
const iconSrc = useIcon(icon);
const colors = useMemo(() => ["#ffd160", "#2760ff", "#15e8f5"], []);
const [showChart, setShowChart] = useState(true);
let dto = null;
const switchStyle = {};
let dto = null;
const switchStyle = {};
if (props.switchPosition) {
props.switchPosition.forEach((item, index) => {
if (item != null) {
switchStyle[index == 0 ? 'top' : 'left'] = item + 'px';
}
});
}
if (dateOptions) {
dto = dateOptions.map((item) => (
<Radio.Button value={item} key={item} className="radio-group__item">
{item}
</Radio.Button>
));
}
if (props.switchPosition) {
props.switchPosition.forEach((item, index) => {
if (item != null) {
switchStyle[index == 0 ? "top" : "left"] = item + "px";
}
});
}
function handleSwitchChange(v) {
v ? setShowChart(true) : setShowChart(false);
onSwitch(v);
}
if (dateOptions) {
dto = (
<Select
defaultValue={defaultSelect || dateOptions[0]}
style={{ width: selectWidth || 60 }}
popupClassName="xc-date-selector-menu"
className={cls.graphBaseDate + " " + cls.radioGroup}
options={dateOptions.map((item) => ({ label: item, value: item }))}
suffixIcon={<img src={triangle} alt="#" />}
notFoundContent={
<span
style={{
color: "#fff",
fontSize: "14px",
lineHeight: 1,
paddingLeft: "12px",
}}
>
- -
</span>
}
onChange={(value, option) => onDateChange(value)}
/>
);
}
return (
<div
className={
'graph-base ' +
cls[bgClass] +
' ' +
cls.graphBase +
' ' +
props.className
}
style={{ ...props.style }}
>
<div className={cls.graphBaseTitle}>
<img src={iconSrc} alt="#" />
<h2>{title}</h2>
</div>
<div className={cls.graphBaseContent}>
{desc && <div className={cls.graphBaseDesc}>{desc}</div>}
{switchOptions && (
<div className={cls.graphBaseSwitch} style={switchStyle}>
<Switch size="small" defaultChecked onChange={handleSwitchChange} />
{showChart && <span className={cls.switchLabel}>历史详情</span>}
{!showChart && <span className={cls.switchLabel}>实时流量</span>}
</div>
)}
{legend && showChart && (
<div className={cls.legend}>
{legend.map((item, index) => (
<div className={cls.legendItem} key={item}>
<span
className={cls.lengedItemPrefix}
style={{ backgroundColor: colors[index] }}
></span>
<span className={cls.legendItemLabel}>{item}</span>
</div>
))}
</div>
)}
{dateOptions && (
<Radio.Group
defaultValue={dateOptions[0]}
buttonStyle="solid"
className={cls.graphBaseDate + ' ' + cls.radioGroup}
onChange={({ target }) => onDateChange(target.value)}
>
{dto}
</Radio.Group>
)}
{props.children}
</div>
</div>
);
function handleSwitchChange(v) {
v ? setShowChart(true) : setShowChart(false);
onSwitch(v);
}
return (
<div
className={
"graph-base " +
cls[bgClass] +
" " +
cls.graphBase +
" " +
props.className
}
style={{ ...props.style }}
>
<div className={cls.graphBaseTitle}>
<img src={iconSrc} alt="#" />
<h2>{title}</h2>
{desc && <div className={cls.graphBaseDesc}>{desc}</div>}
</div>
<div className={cls.graphBaseContent}>
{switchOptions && (
<div className={cls.graphBaseSwitch} style={switchStyle}>
<Switch size="small" defaultChecked onChange={handleSwitchChange} />
{showChart && <span className={cls.switchLabel}>历史详情</span>}
{!showChart && <span className={cls.switchLabel}>实时流量</span>}
</div>
)}
{legend && showChart && (
<div className={cls.legend}>
{legend.map((item, index) => (
<div className={cls.legendItem} key={item}>
<span
className={cls.lengedItemPrefix}
style={{ backgroundColor: colors[index] }}
></span>
<span className={cls.legendItemLabel}>{item}</span>
</div>
))}
</div>
)}
{dateOptions && dto}
{props.children}
</div>
</div>
);
}
export default GraphBase;

View File

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

View File

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

View File

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

View File

@ -1,98 +1,105 @@
import * as echarts from 'echarts';
import { randomInt } from '../../../../utils';
import * as echarts from "echarts";
import { randomInt } from "../../../../utils";
export default function getOptions(seriesData, name) {
const colors = [
'#12FFF5',
'#2760FF',
'#FFD160',
'#E80091',
'#8064ff',
'#ff8a3b',
'#8cd26d',
'#2aa1ff',
];
return {
color: colors,
grid: { top: 38, right: 12, bottom: 20, left: 48 },
legend: {
show: true,
icon: 'roundRect',
top: 10,
right: 10,
padding: 0,
itemWidth: 8,
itemHeight: 8,
itemGap: 3,
height: 8,
textStyle: {
color: '#DFF1FE',
fontSize: 10,
},
},
xAxis: {
type: 'category',
data: Array(7)
.fill(1)
.map((_, index) => {
const today = new Date();
const dtimestamp = today - index * 24 * 60 * 60 * 1000;
return `${new Date(dtimestamp).getMonth() + 1}.${new Date(
dtimestamp,
).getDate()}`;
})
.reverse(),
axisLabel: {
color: '#fff',
fontSize: 12,
},
axisTick: { show: false },
axisLine: {
lineStyle: {
width: 1,
color: '#213259',
},
},
},
yAxis: {
name: '单位m³/h',
nameTextStyle: {
color: '#fff',
fontSize: 10,
align: 'right',
},
type: 'value',
axisLabel: {
color: '#fff',
fontSize: 12,
formatter: '{value}',
},
axisLine: {
show: true,
lineStyle: {
color: '#213259',
},
},
splitLine: {
lineStyle: {
color: '#213259a0',
},
},
},
series: seriesData.map((arr, index) => ({
name: index + 1 + '#' + name,
data: arr,
type: 'line',
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: colors[index] + '40' },
{ offset: 0.5, color: colors[index] + '20' },
{ offset: 1, color: colors[index] + '00' },
]),
},
})),
tooltip: {
trigger: 'axis',
},
};
const colors = [
"#12FFF5",
"#2760FF",
"#FFD160",
"#E80091",
"#8064ff",
"#ff8a3b",
"#8cd26d",
"#2aa1ff",
];
return {
color: colors,
grid: { top: 38, right: 12, bottom: 20, left: 48 },
legend: {
show: true,
icon: "roundRect",
top: 10,
right: 10,
padding: 0,
itemWidth: 8,
itemHeight: 8,
itemGap: 3,
height: 8,
textStyle: {
color: "#DFF1FE",
fontSize: 10,
},
},
xAxis: {
type: "category",
data: Array(7)
.fill(1)
.map((_, index) => {
const today = new Date();
const dtimestamp = today - (index+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,
formatter: "{value}",
},
axisLine: {
show: true,
lineStyle: {
color: "#213259",
},
},
splitLine: {
lineStyle: {
color: "#213259a0",
},
},
},
series: seriesData.map((arr, index) => ({
name: index + 1 + "#" + name,
data: arr,
type: "line",
symbol: 'circle',
symbolSize: 6,
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,37 +1,31 @@
import cls from './index.module.css';
import ReactECharts from 'echarts-for-react';
import getOptions from './chart.config';
// import SocketContext from '../../../../store/socket-data-provider';
import { useContext } from 'react';
import cls from "./index.module.css";
import ReactECharts from "echarts-for-react";
import getOptions from "./chart.config";
import { useSelector, useDispatch } from "react-redux";
function GasChart(props) {
const { dataSource } = props;
// const { hisState } = useContext(SocketContext);
const hisState = null;
const dataName = dataSource == 'gas-i' ? 'kilnGasT1' : 'kilnGasT2';
const { dataSource } = props;
const hisState = useSelector((state) => state.natGas.history);
const dataName = dataSource == "gas-i" ? "gasIHistory" : "gasIIHistory";
// keys() sort()
const seriesData = hisState?.[dataName]
? Object.keys(hisState?.[dataName])
.sort()
.map((key, index) => hisState?.[dataName][key])
: Array(dataSource == 'gas-i' ? 8 : 4).fill(Array(7).fill(0));
const seriesData = hisState?.[dataName]
? Object.keys(hisState?.[dataName])
.sort()
.map((key, index) => hisState?.[dataName][key])
: Array(dataSource == "gas-i" ? 8 : 4).fill(Array(7).fill(0));
// debug
console.log('天然气 series data', dataName, hisState?.[dataName], seriesData);
return (
<div className={cls.gasChart}>
<ReactECharts
key={Math.random()}
option={getOptions(
seriesData,
dataSource == 'gas-i' ? '天然气I' : '天然气II',
)}
style={{ height: '100%' }}
/>
</div>
);
return (
<div className={cls.gasChart}>
<ReactECharts
key={dataSource}
option={getOptions(
seriesData,
dataSource == "gas-i" ? "天然气I" : "天然气II"
)}
style={{ height: "100%" }}
/>
</div>
);
}
export default GasChart;

View File

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

View File

@ -1,14 +1,27 @@
.gridList {
margin-top: 12px;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 8px;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 8px;
}
.listItem {
border-radius: 2px;
padding: 12px 0;
text-align: center;
color: #fff;
box-shadow: inset 0 0 16px 4px rgba(255, 255, 255, 0.197);
color: #fff;
box-shadow: inset 0 0 16px 4px rgba(255, 255, 255, 0.197);
display: flex;
align-items: center;
gap: 12px;
}
.item_label {
flex: 5;
text-align: right;
}
.item_value {
flex: 6;
text-align: left;
}

View File

@ -1,71 +1,109 @@
//
import cls from './index.module.css';
import BottomBarItem from '../BottomItemBackground';
import { Switch, Radio } from 'antd';
import { useState } from 'react';
import GridList from './gridList';
import GasChart from './gasChart';
import cls from "./index.module.css";
import BottomBarItem from "../BottomItemBackground";
import triangle from "../../../assets/Icon/triangle.svg";
import { Switch, Select, Radio } from "antd";
import { useState } from "react";
import GridList from "./gridList";
import GasChart from "./gasChart";
import dayjs from "dayjs";
function GasII(props) {
const [dataSource, setDataSource] = useState('gas-i'); // gas-i , gas-ii
const [showChart, setShowChart] = useState(true);
const [dataSource, setDataSource] = useState("gas-i"); // gas-i , gas-ii
const [showChart, setShowChart] = useState(true);
function handleSwitchChange(val) {
if (val) {
setShowChart(true);
} else {
setShowChart(false);
}
}
function handleSwitchChange(val) {
if (val) {
setShowChart(true);
} else {
setShowChart(false);
}
}
function handleSourceChange(e) {
console.log('val', e.target.value);
if (e.target.value == 'ii') {
// II
setDataSource('gas-ii');
} else if (e.target.value == 'i') {
// I
setDataSource('gas-i');
}
}
// function handleSourceChange(e) {
// if (e.target.value == "ii") {
// // II
// setDataSource("gas-ii");
// } else if (e.target.value == "i") {
// // I
// setDataSource("gas-i");
// }
// }
return (
<BottomBarItem
icon="pause"
title="天然气流量"
className={`${cls.gas} ${props.className}`}
style={props.style}
>
{/* legend */}
<div className={cls.headWidget}>
<div className="flex items-center">
<Switch size="small" defaultChecked onChange={handleSwitchChange} />
{showChart && <span className={cls.switchLabel}>历史详情</span>}
{!showChart && <span className={cls.switchLabel}>实时流量</span>}
</div>
function handleDateChange(value) {
if (value == "天然气I") {
setDataSource("gas-i");
} else {
setDataSource("gas-ii");
}
}
<Radio.Group
defaultValue="i"
buttonStyle="solid"
className={cls.radioGroup}
onChange={handleSourceChange}
>
<Radio.Button value="i" className="radio-group__item">
天然气 I
</Radio.Button>
<Radio.Button value="ii" className="radio-group__item">
天然气 II
</Radio.Button>
</Radio.Group>
</div>
const desc =
dayjs().subtract(7, "day").format("YYYY.MM.DD") +
" - " +
dayjs().subtract(1, "day").format("YYYY.MM.DD");
return (
<BottomBarItem
icon="pause"
title="天然气流量"
desc={desc}
className={`${cls.gas} ${props.className}`}
style={props.style}
>
{/* legend */}
<div className={cls.headWidget}>
<div className="flex items-center">
<Switch size="small" defaultChecked onChange={handleSwitchChange} />
{showChart && <span className={cls.switchLabel}>历史详情</span>}
{!showChart && <span className={cls.switchLabel}>实时流量</span>}
</div>
<div className={cls.chart}>
{showChart && <GasChart dataSource={dataSource} />}
{!showChart && <GridList dataSource={dataSource} />}
</div>
</BottomBarItem>
);
<Select
defaultValue={"天然气I"}
style={{ width: 90 }}
popupClassName="xc-date-selector-menu"
className={cls.radioGroup}
options={["天然气I", "天然气II"].map((item) => ({
label: item,
value: item,
}))}
suffixIcon={<img src={triangle} alt="#" />}
notFoundContent={
<span
style={{
color: "#fff",
fontSize: "14px",
lineHeight: 1,
paddingLeft: "12px",
}}
>
- -
</span>
}
onChange={(value, option) => handleDateChange(value)}
/>
{/* <Radio.Group
defaultValue="i"
buttonStyle="solid"
className={cls.radioGroup}
onChange={handleSourceChange}
>
<Radio.Button value="i" className="radio-group__item">
天然气 I
</Radio.Button>
<Radio.Button value="ii" className="radio-group__item">
天然气 II
</Radio.Button>
</Radio.Group> */}
</div>
<div className={cls.chart}>
{showChart && <GasChart dataSource={dataSource} />}
{!showChart && <GridList dataSource={dataSource} />}
</div>
</BottomBarItem>
);
}
export default GasII;

View File

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

View File

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

View File

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

View File

@ -0,0 +1,24 @@
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,183 +1,339 @@
import cls from './index.module.css';
import { randomInt } from '../../../../utils';
import * as echarts from 'echarts';
import { Switch, Radio } from 'antd';
import ReactECharts from 'echarts-for-react';
import cls from "./index.module.css";
import * as echarts from "echarts";
import { Select } from "antd";
import ReactECharts from "echarts-for-react";
import { useEffect, useState } from "react";
import { useSelector } from "react-redux";
import triangle from "../../../../assets/Icon/triangle.svg";
import dayjs from "dayjs";
const SmokeTrendChart = (props) => {
const options = {
color: ['#FFD160', '#12FFF5', '#2760FF'],
grid: { top: 38, right: 12, bottom: 20, left: 48 },
xAxis: {
type: 'category',
data: Array(7)
.fill(1)
.map((_, index) => {
const today = new Date();
const dtimestamp = today - index * 24 * 60 * 60 * 1000;
return `${new Date(dtimestamp).getMonth() + 1}.${new Date(
dtimestamp,
).getDate()}`;
})
.reverse(),
axisLabel: {
color: '#fff',
fontSize: 12,
},
axisTick: { show: false },
axisLine: {
lineStyle: {
width: 1,
color: '#213259',
},
},
},
yAxis: {
name: '单位m³/h',
nameTextStyle: {
color: '#fff',
fontSize: 10,
align: 'right',
},
type: 'value',
axisLabel: {
color: '#fff',
fontSize: 12,
formatter: '{value} %',
},
axisLine: {
show: true,
lineStyle: {
color: '#213259',
},
},
splitLine: {
lineStyle: {
color: '#213259a0',
},
},
interval: 10,
min: 0,
max: 100,
},
series: [
{
data: Array(7)
.fill(1)
.map((_) => {
return randomInt(60, 100);
}),
type: 'line',
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#FFD16040' },
{ offset: 0.5, color: '#FFD16020' },
{ offset: 1, color: '#FFD16010' },
]),
},
// smooth: true,
},
{
data: Array(7)
.fill(1)
.map((_) => {
return randomInt(60, 100);
}),
type: 'line',
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#12FFF540' },
{ offset: 0.5, color: '#12FFF520' },
{ offset: 1, color: '#12FFF510' },
]),
},
// smooth: true,
},
{
data: Array(7)
.fill(1)
.map((_) => {
return randomInt(60, 100);
}),
type: 'line',
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#2760FF40' },
{ offset: 0.5, color: '#2760FF20' },
{ offset: 1, color: '#2760FF10' },
]),
},
// smooth: true,
},
],
tooltip: {
trigger: 'axis',
},
};
const dayTrend = useSelector((state) => state.smoke?.dayTrend);
const weekTrend = useSelector((state) => state.smoke?.weekTrend);
const monthTrend = useSelector((state) => state.smoke?.monthTrend);
const yearTrend = useSelector((state) => state.smoke?.yearTrend);
function handleSwitchChange(val) {
// val: boolean
console.log('switch change', val);
}
const [source, setSource] = useState("O2_float");
const [period, setPeriod] = useState("day");
return (
<div className={cls.energyCostChart}>
<div className={cls.titleBar}>
<h2>烟气趋势图</h2>
<Switch defaultChecked onChange={handleSwitchChange} />
<div className={cls.legend}>
<span className="legend__title">班次详情</span>
<ul className="legend__list">
<li>总量</li>
<li>白班</li>
<li>夜班</li>
</ul>
</div>
</div>
const currentTrend =
period === "day"
? dayTrend
: period === "week"
? weekTrend
: period === "month"
? monthTrend
: yearTrend;
<div className={`${cls.choiceBar} flex items-center justify-between`}>
<Radio.Group
defaultValue="oxygen"
buttonStyle="solid"
className={`${cls.radioGroup} flex items-center justify-between`}
>
<Radio.Button value="oxygen" className="radio-group__item">
氧气含量
</Radio.Button>
<Radio.Button value="so2" className="radio-group__item">
二氧化硫
</Radio.Button>
<Radio.Button value="no" className="radio-group__item">
一氧化氮
</Radio.Button>
<Radio.Button value="no2" className="radio-group__item">
二氧化氮
</Radio.Button>
</Radio.Group>
const options = getOptions(source, period, currentTrend);
<Radio.Group
defaultValue="week"
buttonStyle="solid"
className={cls.radioGroup}
>
<Radio.Button value="day" className="radio-group__item">
</Radio.Button>
<Radio.Button value="week" className="radio-group__item">
</Radio.Button>
<Radio.Button value="month" className="radio-group__item">
</Radio.Button>
<Radio.Button value="year" className="radio-group__item">
</Radio.Button>
</Radio.Group>
</div>
<ReactECharts option={options} style={{ height: '240px' }} />
</div>
);
const [desc, setDesc] = useState("");
useEffect(() => {
switch (period) {
case "day":
setDesc(
dayjs().subtract(1, "day").format("YYYY.MM.DD") +
" 7点 - " +
dayjs().format("YYYY.MM.DD") +
" 7点"
);
break;
case "month":
setDesc(
dayjs().subtract(1, "month").format("YYYY.MM.") +
"29 - " +
dayjs().format("YYYY.MM.") +
"28"
);
break;
case "week":
setDesc(
dayjs().subtract(7, "day").format("YYYY.MM.DD") +
" - " +
dayjs().subtract(1, "day").format("YYYY.MM.DD")
);
break;
case "year":
setDesc(
dayjs().subtract(1, "year").endOf("year").format("YYYY.MM.") +
"29 - " +
dayjs().endOf("year").format("YYYY.MM.") +
"28"
);
break;
}
}, [period]);
function handleDateChange(value) {
setPeriod(
{
: "day",
: "week",
: "month",
: "year",
}[value]
);
}
function handleSourceChange(value) {
setSource(
{
氧气: "O2_float",
氮氧化物: "NOX_float",
二氧化硫: "SO2_float",
颗粒物: "dust_float",
}[value]
);
}
return (
<div className={cls.energyCostChart}>
<div className={cls.titleBar}>
<h2>烟气趋势图</h2>
{/* <Switch defaultChecked onChange={handleSwitchChange} /> */}
{/* <div className={cls.legend}>
<span className="legend__title">班次详情</span>
<ul className="legend__list">
<li>总量</li>
<li>白班</li>
<li>夜班</li>
</ul>
</div> */}
</div>
<div className={`${cls.choiceBar} flex items-center justify-between`}>
{/* <Radio.Group
value={source}
onChange={(e) => setSource(e.target.value)}
buttonStyle="solid"
className={`${cls.radioGroup} flex items-center justify-between`}
>
<Radio.Button value="O2_float" className="radio-group__item">
氧气
</Radio.Button>
<Radio.Button value="NOX_float" className="radio-group__item">
氮氧化物
</Radio.Button>
<Radio.Button value="SO2_float" className="radio-group__item">
二氧化硫
</Radio.Button>
<Radio.Button value="dust_float" className="radio-group__item">
颗粒物
</Radio.Button>
</Radio.Group> */}
<Select
defaultValue={"氧气"}
style={{ width: 100 }}
popupClassName="xc-date-selector-menu"
className={cls.radioGroupShort}
options={["氧气", "氮氧化物", "二氧化硫", "颗粒物"].map((item) => ({
label: item,
value: item,
}))}
suffixIcon={<img src={triangle} alt="#" />}
notFoundContent={
<span
style={{
color: "#fff",
fontSize: "14px",
lineHeight: 1,
paddingLeft: "12px",
}}
>
- -
</span>
}
onChange={(value, option) => handleSourceChange(value)}
/>
<div className={cls.graphBaseDesc}>{desc}</div>
{/* <Radio.Group
value={period}
onChange={(e) => setPeriod(e.target.value)}
buttonStyle="solid"
className={cls.radioGroup}
>
<Radio.Button value="day" className="radio-group__item">
</Radio.Button>
<Radio.Button value="week" className="radio-group__item">
</Radio.Button>
<Radio.Button value="month" className="radio-group__item">
</Radio.Button>
<Radio.Button value="year" className="radio-group__item">
</Radio.Button>
</Radio.Group> */}
<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>
{options && <ReactECharts option={options} style={{ height: "220px" }} />}
{!options && (
<p
style={{
color: "#cccf",
fontSize: "24px",
userSelect: "none",
textAlign: "center",
paddingTop: "96px",
}}
>
暂无数据
</p>
)}
</div>
);
};
export default SmokeTrendChart;
function getOptions(source, period, trend) {
if (
trend[source].length === 0 ||
trend[source].filter((item) => item.value).length == 0
)
return null;
return {
color: ["#FFD160", "#12FFF5", "#2760FF"],
grid: {
top: 40,
right: 12,
bottom: 20,
left: source == "O2_float" ? 56 : 72,
},
xAxis: {
type: "category",
// data: Array(7)
// .fill(1)
// .map((_, index) => {
// const today = new Date();
// const dtimestamp = today - index * 24 * 60 * 60 * 1000;
// return `${new Date(dtimestamp).getMonth() + 1}.${new Date(
// dtimestamp
// ).getDate()}`;
// })
// .reverse(),
data: trend[source].map((item) => item.time),
axisLabel: {
color: "#fff",
fontSize: 12,
},
axisTick: { show: false },
axisLine: {
lineStyle: {
width: 1,
color: "#213259",
},
},
},
yAxis: {
name: source == "O2_float" ? "单位:%" : "单位mg/m³",
nameTextStyle: {
color: "#fff",
fontSize: 13,
align: "right",
},
type: "value",
axisLabel: {
color: "#fff",
fontSize: 14,
formatter: "{value}",
},
axisLine: {
show: true,
lineStyle: {
color: "#213259",
},
},
splitLine: {
lineStyle: {
color: "#213259a0",
},
},
},
series: [
{
data: trend[source].map((item) =>
!(item.value == null || isNaN(+item.value))
? (+item.value).toFixed(2)
: null
),
type: "line",
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: "#FFD16040" },
{ offset: 0.5, color: "#FFD16020" },
{ offset: 1, color: "#FFD16010" },
]),
},
// smooth: true,
},
// {
// data: Array(7)
// .fill(1)
// .map((_) => {
// return randomInt(60, 100);
// }),
// type: "line",
// areaStyle: {
// color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
// { offset: 0, color: "#12FFF540" },
// { offset: 0.5, color: "#12FFF520" },
// { offset: 1, color: "#12FFF510" },
// ]),
// },
// // smooth: true,
// },
// {
// data: Array(7)
// .fill(1)
// .map((_) => {
// return randomInt(60, 100);
// }),
// type: "line",
// areaStyle: {
// color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
// { offset: 0, color: "#2760FF40" },
// { offset: 0.5, color: "#2760FF20" },
// { offset: 1, color: "#2760FF10" },
// ]),
// },
// // smooth: true,
// },
],
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow",
},
className: "xc-chart-tooltip",
},
};
}

View File

@ -1,91 +1,102 @@
.energyCostChart {
height: 1px;
flex: 1;
padding-top: 8px;
height: 1px;
flex: 1;
padding-top: 8px;
}
.energyCostChart .titleBar {
width: 400px;
margin-bottom: 4px;
display: flex;
justify-content: space-between;
align-items: center;
color: white;
width: 400px;
margin-bottom: 4px;
display: flex;
justify-content: space-between;
align-items: center;
color: white;
}
.energyCostChart .titleBar h2 {
margin: 0;
font-size: 18px;
line-height: 32px;
letter-spacing: 1.2px;
color: #52fff8;
margin: 0;
font-size: 18px;
line-height: 32px;
letter-spacing: 1.2px;
color: #52fff8;
}
.energyCostChart .titleBar .legend {
display: flex;
align-items: center;
display: flex;
align-items: center;
}
.energyCostChart .titleBar .legend * {
font-size: 14px;
line-height: 14px;
color: #dff1fe;
font-size: 14px;
line-height: 14px;
color: #dff1fe;
}
.energyCostChart .titleBar .legend ul {
display: flex;
margin: 0;
margin-left: 8px;
padding: 0;
list-style: none;
align-items: center;
display: flex;
margin: 0;
margin-left: 8px;
padding: 0;
list-style: none;
align-items: center;
}
.energyCostChart .titleBar .legend ul li {
position: relative;
margin: 4px;
padding-left: 16px;
position: relative;
margin: 4px;
padding-left: 16px;
}
.energyCostChart .titleBar .legend ul li::before {
content: '';
position: absolute;
left: 2px;
top: 2px;
display: inline-block;
width: 12px;
height: 12px;
border-radius: 2px;
content: "";
position: absolute;
left: 2px;
top: 2px;
display: inline-block;
width: 12px;
height: 12px;
border-radius: 2px;
}
.energyCostChart .titleBar .legend ul li:first-child::before {
background-color: #ffd160;
background-color: #ffd160;
}
.energyCostChart .titleBar .legend ul li:nth-child(2)::before {
background-color: #12fff5;
background-color: #12fff5;
}
.energyCostChart .titleBar .legend ul li:nth-child(3)::before {
background-color: #2760ff;
background-color: #2760ff;
}
.choiceBar {
margin: 4px 0;
margin: 4px 0;
}
.radioGroup * {
border: none !important;
border-radius: 0 !important;
border: none !important;
border-radius: 0 !important;
}
.radioGroupShort * {
border: none !important;
border-radius: 6px !important;
}
.radioGroup *:focus-within {
box-shadow: none !important;
box-shadow: none !important;
}
.radioGroup *::before {
width: 0 !important;
width: 0 !important;
}
.radioGroup_button_wrapper {
color: #fff !important;
background: #03233c !important;
color: #fff !important;
background: #03233c !important;
}
.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,23 +1,19 @@
import cls from './index.module.scss';
import Container from '../../Container';
import TechSplitline from '../TechSplitline';
import SmokeTrendChart from './SmokeTrendChart';
import cls from "./index.module.scss";
import Container from "../../Container";
import TechSplitline from "../TechSplitline";
import SmokeTrendChart from "./SmokeTrendChart";
import SmokeHandleTable from "./SmokeHandleTable";
function SmokeHandle(props) {
return (
<Container title="烟气处理" icon="smoke" className={cls.smokeHandle}>
<div className={`${cls.smokeHandle__content} flex flex-col`}>
<div className={cls.info__item_groups}>
<div className={cls.info__item}> : 72%</div>
<div className={cls.info__item}>一氧化氮排放浓度:59mg/</div>
<div className={cls.info__item}>二氧化硫排放浓度:59mg/</div>
<div className={cls.info__item}>二氧化氮排放浓度:59mg/</div>
</div>
<TechSplitline />
<SmokeTrendChart />
</div>
</Container>
);
return (
<Container title="烟气处理" icon="smoke" className={cls.smokeHandle}>
<div className={`${cls.smokeHandle__content} flex flex-col`}>
<SmokeHandleTable />
<TechSplitline />
<SmokeTrendChart />
</div>
</Container>
);
}
export default SmokeHandle;

View File

@ -3,7 +3,7 @@
background: url(../../../assets/smoke.png) no-repeat;
background-size: 100% 100%;
width: 626px;
height: 540px;
height: 490px;
.smokeHandle__content {
margin-top: 8px;
}
@ -13,19 +13,17 @@
border-radius: 2px;
color: hsl(0, 0%, 100%, 0.9);
box-shadow: inset 0 0 17px 0px hsla(0, 0%, 100%, 0.15);
// width: 288px;
height: 56px;
font-size: 20px;
height: 32px;
font-size: 16px;
letter-spacing: 1.43px;
line-height: 56px;
line-height: 32px;
text-align: center;
user-select: none;
}
.info__item_groups {
margin-bottom: 12px;
margin-left: 8px;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 8px;
gap: 4px;
}

View File

@ -0,0 +1,41 @@
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

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

View File

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

View File

@ -1,163 +1,213 @@
import cls from './index.module.css';
import GraphBase from '../GraphBase';
import ReactECharts from 'echarts-for-react';
import cls from "./index.module.css";
import GraphBase from "../GraphBase";
import ReactECharts from "echarts-for-react";
import { useSelector } from "react-redux";
import { useState } from "react";
import dayjs from 'dayjs'
function FaultTotal(props) {
const options = {
color: [
'#2760FF',
'#5B9BFF',
'#FFD160',
'#8167F6',
'#99D66C',
'#FF8A40',
'#12FFF5',
],
grid: { top: 42, right: 12, bottom: 20, left: 48 },
legend: {
top: 10,
padding: 5,
itemWidth: 12,
itemHeight: 12,
itemGap: 12,
height: 12,
textStyle: {
color: '#DFF1FE',
fontSize: 12,
},
},
xAxis: {
type: 'category',
data: Array(5)
.fill(1)
.map((_, index) => {
return '产线' + (index + 1);
}),
axisLabel: {
color: '#fff',
fontSize: 12,
},
axisTick: { show: false },
axisLine: {
lineStyle: {
width: 1,
color: '#213259',
},
},
},
yAxis: {
name: '单位/个',
nameTextStyle: {
color: '#fff',
fontSize: 10,
align: 'right',
},
type: 'value',
axisLabel: {
color: '#fff',
fontSize: 12,
formatter: '{value}',
},
axisLine: {
show: true,
lineStyle: {
color: '#213259',
},
},
splitLine: {
lineStyle: {
color: '#213259a0',
},
},
// interval: 10,
// min: 0,
// max: 100,
},
series: [
{
name: '缺陷1',
type: 'bar',
stack: 'abcd',
emphasis: {
focus: 'series',
},
data: [320, 332, 301, 334, 390, 330, 320],
},
{
name: '缺陷2',
type: 'bar',
stack: 'abcd',
emphasis: {
focus: 'series',
},
data: [120, 132, 101, 134, 90, 230, 210],
},
{
name: '缺陷3',
type: 'bar',
stack: 'abcd',
emphasis: {
focus: 'series',
},
data: [220, 182, 191, 234, 290, 330, 310],
},
{
name: '缺陷4',
type: 'bar',
stack: 'abcd',
emphasis: {
focus: 'series',
},
data: [150, 232, 201, 154, 190, 330, 410],
},
{
name: '缺陷5',
type: 'bar',
stack: 'abcd',
emphasis: {
focus: 'series',
},
data: [862, 1018, 964, 1026, 1679, 1600, 1570],
},
{
name: '缺陷6',
type: 'bar',
barGap: 20,
barWidth: 12,
stack: 'abcd',
emphasis: {
focus: 'series',
},
data: [620, 732, 701, 734, 1090, 1130, 1120],
},
],
tooltip: {
trigger: 'axis',
},
};
const [currentSelect, setCurrentSelect] = useState("日");
const isra = useSelector((state) => state.isra);
function handleDateChange(v) {
console.log('date ', v);
}
const currentStatistic =
currentSelect == "日"
? isra.dayStatistic
: currentSelect == "周"
? isra.weekStatistic
: currentSelect == "月"
? isra.monthStatistic
: currentSelect == "月"
? isra.yearStatistic
: [];
// 使
const bgSize =
props.page == 'home' ? ['middle', 'short'] : ['middle', 'long'];
const series = preHandleStatisticData(currentStatistic, isra.checkType ?? []);
const options = getOptions(series, isra, currentStatistic);
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>
);
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: {
top: 10,
left: 60,
padding: 5,
itemWidth: 12,
itemHeight: 12,
itemGap: 12,
height: 12,
textStyle: {
color: "#DFF1FE",
fontSize: 12,
},
data: isra.checkType,
},
xAxis: {
type: "category",
data: currentStatistic.map((item) => item.name),
axisLabel: {
color: "#fffc",
fontSize: 12,
},
axisTick: { show: false },
axisLine: {
lineStyle: {
width: 1,
color: "#213259",
},
},
},
yAxis: {
name: "单位/个",
nameTextStyle: {
color: "#fff",
fontSize: 10,
align: "right",
},
type: "value",
axisLabel: {
color: "#fff",
fontSize: 12,
formatter: "{value}",
},
axisLine: {
show: true,
lineStyle: {
color: "#213259",
},
},
splitLine: {
lineStyle: {
color: "#213259a0",
},
},
},
series,
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow",
},
className: "xc-chart-tooltip",
// backgroundColor: ''
},
};
}

View File

@ -1,107 +1,244 @@
import cls from './index.module.css';
import GraphBase from '../GraphBase';
import ReactECharts from 'echarts-for-react';
import { useState } from 'react';
import cls from "./index.module.css";
import GraphBase from "../GraphBase";
import ReactECharts from "echarts-for-react";
import { useSelector } from "react-redux";
import { useEffect, useState } from "react";
import { randomInt } from "../../../utils";
import * as echarts from "echarts";
function FaultType(props) {
const options = {
colors: [
'#2760FF',
'#5B9BFF',
'#FFD160',
'#8167F6',
'#99D66C',
'#FF8A40',
'#12FFF5',
],
grid: {
left: 24,
top: 10,
bottom: 10,
right: 24,
},
legend: {
icon: 'circle',
top: 32,
right: 0,
bottom: 32,
width: 296,
height: 130,
itemGap: 30,
formatter: function (name) {
return `${name} {sub|${
options.series[0].data.find((o) => o.name == name).value
}}`;
},
textStyle: {
color: '#DFF1FE',
fontSize: 18,
rich: {
sub: {
color: '#fff9',
fontSize: 18,
},
},
},
},
series: [
{
type: 'pie',
center: ['26%', '54%'],
radius: ['55%', '75%'],
avoidLabelOverlap: false,
label: {
show: true,
formatter: '{d}%',
fontSize: 14,
color: 'inherit',
},
labelLine: {
length: 0,
},
data: [
{ value: 1048, name: '缺陷1' },
{ value: 735, name: '缺陷2' },
{ value: 580, name: '缺陷3' },
{ value: 484, name: '缺陷4' },
{ value: 300, name: '缺陷5' },
{ value: 300, name: '缺陷6' },
{ value: 300, name: '缺陷8' },
],
},
],
};
const [init, setInit] = useState(true);
const [currentLine, setCurrentLine] = useState("Y61");
const isra = useSelector((state) => state.isra);
const currentStatistic = isra.dayStatistic || [];
const currentLineStatistic =
currentLine != ""
? currentStatistic.find((item) => item.name === currentLine)?.data || []
: [];
const lines = currentStatistic.map((item) => item.name);
const CHART_TYPE = "line"; // "pie" | "line";
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' },
]);
useEffect(() => {
if (init == false) return;
if (lines.length) {
setInit(false);
setCurrentLine(lines[0]);
}
}, [lines]);
function handleDateChange(v) {
console.log('date ', v);
}
const options = init
? {}
: getOptions(
CHART_TYPE == "pie"
? getSeries(currentStatistic, currentLine)
: currentLineStatistic,
CHART_TYPE
);
// 使
const bgSize =
props.page == 'home' ? ['middle', 'short'] : ['middle', 'short'];
function handleLineChange(line) {
setCurrentLine(line);
}
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>
);
// 使
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,
top: 10,
bottom: 10,
right: 24,
};
const legend_common = {
icon: "circle",
top: 32,
right: 0,
bottom: 32,
width: 296,
height: 130,
itemGap: 30,
textStyle: {
color: "#DFF1FE",
fontSize: 18,
rich: {
sub: {
color: "#fff9",
fontSize: 18,
},
},
},
};
if (chart_type == "pie") {
return {
color,
grid,
legend: {
...legend_common,
formatter: function (name) {
return `${name} {sub|${
data[0].data.find((o) => o.name == name).value
}}`;
},
},
series: data,
};
} else if (chart_type == "line") {
const dataList = data.map((item) => ({
category: item.checkType,
value: item.checkNum,
}));
return {
grid: {
top: 48,
left: 48,
bottom: 40,
right: 18,
},
legend: {
...legend_common,
},
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow",
},
symbol: 'rect',
className: "xc-chart-tooltip",
// backgroundColor: ''
},
xAxis: {
type: "category",
data: (dataList || []).map((item) => item.category),
axisLabel: {
color: "#fff",
fontSize: 10,
rotate: 20,
},
axisTick: { show: false },
axisLine: {
lineStyle: {
width: 1,
color: "#213259",
},
},
},
yAxis: {
name: "单位/个",
nameTextStyle: {
color: "#fff",
fontSize: 10,
align: "right",
},
type: "value",
axisLabel: {
color: "#fff",
fontSize: 12,
formatter: "{value}",
},
axisLine: {
show: true,
lineStyle: {
color: "#213259",
},
},
splitLine: {
lineStyle: {
color: "#213259a0",
},
},
},
series: [
{
type: "bar",
barWidth: 14,
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
// i % 8 8
{ offset: 0, color: "#5CB7FF" },
{ offset: 1, color: "#364BFE" },
]),
},
label: {
show: true,
position: "top",
distance: 10,
fontSize: 10,
color: "#fffc",
},
data: (dataList || []).map((item) =>
item.value == null || isNaN(+item.value) ? null : (+item.value).toFixed(0)
),
},
],
};
}
}
function getSeries(currentStatistic, currentLine) {
const currentItem = currentStatistic.find((item) => item.name == currentLine);
return [
{
type: "pie",
center: ["26%", "54%"],
radius: ["55%", "75%"],
avoidLabelOverlap: false,
label: {
show: true,
formatter: "{d}%",
fontSize: 14,
color: "inherit",
},
labelLine: {
length: 0,
},
data: currentItem.data.map((item) => ({
value: item.checkNum,
name: item.checkType,
})),
},
];
}

View File

@ -1,19 +1,19 @@
import cls from './good.module.scss';
import Container from '../../Container';
import TodayTableData from './components/TodayTableData';
import GoodRateChart from './components/GoodRateChart';
import TechSplitline from '../TechSplitline';
import cls from "./good.module.scss";
import Container from "../../Container";
import TodayTableData from "./components/TodayTableData";
import GoodRateChart from "./components/GoodRateChart";
import TechSplitline from "../TechSplitline";
const GoodProduction = () => {
return (
<Container icon="good" title="本日生产良品率" className={cls.goodProd}>
<div className={`${cls.goodProd__content} h-full`}>
<TodayTableData />
<TechSplitline />
<GoodRateChart />
</div>
</Container>
);
return (
<Container icon="good" title="本日生产良品率" className={cls.goodProd}>
<div className={`${cls.goodProd__content} h-full`}>
<TodayTableData />
<TechSplitline />
<GoodRateChart />
</div>
</Container>
);
};
export default GoodProduction;

View File

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

View File

@ -1,86 +1,95 @@
.GoodRateChart {
height: 1px;
flex: 1;
padding-top: 8px;
/* background: #ae27276a; */
height: 1px;
flex: 1;
padding-top: 8px;
/* background: #ae27276a; */
}
.GoodRateChart .titleBar {
display: flex;
justify-content: space-between;
align-items: center;
color: white;
display: flex;
justify-content: flex-start;
align-items: center;
gap: 5px;
color: white;
}
.GoodRateChart .titleBar h2 {
margin: 0;
font-size: 18px;
line-height: 32px;
letter-spacing: 1.2px;
color: #52fff8;
margin: 0;
font-size: 16px;
line-height: 32px;
letter-spacing: 1px;
color: #52fff8;
}
.GoodRateChart .titleBar .legend {
display: flex;
align-items: center;
display: flex;
align-items: center;
}
.GoodRateChart .titleBar .legend * {
font-size: 14px;
line-height: 14px;
color: #dff1fe;
font-size: 14px;
line-height: 14px;
color: #dff1fe;
}
.graphBaseDesc {
margin: 0 6px;
font-size: 16px;
color: #76fff9;
flex: 1;
}
.GoodRateChart .titleBar .legend ul {
display: flex;
margin: 0;
margin-left: 8px;
padding: 0;
list-style: none;
align-items: center;
display: flex;
margin: 0;
margin-left: 5px;
padding: 0;
list-style: none;
align-items: center;
}
.GoodRateChart .titleBar .legend ul li {
position: relative;
margin: 4px;
padding-left: 16px;
position: relative;
margin: 4px;
padding-left: 16px;
}
.GoodRateChart .titleBar .legend ul li::before {
content: '';
position: absolute;
left: 2px;
top: 2px;
display: inline-block;
width: 12px;
height: 12px;
border-radius: 2px;
content: "";
position: absolute;
left: 2px;
top: 2px;
display: inline-block;
width: 12px;
height: 12px;
border-radius: 2px;
}
.GoodRateChart .titleBar .legend ul li:first-child::before {
background-color: #ffd160;
background-color: #ffd160;
}
.GoodRateChart .titleBar .legend ul li:nth-child(2)::before {
background-color: #12fff5;
background-color: #12fff5;
}
.GoodRateChart .titleBar .legend ul li:nth-child(3)::before {
background-color: #2760ff;
background-color: #2760ff;
}
.radioGroup * {
border: none !important;
border-radius: 0 !important;
border: none !important;
border-radius: 6px !important;
/* transform: translateX(224px) !important; */
}
.radioGroup *:focus-within {
box-shadow: none !important;
box-shadow: none !important;
}
.radioGroup *::before {
width: 0 !important;
width: 0 !important;
}
.radioGroup_button_wrapper {
color: #fff !important;
background: #03233c !important;
color: #fff !important;
background: #03233c !important;
}
.radioGroup_button_wrapper.ant-radio-button-wrapper-checked {
background: #02457e !important;
background: #02457e !important;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,65 +1,186 @@
import GraphBase from '../../../Common/GraphBase';
import ReactECharts from 'echarts-for-react';
import getOptions from '../../../../hooks/getChartOption';
// function rand(max) {
// return Math.ceil(Math.random() * max);
// }
// function getArr(len) {
// return Array(len).fill(1).map(() => rand(100))
// }
// function getArrs(len) {
// return Array(len).fill(1).map(() => getArr(7))
// }
// function fan4(...arrs) {
// const total = arrs[0].map((_, i) =>
// arrs.reduce((sum, arr) => sum + arr[i], 0),
// );
// arrs.unshift(total);
// return arrs;
// }
// function main() {
// // console.log(JSON.stringify(fan(getArrs(3))))
// console.log(fan(getArrs(3)))
// }
import GraphBase from "../../../Common/GraphBase";
import ReactECharts from "echarts-for-react";
// import getOptions from "../../../../hooks/getChartOption";
import { useSelector } from "react-redux";
import { useState } from "react";
import * as echarts from "echarts";
import dayjs from "dayjs";
function Oxygen(props) {
function handleSwitch(v) {
console.log('switched ', v);
}
const dayTrend = useSelector((state) => state.smoke?.dayTrend);
const weekTrend = useSelector((state) => state.smoke?.weekTrend);
const monthTrend = useSelector((state) => state.smoke?.monthTrend);
const yearTrend = useSelector((state) => state.smoke?.yearTrend);
const [period, setPeriod] = useState("日");
const [timestr, setTimestr] = useState(
dayjs().subtract(7, "day").format("YYYY.MM.DD") +
" - " +
dayjs().subtract(1, "day").format("YYYY.MM.DD")
);
function handleDateChange(v) {
console.log('date ', v);
}
const currentTrend =
period === "日"
? dayTrend
: period === "周"
? weekTrend
: period === "月"
? monthTrend
: yearTrend;
return (
<GraphBase
icon="battery"
title="氧气含量"
desc="能耗趋势图"
switchOptions={true}
onSwitch={handleSwitch}
dateOptions={['日', '周', '月', '年']}
legend={['总量', '白班', '夜班']}
onDateChange={handleDateChange}
size={['long', 'middle']}
>
{/* real echarts here */}
<ReactECharts
key={Math.random()}
option={getOptions(
[
[172, 165, 135, 35, 101, 53, 68], //
[87, 68, 81, 33, 35, 44, 38], //
[85, 97, 54, 2, 66, 9, 30], //
],
'氧气',
)}
style={{ height: '100%' }}
/>
{/* real table data here */}
</GraphBase>
);
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]
);
}
return (
<GraphBase
icon="smoke"
title="氧气含量"
desc={`能耗趋势图 ${timestr}`}
switchOptions={false}
defaultSelect={period}
onSwitch={handleSwitch}
dateOptions={["日", "周", "月", "年"]}
onDateChange={handleDateChange}
size={["long", "middle"]}
>
{options && (
<ReactECharts
key={Math.random()}
option={options}
style={{ height: "100%" }}
/>
)}
{!options && (
<p
style={{
color: "#cccf",
fontSize: "24px",
userSelect: "none",
textAlign: "center",
paddingTop: "160px",
}}
>
暂无数据
</p>
)}
</GraphBase>
);
}
export default Oxygen;
function getOptions(source, period, trend) {
if (
trend[source].length == 0 ||
trend[source].filter((item) => item.value).length == 0
)
return null;
return {
color: ["#FFD160", "#12FFF5", "#2760FF"],
grid: { top: 40, right: 12, bottom: 20, left: 80 },
xAxis: {
type: "category",
// data: Array(7)
// .fill(1)
// .map((_, index) => {
// const today = new Date();
// const dtimestamp = today - index * 24 * 60 * 60 * 1000;
// return `${new Date(dtimestamp).getMonth() + 1}.${new Date(
// dtimestamp
// ).getDate()}`;
// })
// .reverse(),
data: trend[source].map((item) => item.time),
axisLabel: {
color: "#fff",
fontSize: 12,
},
axisTick: { show: false },
axisLine: {
lineStyle: {
width: 1,
color: "#213259",
},
},
},
yAxis: {
name: "单位/%",
nameTextStyle: {
color: "#fff",
fontSize: 16,
align: "right",
},
type: "value",
axisLabel: {
color: "#fff",
fontSize: 16,
formatter: "{value} %",
},
min: 0,
max: 100,
axisLine: {
show: true,
lineStyle: {
color: "#213259",
},
},
splitLine: {
lineStyle: {
color: "#213259a0",
},
},
},
series: [
{
data: trend[source].map((item) =>
!(item.value == null || isNaN(+item.value))
? (+item.value).toFixed(2)
: null
),
type: "line",
symbol: "circle",
symbolSize: 6,
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: "#FFD16040" },
{ offset: 0.5, color: "#FFD16020" },
{ offset: 1, color: "#FFD16010" },
]),
},
},
],
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow",
},
className: "xc-chart-tooltip",
},
};
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,125 +1,65 @@
import { useState } from 'react';
import cls from './index.module.css';
import Chart2 from '../../../Common/TimeFireDir';
import VideoContainer from './VideoContainer';
import { useState } from "react";
import cls from "./index.module.css";
import Chart2 from "../../../Common/TimeFireDir";
import VideoContainer from "./VideoContainer";
function KilnCenter() {
const [floor, setFloor] = useState(0);
const [floor, setFloor] = useState(0);
function onFloorUpdate(flr) {
setFloor(flr);
}
function onFloorUpdate(flr) {
setFloor(flr);
}
return (
<div
className="bgKilnInner"
style={{
width: '100%',
position: 'absolute',
top: '12%',
display: 'flex',
flexDirection: 'column',
}}
>
{/* 时间火向数据 */}
<div
className="fireAndTime"
style={{ position: 'absolute', top: '-112px', height: '212px' }}
>
<Chart2 />
</div>
return (
<div
className="bgKilnInner"
style={{
width: "100%",
position: "absolute",
top: "12%",
display: "flex",
flexDirection: "column",
}}
>
{/* 时间火向数据 */}
<div
className="fireAndTime"
style={{ position: "absolute", top: "-112px", height: "212px" }}
>
<Chart2 />
</div>
{/* menu */}
<div
className="subMenu"
style={{
display: 'flex',
marginBottom: '24px',
justifyContent: 'center',
}}
>
<div
className={
'flr flr1 ' + cls.menuItem + ' ' + (floor == 1 ? cls.active : '')
}
onClick={() => onFloorUpdate(1)}
>
一层
</div>
<div
className={
'flr flr2 ' + cls.menuItem + ' ' + (floor == 2 ? cls.active : '')
}
onClick={() => onFloorUpdate(2)}
>
二层
</div>
</div>
{/* menu */}
<div
className="subMenu"
style={{
display: "flex",
marginBottom: "24px",
justifyContent: "center",
}}
>
<div
className={
"flr flr1 " + cls.menuItem + " " + (floor == 1 ? cls.active : "")
}
onClick={() => onFloorUpdate(1)}
>
碹顶
</div>
<div
className={
"flr flr2 " + cls.menuItem + " " + (floor == 2 ? cls.active : "")
}
onClick={() => onFloorUpdate(2)}
>
池底
</div>
</div>
{/* video */}
<VideoContainer onFloorUpdate={onFloorUpdate} floor={floor} />
{/* <div className={cls.videoLayer2}></div> */}
{/* left side */}
{/* <div
className="leftSide"
style={{
position: 'absolute',
left: '88px',
top: '24%',
display: 'grid',
gridTemplateColumns: '100px 100px',
gap: '20px 18px',
gridAutoRows: '64px',
}}
>
{data.map((item) => (
<div
className="leftSideItem"
style={{
background: '#fff3',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
background: '#32535d',
}}
>
<span style={{ fontSize: '18px', lineHeight: 1, color: '#2EE4E6' }}>
{item.name}
</span>
<span
style={{ fontSize: '24px', lineHeight: '32px', color: '#fff' }}
>
{item.value}
</span>
</div>
))}
</div>
<div
className="toolbox"
style={{
position: 'absolute',
bottom: '32px',
left: '64px',
display: 'flex',
alignItems: 'center',
gap: '24px',
}}
>
<div
className="tlj tlj1"
style={{ background: '#ccc', width: '200px', height: '100px' }}
></div>
<div
className="tlj tlj2"
style={{ background: '#ccc', width: '200px', height: '100px' }}
></div>
</div> */}
</div>
);
{/* video */}
<VideoContainer onFloorUpdate={onFloorUpdate} floor={floor} />
</div>
);
}
export default KilnCenter;

View File

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

View File

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

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