大屏样式
This commit is contained in:
parent
bda855430d
commit
bbb7de918e
11
package-lock.json
generated
11
package-lock.json
generated
@ -36,6 +36,7 @@
|
||||
"browserslist": "^4.18.1",
|
||||
"camelcase": "^6.2.1",
|
||||
"case-sensitive-paths-webpack-plugin": "^2.4.0",
|
||||
"classnames": "^2.5.1",
|
||||
"css-loader": "^6.5.1",
|
||||
"css-minimizer-webpack-plugin": "^3.2.0",
|
||||
"dotenv": "^10.0.0",
|
||||
@ -5939,6 +5940,11 @@
|
||||
"resolved": "https://registry.npmmirror.com/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz",
|
||||
"integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA=="
|
||||
},
|
||||
"node_modules/classnames": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmmirror.com/classnames/-/classnames-2.5.1.tgz",
|
||||
"integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow=="
|
||||
},
|
||||
"node_modules/clean-css": {
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmmirror.com/clean-css/-/clean-css-5.3.2.tgz",
|
||||
@ -21198,6 +21204,11 @@
|
||||
"resolved": "https://registry.npmmirror.com/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz",
|
||||
"integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA=="
|
||||
},
|
||||
"classnames": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmmirror.com/classnames/-/classnames-2.5.1.tgz",
|
||||
"integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow=="
|
||||
},
|
||||
"clean-css": {
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmmirror.com/clean-css/-/clean-css-5.3.2.tgz",
|
||||
|
@ -31,6 +31,7 @@
|
||||
"browserslist": "^4.18.1",
|
||||
"camelcase": "^6.2.1",
|
||||
"case-sensitive-paths-webpack-plugin": "^2.4.0",
|
||||
"classnames": "^2.5.1",
|
||||
"css-loader": "^6.5.1",
|
||||
"css-minimizer-webpack-plugin": "^3.2.0",
|
||||
"dotenv": "^10.0.0",
|
||||
|
@ -11,41 +11,11 @@ import {
|
||||
Observable,
|
||||
Vector3,
|
||||
} from "@babylonjs/core";
|
||||
import {
|
||||
GlassAnimation1_1,
|
||||
GlassAnimation1_2D,
|
||||
GlassAnimation1_2U,
|
||||
GlassAnimation1_3,
|
||||
GlassAnimation1_4,
|
||||
GlassAnimation2_1,
|
||||
GlassAnimation2_2D,
|
||||
GlassAnimation2_2U,
|
||||
GlassAnimation2_3,
|
||||
GlassAnimation2_4,
|
||||
GlassAnimation3_1,
|
||||
GlassAnimation3_2D,
|
||||
GlassAnimation3_2U,
|
||||
GlassAnimation3_3,
|
||||
GlassAnimation3_4,
|
||||
GlassAnimation4_1,
|
||||
GlassAnimation4_2D,
|
||||
GlassAnimation4_2U,
|
||||
GlassAnimation4_3,
|
||||
GlassAnimation4_4,
|
||||
} from "./GlassAnimation";
|
||||
import { useAppSelector } from "../store/hooks";
|
||||
import {
|
||||
GlassStatus,
|
||||
selectGlassStatus,
|
||||
} from "../store/ProductionMonitoringEntity";
|
||||
import "../page/style/standard.css";
|
||||
import { MyObservable } from "../context/MyObservable";
|
||||
import { Button, ButtonGroup } from "@mui/material";
|
||||
import intl from "react-intl-universal";
|
||||
import { EquStatusInterface, selectEquStatus } from "../store/EquStatusEntity";
|
||||
import EquMap from "./EquMap";
|
||||
|
||||
const onMainCamObservable = new Observable();
|
||||
const onEquObservable = new Observable();
|
||||
|
||||
const myStyle = {
|
||||
@ -54,57 +24,18 @@ const myStyle = {
|
||||
outline: "none",
|
||||
};
|
||||
|
||||
const DetailCamera = {
|
||||
alpha: BABYLON.Tools.ToRadians(270),
|
||||
beta: BABYLON.Tools.ToRadians(25),
|
||||
radius: 120,
|
||||
target: new BABYLON.Vector3(-110, 0, -8),
|
||||
// Part_1: {
|
||||
// alpha: BABYLON.Tools.ToRadians(270),
|
||||
// beta: BABYLON.Tools.ToRadians(25),
|
||||
// radius: 85,
|
||||
// target: new BABYLON.Vector3(-110, 0, -8),
|
||||
// },
|
||||
// Part_2: {
|
||||
// alpha: BABYLON.Tools.ToRadians(270),
|
||||
// beta: BABYLON.Tools.ToRadians(25),
|
||||
// radius: 85,
|
||||
// target: new BABYLON.Vector3(-40, 0, -8),
|
||||
// },
|
||||
// Part_3: {
|
||||
// alpha: BABYLON.Tools.ToRadians(270),
|
||||
// beta: BABYLON.Tools.ToRadians(25),
|
||||
// radius: 85,
|
||||
// target: new BABYLON.Vector3(0, 0, -8),
|
||||
// },
|
||||
// Part_4: {
|
||||
// alpha: BABYLON.Tools.ToRadians(270),
|
||||
// beta: BABYLON.Tools.ToRadians(25),
|
||||
// radius: 85,
|
||||
// target: new BABYLON.Vector3(110, 0, -8),
|
||||
// },
|
||||
};
|
||||
|
||||
interface MybabylonJSProps {
|
||||
modelPath: string; // 明确 modelPath 属性的类型为 string
|
||||
}
|
||||
|
||||
function MybabylonJS({ modelPath }: MybabylonJSProps) {
|
||||
const onGlassObservable = useContext(MyObservable);
|
||||
const EquStatus = useAppSelector(selectEquStatus);
|
||||
const canvasRef = useRef(null);
|
||||
onEquObservable.notifyObservers(EquStatus);
|
||||
// const thisLineGlassStatus = useAppSelector(selectGlassStatus)
|
||||
// onGlassObservable.notifyObservers(thisLineGlassStatus)
|
||||
const [SelectedMeshName, setSelectedMeshName] = useState<string | null>(null);
|
||||
|
||||
interface MybabylonJSProps {
|
||||
modelPath: string;
|
||||
}
|
||||
|
||||
// 使用 useRef 来存储当前加载的模型引用
|
||||
const currentMeshesRef = useRef<Array<BABYLON.AbstractMesh>>([]);
|
||||
|
||||
useEffect(() => {
|
||||
// 确保 canvas 引用存在
|
||||
if (!canvasRef.current) return;
|
||||
@ -120,19 +51,6 @@ function MybabylonJS({ modelPath }: MybabylonJSProps) {
|
||||
const scene = new BABYLON.Scene(engine);
|
||||
scene.clearColor = new BABYLON.Color4(0, 0, 0, 0);
|
||||
|
||||
const light = new BABYLON.DirectionalLight(
|
||||
"light",
|
||||
new BABYLON.Vector3(20, 20, 100),
|
||||
scene
|
||||
);
|
||||
const light2 = new BABYLON.PointLight(
|
||||
"light2",
|
||||
new BABYLON.Vector3(20, 20, 100),
|
||||
scene
|
||||
);
|
||||
|
||||
const Glass1_1 = new BABYLON.TransformNode("Glass1_1");
|
||||
|
||||
const baseLight = new HemisphericLight(
|
||||
"hemiLight",
|
||||
new Vector3(-1, 1, 0),
|
||||
@ -148,9 +66,14 @@ function MybabylonJS({ modelPath }: MybabylonJSProps) {
|
||||
"camera",
|
||||
BABYLON.Tools.ToRadians(245),
|
||||
BABYLON.Tools.ToRadians(25),
|
||||
90,
|
||||
modelPath.slice(-1) === "1"
|
||||
? 110
|
||||
: modelPath.slice(-3) === "5-2"
|
||||
? 100
|
||||
: 80,
|
||||
new BABYLON.Vector3(-13, 0, 0)
|
||||
);
|
||||
console.log("camera", camera);
|
||||
camera.lowerRadiusLimit = 10;
|
||||
camera.upperRadiusLimit = 600;
|
||||
|
||||
@ -194,8 +117,6 @@ function MybabylonJS({ modelPath }: MybabylonJSProps) {
|
||||
let hl = new BABYLON.HighlightLayer("hl1", scene);
|
||||
let hl2 = new BABYLON.HighlightLayer("hl2", scene);
|
||||
|
||||
// var LOD0MESH = await BABYLON.SceneLoader.ImportMeshAsync('', '/test/', `${modelPath}.babylon`, scene);
|
||||
|
||||
// 定义一个函数来加载或重新加载模型
|
||||
const loadOrReloadModel = async () => {
|
||||
// 在加载新模型之前卸载已加载的模型
|
||||
@ -213,11 +134,6 @@ function MybabylonJS({ modelPath }: MybabylonJSProps) {
|
||||
`${modelPath}.babylon`,
|
||||
scene
|
||||
);
|
||||
// var LOD0MESH = await BABYLON.SceneLoader.ImportMeshAsync('', '/test/', `line1.babylon`, scene);
|
||||
// var LOD1MESH = await BABYLON.SceneLoader.ImportMeshAsync('', '/test/', `line2.babylon`, scene);
|
||||
// var LOD2MESH = await BABYLON.SceneLoader.ImportMeshAsync('', '/test/', `line3.babylon`, scene);
|
||||
// var LOD3MESH = await BABYLON.SceneLoader.ImportMeshAsync('', '/test/', `line4.babylon`, scene);
|
||||
// var LOD4MESH = await BABYLON.SceneLoader.ImportMeshAsync('', '/test/', `line5.babylon`, scene);
|
||||
// 将新加载的模型添加到 currentMeshesRef 中
|
||||
currentMeshesRef.current.push(...LOD0MESH.meshes);
|
||||
|
||||
@ -264,7 +180,6 @@ function MybabylonJS({ modelPath }: MybabylonJSProps) {
|
||||
};
|
||||
});
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
onEquObservable.add((eventData, eventState) => {
|
||||
LOD0MESH.meshes.find((mesh) => {
|
||||
// @ts-ignore
|
||||
@ -285,8 +200,6 @@ function MybabylonJS({ modelPath }: MybabylonJSProps) {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
} catch (error) {
|
||||
console.error("加载模型失败:", error);
|
||||
}
|
||||
@ -299,50 +212,22 @@ function MybabylonJS({ modelPath }: MybabylonJSProps) {
|
||||
camera.target = new BABYLON.Vector3(-13, 0, 0);
|
||||
camera.alpha = BABYLON.Tools.ToRadians(245);
|
||||
camera.beta = BABYLON.Tools.ToRadians(25);
|
||||
camera.radius = 90;
|
||||
camera.radius =
|
||||
modelPath.slice(-1) === "1"
|
||||
? 110
|
||||
: modelPath.slice(-3) === "5-2"
|
||||
? 100
|
||||
: 80;
|
||||
}
|
||||
|
||||
let resetCamera = setTimeout(reset, 15000);
|
||||
scene.onPointerObservable.add((pointerInfo) => {
|
||||
// console.log(camera.target, camera.alpha * 180 / 3.14, camera.beta * 180 / 3.14, camera.radius)
|
||||
switch (pointerInfo.type) {
|
||||
case BABYLON.PointerEventTypes.POINTERMOVE:
|
||||
clearTimeout(resetCamera);
|
||||
resetCamera = setTimeout(reset, 15000);
|
||||
}
|
||||
});
|
||||
|
||||
// onMainCamObservable.add((eventData, eventState) => {
|
||||
// clearTimeout(resetCamera);
|
||||
// resetCamera = setTimeout(reset, 5000);
|
||||
// switch (eventData) {
|
||||
// case 1:
|
||||
// camera.target = DetailCamera.Part_1.target;
|
||||
// camera.alpha = DetailCamera.Part_1.alpha;
|
||||
// camera.beta = DetailCamera.Part_1.beta;
|
||||
// camera.radius = DetailCamera.Part_1.radius;
|
||||
// break;
|
||||
// case 2:
|
||||
// camera.target = DetailCamera.Part_2.target;
|
||||
// camera.alpha = DetailCamera.Part_2.alpha;
|
||||
// camera.beta = DetailCamera.Part_2.beta;
|
||||
// camera.radius = DetailCamera.Part_2.radius;
|
||||
// break;
|
||||
// case 3:
|
||||
// camera.target = DetailCamera.Part_3.target;
|
||||
// camera.alpha = DetailCamera.Part_3.alpha;
|
||||
// camera.beta = DetailCamera.Part_3.beta;
|
||||
// camera.radius = DetailCamera.Part_3.radius;
|
||||
// break;
|
||||
// case 4:
|
||||
// camera.target = DetailCamera.Part_4.target;
|
||||
// camera.alpha = DetailCamera.Part_4.alpha;
|
||||
// camera.beta = DetailCamera.Part_4.beta;
|
||||
// camera.radius = DetailCamera.Part_4.radius;
|
||||
// break;
|
||||
// }
|
||||
// });
|
||||
|
||||
return scene;
|
||||
};
|
||||
|
||||
@ -375,52 +260,8 @@ function MybabylonJS({ modelPath }: MybabylonJSProps) {
|
||||
};
|
||||
}, [modelPath]);
|
||||
|
||||
// const handleClick1 = () => {
|
||||
// onMainCamObservable.notifyObservers(1);
|
||||
// };
|
||||
// const handleClick2 = () => {
|
||||
// onMainCamObservable.notifyObservers(2);
|
||||
// };
|
||||
// const handleClick3 = () => {
|
||||
// onMainCamObservable.notifyObservers(3);
|
||||
// };
|
||||
// const handleClick4 = () => {
|
||||
// onMainCamObservable.notifyObservers(4);
|
||||
// };
|
||||
|
||||
return (
|
||||
<div style={myStyle}>
|
||||
{/* <ButtonGroup
|
||||
variant="contained"
|
||||
aria-label="outlined button group"
|
||||
className={"btnArea"}
|
||||
>
|
||||
<h2>当前选择: {SelectedMeshName}</h2>
|
||||
<Button
|
||||
sx={{ backgroundColor: "rgba(86, 244, 231, 0.69)" }}
|
||||
onClick={handleClick1}
|
||||
>
|
||||
{intl.get("Part1")}
|
||||
</Button>
|
||||
<Button
|
||||
sx={{ backgroundColor: "rgba(86, 244, 231, 0.69)" }}
|
||||
onClick={handleClick2}
|
||||
>
|
||||
{intl.get("Part2")}
|
||||
</Button>
|
||||
<Button
|
||||
sx={{ backgroundColor: "rgba(86, 244, 231, 0.69)" }}
|
||||
onClick={handleClick3}
|
||||
>
|
||||
{intl.get("Part3")}
|
||||
</Button>
|
||||
<Button
|
||||
sx={{ backgroundColor: "rgba(86, 244, 231, 0.69)" }}
|
||||
onClick={handleClick4}
|
||||
>
|
||||
{intl.get("Part4")}
|
||||
</Button>
|
||||
</ButtonGroup> */}
|
||||
<canvas ref={canvasRef} style={myStyle} />
|
||||
</div>
|
||||
);
|
||||
|
45
src/page/Component/ScrollBoard/index.css
Normal file
45
src/page/Component/ScrollBoard/index.css
Normal file
@ -0,0 +1,45 @@
|
||||
.dv-scroll-board {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
color: #fff;
|
||||
}
|
||||
.dv-scroll-board .text {
|
||||
padding: 0 10px;
|
||||
box-sizing: border-box;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.dv-scroll-board .header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
font-size: 15px;
|
||||
}
|
||||
.dv-scroll-board .header .header-item {
|
||||
transition: all 0.3s;
|
||||
padding: 0 10px;
|
||||
box-sizing: border-box;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.dv-scroll-board .rows {
|
||||
overflow: hidden;
|
||||
}
|
||||
.dv-scroll-board .rows .ceil {
|
||||
padding: 0 10px;
|
||||
box-sizing: border-box;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.dv-scroll-board .rows .row-item {
|
||||
display: flex;
|
||||
font-size: 14px;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
.dv-scroll-board .rows .row-item .index {
|
||||
border-radius: 3px;
|
||||
padding: 0px 3px;
|
||||
}
|
440
src/page/Component/ScrollBoard/index.tsx
Normal file
440
src/page/Component/ScrollBoard/index.tsx
Normal file
@ -0,0 +1,440 @@
|
||||
import React, { useEffect, useState, useRef, useMemo, forwardRef } from "react";
|
||||
import useAutoResize from "./use/autoResize";
|
||||
import { deepMerge } from "./util";
|
||||
import { deepClone } from "./util/utils";
|
||||
import { co } from "./util";
|
||||
import classnames from "classnames";
|
||||
import "./index.css";
|
||||
import { current } from "@reduxjs/toolkit";
|
||||
interface ScrollBoardProps {
|
||||
config?: object;
|
||||
onClick?: () => void;
|
||||
onMouseOver?: () => void;
|
||||
className?: string;
|
||||
style?: object;
|
||||
}
|
||||
interface TaskType {
|
||||
end: () => void;
|
||||
pause: () => void;
|
||||
resume: () => void;
|
||||
}
|
||||
|
||||
const defaultConfig = {
|
||||
/**
|
||||
* @description Board header
|
||||
* @type {Array<String>}
|
||||
* @default header = []
|
||||
* @example header = ['column1', 'column2', 'column3']
|
||||
*/
|
||||
header: [],
|
||||
/**
|
||||
* @description Board data
|
||||
* @type {Array<Array>}
|
||||
* @default data = []
|
||||
*/
|
||||
data: [],
|
||||
/**
|
||||
* @description Row num
|
||||
* @type {Number}
|
||||
* @default rowNum = 5
|
||||
*/
|
||||
rowNum: 5,
|
||||
/**
|
||||
* @description Header background color
|
||||
* @type {String}
|
||||
* @default headerBGC = '#00BAFF'
|
||||
*/
|
||||
headerBGC: "#00BAFF",
|
||||
/**
|
||||
* @description Odd row background color
|
||||
* @type {String}
|
||||
* @default oddRowBGC = '#003B51'
|
||||
*/
|
||||
oddRowBGC: "#003B51",
|
||||
/**
|
||||
* @description Even row background color
|
||||
* @type {String}
|
||||
* @default evenRowBGC = '#003B51'
|
||||
*/
|
||||
evenRowBGC: "#0A2732",
|
||||
/**
|
||||
* @description Scroll wait time
|
||||
* @type {Number}
|
||||
* @default waitTime = 2000
|
||||
*/
|
||||
waitTime: 2000,
|
||||
/**
|
||||
* @description Header height
|
||||
* @type {Number}
|
||||
* @default headerHeight = 35
|
||||
*/
|
||||
headerHeight: 35,
|
||||
/**
|
||||
* @description Column width
|
||||
* @type {Array<Number>}
|
||||
* @default columnWidth = []
|
||||
*/
|
||||
columnWidth: [],
|
||||
/**
|
||||
* @description Column align
|
||||
* @type {Array<String>}
|
||||
* @default align = []
|
||||
* @example align = ['left', 'center', 'right']
|
||||
*/
|
||||
align: [],
|
||||
/**
|
||||
* @description Show index
|
||||
* @type {Boolean}
|
||||
* @default index = false
|
||||
*/
|
||||
index: false,
|
||||
/**
|
||||
* @description index Header
|
||||
* @type {String}
|
||||
* @default indexHeader = '#'
|
||||
*/
|
||||
indexHeader: "#",
|
||||
/**
|
||||
* @description Carousel type
|
||||
* @type {String}
|
||||
* @default carousel = 'single'
|
||||
* @example carousel = 'single' | 'page'
|
||||
*/
|
||||
carousel: "single",
|
||||
/**
|
||||
* @description Pause scroll when mouse hovered
|
||||
* @type {Boolean}
|
||||
* @default hoverPause = true
|
||||
* @example hoverPause = true | false
|
||||
*/
|
||||
hoverPause: true,
|
||||
};
|
||||
function calcHeaderData({ header, index, indexHeader }: any) {
|
||||
if (!header.length) {
|
||||
return [];
|
||||
}
|
||||
|
||||
header = [...header];
|
||||
|
||||
if (index) header.unshift(indexHeader);
|
||||
|
||||
return header;
|
||||
}
|
||||
function calcRows({ data, index, headerBGC, rowNum }: any) {
|
||||
if (index) {
|
||||
data = data.map((row: any, i: any) => {
|
||||
row = [...row];
|
||||
|
||||
const indexTag = `<span class="index" style="background-color: ${headerBGC};">${
|
||||
i + 1
|
||||
}</span>`;
|
||||
|
||||
row.unshift(indexTag);
|
||||
|
||||
return row;
|
||||
});
|
||||
}
|
||||
|
||||
data = data.map((ceils: any, i: any) => ({ ceils, rowIndex: i }));
|
||||
|
||||
const rowLength = data.length;
|
||||
|
||||
if (rowLength > rowNum && rowLength < 2 * rowNum) {
|
||||
data = [...data, ...data];
|
||||
}
|
||||
|
||||
return data.map((d: any, i: any) => ({ ...d, scroll: i }));
|
||||
}
|
||||
function calcAligns(mergedConfig: any, header: any) {
|
||||
const columnNum = header.length;
|
||||
|
||||
let aligns = new Array(columnNum).fill("left");
|
||||
|
||||
const { align } = mergedConfig;
|
||||
|
||||
return deepMerge(aligns, align);
|
||||
}
|
||||
const ScrollBoard = forwardRef(
|
||||
(
|
||||
{ config, onClick, onMouseOver, className, style }: ScrollBoardProps,
|
||||
ref
|
||||
) => {
|
||||
const { width, height, domRef } = useAutoResize(ref);
|
||||
const [state, setState] = useState({
|
||||
mergedConfig: {
|
||||
align: [],
|
||||
carousel: "",
|
||||
columnWidth: [],
|
||||
data: [],
|
||||
evenRowBGC: "",
|
||||
header: [],
|
||||
headerBGC: "",
|
||||
headerHeight: 35,
|
||||
hoverPause: true,
|
||||
index: false,
|
||||
oddRowBGC: "",
|
||||
indexHeader: "#",
|
||||
rowNum: 5,
|
||||
waitTime: 2000,
|
||||
},
|
||||
header: [],
|
||||
rows: [],
|
||||
widths: [],
|
||||
heights: [],
|
||||
aligns: [],
|
||||
});
|
||||
const { mergedConfig, header, rows, widths, heights, aligns } = state;
|
||||
const stateRef = useRef({
|
||||
...state,
|
||||
rowsData: [],
|
||||
avgHeight: 0,
|
||||
animationIndex: 0,
|
||||
});
|
||||
Object.assign(stateRef.current, state);
|
||||
function onResize() {
|
||||
if (!mergedConfig) return;
|
||||
|
||||
const widths = calcWidths(mergedConfig, stateRef.current.rowsData);
|
||||
|
||||
const heights = calcHeights(mergedConfig, header);
|
||||
|
||||
const data: any = { widths, heights };
|
||||
|
||||
Object.assign(stateRef.current, data);
|
||||
setState((state) => ({ ...state, ...data }));
|
||||
}
|
||||
function calcData() {
|
||||
const mergedConfig = deepMerge(
|
||||
// deepClone(defaultConfig, true),
|
||||
deepClone(defaultConfig),
|
||||
config || {}
|
||||
);
|
||||
|
||||
const header = calcHeaderData(mergedConfig);
|
||||
|
||||
const rows = calcRows(mergedConfig);
|
||||
|
||||
const widths = calcWidths(mergedConfig, stateRef.current.rowsData);
|
||||
|
||||
const heights = calcHeights(mergedConfig, header);
|
||||
|
||||
const aligns = calcAligns(mergedConfig, header);
|
||||
|
||||
const data: any = {
|
||||
mergedConfig,
|
||||
header,
|
||||
rows,
|
||||
widths,
|
||||
aligns,
|
||||
heights,
|
||||
};
|
||||
|
||||
Object.assign(stateRef.current, data, {
|
||||
rowsData: rows,
|
||||
animationIndex: 0,
|
||||
});
|
||||
|
||||
setState((state) => ({ ...state, ...data }));
|
||||
}
|
||||
|
||||
function calcWidths({ columnWidth, header }: any, rowsData: any) {
|
||||
const usedWidth = columnWidth.reduce((all: any, w: any) => all + w, 0);
|
||||
|
||||
let columnNum = 0;
|
||||
if (rowsData[0]) {
|
||||
columnNum = rowsData[0].ceils.length;
|
||||
} else if (header.length) {
|
||||
columnNum = header.length;
|
||||
}
|
||||
|
||||
const avgWidth = (width - usedWidth) / (columnNum - columnWidth.length);
|
||||
|
||||
const widths = new Array(columnNum).fill(avgWidth);
|
||||
|
||||
return deepMerge(widths, columnWidth);
|
||||
}
|
||||
function calcHeights({ headerHeight, rowNum, data }: any, header: any) {
|
||||
let allHeight = height;
|
||||
|
||||
if (header.length) allHeight -= headerHeight;
|
||||
|
||||
const avgHeight = allHeight / rowNum;
|
||||
|
||||
Object.assign(stateRef.current, { avgHeight });
|
||||
|
||||
return new Array(data.length).fill(avgHeight);
|
||||
}
|
||||
function* animation(
|
||||
start = false
|
||||
): Generator<Promise<void>, void, unknown> {
|
||||
let {
|
||||
avgHeight,
|
||||
animationIndex,
|
||||
mergedConfig: { waitTime, carousel, rowNum },
|
||||
rowsData,
|
||||
} = stateRef.current;
|
||||
const rowLength = rowsData.length;
|
||||
|
||||
if (start) yield new Promise((resolve) => setTimeout(resolve, waitTime));
|
||||
|
||||
const animationNum = carousel === "single" ? 1 : rowNum;
|
||||
|
||||
let rows: any = rowsData.slice(animationIndex);
|
||||
rows.push(...rowsData.slice(0, animationIndex));
|
||||
rows = rows.slice(0, carousel === "page" ? rowNum * 2 : rowNum + 1);
|
||||
|
||||
const heights: any = new Array(rowLength).fill(avgHeight);
|
||||
setState((state) => ({ ...state, rows, heights }));
|
||||
|
||||
yield new Promise((resolve) => setTimeout(resolve, 300));
|
||||
|
||||
animationIndex += animationNum;
|
||||
|
||||
const back = animationIndex - rowLength;
|
||||
if (back >= 0) animationIndex = back;
|
||||
|
||||
const newHeights: any = [...heights];
|
||||
newHeights.splice(0, animationNum, ...new Array(animationNum).fill(0));
|
||||
|
||||
Object.assign(stateRef.current, { animationIndex });
|
||||
setState((state) => ({ ...state, heights: newHeights }));
|
||||
}
|
||||
function emitEvent(handle: any, ri: any, ci: any, row: any, ceil: any) {
|
||||
const { ceils, rowIndex } = row;
|
||||
|
||||
handle && handle({ row: ceils, ceil, rowIndex, columnIndex: ci });
|
||||
}
|
||||
|
||||
function handleHover(
|
||||
enter: any,
|
||||
ri?: any,
|
||||
ci?: any,
|
||||
row?: any,
|
||||
ceil?: any
|
||||
) {
|
||||
if (enter) emitEvent(onMouseOver, ri, ci, row, ceil);
|
||||
|
||||
if (!mergedConfig.hoverPause) return;
|
||||
|
||||
if (task.current) {
|
||||
const { pause, resume } = task.current;
|
||||
|
||||
enter
|
||||
? (function () {
|
||||
if (pause) pause();
|
||||
})()
|
||||
: (function () {
|
||||
if (resume) resume();
|
||||
})();
|
||||
}
|
||||
}
|
||||
|
||||
const getBackgroundColor = (rowIndex: any) =>
|
||||
mergedConfig[rowIndex % 2 === 0 ? "evenRowBGC" : "oddRowBGC"];
|
||||
|
||||
const task = useRef<TaskType>(null);
|
||||
|
||||
useEffect(() => {
|
||||
calcData();
|
||||
|
||||
let start = true;
|
||||
|
||||
function* loop() {
|
||||
while (true) {
|
||||
yield* animation(start);
|
||||
|
||||
start = false;
|
||||
|
||||
const { waitTime } = stateRef.current.mergedConfig;
|
||||
|
||||
yield new Promise((resolve) => setTimeout(resolve, waitTime - 300));
|
||||
}
|
||||
}
|
||||
|
||||
const {
|
||||
mergedConfig: { rowNum },
|
||||
rows: rowsData,
|
||||
} = stateRef.current;
|
||||
|
||||
const rowLength = rowsData.length;
|
||||
if (rowNum >= rowLength) return;
|
||||
// @ts-ignore
|
||||
task.current = co(loop);
|
||||
if (task.current) {
|
||||
return task.current.end;
|
||||
}
|
||||
}, [config, domRef.current]);
|
||||
|
||||
useEffect(onResize, [width, height, domRef.current]);
|
||||
|
||||
const classNames = useMemo(
|
||||
() => classnames("dv-scroll-board", className),
|
||||
[className]
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={classNames} style={style} ref={domRef}>
|
||||
{!!header.length && !!mergedConfig && (
|
||||
<div
|
||||
className="header"
|
||||
style={{ backgroundColor: `${mergedConfig.headerBGC}` }}
|
||||
>
|
||||
{header.map((headerItem, i) => (
|
||||
<div
|
||||
className="header-item"
|
||||
key={`${headerItem}-${i}`}
|
||||
style={{
|
||||
height: `${mergedConfig.headerHeight}px`,
|
||||
lineHeight: `${mergedConfig.headerHeight}px`,
|
||||
width: `${widths[i]}px`,
|
||||
}}
|
||||
// @ts-ignore
|
||||
align={aligns[i]}
|
||||
dangerouslySetInnerHTML={{ __html: headerItem }}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!!mergedConfig && (
|
||||
<div
|
||||
className="rows"
|
||||
style={{
|
||||
height: `${
|
||||
height - (header.length ? mergedConfig.headerHeight : 0)
|
||||
}px`,
|
||||
}}
|
||||
>
|
||||
{rows.map((row: any, ri) => (
|
||||
<div
|
||||
className="row-item"
|
||||
key={`${row.toString()}-${row.scroll}`}
|
||||
style={{
|
||||
height: `${heights[ri]}px`,
|
||||
lineHeight: `${heights[ri]}px`,
|
||||
backgroundColor: `${getBackgroundColor(row.rowIndex)}`,
|
||||
}}
|
||||
>
|
||||
{row.ceils.map((ceil: any, ci: any) => (
|
||||
<div
|
||||
className="ceil"
|
||||
key={`${ceil}-${ri}-${ci}`}
|
||||
style={{ width: `${widths[ci]}px` }}
|
||||
// @ts-ignore
|
||||
align={aligns[ci]}
|
||||
dangerouslySetInnerHTML={{ __html: ceil }}
|
||||
onClick={() => emitEvent(onClick, ri, ci, row, ceil)}
|
||||
onMouseEnter={() => handleHover(true, ri, ci, row, ceil)}
|
||||
onMouseLeave={() => handleHover(false)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default ScrollBoard;
|
57
src/page/Component/ScrollBoard/use/autoResize.ts
Normal file
57
src/page/Component/ScrollBoard/use/autoResize.ts
Normal file
@ -0,0 +1,57 @@
|
||||
import {
|
||||
useState,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useRef,
|
||||
useImperativeHandle,
|
||||
} from "react";
|
||||
import { debounce, observerDomResize } from "../util/index";
|
||||
|
||||
export default function useAutoResize(ref: any) {
|
||||
const [state, setState] = useState({ width: 0, height: 0 });
|
||||
|
||||
const domRef = useRef(null);
|
||||
|
||||
const setWH = useCallback(() => {
|
||||
const { clientWidth, clientHeight } = domRef.current || {
|
||||
clientWidth: 0,
|
||||
clientHeight: 0,
|
||||
};
|
||||
|
||||
setState({ width: clientWidth, height: clientHeight });
|
||||
|
||||
if (!domRef.current) {
|
||||
console.warn(
|
||||
"DataV: Failed to get dom node, component rendering may be abnormal!"
|
||||
);
|
||||
} else if (!clientWidth || !clientHeight) {
|
||||
console.warn(
|
||||
"DataV: Component width or height is 0px, rendering abnormality may occur!"
|
||||
);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useImperativeHandle(ref, () => ({ setWH }), []);
|
||||
|
||||
useEffect(() => {
|
||||
const debounceSetWHFun = debounce(setWH, 100);
|
||||
|
||||
debounceSetWHFun();
|
||||
const domObserver = observerDomResize(domRef.current, debounceSetWHFun);
|
||||
|
||||
window.addEventListener("resize", debounceSetWHFun);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("resize", debounceSetWHFun);
|
||||
|
||||
if (!domObserver) {
|
||||
return;
|
||||
}
|
||||
|
||||
domObserver.disconnect();
|
||||
domObserver.takeRecords();
|
||||
};
|
||||
}, []);
|
||||
|
||||
return { ...state, domRef, setWH };
|
||||
}
|
57
src/page/Component/ScrollBoard/use/autoResize1.js
Normal file
57
src/page/Component/ScrollBoard/use/autoResize1.js
Normal file
@ -0,0 +1,57 @@
|
||||
import {
|
||||
useState,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useRef,
|
||||
useImperativeHandle,
|
||||
} from "react";
|
||||
import { debounce, observerDomResize } from "../util/index";
|
||||
|
||||
export default function useAutoResize(ref) {
|
||||
const [state, setState] = useState({ width: 0, height: 0 });
|
||||
|
||||
const domRef = useRef(null);
|
||||
|
||||
const setWH = useCallback(() => {
|
||||
const { clientWidth, clientHeight } = domRef.current || {
|
||||
clientWidth: 0,
|
||||
clientHeight: 0,
|
||||
};
|
||||
|
||||
setState({ width: clientWidth, height: clientHeight });
|
||||
|
||||
if (!domRef.current) {
|
||||
console.warn(
|
||||
"DataV: Failed to get dom node, component rendering may be abnormal!"
|
||||
);
|
||||
} else if (!clientWidth || !clientHeight) {
|
||||
console.warn(
|
||||
"DataV: Component width or height is 0px, rendering abnormality may occur!"
|
||||
);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useImperativeHandle(ref, () => ({ setWH }), []);
|
||||
|
||||
useEffect(() => {
|
||||
const debounceSetWHFun = debounce(setWH, 100);
|
||||
|
||||
debounceSetWHFun();
|
||||
const domObserver = observerDomResize(domRef.current, debounceSetWHFun);
|
||||
|
||||
window.addEventListener("resize", debounceSetWHFun);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("resize", debounceSetWHFun);
|
||||
|
||||
if (!domObserver) {
|
||||
return;
|
||||
}
|
||||
|
||||
domObserver.disconnect();
|
||||
domObserver.takeRecords();
|
||||
};
|
||||
}, []);
|
||||
|
||||
return { ...state, domRef, setWH };
|
||||
}
|
114
src/page/Component/ScrollBoard/util/index.ts
Normal file
114
src/page/Component/ScrollBoard/util/index.ts
Normal file
@ -0,0 +1,114 @@
|
||||
export function co(gen: any) {
|
||||
let destroyed = false;
|
||||
|
||||
// 处理 return 之后 resume 的问题
|
||||
let stop = false;
|
||||
|
||||
let val: any = null;
|
||||
|
||||
if (typeof gen === "function") gen = gen();
|
||||
|
||||
if (!gen || typeof gen.next !== "function") return () => ({});
|
||||
|
||||
Promise.resolve().then(() => {
|
||||
destroyed || next(gen.next());
|
||||
});
|
||||
|
||||
return {
|
||||
end() {
|
||||
destroyed = true;
|
||||
|
||||
Promise.resolve().then(() => {
|
||||
gen.return();
|
||||
|
||||
gen = null;
|
||||
});
|
||||
},
|
||||
pause() {
|
||||
if (!destroyed) {
|
||||
stop = true;
|
||||
}
|
||||
},
|
||||
resume() {
|
||||
const oldVal = val;
|
||||
|
||||
if (!destroyed && stop) {
|
||||
stop = false;
|
||||
|
||||
Promise.resolve(val).then(function () {
|
||||
if (!destroyed && !stop && oldVal === val) {
|
||||
next(gen.next());
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
function next(ret: any) {
|
||||
if (ret.done) return ret.value;
|
||||
|
||||
val = ret.value;
|
||||
|
||||
return Promise.resolve(ret.value).then(() => {
|
||||
!destroyed && !stop && next(gen.next());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 将函数转成防抖动函数
|
||||
* @param {Function} 需要转成防抖动函数的函数
|
||||
* @param {number} 延迟时间(毫秒数)
|
||||
* @param {boolean} 是否执行第一次
|
||||
* @return {undefined} 无返回值
|
||||
*/
|
||||
export function debounce(fn: any, delay = 600, runFirstFn = true) {
|
||||
let timer: any = null;
|
||||
|
||||
return function (this: any, ...rest: any) {
|
||||
// 清除定时器
|
||||
clearTimeout(timer);
|
||||
if (runFirstFn) {
|
||||
fn.apply(this, rest);
|
||||
runFirstFn = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// 设置定时器
|
||||
timer = setTimeout(fn.bind(this, ...rest), delay);
|
||||
};
|
||||
}
|
||||
export function observerDomResize(dom: any, callback: any) {
|
||||
const MutationObserver = window.MutationObserver;
|
||||
// window.WebKitMutationObserver ||
|
||||
// window.MozMutationObserver;
|
||||
|
||||
const observer = new MutationObserver(callback);
|
||||
|
||||
observer.observe(dom, {
|
||||
attributes: true,
|
||||
attributeFilter: ["style"],
|
||||
attributeOldValue: true,
|
||||
});
|
||||
return observer;
|
||||
}
|
||||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
||||
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
|
||||
var _util = require("./../util/utils");
|
||||
export function deepMerge(target: any, merged: any) {
|
||||
for (var key in merged) {
|
||||
if (target[key] && _typeof2["default"](target[key]) === "object") {
|
||||
deepMerge(target[key], merged[key]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_typeof2["default"](merged[key]) === "object") {
|
||||
target[key] = _util.deepClone(merged[key], true);
|
||||
continue;
|
||||
}
|
||||
|
||||
target[key] = merged[key];
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
32
src/page/Component/ScrollBoard/util/utils.ts
Normal file
32
src/page/Component/ScrollBoard/util/utils.ts
Normal file
@ -0,0 +1,32 @@
|
||||
/**
|
||||
* @description Clone an object or array
|
||||
* @param {Object|Array} object Cloned object
|
||||
* @param {Boolean} recursion Whether to use recursive cloning
|
||||
* @return {Object|Array} Clone object
|
||||
*/
|
||||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
||||
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
|
||||
export function deepClone(object: any) {
|
||||
var recursion =
|
||||
arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
||||
if (!object) return object;
|
||||
var parse = JSON.parse,
|
||||
stringify = JSON.stringify;
|
||||
if (!recursion) return parse(stringify(object));
|
||||
var clonedObj: any = object instanceof Array ? [] : {};
|
||||
|
||||
if (object && _typeof2["default"](object) === "object") {
|
||||
for (var key in object) {
|
||||
if (object.hasOwnProperty(key)) {
|
||||
if (object[key] && _typeof2["default"](object[key]) === "object") {
|
||||
// clonedObj[key] = deepClone(object[key], true);
|
||||
clonedObj[key] = deepClone(object[key]);
|
||||
} else {
|
||||
clonedObj[key] = object[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return clonedObj;
|
||||
}
|
@ -1,16 +1,60 @@
|
||||
import TitleBox from "../Component/TitleBox";
|
||||
import LineChart from "./LineChart";
|
||||
import ScrollBoard from "./../../Component/ScrollBoard";
|
||||
import SwitchButton from "../Component/SwitchButton";
|
||||
import { useState } from "react";
|
||||
function CenterDown() {
|
||||
const nameList = [{ name: "天" }, { name: "周" }, { name: "月" }];
|
||||
const [activeName, setActiveName] = useState<string>(nameList[0].name);
|
||||
const config = {
|
||||
header: ["序号", "报警时间", "报警编码", "设备状态"],
|
||||
headerHeight: 36,
|
||||
rowNum: 6,
|
||||
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", "行1列1", "行1列2", "<span style='color:#FF1E1E'>行1列3</span>"],
|
||||
["2", "行2列1", "行2列2", "<span style='color:#FF1E1E'>行2列3</span>"],
|
||||
["3", "行3列1", "行3列2", "<span style='color:#FF1E1E'>行3列3</span>"],
|
||||
["4", "行4列1", "行4列2", "<span style='color:#FFB40F'>行4列3</span>"],
|
||||
["5", "行5列1", "行5列2", "<span style='color:#FF1E1E'>行5列3</span>"],
|
||||
["6", "行6列1", "行6列2", "<span style='color:#FFB40F'>行6列3</span>"],
|
||||
["7", "行7列1", "行7列2", "<span style='color:#FF1E1E'>行7列3</span>"],
|
||||
["8", "行8列1", "行8列2", "<span style='color:#FF1E1E'>行8列3</span>"],
|
||||
["9", "行9列1", "行9列2", "<span style='color:#FF1E1E'>行9列3</span>"],
|
||||
[
|
||||
"10",
|
||||
"行10列1",
|
||||
"行10列2",
|
||||
"<span style='color:#FFB40F'>行10列3</span>",
|
||||
],
|
||||
],
|
||||
};
|
||||
return (
|
||||
<div className="center_down flex-row">
|
||||
<div className="center_down_inner flex-col left-box">
|
||||
<TitleBox title={"center_down_left"} />
|
||||
<span className="alarm_num_title">— 报警总数 —</span>
|
||||
<div className="alarm_num">321,343</div>
|
||||
<div style={{ padding: 10, height: "270px" }}>
|
||||
<ScrollBoard
|
||||
config={config}
|
||||
style={{ width: "492px", height: "250px" }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{/* 产线成品率 */}
|
||||
<div className="center_down_inner flex-col right_box">
|
||||
<TitleBox title={"center_down_right"} />
|
||||
<div className="left_up_switch">
|
||||
<SwitchButton
|
||||
nameList={nameList}
|
||||
activeName={activeName}
|
||||
setActiveName={setActiveName}
|
||||
/>
|
||||
</div>
|
||||
<div className="chart_box">
|
||||
<LineChart />
|
||||
</div>
|
||||
|
@ -1,8 +1,11 @@
|
||||
import LinePageBabylon from "../../../babylonjs/LinePageBabylon";
|
||||
import { useParams } from "react-router-dom";
|
||||
function CenterUp() {
|
||||
const { LineID } = useParams();
|
||||
const lineID = LineID?.toString() || "1-1";
|
||||
return (
|
||||
<div className="center_up">
|
||||
<LinePageBabylon modelPath={`Line1-2`} />
|
||||
<LinePageBabylon modelPath={`Line${lineID}`} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -70,31 +70,44 @@ export default function getOptions() {
|
||||
},
|
||||
},
|
||||
},
|
||||
tooltip: {},
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
className: "luoyang-chart-tooltip",
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: "产线1",
|
||||
type: "line",
|
||||
symbol: "circle",
|
||||
symbolSize: 4,
|
||||
data: [20, 32, 10, 34, 90, 30, 20],
|
||||
},
|
||||
{
|
||||
name: "产线2",
|
||||
type: "line",
|
||||
symbol: "circle",
|
||||
symbolSize: 4,
|
||||
data: [22, 82, 91, 34, 90, 33, 31],
|
||||
},
|
||||
{
|
||||
name: "产线3",
|
||||
type: "line",
|
||||
symbol: "circle",
|
||||
symbolSize: 4,
|
||||
data: [50, 32, 20, 54, 19, 33, 41],
|
||||
},
|
||||
{
|
||||
name: "产线4",
|
||||
type: "line",
|
||||
symbol: "circle",
|
||||
symbolSize: 4,
|
||||
data: [30, 32, 30, 34, 90, 33, 32],
|
||||
},
|
||||
{
|
||||
name: "产线5",
|
||||
type: "line",
|
||||
symbol: "circle",
|
||||
symbolSize: 4,
|
||||
data: [20, 92, 91, 94, 90, 30, 53],
|
||||
},
|
||||
],
|
||||
|
@ -49,7 +49,13 @@ export default function getOptions() {
|
||||
},
|
||||
},
|
||||
},
|
||||
tooltip: {},
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
axisPointer: {
|
||||
type: "shadow",
|
||||
},
|
||||
className: "luoyang-chart-tooltip",
|
||||
},
|
||||
series: [
|
||||
{
|
||||
data: [120, 200, 150, 80, 70, 110],
|
||||
|
@ -1,10 +1,32 @@
|
||||
import TitleBox from "../Component/TitleBox";
|
||||
import SwitchButton from "../Component/SwitchButton";
|
||||
import BarChart from "./BarChart";
|
||||
import ScrollBoard from "./../../Component/ScrollBoard";
|
||||
import { useState } from "react";
|
||||
function LeftDown() {
|
||||
const nameList = [{ name: "表单" }, { name: "柱状" }];
|
||||
const [activeName, setActiveName] = useState<string>(nameList[0].name);
|
||||
const config = {
|
||||
header: ["序号", "缺陷种类", "缺陷数量"],
|
||||
headerHeight: 30,
|
||||
rowNum: 4,
|
||||
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列1", "行1列2", "行1列3"],
|
||||
["行2列1", "行2列2", "行2列3"],
|
||||
["行3列1", "行3列2", "行3列3"],
|
||||
["行4列1", "行4列2", "行4列3"],
|
||||
["行5列1", "行5列2", "行5列3"],
|
||||
["行6列1", "行6列2", "行6列3"],
|
||||
["行7列1", "行7列2", "行7列3"],
|
||||
["行8列1", "行8列2", "行8列3"],
|
||||
["行9列1", "行9列2", "行9列3"],
|
||||
["行10列1", "行10列2", "行10列3"],
|
||||
],
|
||||
};
|
||||
return (
|
||||
<div className="left_down">
|
||||
<TitleBox title={"left_down"} />
|
||||
@ -22,7 +44,14 @@ function LeftDown() {
|
||||
<div className="left_down_box2 flex-col" />
|
||||
</div>
|
||||
<div className="left_down_content">
|
||||
{activeName === "表单" ? "表单" : <BarChart />}
|
||||
{activeName === "表单" ? (
|
||||
<ScrollBoard
|
||||
config={config}
|
||||
style={{ width: "380px", height: "150px" }}
|
||||
/>
|
||||
) : (
|
||||
<BarChart />
|
||||
)}
|
||||
</div>
|
||||
<div className="left_down_title flex-row">
|
||||
<div className="left_down_box1 flex-col" />
|
||||
@ -30,7 +59,14 @@ function LeftDown() {
|
||||
<div className="left_down_box2 flex-col" />
|
||||
</div>
|
||||
<div className="left_down_content">
|
||||
{activeName === "表单" ? "表单" : <BarChart />}
|
||||
{activeName === "表单" ? (
|
||||
<ScrollBoard
|
||||
config={config}
|
||||
style={{ width: "380px", height: "150px" }}
|
||||
/>
|
||||
) : (
|
||||
<BarChart />
|
||||
)}
|
||||
</div>
|
||||
<div className="left_down_title flex-row">
|
||||
<div className="left_down_box1 flex-col" />
|
||||
@ -38,7 +74,14 @@ function LeftDown() {
|
||||
<div className="left_down_box2 flex-col" />
|
||||
</div>
|
||||
<div className="left_down_content">
|
||||
{activeName === "表单" ? "表单" : <BarChart />}
|
||||
{activeName === "表单" ? (
|
||||
<ScrollBoard
|
||||
config={config}
|
||||
style={{ width: "380px", height: "150px" }}
|
||||
/>
|
||||
) : (
|
||||
<BarChart />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -69,7 +69,13 @@ export default function getOptions() {
|
||||
},
|
||||
},
|
||||
},
|
||||
tooltip: {},
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
axisPointer: {
|
||||
type: "shadow",
|
||||
},
|
||||
className: "luoyang-chart-tooltip",
|
||||
},
|
||||
dataset: {
|
||||
source: [
|
||||
["product", "产线1", "产线2", "产线3", "产线4", "产线5"],
|
||||
|
@ -70,18 +70,25 @@ export default function getOptions() {
|
||||
},
|
||||
},
|
||||
},
|
||||
tooltip: {},
|
||||
series: [
|
||||
{
|
||||
name: "投入",
|
||||
type: "line",
|
||||
symbol: "circle",
|
||||
symbolSize: 4,
|
||||
data: [20, 32, 10, 34, 90, 30, 20],
|
||||
},
|
||||
{
|
||||
name: "产出",
|
||||
type: "line",
|
||||
symbol: "circle",
|
||||
symbolSize: 4,
|
||||
data: [22, 82, 91, 34, 90, 33, 31],
|
||||
},
|
||||
],
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
className: "luoyang-chart-tooltip",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,32 @@
|
||||
import TitleBox from "../Component/TitleBox";
|
||||
import SwitchButton from "../Component/SwitchButton";
|
||||
import LineChart from "./LineChart";
|
||||
import ScrollBoard from "./../../Component/ScrollBoard";
|
||||
import { useState } from "react";
|
||||
function RightDown() {
|
||||
const nameList = [{ name: "表单" }, { name: "折线" }];
|
||||
const [activeName, setActiveName] = useState<string>(nameList[0].name);
|
||||
const config = {
|
||||
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: [
|
||||
["行1列1", "行1列2", "行1列3"],
|
||||
["行2列1", "行2列2", "行2列3"],
|
||||
["行3列1", "行3列2", "行3列3"],
|
||||
["行4列1", "行4列2", "行4列3"],
|
||||
["行5列1", "行5列2", "行5列3"],
|
||||
["行6列1", "行6列2", "行6列3"],
|
||||
["行7列1", "行7列2", "行7列3"],
|
||||
["行8列1", "行8列2", "行8列3"],
|
||||
["行9列1", "行9列2", "行9列3"],
|
||||
["行10列1", "行10列2", "行10列3"],
|
||||
],
|
||||
};
|
||||
return (
|
||||
<div className="right_down">
|
||||
<TitleBox title={"right_down"} />
|
||||
@ -22,7 +44,14 @@ function RightDown() {
|
||||
<div className="left_down_box2 flex-col" />
|
||||
</div>
|
||||
<div className="right_down_content">
|
||||
{activeName === "表单" ? "表单" : <LineChart />}
|
||||
{activeName === "表单" ? (
|
||||
<ScrollBoard
|
||||
config={config}
|
||||
style={{ width: "380px", height: "180px" }}
|
||||
/>
|
||||
) : (
|
||||
<LineChart />
|
||||
)}
|
||||
</div>
|
||||
<div className="left_down_title flex-row">
|
||||
<div className="left_down_box1 flex-col" />
|
||||
@ -30,7 +59,14 @@ function RightDown() {
|
||||
<div className="left_down_box2 flex-col" />
|
||||
</div>
|
||||
<div className="right_down_content">
|
||||
{activeName === "表单" ? "表单" : <LineChart />}
|
||||
{activeName === "表单" ? (
|
||||
<ScrollBoard
|
||||
config={config}
|
||||
style={{ width: "380px", height: "180px" }}
|
||||
/>
|
||||
) : (
|
||||
<LineChart />
|
||||
)}
|
||||
</div>
|
||||
<div className="left_down_title flex-row">
|
||||
<div className="left_down_box1 flex-col" />
|
||||
@ -38,7 +74,14 @@ function RightDown() {
|
||||
<div className="left_down_box2 flex-col" />
|
||||
</div>
|
||||
<div className="right_down_content">
|
||||
{activeName === "表单" ? "表单" : <LineChart />}
|
||||
{activeName === "表单" ? (
|
||||
<ScrollBoard
|
||||
config={config}
|
||||
style={{ width: "380px", height: "180px" }}
|
||||
/>
|
||||
) : (
|
||||
<LineChart />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,8 +1,36 @@
|
||||
import TitleBox from "../Component/TitleBox";
|
||||
import ScrollBoard from "./../../Component/ScrollBoard";
|
||||
function RightUp() {
|
||||
const config = {
|
||||
header: ["产线", "上片数据量", "成品下片数量", "成品下片"],
|
||||
headerHeight: 32,
|
||||
rowNum: 5,
|
||||
headerBGC: "rgba(79, 114, 136, 0.3)",
|
||||
oddRowBGC: "rgba(79, 114, 136, 0.3)",
|
||||
evenRowBGC: "rgba(76, 97, 123, 0.1)",
|
||||
columnWidth: [73, 100, 117, 90],
|
||||
data: [
|
||||
["1", "行1列1", "行1列2", "行1列3"],
|
||||
["2", "行2列1", "行2列2", "行2列3"],
|
||||
["3", "行3列1", "行3列2", "行3列3"],
|
||||
["4", "行4列1", "行4列2", "行4列3"],
|
||||
["5", "行5列1", "行5列2", "行5列3"],
|
||||
["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 (
|
||||
<div className="right_up">
|
||||
<TitleBox title={"right_up"} />
|
||||
<div style={{ padding: "10px", height: "213px" }}>
|
||||
<ScrollBoard
|
||||
config={config}
|
||||
style={{ width: "380px", height: "193px" }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -76,6 +76,7 @@
|
||||
background: url(../../../public/png/rect/lp_center_down.png) no-repeat;
|
||||
background-size: 100% 100%;
|
||||
background-position: 0 0;
|
||||
position: relative;
|
||||
}
|
||||
.center_down .left-box {
|
||||
margin-right: 15px;
|
||||
@ -129,6 +130,7 @@
|
||||
.left_down_title {
|
||||
height: 18px;
|
||||
justify-content: center;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.left_down_box1 {
|
||||
width: 56px;
|
||||
@ -166,3 +168,22 @@
|
||||
height: 185px;
|
||||
/* padding-bottom: 5px; */
|
||||
}
|
||||
.dv-scroll-board .header .header-item,
|
||||
.dv-scroll-board .rows .ceil {
|
||||
border-right: 1px solid #0d1728;
|
||||
}
|
||||
.dv-scroll-board .header .header-item:last-child,
|
||||
.dv-scroll-board .rows .ceil:last-child {
|
||||
border-right: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.luoyang-chart-tooltip {
|
||||
background: #0a2b4f77 !important;
|
||||
border: none !important;
|
||||
backdrop-filter: blur(12px);
|
||||
}
|
||||
|
||||
.luoyang-chart-tooltip * {
|
||||
color: #fff !important;
|
||||
}
|
||||
|
@ -1,11 +1,7 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"esnext"
|
||||
],
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
@ -18,9 +14,8 @@
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx"
|
||||
"jsx": "react-jsx",
|
||||
"downlevelIteration": true
|
||||
},
|
||||
"include": [
|
||||
"src"
|
||||
],
|
||||
"include": ["src"]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user