This commit is contained in:
朱菊兰 2024-08-27 10:48:46 +08:00
parent bbb7de918e
commit 2cb5c7fcd2
26 changed files with 1733 additions and 268 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

BIN
public/png/lp/line_part.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

View File

@ -0,0 +1,447 @@
import React, { useEffect, useRef, useState, useContext, useMemo } from "react";
import * as BABYLON from "@babylonjs/core";
import "@babylonjs/core/Debug/debugLayer";
import "@babylonjs/inspector";
import "@babylonjs/loaders/glTF";
import { GridMaterial } from "@babylonjs/materials/";
import {
Animatable,
HemisphericLight,
Mesh,
Observable,
Vector3,
} from "@babylonjs/core";
import { useAppSelector } from "../store/hooks";
import "../page/style/standard.css";
import { EquStatusInterface, selectEquStatus } from "../store/EquStatusEntity";
import EquMap from "./EquMap";
// const onEquObservable = new Observable();
const myStyle = {
width: "1041px",
height: "562px",
outline: "none",
};
interface MybabylonJSProps {
modelPath: string; // 明确 modelPath 属性的类型为 string
}
interface EqInfoListInterface {
[key: string]: EqInfo[];
}
interface EqInfo {
name: string;
inputNum: number;
outPut: number;
position: [number, number];
}
const eqInfoList: EqInfoListInterface = {
"Line1-1": [
{ name: "磨边机", inputNum: 100, outPut: 100, position: [134, 202] },
{ name: "磨边机", inputNum: 101, outPut: 101, position: [82, 306] },
{ name: "磨边机", inputNum: 105, outPut: 105, position: [342, 400] },
{ name: "打孔机", inputNum: 100, outPut: 100, position: [337, 51] },
{ name: "打孔机", inputNum: 101, outPut: 101, position: [338, 156] },
{ name: "打孔机", inputNum: 105, outPut: 105, position: [510, 310] },
{ name: "丝印机", inputNum: 100, outPut: 100, position: [521, 4] },
{ name: "丝印机", inputNum: 101, outPut: 101, position: [520, 90] },
{ name: "丝印机", inputNum: 105, outPut: 105, position: [672, 226] },
{ name: "一次固化", inputNum: 100, outPut: 100, position: [756, 2] },
{ name: "一次固化", inputNum: 101, outPut: 101, position: [833, 90] },
{ name: "一次固化", inputNum: 105, outPut: 105, position: [835, 186] },
],
"Line1-2": [
{ name: "退火", inputNum: 100, outPut: 100, position: [100, 210] },
{ name: "铺纸机", inputNum: 100, outPut: 100, position: [410, 58] },
{ name: "铺纸机", inputNum: 100, outPut: 100, position: [594, 252] },
{ name: "下片机", inputNum: 100, outPut: 100, position: [610, 5] },
{ name: "下片机", inputNum: 100, outPut: 100, position: [838, 1] },
{ name: "下片机", inputNum: 100, outPut: 100, position: [837, 145] },
],
"Line2-1": [
{ name: "磨边机", inputNum: 100, outPut: 100, position: [134, 202] },
{ name: "磨边机", inputNum: 105, outPut: 105, position: [342, 400] },
{ name: "打孔机", inputNum: 101, outPut: 101, position: [338, 156] },
{ name: "打孔机", inputNum: 105, outPut: 105, position: [510, 310] },
{ name: "丝印机", inputNum: 101, outPut: 101, position: [520, 90] },
{ name: "丝印机", inputNum: 105, outPut: 105, position: [672, 226] },
{ name: "一次固化", inputNum: 100, outPut: 100, position: [724, 38] },
{ name: "一次固化", inputNum: 105, outPut: 105, position: [835, 186] },
],
"Line2-2": [
{ name: "退火", inputNum: 100, outPut: 100, position: [215, 247] },
{ name: "铺纸机", inputNum: 100, outPut: 100, position: [710, 237] },
{ name: "下片机", inputNum: 100, outPut: 100, position: [502, 58] },
{ name: "下片机", inputNum: 100, outPut: 100, position: [733, 3] },
],
"Line3-1": [
{ name: "磨边机", inputNum: 100, outPut: 100, position: [134, 202] },
{ name: "磨边机", inputNum: 105, outPut: 105, position: [342, 400] },
{ name: "打孔机", inputNum: 101, outPut: 101, position: [338, 156] },
{ name: "打孔机", inputNum: 105, outPut: 105, position: [510, 310] },
{ name: "丝印机", inputNum: 101, outPut: 101, position: [520, 90] },
{ name: "丝印机", inputNum: 105, outPut: 105, position: [672, 226] },
{ name: "一次固化", inputNum: 100, outPut: 100, position: [724, 38] },
{ name: "一次固化", inputNum: 105, outPut: 105, position: [835, 186] },
],
"Line3-2": [
{ name: "退火", inputNum: 100, outPut: 100, position: [187, 247] },
{ name: "铺纸机", inputNum: 100, outPut: 100, position: [502, 58] },
{ name: "下片机", inputNum: 100, outPut: 100, position: [733, 3] },
{ name: "下片机", inputNum: 100, outPut: 100, position: [710, 237] },
],
"Line4-1": [
{ name: "磨边机", inputNum: 100, outPut: 100, position: [231, 216] },
{ name: "磨边机", inputNum: 105, outPut: 105, position: [403, 400] },
{ name: "一次固化", inputNum: 101, outPut: 101, position: [520, 90] },
{ name: "一次固化", inputNum: 105, outPut: 105, position: [643, 276] },
{ name: "二次固化", inputNum: 100, outPut: 100, position: [724, 38] },
{ name: "二次固化", inputNum: 105, outPut: 105, position: [835, 186] },
],
"Line4-2": [
{ name: "退火", inputNum: 100, outPut: 100, position: [187, 247] },
{ name: "铺纸机", inputNum: 100, outPut: 100, position: [710, 237] },
{ name: "铺纸机", inputNum: 100, outPut: 100, position: [820, 237] },
{ name: "下片机", inputNum: 100, outPut: 100, position: [553, 7] },
{ name: "下片机", inputNum: 100, outPut: 100, position: [839, 137] },
],
"Line5-1": [
{ name: "磨边机", inputNum: 100, outPut: 100, position: [134, 202] },
{ name: "磨边机", inputNum: 101, outPut: 101, position: [82, 306] },
{ name: "磨边机", inputNum: 105, outPut: 105, position: [342, 400] },
{ name: "一次固化", inputNum: 100, outPut: 100, position: [521, 4] },
{ name: "一次固化", inputNum: 101, outPut: 101, position: [520, 90] },
{ name: "一次固化", inputNum: 105, outPut: 105, position: [672, 287] },
{ name: "二次固化", inputNum: 100, outPut: 100, position: [756, 2] },
{ name: "二次固化", inputNum: 101, outPut: 101, position: [833, 90] },
{ name: "二次固化", inputNum: 105, outPut: 105, position: [835, 186] },
],
"Line5-2": [
{ name: "退火", inputNum: 100, outPut: 100, position: [100, 270] },
{ name: "铺纸机", inputNum: 100, outPut: 100, position: [434, 133] },
{ name: "铺纸机", inputNum: 100, outPut: 100, position: [640, 305] },
{ name: "下片机", inputNum: 100, outPut: 100, position: [645, 54] },
{ name: "下片机", inputNum: 100, outPut: 100, position: [838, 1] },
{ name: "下片机", inputNum: 100, outPut: 100, position: [837, 226] },
],
};
function MybabylonJS({ modelPath }: MybabylonJSProps) {
console.log("modelPath:;;;;;;", modelPath);
// const EquStatus = useAppSelector(selectEquStatus);
const canvasRef = useRef(null);
// onEquObservable.notifyObservers(EquStatus);
const [SelectedMeshName, setSelectedMeshName] = useState<string | null>(null);
// 使用 useRef 来存储当前加载的模型引用
const currentMeshesRef = useRef<Array<BABYLON.AbstractMesh>>([]);
useEffect(() => {
// 确保 canvas 引用存在
if (!canvasRef.current) return;
const canvas = canvasRef.current;
const engine = new BABYLON.Engine(canvas, true, {
preserveDrawingBuffer: true,
stencil: true,
});
const createScene = async function () {
// This creates a basic Babylon Scene object (non-mesh)
const scene = new BABYLON.Scene(engine);
scene.clearColor = new BABYLON.Color4(0, 0, 0, 0);
const baseLight = new HemisphericLight(
"hemiLight",
new Vector3(-1, 1, 0),
scene
);
baseLight.intensity = 1;
baseLight.diffuse = new BABYLON.Color3(1, 1, 1);
baseLight.specular = new BABYLON.Color3(0.25, 0.25, 0.25);
baseLight.groundColor = new BABYLON.Color3(0.5, 0.5, 0.5);
//add an arcRotateCamera to the scene
const camera = new BABYLON.ArcRotateCamera(
"camera",
BABYLON.Tools.ToRadians(245),
BABYLON.Tools.ToRadians(25),
modelPath.slice(-1) === "1"
? 110
: modelPath.slice(-3) === "5-2"
? 100
: 75,
new BABYLON.Vector3(-13, 0, 0)
);
console.log("camera", camera);
camera.lowerRadiusLimit = 10;
camera.upperRadiusLimit = 600;
// This attaches the camera to the canvas
camera.attachControl(canvas, true);
//创建一个材质
const newMt = new BABYLON.StandardMaterial("newMt");
newMt.diffuseColor = BABYLON.Color3.Blue();
const ground = BABYLON.MeshBuilder.CreateGround(
"ground",
{
width: 1000,
height: 1000,
subdivisions: 1,
},
scene
);
ground.scaling.x = 100;
ground.scaling.z = ground.scaling.x;
ground.isPickable = false;
let grid = new GridMaterial("grid", scene);
grid.majorUnitFrequency = 10;
grid.minorUnitVisibility = 0.3;
grid.gridRatio = 0.04;
grid.backFaceCulling = !1;
grid.mainColor = new BABYLON.Color3(1, 1, 1);
grid.lineColor = new BABYLON.Color3(1, 1, 1);
grid.opacity = 0;
grid.zOffset = 1;
grid.opacityTexture = new BABYLON.Texture(
"/public/png/backgroundGround.png",
scene
);
ground.material = grid;
let hl = new BABYLON.HighlightLayer("hl1", scene);
let hl2 = new BABYLON.HighlightLayer("hl2", scene);
// 定义一个函数来加载或重新加载模型
const loadOrReloadModel = async () => {
// 在加载新模型之前卸载已加载的模型
currentMeshesRef.current.forEach((mesh) => {
if (mesh && mesh.parent) {
scene.removeMesh(mesh, true);
}
});
currentMeshesRef.current = []; // 重置模型数组
try {
// 使用 ImportMeshAsync 加载新模型
var LOD0MESH = await BABYLON.SceneLoader.ImportMeshAsync(
"",
"/Line/",
`${modelPath}.babylon`,
scene
);
// 将新加载的模型添加到 currentMeshesRef 中
currentMeshesRef.current.push(...LOD0MESH.meshes);
// ...为新加载的模型设置交互逻辑
LOD0MESH.meshes.map((mesh) => {
mesh.isPickable = true;
mesh.actionManager = new BABYLON.ActionManager(scene);
// console.log("mesh==========", mesh);
if (modelPath.slice(-1) === "1") {
if (
mesh.name.includes("磨边机") ||
mesh.name.includes("打孔机") ||
mesh.name.includes("丝印机") ||
mesh.name.includes("固化")
) {
// @ts-ignore
hl.addMesh(mesh, BABYLON.Color3.Green());
}
} else {
if (
mesh.name.includes("钢化") ||
mesh.name.includes("铺纸机") ||
mesh.name.includes("下片机械手")
) {
// @ts-ignore
hl.addMesh(mesh, BABYLON.Color3.Green());
}
}
//鼠标移动到物体上亮显
// mesh.actionManager.registerAction(
// new BABYLON.ExecuteCodeAction(
// BABYLON.ActionManager.OnPointerOverTrigger,
// (a) => {
// console.log("================", a);
// // @ts-ignore
// hl.addMesh(mesh, BABYLON.Color3.Green());
// }
// )
// );
// 鼠标移出物体上不亮
// mesh.actionManager.registerAction(
// new BABYLON.ExecuteCodeAction(
// BABYLON.ActionManager.OnPointerOutTrigger,
// () => {
// // @ts-ignore
// hl.removeMesh(mesh);
// }
// )
// );
mesh._scene.onPointerDown = async (event, _pickResult) => {
const pickInfo = mesh._scene.pick(
mesh._scene.pointerX,
mesh._scene.pointerY
);
const clickedPosition = _pickResult.pickedPoint;
//如果需要获取吗模型根节点,而不是模型中某个组件,请用一下方法
// getRootNode(pickInfo.pickedMesh as BABYLON.Node) 如上篇文章getRootNode函数
//判断是否是右键
if (!(event.buttons === 1 && pickInfo.pickedMesh)) return;
const MeshName1 = pickInfo.pickedMesh.name.split(".")[0];
setSelectedMeshName(MeshName1);
};
});
// onEquObservable.add((eventData, eventState) => {
// LOD0MESH.meshes.find((mesh) => {
// // @ts-ignore
// hl2.removeMesh(mesh);
// });
// Object.keys(eventData as EquStatusInterface).map((key) => {
// // @ts-ignore
// if (eventData[key] == 2) {
// // @ts-ignore
// EquMap[key].map((name) => {
// LOD0MESH.meshes.find((mesh) => {
// if (mesh.name == name) {
// // @ts-ignore
// hl2.addMesh(mesh, BABYLON.Color3.Red());
// }
// });
// });
// }
// });
// });
} catch (error) {
console.error("加载模型失败:", error);
}
};
// 调用函数以加载或重新加载模型
loadOrReloadModel();
function reset() {
camera.target = new BABYLON.Vector3(-13, 0, 0);
camera.alpha = BABYLON.Tools.ToRadians(245);
camera.beta = BABYLON.Tools.ToRadians(25);
camera.radius =
modelPath.slice(-1) === "1"
? 110
: modelPath.slice(-3) === "5-2"
? 100
: 75;
}
let resetCamera = setTimeout(reset, 15000);
scene.onPointerObservable.add((pointerInfo) => {
switch (pointerInfo.type) {
case BABYLON.PointerEventTypes.POINTERMOVE:
clearTimeout(resetCamera);
resetCamera = setTimeout(reset, 15000);
}
});
return scene;
};
// call the createScene function
const scene = createScene();
scene.then((scene) => {});
// run the render loop
scene.then(
(scene) => {
engine.runRenderLoop(function () {
scene.render();
});
},
(reason) => {
console.log(reason);
}
);
// Resize
window.addEventListener("resize", function () {
engine.resize();
});
// 组件卸载时的清理逻辑
// return () => {
// // 清理场景和引擎资源
// engine.dispose();
// };
}, [modelPath]);
const resetModel = () => {
//模型初始位置
console.log("回到初始位置");
};
return (
<div style={myStyle}>
<h2 className="model_name">: {SelectedMeshName}</h2>
<div className="model_info">
<span className="reset_btn" onClick={resetModel}></span>
<span className="title">线</span>
</div>
{/* <div className="eq_detail_info">
<div>
<span className="left_name"></span>
<span className="right_value"></span>
</div>
<div>
<span className="left_name"></span>
<span className="right_value">12,302</span>
</div>
<div>
<span className="left_name"></span>
<span className="right_value">1,302</span>
</div>
<div>
<span className="left_name"></span>
<span className="right_value"></span>
</div>
<div>
<span className="left_name">线</span>
<span className="right_value">线</span>
</div>
</div> */}
{eqInfoList[modelPath] &&
eqInfoList[modelPath].map((item, index) => {
return (
<div
className="eq_info"
key={index}
style={{ left: item.position[0], top: item.position[1] }}
>
<div>
<span className="left_name"></span>
<span className="right_value">{item.name}</span>
</div>
<div>
<span className="left_name"></span>
<span className="right_value">{item.inputNum}</span>
</div>
<div>
<span className="left_name"></span>
<span className="right_value">{item.outPut}</span>
</div>
</div>
);
})}
<canvas ref={canvasRef} style={myStyle} />
</div>
);
}
export default MybabylonJS;

View File

@ -15,31 +15,282 @@ import { useAppSelector } from "../store/hooks";
import "../page/style/standard.css"; import "../page/style/standard.css";
import { EquStatusInterface, selectEquStatus } from "../store/EquStatusEntity"; import { EquStatusInterface, selectEquStatus } from "../store/EquStatusEntity";
import EquMap from "./EquMap"; import EquMap from "./EquMap";
import AlarmTipGreen from "./../page/LinePage/assets/icon/g.png";
import AlarmTipYellow from "./../page/LinePage/assets/icon/y.png";
import AlarmTipRed from "./../page/LinePage/assets/icon/r.png";
const onEquObservable = new Observable(); // const onEquObservable = new Observable();
const myStyle = { const myStyle = {
width: "1041px", width: "1041px",
height: "562px", height: "562px",
outline: "none", outline: "none",
}; };
interface MybabylonJSProps { interface MybabylonJSProps {
modelPath: string; // 明确 modelPath 属性的类型为 string modelPath: string; // 明确 modelPath 属性的类型为 string
} }
interface EqInfoListInterface {
[key: string]: EqInfo[];
}
interface EqInfo {
name: string;
inputNum: number;
outPut: number;
position: [number, number];
}
const eqInfoList: EqInfoListInterface = {
"Line1-1": [
{ name: "磨边机", inputNum: 100, outPut: 100, position: [134, 202] },
{ name: "磨边机", inputNum: 101, outPut: 101, position: [82, 306] },
{ name: "磨边机", inputNum: 105, outPut: 105, position: [342, 400] },
{ name: "打孔机", inputNum: 100, outPut: 100, position: [337, 51] },
{ name: "打孔机", inputNum: 101, outPut: 101, position: [338, 156] },
{ name: "打孔机", inputNum: 105, outPut: 105, position: [510, 310] },
{ name: "丝印机", inputNum: 100, outPut: 100, position: [521, 4] },
{ name: "丝印机", inputNum: 101, outPut: 101, position: [520, 90] },
{ name: "丝印机", inputNum: 105, outPut: 105, position: [672, 226] },
{ name: "一次固化", inputNum: 100, outPut: 100, position: [756, 2] },
{ name: "一次固化", inputNum: 101, outPut: 101, position: [833, 90] },
{ name: "一次固化", inputNum: 105, outPut: 105, position: [835, 186] },
],
"Line1-2": [
{ name: "退火", inputNum: 100, outPut: 100, position: [100, 210] },
{ name: "铺纸机", inputNum: 100, outPut: 100, position: [410, 58] },
{ name: "铺纸机", inputNum: 100, outPut: 100, position: [594, 252] },
{ name: "下片机", inputNum: 100, outPut: 100, position: [610, 5] },
{ name: "下片机", inputNum: 100, outPut: 100, position: [838, 1] },
{ name: "下片机", inputNum: 100, outPut: 100, position: [837, 145] },
],
"Line2-1": [
{ name: "磨边机", inputNum: 100, outPut: 100, position: [134, 202] },
{ name: "磨边机", inputNum: 105, outPut: 105, position: [342, 400] },
{ name: "打孔机", inputNum: 101, outPut: 101, position: [338, 156] },
{ name: "打孔机", inputNum: 105, outPut: 105, position: [510, 310] },
{ name: "丝印机", inputNum: 101, outPut: 101, position: [520, 90] },
{ name: "丝印机", inputNum: 105, outPut: 105, position: [672, 226] },
{ name: "一次固化", inputNum: 100, outPut: 100, position: [724, 38] },
{ name: "一次固化", inputNum: 105, outPut: 105, position: [835, 186] },
],
"Line2-2": [
{ name: "退火", inputNum: 100, outPut: 100, position: [215, 247] },
{ name: "铺纸机", inputNum: 100, outPut: 100, position: [710, 237] },
{ name: "下片机", inputNum: 100, outPut: 100, position: [502, 58] },
{ name: "下片机", inputNum: 100, outPut: 100, position: [733, 3] },
],
"Line3-1": [
{ name: "磨边机", inputNum: 100, outPut: 100, position: [134, 202] },
{ name: "磨边机", inputNum: 105, outPut: 105, position: [342, 400] },
{ name: "打孔机", inputNum: 101, outPut: 101, position: [338, 156] },
{ name: "打孔机", inputNum: 105, outPut: 105, position: [510, 310] },
{ name: "丝印机", inputNum: 101, outPut: 101, position: [520, 90] },
{ name: "丝印机", inputNum: 105, outPut: 105, position: [672, 226] },
{ name: "一次固化", inputNum: 100, outPut: 100, position: [724, 38] },
{ name: "一次固化", inputNum: 105, outPut: 105, position: [835, 186] },
],
"Line3-2": [
{ name: "退火", inputNum: 100, outPut: 100, position: [187, 247] },
{ name: "铺纸机", inputNum: 100, outPut: 100, position: [502, 58] },
{ name: "下片机", inputNum: 100, outPut: 100, position: [733, 3] },
{ name: "下片机", inputNum: 100, outPut: 100, position: [710, 237] },
],
"Line4-1": [
{ name: "磨边机", inputNum: 100, outPut: 100, position: [231, 216] },
{ name: "磨边机", inputNum: 105, outPut: 105, position: [403, 400] },
{ name: "一次固化", inputNum: 101, outPut: 101, position: [520, 90] },
{ name: "一次固化", inputNum: 105, outPut: 105, position: [643, 276] },
{ name: "二次固化", inputNum: 100, outPut: 100, position: [724, 38] },
{ name: "二次固化", inputNum: 105, outPut: 105, position: [835, 186] },
],
"Line4-2": [
{ name: "退火", inputNum: 100, outPut: 100, position: [187, 247] },
{ name: "铺纸机", inputNum: 100, outPut: 100, position: [710, 237] },
{ name: "铺纸机", inputNum: 100, outPut: 100, position: [820, 237] },
{ name: "下片机", inputNum: 100, outPut: 100, position: [553, 7] },
{ name: "下片机", inputNum: 100, outPut: 100, position: [839, 137] },
],
"Line5-1": [
{ name: "磨边机", inputNum: 100, outPut: 100, position: [134, 202] },
{ name: "磨边机", inputNum: 101, outPut: 101, position: [82, 306] },
{ name: "磨边机", inputNum: 105, outPut: 105, position: [342, 400] },
{ name: "一次固化", inputNum: 100, outPut: 100, position: [521, 4] },
{ name: "一次固化", inputNum: 101, outPut: 101, position: [520, 90] },
{ name: "一次固化", inputNum: 105, outPut: 105, position: [672, 287] },
{ name: "二次固化", inputNum: 100, outPut: 100, position: [756, 2] },
{ name: "二次固化", inputNum: 101, outPut: 101, position: [833, 90] },
{ name: "二次固化", inputNum: 105, outPut: 105, position: [835, 186] },
],
"Line5-2": [
{ name: "退火", inputNum: 100, outPut: 100, position: [100, 270] },
{ name: "铺纸机", inputNum: 100, outPut: 100, position: [434, 133] },
{ name: "铺纸机", inputNum: 100, outPut: 100, position: [640, 305] },
{ name: "下片机", inputNum: 100, outPut: 100, position: [645, 54] },
{ name: "下片机", inputNum: 100, outPut: 100, position: [838, 1] },
{ name: "下片机", inputNum: 100, outPut: 100, position: [837, 226] },
],
};
interface EqInfoInterface {
name: string;
data: Array<{ name: string; value: number }>;
position: Array<number>;
}
interface EqInfoDataInterface {
[key: string]: Array<EqInfoInterface>;
}
const eqInfoData: EqInfoDataInterface = {
"Line5-1": [
{
name: "磨边进口",
data: [
{ name: "1支线", value: 413 },
{ name: "2支线", value: 435 },
{ name: "3支线", value: 397 },
],
position: [154, 266],
},
{
name: "磨边清洗出口",
data: [
{ name: "1支线", value: 401 },
{ name: "2支线", value: 418 },
{ name: "3支线", value: 389 },
],
position: [331, 177],
},
{
name: "一次镀膜进口",
data: [
{ name: "1支线", value: 400 },
{ name: "2支线", value: 418 },
{ name: "3支线", value: 388 },
],
position: [555, 329],
},
{
name: "二次镀膜进口",
data: [
{ name: "1支线", value: 387 },
{ name: "2支线", value: 399 },
{ name: "3支线", value: 381 },
],
position: [550, 85],
},
{
name: "二次固化出口",
data: [
{ name: "1支线", value: 384 },
{ name: "2支线", value: 398 },
{ name: "3支线", value: 377 },
],
position: [857, 184],
},
{
name: "钢化进口",
data: [{ name: "钢化进口", value: 1157 }],
position: [870, 48],
},
],
"Line5-2": [
{
name: "钢化出口",
data: [{ name: "钢化出口", value: 1124 }],
position: [305, 255],
},
{
name: "包装清洗机入口",
data: [
{ name: "包装清洗机5_1", value: 515 },
{ name: "包装清洗机5_2", value: 507 },
],
position: [508, 319],
},
{
name: "包装清洗机出口",
data: [
{ name: "包装清洗机5_1", value: 515 },
{ name: "包装清洗机5_2", value: 505 },
],
position: [444, 159],
},
{
name: "铺纸机",
data: [
{ name: "铺纸机5_1", value: 509 },
{ name: "铺纸机5_2", value: 504 },
],
position: [696, 272],
},
{
name: "下片机械手",
data: [
{ name: "下片机械手5_1", value: 347 },
{ name: "下片机械手5_2", value: 334 },
{ name: "下片机械手5_3", value: 316 },
],
position: [712, 28],
},
],
};
interface EqStatusListInterface {
[key: string]: Array<{
equipment: string;
alarm: boolean;
online: boolean;
}>;
}
const eqStatusList: EqStatusListInterface = {
"Line5-1": [
{ equipment: "磨边机5_1", alarm: false, online: true },
{ equipment: "磨边机5_2", alarm: false, online: true },
{ equipment: "磨边机5_3", alarm: false, online: true },
{ equipment: "清洗机5_1", alarm: false, online: true },
{ equipment: "清洗机5_2", alarm: false, online: true },
{ equipment: "清洗机5_3", alarm: false, online: true },
{ equipment: "一次镀膜5_2", alarm: false, online: true },
{ equipment: "一次镀膜5_3", alarm: false, online: true },
{ equipment: "一次固化5_1", alarm: false, online: true },
{ equipment: "一次镀膜5_1", alarm: false, online: true },
{ equipment: "一次固化5_2", alarm: false, online: true },
{ equipment: "一次固化5_3", alarm: false, online: true },
{ equipment: "二次镀膜5_1", alarm: false, online: true },
{ equipment: "二次镀膜5_2", alarm: false, online: true },
{ equipment: "二次镀膜5_3", alarm: false, online: true },
{ equipment: "二次固化5_1", alarm: false, online: true },
{ equipment: "二次固化5_2", alarm: false, online: true },
{ equipment: "二次固化5_3", alarm: false, online: true },
],
"Line5-2": [
{ equipment: "钢化炉5", alarm: false, online: true },
{ equipment: "包装清洗机5_1", alarm: false, online: true },
{ equipment: "包装清洗机5_2", alarm: false, online: true },
{ equipment: "在线铺纸机5_1", alarm: false, online: true },
{ equipment: "在线铺纸机5_2", alarm: false, online: true },
{ equipment: "下片机械手5_1", alarm: false, online: true },
{ equipment: "下片机械手5_2", alarm: false, online: true },
{ equipment: "下片机械手5_3", alarm: false, online: true },
],
};
function MybabylonJS({ modelPath }: MybabylonJSProps) { function MybabylonJS({ modelPath }: MybabylonJSProps) {
const EquStatus = useAppSelector(selectEquStatus); console.log("modelPath:;;;;;;", modelPath);
// const EquStatus = useAppSelector(selectEquStatus);
const canvasRef = useRef(null); const canvasRef = useRef(null);
onEquObservable.notifyObservers(EquStatus); const resetRef = useRef<(() => void) | null>(null);
const [SelectedMeshName, setSelectedMeshName] = useState<string | null>(null); // onEquObservable.notifyObservers(EquStatus);
const [selectedMeshName, setSelectedMeshName] = useState<string | null>(null);
const [selectedMeshObj, setSelectedMeshObj] = useState({
equipment: "",
alarm: false,
online: true,
});
const [showInfo, setShowInfo] = useState(true);
// 使用 useRef 来存储当前加载的模型引用 // 使用 useRef 来存储当前加载的模型引用
const currentMeshesRef = useRef<Array<BABYLON.AbstractMesh>>([]); const currentMeshesRef = useRef<Array<BABYLON.AbstractMesh>>([]);
useEffect(() => { useEffect(() => {
console.log("canvasRef++++++", canvasRef);
console.log("resetRef++++++", resetRef);
// 确保 canvas 引用存在 // 确保 canvas 引用存在
if (!canvasRef.current) return; if (!canvasRef.current) return;
const canvas = canvasRef.current; const canvas = canvasRef.current;
const engine = new BABYLON.Engine(canvas, true, { const engine = new BABYLON.Engine(canvas, true, {
preserveDrawingBuffer: true, preserveDrawingBuffer: true,
@ -50,7 +301,6 @@ function MybabylonJS({ modelPath }: MybabylonJSProps) {
// This creates a basic Babylon Scene object (non-mesh) // This creates a basic Babylon Scene object (non-mesh)
const scene = new BABYLON.Scene(engine); const scene = new BABYLON.Scene(engine);
scene.clearColor = new BABYLON.Color4(0, 0, 0, 0); scene.clearColor = new BABYLON.Color4(0, 0, 0, 0);
const baseLight = new HemisphericLight( const baseLight = new HemisphericLight(
"hemiLight", "hemiLight",
new Vector3(-1, 1, 0), new Vector3(-1, 1, 0),
@ -70,10 +320,9 @@ function MybabylonJS({ modelPath }: MybabylonJSProps) {
? 110 ? 110
: modelPath.slice(-3) === "5-2" : modelPath.slice(-3) === "5-2"
? 100 ? 100
: 80, : 75,
new BABYLON.Vector3(-13, 0, 0) new BABYLON.Vector3(-13, 0, 0)
); );
console.log("camera", camera);
camera.lowerRadiusLimit = 10; camera.lowerRadiusLimit = 10;
camera.upperRadiusLimit = 600; camera.upperRadiusLimit = 600;
@ -106,7 +355,7 @@ function MybabylonJS({ modelPath }: MybabylonJSProps) {
grid.backFaceCulling = !1; grid.backFaceCulling = !1;
grid.mainColor = new BABYLON.Color3(1, 1, 1); grid.mainColor = new BABYLON.Color3(1, 1, 1);
grid.lineColor = new BABYLON.Color3(1, 1, 1); grid.lineColor = new BABYLON.Color3(1, 1, 1);
grid.opacity = 0.8; grid.opacity = 0;
grid.zOffset = 1; grid.zOffset = 1;
grid.opacityTexture = new BABYLON.Texture( grid.opacityTexture = new BABYLON.Texture(
"/public/png/backgroundGround.png", "/public/png/backgroundGround.png",
@ -142,25 +391,50 @@ function MybabylonJS({ modelPath }: MybabylonJSProps) {
LOD0MESH.meshes.map((mesh) => { LOD0MESH.meshes.map((mesh) => {
mesh.isPickable = true; mesh.isPickable = true;
mesh.actionManager = new BABYLON.ActionManager(scene); mesh.actionManager = new BABYLON.ActionManager(scene);
//鼠标移动到物体上亮显 // console.log("mesh==========", mesh);
mesh.actionManager.registerAction( if (modelPath.slice(-1) === "1") {
new BABYLON.ExecuteCodeAction( if (
BABYLON.ActionManager.OnPointerOverTrigger, mesh.name.includes("磨边") ||
() => { mesh.name.includes("清洗") ||
mesh.name.includes("镀膜") ||
mesh.name.includes("固化")
) {
// @ts-ignore // @ts-ignore
hl.addMesh(mesh, BABYLON.Color3.Green()); hl.addMesh(mesh, BABYLON.Color3.Green());
} }
) } else {
); if (
mesh.actionManager.registerAction( mesh.name.includes("钢化") ||
new BABYLON.ExecuteCodeAction( mesh.name.includes("包装") ||
BABYLON.ActionManager.OnPointerOutTrigger, mesh.name.includes("铺纸") ||
() => { mesh.name.includes("下片机械手")
) {
// @ts-ignore // @ts-ignore
hl.removeMesh(mesh); hl.addMesh(mesh, BABYLON.Color3.Green());
} }
) }
);
//鼠标移动到物体上亮显
// mesh.actionManager.registerAction(
// new BABYLON.ExecuteCodeAction(
// BABYLON.ActionManager.OnPointerOverTrigger,
// (a) => {
// console.log("================", a);
// // @ts-ignore
// hl.addMesh(mesh, BABYLON.Color3.Green());
// }
// )
// );
// 鼠标移出物体上不亮
// mesh.actionManager.registerAction(
// new BABYLON.ExecuteCodeAction(
// BABYLON.ActionManager.OnPointerOutTrigger,
// () => {
// // @ts-ignore
// hl.removeMesh(mesh);
// }
// )
// );
mesh._scene.onPointerDown = async (event, _pickResult) => { mesh._scene.onPointerDown = async (event, _pickResult) => {
const pickInfo = mesh._scene.pick( const pickInfo = mesh._scene.pick(
@ -177,29 +451,34 @@ function MybabylonJS({ modelPath }: MybabylonJSProps) {
const MeshName1 = pickInfo.pickedMesh.name.split(".")[0]; const MeshName1 = pickInfo.pickedMesh.name.split(".")[0];
setSelectedMeshName(MeshName1); setSelectedMeshName(MeshName1);
eqStatusList[modelPath].map((item: any) => {
if (item.equipment === MeshName1) {
setSelectedMeshObj(item);
}
});
}; };
}); });
onEquObservable.add((eventData, eventState) => { // onEquObservable.add((eventData, eventState) => {
LOD0MESH.meshes.find((mesh) => { // LOD0MESH.meshes.find((mesh) => {
// @ts-ignore // // @ts-ignore
hl2.removeMesh(mesh); // hl2.removeMesh(mesh);
}); // });
Object.keys(eventData as EquStatusInterface).map((key) => { // Object.keys(eventData as EquStatusInterface).map((key) => {
// @ts-ignore // // @ts-ignore
if (eventData[key] == 2) { // if (eventData[key] == 2) {
// @ts-ignore // // @ts-ignore
EquMap[key].map((name) => { // EquMap[key].map((name) => {
LOD0MESH.meshes.find((mesh) => { // LOD0MESH.meshes.find((mesh) => {
if (mesh.name == name) { // if (mesh.name == name) {
// @ts-ignore // // @ts-ignore
hl2.addMesh(mesh, BABYLON.Color3.Red()); // hl2.addMesh(mesh, BABYLON.Color3.Red());
} // }
}); // });
}); // });
} // }
}); // });
}); // });
} catch (error) { } catch (error) {
console.error("加载模型失败:", error); console.error("加载模型失败:", error);
} }
@ -217,8 +496,12 @@ function MybabylonJS({ modelPath }: MybabylonJSProps) {
? 110 ? 110
: modelPath.slice(-3) === "5-2" : modelPath.slice(-3) === "5-2"
? 100 ? 100
: 80; : 75;
setShowInfo(true);
setSelectedMeshName(null);
} }
// 外部初始位置按钮
resetRef.current = reset;
let resetCamera = setTimeout(reset, 15000); let resetCamera = setTimeout(reset, 15000);
scene.onPointerObservable.add((pointerInfo) => { scene.onPointerObservable.add((pointerInfo) => {
@ -226,6 +509,7 @@ function MybabylonJS({ modelPath }: MybabylonJSProps) {
case BABYLON.PointerEventTypes.POINTERMOVE: case BABYLON.PointerEventTypes.POINTERMOVE:
clearTimeout(resetCamera); clearTimeout(resetCamera);
resetCamera = setTimeout(reset, 15000); resetCamera = setTimeout(reset, 15000);
setShowInfo(false);
} }
}); });
return scene; return scene;
@ -234,17 +518,16 @@ function MybabylonJS({ modelPath }: MybabylonJSProps) {
// call the createScene function // call the createScene function
const scene = createScene(); const scene = createScene();
scene.then((scene) => {});
// run the render loop // run the render loop
scene.then( scene.then(
(scene) => { (scene) => {
console.log("createScene被调用了=====", scene);
engine.runRenderLoop(function () { engine.runRenderLoop(function () {
scene.render(); scene.render();
}); });
}, },
(reason) => { (reason) => {
console.log(reason); console.log("reason=============", reason);
} }
); );
@ -252,16 +535,107 @@ function MybabylonJS({ modelPath }: MybabylonJSProps) {
window.addEventListener("resize", function () { window.addEventListener("resize", function () {
engine.resize(); engine.resize();
}); });
// 组件卸载时的清理逻辑 // 组件卸载时的清理逻辑
return () => { return () => {
// 清理场景和引擎资源 // 清理场景和引擎资源
engine.dispose(); engine.dispose();
}; };
}, [modelPath]); }, [modelPath]);
const resetModel = () => {
//模型初始位置
console.log("回到初始位置");
if (resetRef.current) {
resetRef.current();
}
};
return ( return (
<div style={myStyle}> <div style={myStyle}>
{/* <h2 className="model_name">当前选择: {selectedMeshName}</h2> */}
<div className="model_info">
<span className="reset_btn" onClick={resetModel}></span>
<span className="title">线</span>
</div>
{selectedMeshName && (
<div className="eq_detail_info">
<div>
<span className="left_name"></span>
<span className="right_value">{selectedMeshObj.equipment}</span>
</div>
<div>
<span className="left_name"></span>
<span className="right_value">
{selectedMeshObj.alarm ? (
<>
<img
src={AlarmTipRed}
alt=""
width={17}
style={{ position: "relative", top: "2px", marginRight: 5 }}
/>
<span></span>
</>
) : (
<>
<img
src={AlarmTipGreen}
alt=""
width={17}
style={{ position: "relative", top: "2px", marginRight: 5 }}
/>
<span></span>
</>
)}
</span>
</div>
<div>
<span className="left_name">线</span>
<span className="right_value">
{selectedMeshObj.online ? (
<>
<img
src={AlarmTipGreen}
alt=""
width={17}
style={{ position: "relative", top: "2px", marginRight: 5 }}
/>
<span>线</span>
</>
) : (
<>
<img
src={AlarmTipYellow}
alt=""
width={17}
style={{ position: "relative", top: "2px", marginRight: 5 }}
/>
<span>线</span>
</>
)}
</span>
</div>
</div>
)}
{showInfo &&
eqInfoData[modelPath] &&
eqInfoData[modelPath].map((item, index) => {
return (
<div
className="eq_info"
key={index}
style={{ left: item.position[0], top: item.position[1] }}
>
<div className="eq_info_inner">{item.name}</div>
{item.data.map((info, index) => {
return (
<div className="eq_info_inner">
{info.name}{info.value}
</div>
);
})}
</div>
);
})}
<canvas ref={canvasRef} style={myStyle} /> <canvas ref={canvasRef} style={myStyle} />
</div> </div>
); );

View File

@ -1,15 +1,54 @@
import ReactECharts from "echarts-for-react";
import TitleBox from "../Component/TitleBox"; import TitleBox from "../Component/TitleBox";
import LineChart from "./LineChart";
import ScrollBoard from "./../../Component/ScrollBoard"; import ScrollBoard from "./../../Component/ScrollBoard";
import SwitchButton from "../Component/SwitchButton"; import SwitchButton from "../Component/SwitchButton";
import { useState } from "react"; import { useState } from "react";
import getOptions from "./LineChart/chart.config";
import { useParams } from "react-router-dom";
function CenterDown() { function CenterDown() {
const nameList = [{ name: "天" }, { name: "周" }, { name: "月" }]; const { LineID } = useParams();
const [activeName, setActiveName] = useState<string>(nameList[0].name); const lineID = LineID?.toString() || "1-1";
console.log(lineID.slice(-1));
// 假数据
const dataSource = {
day: {
yData1: [76.1, 77.4, 75.2, 74.1, 78.5, 81.3, 79.2],
yData2: [77.2, 78.1, 78.2, 77.1, 79.2, 78.3, 79.5],
yData3: [75.1, 74.3, 71.3, 79.8, 82.3, 81.4, 80.3],
yData4: [82.4, 83.1, 88.4, 85.3, 87.1, 82.5, 84.9],
yData5: [82.3, 81.9, 85.8, 81.9, 84.1, 83.5, 82.3],
},
week: {
yData1: [120, 200, 150, 80, 100, 89, 69],
yData2: [100, 150, 120, 70, 90, 97, 89],
yData3: [80, 120, 90, 60, 80, 79, 98],
yData4: [60, 90, 70, 40, 60, 69, 98],
yData5: [40, 60, 50, 20, 40, 89, 99],
},
month: {
yData1: [1200, 2000, 1500, 800, 1000, 999, 889],
yData2: [1000, 1500, 1200, 700, 900, 987, 897],
yData3: [800, 1200, 900, 600, 800, 962, 759],
yData4: [600, 900, 700, 400, 600, 896, 987],
yData5: [400, 600, 500, 200, 400, 986, 951],
},
};
const nameList = [
{ name: "天", ename: "day" },
{ name: "周", ename: "week" },
{ name: "月", ename: "month" },
];
const [activeName, setActiveName] = useState<string>(nameList[0].ename);
let chartData = (dataSource as { [key: string]: any })[activeName];
const handleButtonChange = (activeName: string) => {
setActiveName(activeName);
};
const options = getOptions(chartData);
const config = { const config = {
header: ["序号", "报警时间", "报警编码", "设备状态"], header: ["序号", "报警时间", "报警编码", "设备状态"],
headerHeight: 36, headerHeight: 36,
rowNum: 6, rowNum: 6,
align: ["center", "left", "left", "left"],
headerBGC: "rgba(79, 114, 136, 0.3)", headerBGC: "rgba(79, 114, 136, 0.3)",
oddRowBGC: "rgba(79, 114, 136, 0.3)", oddRowBGC: "rgba(79, 114, 136, 0.3)",
evenRowBGC: "rgba(76, 97, 123, 0.1)", evenRowBGC: "rgba(76, 97, 123, 0.1)",
@ -32,6 +71,138 @@ function CenterDown() {
], ],
], ],
}; };
const config1 = {
header: ["序号", "报警时间", "报警设备", "报警内容"],
headerHeight: 36,
rowNum: 6,
align: ["center", "left", "left", "left"],
headerBGC: "rgba(79, 114, 136, 0.3)",
oddRowBGC: "rgba(79, 114, 136, 0.3)",
evenRowBGC: "rgba(76, 97, 123, 0.1)",
columnWidth: [80, 137, 137, 137],
data: [
[
"1",
"2024/8/28 08:32",
"清洗机5_1",
"<span style='color:#FF1E1E'>故障</span>",
],
[
"2",
"2024/8/28 06:12",
"清洗机5_1",
"<span style='color:#FFB40F'>离线</span>",
],
[
"3",
"2024/8/28 06:05",
"磨边机5_2",
"<span style='color:#FFB40F'>离线</span>",
],
[
"4",
"2024/8/28 04:43",
"二次镀膜机5_1",
"<span style='color:#FFB40F'>离线</span>",
],
[
"5",
"2024/8/28 02:14",
"磨边机5_1",
"<span style='color:#FF1E1E'>故障</span>",
],
[
"6",
"2024/8/27 22:54",
"磨边机5_2",
"<span style='color:#FFB40F'>离线</span>",
],
[
"7",
"2024/8/27 21:55",
"磨边机5_1",
"<span style='color:#FFB40F'>离线</span>",
],
[
"8",
"2024/8/27 21:42",
"一次镀膜机5_2",
"<span style='color:#FFB40F'>离线</span>",
],
[
"9",
"2024/8/27 21:37",
"磨边机5_1",
"<span style='color:#FFB40F'>离线</span>",
],
],
};
const config2 = {
header: ["序号", "报警时间", "报警设备", "报警内容"],
headerHeight: 36,
rowNum: 6,
align: ["center", "left", "left", "left"],
headerBGC: "rgba(79, 114, 136, 0.3)",
oddRowBGC: "rgba(79, 114, 136, 0.3)",
evenRowBGC: "rgba(76, 97, 123, 0.1)",
columnWidth: [80, 137, 137, 137],
data: [
[
"1",
"2024/8/28 07:44",
"下片机械手5_1",
"<span style='color:#FF1E1E'>故障</span>",
],
[
"2",
"2024/8/28 07:35",
"下片机械手5_1",
"<span style='color:#FF1E1E'>故障</span>",
],
[
"3",
"2024/8/28 03:23",
"在线铺纸机5_1",
"<span style='color:#FFB40F'>离线</span>",
],
[
"4",
"2024/8/28 01:36",
"下片机械手5_2",
"<span style='color:#FF1E1E'>故障</span>",
],
[
"5",
"2024/8/28 00:38",
"钢化炉5",
"<span style='color:#FFB40F'>离线</span>",
],
[
"6",
"2024/8/27 23:58",
"下片机械手5_3",
"<span style='color:#FFB40F'>离线</span>",
],
[
"7",
"2024/8/27 23:45",
"下片机械手5_2",
"<span style='color:#FFB40F'>离线</span>",
],
[
"8",
"2024/8/27 22:34",
"钢化炉5",
"<span style='color:#FFB40F'>离线</span>",
],
[
"9",
"2024/8/27 20:31",
"在线铺纸机5_1",
"<span style='color:#FF1E1E'>故障</span>",
],
],
};
return ( return (
<div className="center_down flex-row"> <div className="center_down flex-row">
<div className="center_down_inner flex-col left-box"> <div className="center_down_inner flex-col left-box">
@ -40,7 +211,7 @@ function CenterDown() {
<div className="alarm_num">321,343</div> <div className="alarm_num">321,343</div>
<div style={{ padding: 10, height: "270px" }}> <div style={{ padding: 10, height: "270px" }}>
<ScrollBoard <ScrollBoard
config={config} config={lineID.slice(-1) === "1" ? config1 : config2}
style={{ width: "492px", height: "250px" }} style={{ width: "492px", height: "250px" }}
/> />
</div> </div>
@ -48,16 +219,28 @@ function CenterDown() {
{/* 产线成品率 */} {/* 产线成品率 */}
<div className="center_down_inner flex-col right_box"> <div className="center_down_inner flex-col right_box">
<TitleBox title={"center_down_right"} /> <TitleBox title={"center_down_right"} />
<div className="left_up_switch"> {/* <div className="left_up_switch">
<SwitchButton <SwitchButton nameList={nameList} onChange={handleButtonChange} />
nameList={nameList} </div> */}
activeName={activeName}
setActiveName={setActiveName} {options && (
/>
</div>
<div className="chart_box"> <div className="chart_box">
<LineChart /> {<ReactECharts option={options} style={{ height: "100%" }} />}
</div> </div>
)}
{!options && (
<p
style={{
color: "#cccf",
fontSize: "24px",
userSelect: "none",
textAlign: "center",
paddingTop: "72px",
}}
>
</p>
)}
</div> </div>
</div> </div>
); );

View File

@ -1,18 +1,19 @@
import * as echarts from "echarts"; export default function getOptions(chartData: any) {
export default function getOptions() { if (Object.keys(chartData).length === 0) {
return null;
}
const colors = ["#1A99FF", "#FFB70C", "#C69DFF", "#50F4E3", "#E02094"]; const colors = ["#1A99FF", "#FFB70C", "#C69DFF", "#50F4E3", "#E02094"];
return { return {
color: colors, color: colors,
grid: { top: 38, right: 12, bottom: 26, left: 48 }, grid: { top: 38, right: 12, bottom: 26, left: 48 },
legend: { legend: {
show: true, show: true,
icon: "roundRect",
top: 10, top: 10,
right: 10, right: 10,
padding: 0, padding: 0,
itemWidth: 10, itemWidth: 14,
itemHeight: 10, itemHeight: 10,
itemGap: 3, itemGap: 8,
height: 10, height: 10,
textStyle: { textStyle: {
color: "#DFF1FE", color: "#DFF1FE",
@ -21,17 +22,18 @@ export default function getOptions() {
}, },
xAxis: { xAxis: {
type: "category", type: "category",
data: Array(7) data: ["8/22", "8/23", "8/24", "8/25", "8/26", "8/27", "8/28"],
.fill(1) // data: Array(7)
.map((_, index) => { // .fill(1)
const today = new Date(); // .map((_, index) => {
const dtimestamp = // const today = new Date();
today.getTime() - (index + 1) * 24 * 60 * 60 * 1000; // const dtimestamp =
return `${new Date(dtimestamp).getMonth() + 1}.${new Date( // today.getTime() - (index + 1) * 24 * 60 * 60 * 1000;
dtimestamp // return `${new Date(dtimestamp).getMonth() + 1}.${new Date(
).getDate()}`; // dtimestamp
}) // ).getDate()}`;
.reverse(), // })
// .reverse(),
axisLabel: { axisLabel: {
color: "#fff", color: "#fff",
fontSize: 14, fontSize: 14,
@ -73,6 +75,7 @@ export default function getOptions() {
tooltip: { tooltip: {
trigger: "axis", trigger: "axis",
className: "luoyang-chart-tooltip", className: "luoyang-chart-tooltip",
show: false,
}, },
series: [ series: [
{ {
@ -80,35 +83,35 @@ export default function getOptions() {
type: "line", type: "line",
symbol: "circle", symbol: "circle",
symbolSize: 4, symbolSize: 4,
data: [20, 32, 10, 34, 90, 30, 20], data: chartData.yData1,
}, },
{ {
name: "产线2", name: "产线2",
type: "line", type: "line",
symbol: "circle", symbol: "circle",
symbolSize: 4, symbolSize: 4,
data: [22, 82, 91, 34, 90, 33, 31], data: chartData.yData2,
}, },
{ {
name: "产线3", name: "产线3",
type: "line", type: "line",
symbol: "circle", symbol: "circle",
symbolSize: 4, symbolSize: 4,
data: [50, 32, 20, 54, 19, 33, 41], data: chartData.yData3,
}, },
{ {
name: "产线4", name: "产线4",
type: "line", type: "line",
symbol: "circle", symbol: "circle",
symbolSize: 4, symbolSize: 4,
data: [30, 32, 30, 34, 90, 33, 32], data: chartData.yData4,
}, },
{ {
name: "产线5", name: "产线5",
type: "line", type: "line",
symbol: "circle", symbol: "circle",
symbolSize: 4, symbolSize: 4,
data: [20, 92, 91, 94, 90, 30, 53], data: chartData.yData5,
}, },
], ],
}; };

View File

@ -1,6 +0,0 @@
import ReactECharts from "echarts-for-react";
import getOptions from "./chart.config";
function LineChart() {
return <ReactECharts option={getOptions()} style={{ height: "100%" }} />;
}
export default LineChart;

View File

@ -4,7 +4,7 @@
.switch-button button { .switch-button button {
color: #fff; color: #fff;
font-size: 18px; font-size: 18px;
padding: 4px 15px; padding: 4px 10px;
background-color: rgba(49, 135, 140, 0.3); background-color: rgba(49, 135, 140, 0.3);
cursor: pointer; cursor: pointer;
} }

View File

@ -1,23 +1,59 @@
import { useEffect, useState } from "react";
import "./index.css"; import "./index.css";
interface Name { interface Name {
name: string; name: string;
ename: string;
} }
interface nameListProps { interface nameListProps {
nameList: Name[]; nameList: Name[];
activeName: string; onChange: (value: string) => void;
setActiveName: (name: string) => void; }
function createActiveNameUpdater(nameList: any, activeName: string) {
let activeIndex = nameList.findIndex((obj: any) => obj.name === activeName);
return function updateActiveName() {
activeIndex = (activeIndex + 1) % nameList.length;
return nameList[activeIndex].ename;
};
} }
function SwitchButton(props: nameListProps) { function SwitchButton(props: nameListProps) {
const [activeName, setActiveName] = useState(props.nameList[0].ename);
const [timerId, setTimerId] = useState<any>(null);
let updateActiveName = createActiveNameUpdater(props.nameList, activeName);
useEffect(() => {
const timer = setInterval(() => {
let active = updateActiveName();
setActiveName(active);
props.onChange(active);
}, 60000);
setTimerId(timer);
return () => {
if (timerId !== null) {
clearInterval(timerId);
}
};
}, [props.nameList.length]);
const btnClick = (ename: string) => {
if (timerId !== null) {
clearInterval(timerId);
}
setActiveName(ename);
props.onChange(ename); // 通知父组件
const newTimer = setInterval(() => {
let active = updateActiveName();
setActiveName(active);
props.onChange(active);
}, 60000);
setTimerId(newTimer);
};
return ( return (
<div className="switch-button"> <div className="switch-button">
{props.nameList.map((item, index) => { {props.nameList.map((item, index) => {
return ( return (
<button <button
key={item.name} key={item.ename}
className={props.activeName === item.name ? "active" : ""} className={activeName === item.ename ? "active" : ""}
onClick={() => { onClick={() => btnClick(item.ename)}
props.setActiveName(item.name);
}}
> >
{item.name} {item.name}
</button> </button>

View File

@ -14,12 +14,12 @@ function TitleBox(props: titleProps) {
case "left_up": case "left_up":
return { return {
img: Defect, img: Defect,
title: "产线缺陷汇总", title: "产线报废汇总",
}; };
case "left_down": case "left_down":
return { return {
img: Record, img: Record,
title: "当前产线缺陷", title: "当前产线报废情况",
}; };
case "center_down_left": case "center_down_left":
return { return {
@ -39,7 +39,7 @@ function TitleBox(props: titleProps) {
default: default:
return { return {
img: InputAndOutput, img: InputAndOutput,
title: "产线投入和产出", title: "当前产线投入和产出",
}; };
} }
}; };

View File

@ -1,15 +1,14 @@
import * as echarts from "echarts"; import * as echarts from "echarts";
export default function getOptions() { export default function getOptions(dataProps: number[], color: string[]) {
const colors = ["#1A99FF", "#FFB70C", "#C69DFF", "#50F4E3", "#E02094"]; if (dataProps.length === 0) return null;
return { return {
color: colors,
grid: { top: 30, right: 12, bottom: 26, left: 48 }, grid: { top: 30, right: 12, bottom: 26, left: 48 },
legend: { legend: {
show: false, show: false,
}, },
xAxis: { xAxis: {
type: "category", type: "category",
data: ["缺陷1", "缺陷2", "缺陷3", "缺陷4", "缺陷5", "缺陷6"], data: ["磨边后", "包装1", "包装2"],
axisLabel: { axisLabel: {
color: "#fff", color: "#fff",
fontSize: 14, fontSize: 14,
@ -55,10 +54,11 @@ export default function getOptions() {
type: "shadow", type: "shadow",
}, },
className: "luoyang-chart-tooltip", className: "luoyang-chart-tooltip",
show: false,
}, },
series: [ series: [
{ {
data: [120, 200, 150, 80, 70, 110], data: dataProps,
type: "bar", type: "bar",
barWidth: 10, barWidth: 10,
label: { label: {
@ -69,8 +69,8 @@ export default function getOptions() {
}, },
itemStyle: { itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: "#9DD5FF" }, { offset: 0, color: color[0] },
{ offset: 1, color: "#1295FF" }, { offset: 1, color: color[1] },
]), ]),
}, },
}, },

View File

@ -1,6 +0,0 @@
import ReactECharts from "echarts-for-react";
import getOptions from "./chart.config";
function BarChart() {
return <ReactECharts option={getOptions()} style={{ height: "100%" }} />;
}
export default BarChart;

View File

@ -1,15 +1,23 @@
import ReactECharts from "echarts-for-react";
import TitleBox from "../Component/TitleBox"; import TitleBox from "../Component/TitleBox";
import SwitchButton from "../Component/SwitchButton"; import SwitchButton from "../Component/SwitchButton";
import BarChart from "./BarChart";
import ScrollBoard from "./../../Component/ScrollBoard"; import ScrollBoard from "./../../Component/ScrollBoard";
import { useState } from "react"; import { useState } from "react";
import getOptions from "./BarChart/chart.config";
function LeftDown() { function LeftDown() {
const nameList = [{ name: "表单" }, { name: "柱状" }]; const nameList = [
const [activeName, setActiveName] = useState<string>(nameList[0].name); { name: "表单", ename: "table" },
{ name: "柱状", ename: "chart" },
];
const [activeName, setActiveName] = useState<string>(nameList[0].ename);
const handleButtonChange = (activeName: string) => {
setActiveName(activeName);
};
const config = { const config = {
header: ["序号", "缺陷种类", "缺陷数量"], header: ["序号", "工序类型", "报废数量"],
headerHeight: 30, headerHeight: 30,
rowNum: 4, rowNum: 4,
align: ["center", "left", "left"],
headerBGC: "rgba(79, 114, 136, 0.3)", headerBGC: "rgba(79, 114, 136, 0.3)",
oddRowBGC: "rgba(79, 114, 136, 0.3)", oddRowBGC: "rgba(79, 114, 136, 0.3)",
evenRowBGC: "rgba(76, 97, 123, 0.1)", evenRowBGC: "rgba(76, 97, 123, 0.1)",
@ -27,15 +35,64 @@ function LeftDown() {
["行10列1", "行10列2", "行10列3"], ["行10列1", "行10列2", "行10列3"],
], ],
}; };
const config1 = {
header: ["序号", "工序类型", "报废数量"],
headerHeight: 30,
rowNum: 4,
align: ["center", "left", "left"],
headerBGC: "rgba(79, 114, 136, 0.3)",
oddRowBGC: "rgba(79, 114, 136, 0.3)",
evenRowBGC: "rgba(76, 97, 123, 0.1)",
columnWidth: [73, 117, 190],
data: [
["1", "磨边后", 224],
["2", "包装1", 322],
["3", "包装2", 66],
],
};
const config2 = {
header: ["序号", "工序类型", "报废数量"],
headerHeight: 30,
rowNum: 4,
align: ["center", "left", "left"],
headerBGC: "rgba(79, 114, 136, 0.3)",
oddRowBGC: "rgba(79, 114, 136, 0.3)",
evenRowBGC: "rgba(76, 97, 123, 0.1)",
columnWidth: [73, 117, 190],
data: [
["1", "磨边后", 1119],
["2", "包装1", 1798],
["3", "包装2", 435],
],
};
const config3 = {
header: ["序号", "工序类型", "报废数量"],
headerHeight: 30,
rowNum: 4,
align: ["center", "left", "left"],
headerBGC: "rgba(79, 114, 136, 0.3)",
oddRowBGC: "rgba(79, 114, 136, 0.3)",
evenRowBGC: "rgba(76, 97, 123, 0.1)",
columnWidth: [73, 117, 190],
data: [
["1", "磨边后", 5004],
["2", "包装1", 9122],
["3", "包装2", 1924],
],
};
const color1 = ["#9DD5FF", "#1295FF"];
const color2 = ["#85F6E9", "#2EC6B4"];
const dataProps1 = [224, 322, 66];
const dataProps2 = [1119, 1798, 435];
const dataProps3 = [5004, 9122, 1924];
const options1 = getOptions(dataProps1, color1);
const options2 = getOptions(dataProps2, color2);
const options3 = getOptions(dataProps3, color1);
return ( return (
<div className="left_down"> <div className="left_down">
<TitleBox title={"left_down"} /> <TitleBox title={"left_down"} />
<div className="left_up_switch"> <div className="left_up_switch">
<SwitchButton <SwitchButton nameList={nameList} onChange={handleButtonChange} />
nameList={nameList}
activeName={activeName}
setActiveName={setActiveName}
/>
</div> </div>
<div style={{ padding: "10px", height: "555px" }}> <div style={{ padding: "10px", height: "555px" }}>
<div className="left_down_title flex-row"> <div className="left_down_title flex-row">
@ -44,13 +101,25 @@ function LeftDown() {
<div className="left_down_box2 flex-col" /> <div className="left_down_box2 flex-col" />
</div> </div>
<div className="left_down_content"> <div className="left_down_content">
{activeName === "表单" ? ( {activeName === "table" ? (
<ScrollBoard <ScrollBoard
config={config} config={config1}
style={{ width: "380px", height: "150px" }} style={{ width: "380px", height: "150px" }}
/> />
) : options1 ? (
<ReactECharts option={options1} style={{ height: "100%" }} />
) : ( ) : (
<BarChart /> <p
style={{
color: "#cccf",
fontSize: "24px",
userSelect: "none",
textAlign: "center",
paddingTop: "72px",
}}
>
</p>
)} )}
</div> </div>
<div className="left_down_title flex-row"> <div className="left_down_title flex-row">
@ -59,13 +128,25 @@ function LeftDown() {
<div className="left_down_box2 flex-col" /> <div className="left_down_box2 flex-col" />
</div> </div>
<div className="left_down_content"> <div className="left_down_content">
{activeName === "表单" ? ( {activeName === "table" ? (
<ScrollBoard <ScrollBoard
config={config} config={config2}
style={{ width: "380px", height: "150px" }} style={{ width: "380px", height: "150px" }}
/> />
) : options2 ? (
<ReactECharts option={options2} style={{ height: "100%" }} />
) : ( ) : (
<BarChart /> <p
style={{
color: "#cccf",
fontSize: "24px",
userSelect: "none",
textAlign: "center",
paddingTop: "72px",
}}
>
</p>
)} )}
</div> </div>
<div className="left_down_title flex-row"> <div className="left_down_title flex-row">
@ -74,13 +155,25 @@ function LeftDown() {
<div className="left_down_box2 flex-col" /> <div className="left_down_box2 flex-col" />
</div> </div>
<div className="left_down_content"> <div className="left_down_content">
{activeName === "表单" ? ( {activeName === "table" ? (
<ScrollBoard <ScrollBoard
config={config} config={config3}
style={{ width: "380px", height: "150px" }} style={{ width: "380px", height: "150px" }}
/> />
) : options3 ? (
<ReactECharts option={options3} style={{ height: "100%" }} />
) : ( ) : (
<BarChart /> <p
style={{
color: "#cccf",
fontSize: "24px",
userSelect: "none",
textAlign: "center",
paddingTop: "72px",
}}
>
</p>
)} )}
</div> </div>
</div> </div>

View File

@ -1,23 +1,68 @@
import ReactECharts from "echarts-for-react";
import TitleBox from "../Component/TitleBox"; import TitleBox from "../Component/TitleBox";
import SwitchButton from "../Component/SwitchButton"; import SwitchButton from "../Component/SwitchButton";
import SummaryBarChart from "./SummaryBarChart"; import getOptions from "./SummaryBarChart/chart.config";
import { useState } from "react"; import { useState } from "react";
function LeftUp() { function LeftUp() {
const nameList = [{ name: "天" }, { name: "周" }, { name: "月" }]; // 假数据
const [activeName, setActiveName] = useState<string>(nameList[0].name); const dataSource = {
day: {
xData: ["钢1线", "钢2线", "钢3线", "钢4线", "钢5线"],
yData1: [236, 214, 196, 239, 224],
yData2: [346, 296, 327, 311, 322],
yData3: [78, 85, 56, 106, 66],
sumData: [660, 595, 579, 656, 612],
},
week: {
xData: ["钢1线", "钢2线", "钢3线", "钢4线", "钢5线"],
yData1: [1336, 1223, 1313, 1134, 1119],
yData2: [2146, 1996, 2053, 1857, 1798],
yData3: [892, 658, 467, 758, 435],
sumData: [4374, 3877, 3833, 3749, 3352],
},
month: {
xData: ["钢1线", "钢2线", "钢3线", "钢4线", "钢5线"],
yData1: [5789, 6432, 4679, 5456, 5004],
yData2: [8762, 9732, 8137, 8820, 9122],
yData3: [2468, 3120, 2782, 2395, 1924],
sumData: [17019, 19284, 15598, 16671, 16050],
},
};
const nameList = [
{ name: "天", ename: "day" },
{ name: "周", ename: "week" },
{ name: "月", ename: "month" },
];
const [activeName, setActiveName] = useState<string>(nameList[0].ename);
let chartData = (dataSource as { [key: string]: any })[activeName];
const handleButtonChange = (activeName: string) => {
setActiveName(activeName);
};
const options = getOptions(chartData);
return ( return (
<div className="left_up"> <div className="left_up">
<TitleBox title={"left_up"} /> <TitleBox title={"left_up"} />
<div className="left_up_switch"> <div className="left_up_switch">
<SwitchButton <SwitchButton nameList={nameList} onChange={handleButtonChange} />
nameList={nameList}
activeName={activeName}
setActiveName={setActiveName}
/>
</div> </div>
{options && (
<div className="left_up_chart"> <div className="left_up_chart">
<SummaryBarChart /> {<ReactECharts option={options} style={{ height: "100%" }} />}
</div> </div>
)}
{!options && (
<p
style={{
color: "#cccf",
fontSize: "24px",
userSelect: "none",
textAlign: "center",
paddingTop: "72px",
}}
>
</p>
)}
</div> </div>
); );
} }

View File

@ -1,18 +1,21 @@
import * as echarts from "echarts"; export default function getOptions(chartData: any) {
export default function getOptions() { if (Object.keys(chartData).length === 0) {
const colors = ["#1A99FF", "#FFB70C", "#C69DFF", "#50F4E3", "#E02094"]; return null;
}
const colors = ["#2760FF", "#8167F6", "#5B9BFF", "#99D66C", "#FFD160"];
let sum = chartData.sumData;
return { return {
color: colors, color: colors,
grid: { top: 38, right: 12, bottom: 26, left: 48 }, grid: { top: 48, right: 20, bottom: 5, left: 15, containLabel: true },
legend: { legend: {
show: true, show: true,
icon: "roundRect", icon: "roundRect",
top: 10, top: 10,
right: 10, right: 20,
padding: 0, padding: 0,
itemWidth: 10, itemWidth: 10,
itemHeight: 10, itemHeight: 10,
itemGap: 3, itemGap: 15,
height: 10, height: 10,
textStyle: { textStyle: {
color: "#DFF1FE", color: "#DFF1FE",
@ -21,19 +24,10 @@ export default function getOptions() {
}, },
xAxis: { xAxis: {
type: "category", type: "category",
// data: Array(7) data: chartData.xData,
// .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: { axisLabel: {
color: "#fff", color: "#fff",
fontSize: 14, fontSize: 16,
}, },
axisTick: { show: false }, axisTick: { show: false },
axisLine: { axisLine: {
@ -52,7 +46,7 @@ export default function getOptions() {
type: "value", type: "value",
axisLabel: { axisLabel: {
color: "#fff", color: "#fff",
fontSize: 14, fontSize: 16,
formatter: "{value}", formatter: "{value}",
}, },
axisLine: { axisLine: {
@ -70,74 +64,85 @@ export default function getOptions() {
}, },
}, },
tooltip: { tooltip: {
show: false,
trigger: "axis", trigger: "axis",
axisPointer: { axisPointer: {
type: "shadow", type: "shadow",
}, },
className: "luoyang-chart-tooltip", className: "luoyang-chart-tooltip",
}, },
dataset: {
source: [
["product", "产线1", "产线2", "产线3", "产线4", "产线5"],
["缺陷1", 43, 85, 93, 60, 80],
["缺陷2", 83, 73, 55, 67, 90],
["缺陷3", 86, 65, 82, 68, 90],
["缺陷4", 72, 53, 39, 88, 50],
["缺陷5", 72, 53, 39, 88, 50],
],
},
// Declare several bar series, each will be mapped // Declare several bar series, each will be mapped
// to a column of dataset.source by default. // to a column of dataset.source by default.
series: [ series: [
{ {
data: chartData.yData1,
type: "bar", type: "bar",
barWidth: 8, stack: "a",
itemStyle: { name: "磨边后",
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ barWidth: 14,
{ offset: 0, color: "#9DD5FF" }, label: {
{ offset: 1, color: "#1295FF" }, show: true,
]), position: "right",
color: "inherit",
}, },
}, },
{ {
data: chartData.yData2,
type: "bar", type: "bar",
barWidth: 8, stack: "a",
itemStyle: { name: "包装1",
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ label: {
{ offset: 0, color: "#FFC844" }, show: true,
{ offset: 1, color: "#FFB70C" }, position: "right",
]), color: "inherit",
}, },
}, },
{ {
data: chartData.yData3,
type: "bar", type: "bar",
barWidth: 8, stack: "a",
itemStyle: { name: "包装2",
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ label: {
{ offset: 0, color: "#FF8BC3" }, show: true,
{ offset: 1, color: "#EB46A1" }, position: "right",
]), color: "inherit",
}, },
}, },
// {
// data: chartData.yData4,
// type: "bar",
// stack: "a",
// name: "镀膜",
// label: {
// show: true,
// position: "right",
// color: "inherit",
// },
// },
// {
// data: chartData.yData5,
// type: "bar",
// stack: "a",
// name: "包装",
// label: {
// show: true,
// position: "right",
// color: "inherit",
// },
// },
{ {
data: [0, 0, 0, 0, 0],
type: "bar", type: "bar",
barWidth: 8, stack: "a",
itemStyle: { name: "",
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ label: {
{ offset: 0, color: "#85F6E9" }, show: true,
{ offset: 1, color: "#2EC6B4" }, position: "top",
]), color: "#fff",
formatter: function (params: any) {
return sum[params.dataIndex];
}, },
}, },
{
type: "bar",
barWidth: 8,
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: "#9496FF" },
{ offset: 1, color: "#6567FF" },
]),
},
}, },
], ],
}; };

View File

@ -1,6 +0,0 @@
import ReactECharts from "echarts-for-react";
import getOptions from "./chart.config";
function SummaryBarChart() {
return <ReactECharts option={getOptions()} style={{ height: "100%" }} />;
}
export default SummaryBarChart;

View File

@ -1,9 +1,12 @@
import * as echarts from "echarts"; import * as echarts from "echarts";
export default function getOptions() { export default function getOptions(tempData: any) {
if (Object.keys(tempData).length === 0) {
return null;
}
const colors = ["#1A99FF", "#50F4E3"]; const colors = ["#1A99FF", "#50F4E3"];
return { return {
color: colors, color: colors,
grid: { top: 38, right: 12, bottom: 26, left: 48 }, grid: { top: 30, right: 12, bottom: 10, left: 10, containLabel: true },
legend: { legend: {
show: true, show: true,
icon: "roundRect", icon: "roundRect",
@ -21,17 +24,18 @@ export default function getOptions() {
}, },
xAxis: { xAxis: {
type: "category", type: "category",
data: Array(7) data: tempData.time,
.fill(1) // data: Array(7)
.map((_, index) => { // .fill(1)
const today = new Date(); // .map((_, index) => {
const dtimestamp = // const today = new Date();
today.getTime() - (index + 1) * 24 * 60 * 60 * 1000; // const dtimestamp =
return `${new Date(dtimestamp).getMonth() + 1}.${new Date( // today.getTime() - (index + 1) * 24 * 60 * 60 * 1000;
dtimestamp // return `${new Date(dtimestamp).getMonth() + 1}.${new Date(
).getDate()}`; // dtimestamp
}) // ).getDate()}`;
.reverse(), // })
// .reverse(),
axisLabel: { axisLabel: {
color: "#fff", color: "#fff",
fontSize: 14, fontSize: 14,
@ -76,19 +80,20 @@ export default function getOptions() {
type: "line", type: "line",
symbol: "circle", symbol: "circle",
symbolSize: 4, symbolSize: 4,
data: [20, 32, 10, 34, 90, 30, 20], data: tempData.input,
}, },
{ {
name: "产出", name: "产出",
type: "line", type: "line",
symbol: "circle", symbol: "circle",
symbolSize: 4, symbolSize: 4,
data: [22, 82, 91, 34, 90, 33, 31], data: tempData.output,
}, },
], ],
tooltip: { tooltip: {
trigger: "axis", trigger: "axis",
className: "luoyang-chart-tooltip", className: "luoyang-chart-tooltip",
show: false,
}, },
}; };
} }

View File

@ -1,6 +0,0 @@
import ReactECharts from "echarts-for-react";
import getOptions from "./chart.config";
function BarChart() {
return <ReactECharts option={getOptions()} style={{ height: "100%" }} />;
}
export default BarChart;

View File

@ -1,11 +1,122 @@
import ReactECharts from "echarts-for-react";
import TitleBox from "../Component/TitleBox"; import TitleBox from "../Component/TitleBox";
import SwitchButton from "../Component/SwitchButton"; import SwitchButton from "../Component/SwitchButton";
import LineChart from "./LineChart";
import ScrollBoard from "./../../Component/ScrollBoard"; import ScrollBoard from "./../../Component/ScrollBoard";
import { useState } from "react"; import { useState } from "react";
import getOptions from "./LineChart/chart.config";
function RightDown() { function RightDown() {
const nameList = [{ name: "表单" }, { name: "折线" }]; // 假数据
const [activeName, setActiveName] = useState<string>(nameList[0].name); let tempData = [
{
type: "day",
data: {
time: [
"0:00",
"1:00",
"2:00",
"3:00",
"4:00",
"5:00",
"6:00",
"7:00",
"8:00",
"9:00",
"10:00",
"11:00",
"12:00",
"13:00",
"14:00",
"15:00",
"16:00",
"17:00",
"18:00",
"19:00",
"20:00",
"21:00",
"22:00",
"23:00",
],
input: [
456, 425, 246, 424, 453, 466, 412, 434, 425, 418, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
],
output: [
432, 401, 232, 398, 421, 439, 378, 411, 400, 394, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
],
},
},
{
type: "week",
data: {
time: [
"2024/8/22",
"2024/8/23",
"2024/8/24",
"2024/8/25",
"2024/8/26",
"2024/8/27",
"2024/8/28",
],
input: [9753, 10357, 11246, 10123, 9872, 9985, 10352],
output: [7925, 8216, 9091, 7847, 7589, 8126, 8112],
},
},
{
type: "month",
data: {
time: [
"2024/8/1",
"2024/8/2",
"2024/8/3",
"2024/8/4",
"2024/8/5",
"2024/8/6",
"2024/8/7",
"2024/8/8",
"2024/8/9",
"2024/8/10",
"2024/8/11",
"2024/8/12",
"2024/8/13",
"2024/8/14",
"2024/8/15",
"2024/8/16",
"2024/8/17",
"2024/8/18",
"2024/8/19",
"2024/8/20",
"2024/8/21",
"2024/8/22",
"2024/8/23",
"2024/8/24",
"2024/8/25",
"2024/8/26",
"2024/8/27",
"2024/8/28",
"2024/8/29",
"2024/8/30",
"2024/8/31",
],
input: [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9813, 9753,
10357, 11246, 10123, 9872, 9985, 10352, 4235, 0, 0, 0,
],
output: [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7883, 7925,
8216, 9091, 7847, 7589, 8126, 8112, 3962, 0, 0, 0,
],
},
},
];
const nameList = [
{ name: "表单", ename: "table" },
{ name: "折线", ename: "chart" },
];
const [activeName, setActiveName] = useState<string>(nameList[0].ename);
const handleButtonChange = (activeName: string) => {
setActiveName(activeName);
};
const config = { const config = {
header: ["时间", "投入数量", "产出数量"], header: ["时间", "投入数量", "产出数量"],
headerHeight: 30, headerHeight: 30,
@ -27,15 +138,72 @@ function RightDown() {
["行10列1", "行10列2", "行10列3"], ["行10列1", "行10列2", "行10列3"],
], ],
}; };
const config1 = {
header: ["时间", "投入数量", "产出数量"],
headerHeight: 30,
rowNum: 5,
headerBGC: "rgba(79, 114, 136, 0.3)",
oddRowBGC: "rgba(79, 114, 136, 0.3)",
evenRowBGC: "rgba(76, 97, 123, 0.1)",
columnWidth: [120, 130, 130],
data: [],
};
const config2 = {
header: ["时间", "投入数量", "产出数量"],
headerHeight: 30,
rowNum: 5,
headerBGC: "rgba(79, 114, 136, 0.3)",
oddRowBGC: "rgba(79, 114, 136, 0.3)",
evenRowBGC: "rgba(76, 97, 123, 0.1)",
columnWidth: [120, 130, 130],
data: [],
};
const config3 = {
header: ["时间", "投入数量", "产出数量"],
headerHeight: 30,
rowNum: 5,
headerBGC: "rgba(79, 114, 136, 0.3)",
oddRowBGC: "rgba(79, 114, 136, 0.3)",
evenRowBGC: "rgba(76, 97, 123, 0.1)",
columnWidth: [120, 130, 130],
data: [],
};
let data1Lenght = tempData[0].data.input.length;
for (let i = 0; i < data1Lenght; i++) {
(config1.data as any).push([
tempData[0].data.time ? tempData[0].data.time[i] : "-",
tempData[0].data.input ? tempData[0].data.input[i] : "-",
tempData[0].data.output ? tempData[0].data.output[i] : "-",
]);
}
let data2Lenght = tempData[1].data.input.length;
for (let i = 0; i < data2Lenght; i++) {
(config2.data as any).push([
tempData[1].data.time ? tempData[1].data.time[i] : "-",
tempData[1].data.input ? tempData[1].data.input[i] : "-",
tempData[1].data.output ? tempData[1].data.output[i] : "-",
]);
}
let data3Lenght = tempData[0].data.input.length;
for (let i = 0; i < data3Lenght; i++) {
(config3.data as any).push([
tempData[2].data.time ? tempData[2].data.time[i] : "-",
tempData[2].data.input ? tempData[2].data.input[i] : "-",
tempData[2].data.output ? tempData[2].data.output[i] : "-",
]);
}
const chartData1 = tempData[0].data;
const chartData2 = tempData[1].data;
const chartData3 = tempData[2].data;
const options1 = getOptions(chartData1);
const options2 = getOptions(chartData2);
const options3 = getOptions(chartData3);
return ( return (
<div className="right_down"> <div className="right_down">
<TitleBox title={"right_down"} /> <TitleBox title={"right_down"} />
<div className="left_up_switch"> <div className="left_up_switch">
<SwitchButton <SwitchButton nameList={nameList} onChange={handleButtonChange} />
nameList={nameList}
activeName={activeName}
setActiveName={setActiveName}
/>
</div> </div>
<div style={{ padding: "10px", height: "628px" }}> <div style={{ padding: "10px", height: "628px" }}>
<div className="left_down_title flex-row"> <div className="left_down_title flex-row">
@ -44,13 +212,25 @@ function RightDown() {
<div className="left_down_box2 flex-col" /> <div className="left_down_box2 flex-col" />
</div> </div>
<div className="right_down_content"> <div className="right_down_content">
{activeName === "表单" ? ( {activeName === "table" ? (
<ScrollBoard <ScrollBoard
config={config} config={config1}
style={{ width: "380px", height: "180px" }} style={{ width: "380px", height: "180px" }}
/> />
) : options1 ? (
<ReactECharts option={options1} style={{ height: "100%" }} />
) : ( ) : (
<LineChart /> <p
style={{
color: "#cccf",
fontSize: "24px",
userSelect: "none",
textAlign: "center",
paddingTop: "72px",
}}
>
</p>
)} )}
</div> </div>
<div className="left_down_title flex-row"> <div className="left_down_title flex-row">
@ -59,13 +239,25 @@ function RightDown() {
<div className="left_down_box2 flex-col" /> <div className="left_down_box2 flex-col" />
</div> </div>
<div className="right_down_content"> <div className="right_down_content">
{activeName === "表单" ? ( {activeName === "table" ? (
<ScrollBoard <ScrollBoard
config={config} config={config2}
style={{ width: "380px", height: "180px" }} style={{ width: "380px", height: "180px" }}
/> />
) : options2 ? (
<ReactECharts option={options2} style={{ height: "100%" }} />
) : ( ) : (
<LineChart /> <p
style={{
color: "#cccf",
fontSize: "24px",
userSelect: "none",
textAlign: "center",
paddingTop: "72px",
}}
>
</p>
)} )}
</div> </div>
<div className="left_down_title flex-row"> <div className="left_down_title flex-row">
@ -74,13 +266,25 @@ function RightDown() {
<div className="left_down_box2 flex-col" /> <div className="left_down_box2 flex-col" />
</div> </div>
<div className="right_down_content"> <div className="right_down_content">
{activeName === "表单" ? ( {activeName === "table" ? (
<ScrollBoard <ScrollBoard
config={config} config={config3}
style={{ width: "380px", height: "180px" }} style={{ width: "380px", height: "180px" }}
/> />
) : options3 ? (
<ReactECharts option={options3} style={{ height: "100%" }} />
) : ( ) : (
<LineChart /> <p
style={{
color: "#cccf",
fontSize: "24px",
userSelect: "none",
textAlign: "center",
paddingTop: "72px",
}}
>
</p>
)} )}
</div> </div>
</div> </div>

View File

@ -2,24 +2,20 @@ import TitleBox from "../Component/TitleBox";
import ScrollBoard from "./../../Component/ScrollBoard"; import ScrollBoard from "./../../Component/ScrollBoard";
function RightUp() { function RightUp() {
const config = { const config = {
header: ["产线", "上片数据量", "成品下片数量", "成品下片"], header: ["序号", "产线", "上片数据量", "成品下片数量"],
headerHeight: 32, headerHeight: 32,
rowNum: 5, rowNum: 5,
align: ["center", "left", "left", "left"],
headerBGC: "rgba(79, 114, 136, 0.3)", headerBGC: "rgba(79, 114, 136, 0.3)",
oddRowBGC: "rgba(79, 114, 136, 0.3)", oddRowBGC: "rgba(79, 114, 136, 0.3)",
evenRowBGC: "rgba(76, 97, 123, 0.1)", evenRowBGC: "rgba(76, 97, 123, 0.1)",
columnWidth: [73, 100, 117, 90], columnWidth: [70, 90, 106, 114],
data: [ data: [
["1", "行1列1", "行1列2", "行1列3"], ["1", "钢1线", "82315", "64268"],
["2", "行2列1", "行2列2", "行2列3"], ["2", "钢2线", "78246", "61235"],
["3", "行3列1", "行3列2", "行3列3"], ["3", "钢3线", "79092", "63562"],
["4", "行4列1", "行4列2", "行4列3"], ["4", "钢4线", "84125", "66789"],
["5", "行5列1", "行5列2", "行5列3"], ["5", "钢5线", "85223", "68246"],
["6", "行6列1", "行6列2", "行6列3"],
["7", "行7列1", "行7列2", "行7列3"],
["8", "行8列1", "行8列2", "行8列3"],
["9", "行9列1", "行9列2", "行9列3"],
["10", "行10列1", "行10列2", "行10列3"],
], ],
}; };
return ( return (

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -0,0 +1,23 @@
<?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>矩形备份 16</title>
<defs>
<rect id="path-1" x="107.233171" y="10.535516" width="8" height="8" rx="4"></rect>
<filter x="-75.0%" y="-75.0%" width="250.0%" height="250.0%" filterUnits="objectBoundingBox" id="filter-2">
<feMorphology radius="1" operator="dilate" in="SourceAlpha" result="shadowSpreadOuter1"></feMorphology>
<feOffset dx="0" dy="0" in="shadowSpreadOuter1" result="shadowOffsetOuter1"></feOffset>
<feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
<feColorMatrix values="0 0 0 0 0.278431373 0 0 0 0 1 0 0 0 0 0.152941176 0 0 0 0.5 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
</filter>
</defs>
<g id="洛阳" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="洛阳现场看板tc" transform="translate(-1374.233171, -640.985634)">
<g id="编组-13" transform="translate(1255.024831, 507.964484)">
<g id="矩形备份-16" transform="translate(15.975169, 126.485634)">
<use fill="black" fill-opacity="1" filter="url(#filter-2)" xlink:href="#path-1"></use>
<use fill="#47FF27" fill-rule="evenodd" xlink:href="#path-1"></use>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -64,6 +64,7 @@
background: url(../../../public/png/rect/lp_center_up.png) no-repeat; background: url(../../../public/png/rect/lp_center_up.png) no-repeat;
background-size: 100% 100%; background-size: 100% 100%;
background-position: 0 0; background-position: 0 0;
position: relative;
} }
.center_down { .center_down {
width: 1041px; width: 1041px;
@ -168,6 +169,7 @@
height: 185px; height: 185px;
/* padding-bottom: 5px; */ /* padding-bottom: 5px; */
} }
/* 滚动表格部分 */
.dv-scroll-board .header .header-item, .dv-scroll-board .header .header-item,
.dv-scroll-board .rows .ceil { .dv-scroll-board .rows .ceil {
border-right: 1px solid #0d1728; border-right: 1px solid #0d1728;
@ -177,7 +179,7 @@
border-right: none; border-right: none;
border: none; border: none;
} }
/* chart图部分 */
.luoyang-chart-tooltip { .luoyang-chart-tooltip {
background: #0a2b4f77 !important; background: #0a2b4f77 !important;
border: none !important; border: none !important;
@ -187,3 +189,76 @@
.luoyang-chart-tooltip * { .luoyang-chart-tooltip * {
color: #fff !important; color: #fff !important;
} }
/* 三维页面部分 */
.center_up .model_name {
position: absolute;
left: 0px;
top: 0px;
z-index: 1000;
}
.center_up .model_info {
position: absolute;
left: 100px;
bottom: 0px;
z-index: 1000;
width: 841px;
height: 62px;
background: url(/public/png/lp/line_part.png) 100% no-repeat;
background-size: 100% 100%;
}
.center_up .model_info .reset_btn {
position: absolute;
top: 20px;
left: 40px;
width: 140px;
height: 40px;
cursor: pointer;
}
.center_up .model_info .title {
display: inline-block;
width: 361px;
text-align: center;
font-size: 32px;
color: #fff;
letter-spacing: 5px;
position: absolute;
left: 241px;
bottom: 10px;
}
.center_up .eq_detail_info {
position: absolute;
right: 0px;
bottom: 0px;
z-index: 1002;
width: 240px;
height: 110px;
background: url(/public/png/lp/eq_msg_detail.png) 100% no-repeat;
background-size: 100% 100%;
color: #fff;
padding: 15px 0 0 15px;
}
.center_up .eq_detail_info .left_name {
display: inline-block;
width: 95px;
height: 28px;
text-align: right;
font-size: 18px;
}
.center_up .eq_detail_info .right_value {
display: inline-block;
height: 28px;
font-size: 18px;
}
.center_up .eq_info {
position: absolute;
z-index: 1002;
background: url(/public/png/lp/eq_msg_always.png) 100% no-repeat;
background-size: 100% 100%;
color: #fff;
padding: 10px 15px;
}
.center_up .eq_info .eq_info_inner {
height: 20px;
font-size: 18px;
white-space: nowrap;
}