update data

This commit is contained in:
lb 2023-12-15 17:31:33 +08:00
parent 5107dd8ce8
commit a2349e6f26
10 changed files with 388 additions and 219 deletions

View File

@ -7,7 +7,7 @@ import ReactECharts from 'echarts-for-react';
const EnergyCostChart = (props) => { const EnergyCostChart = (props) => {
const options = { const options = {
color: ['#FFD160', '#12FFF5', '#2760FF'], color: ['#FFD160', '#12FFF5', '#2760FF'],
grid: { top: 32, right: 12, bottom: 20, left: 48 }, grid: { top: 32, right: 12, bottom: 56, left: 48 },
xAxis: { xAxis: {
type: 'category', type: 'category',
data: Array(7) data: Array(7)

View File

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

View File

@ -1,154 +1,205 @@
import cls from './index.module.css'; import cls from "./index.module.css";
import './overwrite.css'; // antd import "./overwrite.css"; // antd
import ReactECharts from 'echarts-for-react'; import ReactECharts from "echarts-for-react";
import * as echarts from 'echarts'; import * as echarts from "echarts";
import { Switch, Radio } from 'antd'; import { Switch, Radio } from "antd";
import { randomInt } from '../../../../../utils'; import { randomInt } from "../../../../../utils";
import { useEffect, useState } from "react";
import { useSelector } from "react-redux";
const GoodRateChart = (props) => { const GoodRateChart = (props) => {
const options = { //
color: ['#FFD160', '#12FFF5', '#2760FF'], const [showMore, setShowMore] = useState(false);
grid: { top: 28, right: 12, bottom: 32, left: 48 }, // key
xAxis: { const [updateKey, setUpdateKey] = useState(Date.now());
type: 'category', //
data: Array(7) const [dateType, setDateType] = useState("day");
.fill(1) const cutting = useSelector((state) => state.cutting);
.map((_, index) => {
const today = new Date();
const dtimestamp = today - index * 24 * 60 * 60 * 1000;
return `${new Date(dtimestamp).getMonth() + 1}.${new Date(
dtimestamp,
).getDate()}`;
})
.reverse(),
axisLabel: {
color: '#fff',
fontSize: 12,
},
axisTick: { show: false },
axisLine: {
lineStyle: {
width: 1,
color: '#213259',
},
},
},
yAxis: {
type: 'value',
axisLabel: {
color: '#fff',
fontSize: 12,
formatter: '{value} %',
},
axisLine: {
show: true,
lineStyle: {
color: '#213259',
},
},
splitLine: {
lineStyle: {
color: '#213259a0',
},
},
interval: 10,
min: 0,
max: 100,
},
series: [
{
data: Array(7)
.fill(1)
.map((_) => {
return randomInt(60, 100);
}),
type: 'line',
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#FFD16040' },
{ offset: 0.5, color: '#FFD16020' },
{ offset: 1, color: '#FFD16010' },
]),
},
// smooth: true,
},
{
data: Array(7)
.fill(1)
.map((_) => {
return randomInt(60, 100);
}),
type: 'line',
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#12FFF540' },
{ offset: 0.5, color: '#12FFF520' },
{ offset: 1, color: '#12FFF510' },
]),
},
// smooth: true,
},
{
data: Array(7)
.fill(1)
.map((_) => {
return randomInt(60, 100);
}),
type: 'line',
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#2760FF40' },
{ offset: 0.5, color: '#2760FF20' },
{ offset: 1, color: '#2760FF10' },
]),
},
// smooth: true,
},
],
tooltip: {
trigger: 'axis',
},
};
function handleSwitchChange(val) { console.log("cutting chart", dateType, cutting.chart[dateType]);
// val: boolean
}
return ( useEffect(() => {
<div className={cls.GoodRateChart}> setUpdateKey(Date.now());
<div className={cls.titleBar}> }, [showMore]);
<h2>生产良品率</h2>
<Switch defaultChecked onChange={handleSwitchChange} /> function handleSwitchChange(val) {
<div className={cls.legend}> // val: boolean
<span className="legend__title">班次详情</span> setShowMore(val);
<ul className="legend__list"> }
<li>总量</li>
<li>白班</li> function handleDateChange({ target }) {
<li>夜班</li> // e: Event
</ul> setDateType(target.value);
</div> }
<Radio.Group
defaultValue="week" // options
buttonStyle="solid" const options = getOptions(cutting.chart[dateType], showMore);
className={cls.radioGroup}
> return (
<Radio.Button value="day" className="radio-group__item"> <div className={cls.GoodRateChart}>
<div className={cls.titleBar}>
</Radio.Button> <h2>生产良品率</h2>
<Radio.Button value="week" className="radio-group__item"> <Switch defaultChecked={showMore} onChange={handleSwitchChange} />
<div className={cls.legend}>
</Radio.Button> <span className="legend__title">班次详情</span>
<Radio.Button value="month" className="radio-group__item"> <ul className="legend__list">
<li>总量</li>
</Radio.Button> {showMore && (
<Radio.Button value="year" className="radio-group__item"> <>
<li>白班</li>
</Radio.Button> <li>夜班</li>
</Radio.Group> </>
</div> )}
<ReactECharts option={options} /> </ul>
</div> </div>
); <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>
<ReactECharts key={updateKey} option={options} />
</div>
);
}; };
export default GoodRateChart; export default GoodRateChart;
function getOptions(dataList, showMore) {
console.log("showmore", showMore);
const list = [...dataList].sort((a, b) => a.dataTime - b.dataTime);
// 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(),
const color = ["#FFD160", "#12FFF5", "#2760FF"];
const grid = { top: 28, right: 12, bottom: 48, left: 48 };
const xAxis = {
type: "category",
data: list.map((item) => item.dataTime.split("T")[0]),
axisLabel: {
color: "#fff",
fontSize: 12,
rotate: 45,
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 = [
{
data: list.map((item) => item.day * 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: list.map((item) => item.night * 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,
},
];
return {
grid,
color,
xAxis,
yAxis,
tooltip: {
trigger: "axis",
formatter: "{b} {c}%",
},
series: [
{
data: list.map((item) => item.sum * 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,
},
...(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,
// },

View File

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

View File

@ -1,9 +1,16 @@
import { useState } from "react"; import { useState } from "react";
import cls from "./index.module.scss"; import cls from "./index.module.scss";
import { ScrollBoard } from "@jiaminghi/data-view-react"; import { ScrollBoard } from "@jiaminghi/data-view-react";
import { useSelector } from "react-redux";
function getRate(decimal) {
return (decimal.toFixed(2) * 100).toFixed(2) + "%";
}
const TodayTableData = (props) => { const TodayTableData = (props) => {
const [config, setConfig] = useState({ const cutting = useSelector((state) => state.cutting);
const config = {
// headerBGC: 'rgba(4, 44, 76, 0.3)', // headerBGC: 'rgba(4, 44, 76, 0.3)',
headerBGC: "rgba(4, 44, 76, .8)", headerBGC: "rgba(4, 44, 76, .8)",
header: [ header: [
@ -18,14 +25,21 @@ const TodayTableData = (props) => {
columnWidth: [90], columnWidth: [90],
headerHeight: 40, headerHeight: 40,
hoverPause: false, hoverPause: false,
data: [ data: cutting.table.map((line) => [
["Y61", "37%", "62%", "97%", "7%"], line.lineName,
["Y62", "95%", "10%", "99%", "3%"], getRate(line.first),
["Y63", "68%", "1%", "92%", "4%"], getRate(line.second),
["Y64", "94%", "21%", "97%", "2%"], getRate(line.product),
["Y65", "99%", "30%", "95%", "5%"], 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 ( return (
<div className={cls.todayTableData}> <div className={cls.todayTableData}>
<ScrollBoard config={config} style={{ width: "100%" }} /> <ScrollBoard config={config} style={{ width: "100%" }} />

View File

@ -60,6 +60,8 @@ body {
background: url(./assets/moxing.png) no-repeat; background: url(./assets/moxing.png) no-repeat;
background-position: 50% 50%; background-position: 50% 50%;
background-size: 170% 200%; background-size: 170% 200%;
position: relative;
z-index: -1;
} }
#FullScreen .Main .Center .Button { #FullScreen .Main .Center .Button {

View File

@ -49,7 +49,7 @@ export default function Home({ active }) {
<CenterTopData /> <CenterTopData />
</motion.div> </motion.div>
</AnimatePresence> </AnimatePresence>
<div key="v3d" className="V3DBorder"></div> <div key="v3d" className="V3DBorder" style={{ zIndex: -2 }}></div>
{fireDir && fireDir == "东火" && ( {fireDir && fireDir == "东火" && (
<video <video
@ -58,7 +58,12 @@ export default function Home({ active }) {
autoPlay autoPlay
loop loop
width={4200} width={4200}
style={{ position: "absolute", top: "-160px", left: "-910px" }} style={{
position: "absolute",
top: "-160px",
left: "-910px",
zIndex: -1,
}}
></video> ></video>
)} )}
@ -69,7 +74,12 @@ export default function Home({ active }) {
autoPlay autoPlay
loop loop
width={4200} width={4200}
style={{ position: "absolute", top: "-180px", left: "-910px" }} style={{
position: "absolute",
top: "-180px",
left: "-910px",
zIndex: -1,
}}
></video> ></video>
)} )}

View File

@ -0,0 +1,41 @@
import { createSlice } from "@reduxjs/toolkit";
export const initialState = {
table: [],
chart: {
year: [],
week: [],
month: [],
day: [],
},
};
const cuttingSlice = createSlice({
name: "cutting",
initialState,
reducers: {
setCuttingTable: (state, action) => {
console.log("setting cuttting table...");
state.table = action.payload;
},
setCuttingChart: (state, action) => {
switch (action.payload.dateType) {
case "year":
state.chart.year = action.payload.detData;
break;
case "weekly":
state.chart.week = action.payload.detData;
break;
case "month":
state.chart.month = action.payload.detData;
break;
case "day":
state.chart.day = action.payload.detData;
break;
}
},
},
});
export default cuttingSlice.reducer;
export const { setCuttingTable, setCuttingChart } = cuttingSlice.actions;

View File

@ -12,6 +12,7 @@ import energySlice from "./features/EnergySlice";
import israReducer from "./features/QualityIsraSlice"; import israReducer from "./features/QualityIsraSlice";
import annealFanFrequenceReducer from "./features/annealFanFrequenceSlice"; import annealFanFrequenceReducer from "./features/annealFanFrequenceSlice";
import annealFanInfoReducer from "./features/annealFanInfoSlice"; import annealFanInfoReducer from "./features/annealFanInfoSlice";
import cuttingReducer from "./features/cuttingSlice";
export const store = configureStore({ export const store = configureStore({
reducer: { reducer: {
@ -41,5 +42,7 @@ export const store = configureStore({
energy: energySlice, energy: energySlice,
// 能耗 // 能耗
isra: israReducer, isra: israReducer,
// 切割
cutting: cuttingReducer
}, },
}); });

View File

@ -255,3 +255,50 @@ new XClient(
} }
} }
); );
type TableDataType = {
name: "table";
type: "cutting";
data: any[];
};
type ChartDataType = {
name: "chart";
type: "cutting";
nightPushData: any[];
dayPushData: any[];
allPushData: any[];
dateType: "day" | "week" | "month" | "year";
};
// 良品率相关数据
new XClient(
// "ws://10.70.27.122:8080/websocket/message?userId=CUTTING",
"ws://10.70.2.2:8080/websocket/message?userId=CUTTING",
"CUTTING_DATA",
(msg) => {
let serializedData: TableDataType | ChartDataType | null = null;
try {
serializedData = JSON.parse(msg.data);
} catch (error) {
console.log("[*] websocket: [unable to serialize] ---> ", msg);
}
console.log("[CUTTING DATA] ---> ", serializedData);
if (serializedData == null) return;
switch (serializedData.name) {
case "table":
store.dispatch({
type: "cutting/setCuttingTable",
payload: serializedData.data,
});
break;
case "chart":
store.dispatch({
type: "cutting/setCuttingChart",
payload: serializedData,
});
break;
}
}
);