diff --git a/package-lock.json b/package-lock.json index 2ced1af..438014a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -36,11 +36,13 @@ "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", "dotenv-expand": "^5.1.0", "echarts": "^5.4.0", + "echarts-for-react": "^3.0.2", "eslint": "^8.3.0", "eslint-config-react-app": "^7.0.1", "eslint-webpack-plugin": "^3.1.1", @@ -5938,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", @@ -6931,6 +6938,19 @@ "zrender": "5.4.3" } }, + "node_modules/echarts-for-react": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/echarts-for-react/-/echarts-for-react-3.0.2.tgz", + "integrity": "sha512-DRwIiTzx8JfwPOVgGttDytBqdp5VzCSyMRIxubgU/g2n9y3VLUmF2FK7Icmg/sNVkv4+rktmrLN9w22U2yy3fA==", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "size-sensor": "^1.0.1" + }, + "peerDependencies": { + "echarts": "^3.0.0 || ^4.0.0 || ^5.0.0", + "react": "^15.0.0 || >=16.0.0" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz", @@ -14843,6 +14863,11 @@ "resolved": "https://registry.npmmirror.com/sisteransi/-/sisteransi-1.0.5.tgz", "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" }, + "node_modules/size-sensor": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/size-sensor/-/size-sensor-1.0.2.tgz", + "integrity": "sha512-2NCmWxY7A9pYKGXNBfteo4hy14gWu47rg5692peVMst6lQLPKrVjhY+UTEsPI5ceFRJSl3gVgMYaUi/hKuaiKw==" + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmmirror.com/slash/-/slash-3.0.0.tgz", @@ -21179,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", @@ -21957,6 +21987,15 @@ "zrender": "5.4.3" } }, + "echarts-for-react": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/echarts-for-react/-/echarts-for-react-3.0.2.tgz", + "integrity": "sha512-DRwIiTzx8JfwPOVgGttDytBqdp5VzCSyMRIxubgU/g2n9y3VLUmF2FK7Icmg/sNVkv4+rktmrLN9w22U2yy3fA==", + "requires": { + "fast-deep-equal": "^3.1.3", + "size-sensor": "^1.0.1" + } + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz", @@ -27955,6 +27994,11 @@ "resolved": "https://registry.npmmirror.com/sisteransi/-/sisteransi-1.0.5.tgz", "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" }, + "size-sensor": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/size-sensor/-/size-sensor-1.0.2.tgz", + "integrity": "sha512-2NCmWxY7A9pYKGXNBfteo4hy14gWu47rg5692peVMst6lQLPKrVjhY+UTEsPI5ceFRJSl3gVgMYaUi/hKuaiKw==" + }, "slash": { "version": "3.0.0", "resolved": "https://registry.npmmirror.com/slash/-/slash-3.0.0.tgz", diff --git a/package.json b/package.json index c688386..64ae578 100644 --- a/package.json +++ b/package.json @@ -31,11 +31,13 @@ "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", "dotenv-expand": "^5.1.0", "echarts": "^5.4.0", + "echarts-for-react": "^3.0.2", "eslint": "^8.3.0", "eslint-config-react-app": "^7.0.1", "eslint-webpack-plugin": "^3.1.1", diff --git a/public/png/1x/编组 27.png b/public/png/1x/编组 27.png deleted file mode 100644 index 901a6e5..0000000 Binary files a/public/png/1x/编组 27.png and /dev/null differ diff --git a/public/png/2x/编组 27@2x.png b/public/png/2x/编组 27@2x.png deleted file mode 100644 index b8af60e..0000000 Binary files a/public/png/2x/编组 27@2x.png and /dev/null differ diff --git a/public/png/background.png b/public/png/background.png index 8e0f45f..34a7a68 100644 Binary files a/public/png/background.png and b/public/png/background.png differ diff --git a/public/png/lp/eq_msg_always.png b/public/png/lp/eq_msg_always.png new file mode 100644 index 0000000..c2e096f Binary files /dev/null and b/public/png/lp/eq_msg_always.png differ diff --git a/public/png/lp/eq_msg_detail.png b/public/png/lp/eq_msg_detail.png new file mode 100644 index 0000000..cd53bcd Binary files /dev/null and b/public/png/lp/eq_msg_detail.png differ diff --git a/public/png/lp/line_part.png b/public/png/lp/line_part.png new file mode 100644 index 0000000..da50aa9 Binary files /dev/null and b/public/png/lp/line_part.png differ diff --git a/public/png/rect/lp_center_down.png b/public/png/rect/lp_center_down.png new file mode 100644 index 0000000..0e92921 Binary files /dev/null and b/public/png/rect/lp_center_down.png differ diff --git a/public/png/rect/lp_center_up.png b/public/png/rect/lp_center_up.png new file mode 100644 index 0000000..b70c3fc Binary files /dev/null and b/public/png/rect/lp_center_up.png differ diff --git a/public/png/rect/lp_left_down.png b/public/png/rect/lp_left_down.png new file mode 100644 index 0000000..8829b14 Binary files /dev/null and b/public/png/rect/lp_left_down.png differ diff --git a/public/png/rect/lp_left_up.png b/public/png/rect/lp_left_up.png new file mode 100644 index 0000000..c959883 Binary files /dev/null and b/public/png/rect/lp_left_up.png differ diff --git a/public/png/rect/lp_right_down.png b/public/png/rect/lp_right_down.png new file mode 100644 index 0000000..ffcf2e7 Binary files /dev/null and b/public/png/rect/lp_right_down.png differ diff --git a/public/png/rect/lp_right_up.png b/public/png/rect/lp_right_up.png new file mode 100644 index 0000000..5a62d50 Binary files /dev/null and b/public/png/rect/lp_right_up.png differ diff --git a/public/png/topTiltle.png b/public/png/topTiltle.png new file mode 100644 index 0000000..23219e0 Binary files /dev/null and b/public/png/topTiltle.png differ diff --git a/public/svg/topback.svg b/public/svg/topback.svg index cff5a04..99cec12 100644 --- a/public/svg/topback.svg +++ b/public/svg/topback.svg @@ -1,100 +1,98 @@ - - - 编组 11 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/App.tsx b/src/App.tsx index 7ea1ba4..5899b51 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -15,6 +15,9 @@ import SwitchLine from "./page/AutoSwitch/SwitchLine"; import {MyObservable} from "./context/MyObservable"; import {Observable} from "@babylonjs/core"; import {selectGlassStatus} from "./store/ProductionMonitoringEntity"; +import TestPage from "./page/TestPage"; +import LDPage from "./page/LDPage" +import LinePage from './page/LinePage'; // const LOCALES_LIST = [ // { @@ -78,6 +81,28 @@ function App() { element: , errorElement: }, + ///////////////////////////////////////////////////////////////////////////// + { + path: "/TP/:LineID?", + element: , + errorElement: + }, + { + path: "/LD", + element: , + errorElement: + }, + /////////////////////////////////////////////////////////////// + { + path: "/LP/:LineID?", + element: , + errorElement: + }, + // { + // path: "/TP/:LineID?", + // element: , + // errorElement: + // }, ]); return ( diff --git a/src/babylonjs/LinePageBabylon.tsx b/src/babylonjs/LinePageBabylon.tsx new file mode 100644 index 0000000..16767a9 --- /dev/null +++ b/src/babylonjs/LinePageBabylon.tsx @@ -0,0 +1,648 @@ +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"; +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 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] }, + ], +}; +interface EqInfoInterface { + name: string; + data: Array<{ name: string; value: number }>; + position: Array; +} +interface EqInfoDataInterface { + [key: string]: Array; +} +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) { + console.log("modelPath:;;;;;;", modelPath); + // const EquStatus = useAppSelector(selectEquStatus); + const canvasRef = useRef(null); + const resetRef = useRef<(() => void) | null>(null); + // onEquObservable.notifyObservers(EquStatus); + const [selectedMeshName, setSelectedMeshName] = useState(null); + const [selectedMeshObj, setSelectedMeshObj] = useState({ + equipment: "", + alarm: false, + online: true, + }); + const [showInfo, setShowInfo] = useState(true); + + // 使用 useRef 来存储当前加载的模型引用 + const currentMeshesRef = useRef>([]); + + useEffect(() => { + console.log("canvasRef++++++", canvasRef); + console.log("resetRef++++++", resetRef); + // 确保 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) + ); + 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("铺纸") || + 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); + eqStatusList[modelPath].map((item: any) => { + if (item.equipment === MeshName1) { + setSelectedMeshObj(item); + } + }); + }; + }); + + // 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; + setShowInfo(true); + setSelectedMeshName(null); + } + // 外部初始位置按钮 + resetRef.current = reset; + + let resetCamera = setTimeout(reset, 15000); + scene.onPointerObservable.add((pointerInfo) => { + switch (pointerInfo.type) { + case BABYLON.PointerEventTypes.POINTERMOVE: + clearTimeout(resetCamera); + resetCamera = setTimeout(reset, 15000); + setShowInfo(false); + } + }); + return scene; + }; + + // call the createScene function + const scene = createScene(); + + // run the render loop + scene.then( + (scene) => { + console.log("createScene被调用了=====", scene); + engine.runRenderLoop(function () { + scene.render(); + }); + }, + (reason) => { + console.log("reason=============", reason); + } + ); + + // Resize + window.addEventListener("resize", function () { + engine.resize(); + }); + // 组件卸载时的清理逻辑 + return () => { + // 清理场景和引擎资源 + engine.dispose(); + }; + }, [modelPath]); + const resetModel = () => { + //模型初始位置 + console.log("回到初始位置"); + if (resetRef.current) { + resetRef.current(); + } + }; + return ( +
+ {/*

当前选择: {selectedMeshName}

*/} +
+ + + 第五产线钢化{modelPath.slice(-1) === "1" ? "前段" : "后段"} + +
+ {selectedMeshName && ( +
+
+ 设备名称: + {selectedMeshObj.equipment} +
+
+ 报警状态: + + {selectedMeshObj.alarm ? ( + <> + + 报警 + + ) : ( + <> + + 正常 + + )} + +
+
+ 在线状态: + + {selectedMeshObj.online ? ( + <> + + 在线 + + ) : ( + <> + + 离线 + + )} + +
+
+ )} + {showInfo && + eqInfoData[modelPath] && + eqInfoData[modelPath].map((item, index) => { + return ( +
+
+ {item.name} +
+ {item.data.map((info, index) => { + return ( +
+ {info.name}:{info.value} +
+ ); + })} +
+ ); + })} + + +
+ ); +} + +export default MybabylonJS; diff --git a/src/babylonjs/MybabylonJS_1.tsx b/src/babylonjs/MybabylonJS_1.tsx index 1a05ab2..ed6e689 100644 --- a/src/babylonjs/MybabylonJS_1.tsx +++ b/src/babylonjs/MybabylonJS_1.tsx @@ -163,8 +163,8 @@ function MybabylonJS({ modelPath }: MybabylonJSProps) { }); currentMeshesRef.current = []; // 重置模型数组 try { // 使用 ImportMeshAsync 加载新模型 - // var LOD0MESH = await BABYLON.SceneLoader.ImportMeshAsync('', '/test/', `${modelPath}.babylon`, scene); - var LOD0MESH = await BABYLON.SceneLoader.ImportMeshAsync('', '/test/', `line1.babylon`, scene); + var LOD0MESH = await BABYLON.SceneLoader.ImportMeshAsync('', '/test/', `${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); diff --git a/src/page/Component/ScrollBoard/index.css b/src/page/Component/ScrollBoard/index.css new file mode 100644 index 0000000..0fd91b7 --- /dev/null +++ b/src/page/Component/ScrollBoard/index.css @@ -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; +} diff --git a/src/page/Component/ScrollBoard/index.tsx b/src/page/Component/ScrollBoard/index.tsx new file mode 100644 index 0000000..703d20c --- /dev/null +++ b/src/page/Component/ScrollBoard/index.tsx @@ -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} + * @default header = [] + * @example header = ['column1', 'column2', 'column3'] + */ + header: [], + /** + * @description Board data + * @type {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} + * @default columnWidth = [] + */ + columnWidth: [], + /** + * @description Column align + * @type {Array} + * @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 = `${ + i + 1 + }`; + + 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, 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(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 ( +
+ {!!header.length && !!mergedConfig && ( +
+ {header.map((headerItem, i) => ( +
+ ))} +
+ )} + + {!!mergedConfig && ( +
+ {rows.map((row: any, ri) => ( +
+ {row.ceils.map((ceil: any, ci: any) => ( +
emitEvent(onClick, ri, ci, row, ceil)} + onMouseEnter={() => handleHover(true, ri, ci, row, ceil)} + onMouseLeave={() => handleHover(false)} + /> + ))} +
+ ))} +
+ )} +
+ ); + } +); + +export default ScrollBoard; diff --git a/src/page/Component/ScrollBoard/use/autoResize.ts b/src/page/Component/ScrollBoard/use/autoResize.ts new file mode 100644 index 0000000..4dfc1dc --- /dev/null +++ b/src/page/Component/ScrollBoard/use/autoResize.ts @@ -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 }; +} diff --git a/src/page/Component/ScrollBoard/use/autoResize1.js b/src/page/Component/ScrollBoard/use/autoResize1.js new file mode 100644 index 0000000..7aae82f --- /dev/null +++ b/src/page/Component/ScrollBoard/use/autoResize1.js @@ -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 }; +} diff --git a/src/page/Component/ScrollBoard/util/index.ts b/src/page/Component/ScrollBoard/util/index.ts new file mode 100644 index 0000000..dadf41b --- /dev/null +++ b/src/page/Component/ScrollBoard/util/index.ts @@ -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; +} diff --git a/src/page/Component/ScrollBoard/util/utils.ts b/src/page/Component/ScrollBoard/util/utils.ts new file mode 100644 index 0000000..7c0e74e --- /dev/null +++ b/src/page/Component/ScrollBoard/util/utils.ts @@ -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; +} diff --git a/src/page/LDPage/index.css b/src/page/LDPage/index.css new file mode 100644 index 0000000..dcf01e1 --- /dev/null +++ b/src/page/LDPage/index.css @@ -0,0 +1,4 @@ +.main-box { + font-size: 50px; + color: #fff; +} \ No newline at end of file diff --git a/src/page/LDPage/index.tsx b/src/page/LDPage/index.tsx new file mode 100644 index 0000000..7532158 --- /dev/null +++ b/src/page/LDPage/index.tsx @@ -0,0 +1,35 @@ +import "./index.css" +import {useEffect} from 'react'; +import {useLocation,useNavigate} from "react-router-dom"; +function LDPage() { + const navigate = useNavigate(); + const {state} = useLocation(); + console.log("LDPage被加载了") +useEffect(() => { + const handleKeyDown = (event:any) => { + if (event.key === 'ArrowUp') { + console.log('LDPage向上键被按下'); + navigate(`/TP/${state.LineID}`); + // 执行向上键的逻辑 + } else if (event.key === 'ArrowDown') { + console.log('LDPage向下键被按下'); + // 执行向下键的逻辑 + } + }; + + window.addEventListener('keydown', handleKeyDown); + + return () => { + window.removeEventListener('keydown', handleKeyDown); + }; +}, []); + + return ( + <> +
LDPage{state.LineID}
+
3434
+ + ); +} + +export default LDPage; \ No newline at end of file diff --git a/src/page/LinePage/Center/CenterDown.tsx b/src/page/LinePage/Center/CenterDown.tsx new file mode 100644 index 0000000..18dfe48 --- /dev/null +++ b/src/page/LinePage/Center/CenterDown.tsx @@ -0,0 +1,248 @@ +import ReactECharts from "echarts-for-react"; +import TitleBox from "../Component/TitleBox"; +import ScrollBoard from "./../../Component/ScrollBoard"; +import SwitchButton from "../Component/SwitchButton"; +import { useState } from "react"; +import getOptions from "./LineChart/chart.config"; +import { useParams } from "react-router-dom"; +function CenterDown() { + const { LineID } = useParams(); + 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(nameList[0].ename); + let chartData = (dataSource as { [key: string]: any })[activeName]; + const handleButtonChange = (activeName: string) => { + setActiveName(activeName); + }; + const options = getOptions(chartData); + const config = { + 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", "行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", + ], + ], + }; + 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", + "故障", + ], + [ + "2", + "2024/8/28 06:12", + "清洗机5_1", + "离线", + ], + [ + "3", + "2024/8/28 06:05", + "磨边机5_2", + "离线", + ], + [ + "4", + "2024/8/28 04:43", + "二次镀膜机5_1", + "离线", + ], + [ + "5", + "2024/8/28 02:14", + "磨边机5_1", + "故障", + ], + [ + "6", + "2024/8/27 22:54", + "磨边机5_2", + "离线", + ], + [ + "7", + "2024/8/27 21:55", + "磨边机5_1", + "离线", + ], + [ + "8", + "2024/8/27 21:42", + "一次镀膜机5_2", + "离线", + ], + [ + "9", + "2024/8/27 21:37", + "磨边机5_1", + "离线", + ], + ], + }; + 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", + "故障", + ], + [ + "2", + "2024/8/28 07:35", + "下片机械手5_1", + "故障", + ], + [ + "3", + "2024/8/28 03:23", + "在线铺纸机5_1", + "离线", + ], + [ + "4", + "2024/8/28 01:36", + "下片机械手5_2", + "故障", + ], + [ + "5", + "2024/8/28 00:38", + "钢化炉5", + "离线", + ], + [ + "6", + "2024/8/27 23:58", + "下片机械手5_3", + "离线", + ], + [ + "7", + "2024/8/27 23:45", + "下片机械手5_2", + "离线", + ], + [ + "8", + "2024/8/27 22:34", + "钢化炉5", + "离线", + ], + [ + "9", + "2024/8/27 20:31", + "在线铺纸机5_1", + "故障", + ], + ], + }; + return ( +
+
+ + — 报警总数 — +
321,343
+
+ +
+
+ {/* 产线成品率 */} +
+ + {/*
+ +
*/} + + {options && ( +
+ {} +
+ )} + {!options && ( +

+ 暂无数据 +

+ )} +
+
+ ); +} +export default CenterDown; diff --git a/src/page/LinePage/Center/CenterUp.tsx b/src/page/LinePage/Center/CenterUp.tsx new file mode 100644 index 0000000..ad8d3c0 --- /dev/null +++ b/src/page/LinePage/Center/CenterUp.tsx @@ -0,0 +1,12 @@ +import LinePageBabylon from "../../../babylonjs/LinePageBabylon"; +import { useParams } from "react-router-dom"; +function CenterUp() { + const { LineID } = useParams(); + const lineID = LineID?.toString() || "1-1"; + return ( +
+ +
+ ); +} +export default CenterUp; diff --git a/src/page/LinePage/Center/LineChart/chart.config.ts b/src/page/LinePage/Center/LineChart/chart.config.ts new file mode 100644 index 0000000..f18994a --- /dev/null +++ b/src/page/LinePage/Center/LineChart/chart.config.ts @@ -0,0 +1,119 @@ +export default function getOptions(chartData: any) { + if (Object.keys(chartData).length === 0) { + return null; + } + const colors = ["#1A99FF", "#FFB70C", "#C69DFF", "#50F4E3", "#E02094"]; + return { + color: colors, + grid: { top: 38, right: 12, bottom: 26, left: 48 }, + legend: { + show: true, + top: 10, + right: 10, + padding: 0, + itemWidth: 14, + itemHeight: 10, + itemGap: 8, + height: 10, + textStyle: { + color: "#DFF1FE", + fontSize: 14, + }, + }, + xAxis: { + type: "category", + data: ["8/22", "8/23", "8/24", "8/25", "8/26", "8/27", "8/28"], + // data: Array(7) + // .fill(1) + // .map((_, index) => { + // const today = new Date(); + // const dtimestamp = + // today.getTime() - (index + 1) * 24 * 60 * 60 * 1000; + // return `${new Date(dtimestamp).getMonth() + 1}.${new Date( + // dtimestamp + // ).getDate()}`; + // }) + // .reverse(), + axisLabel: { + color: "#fff", + fontSize: 14, + }, + axisTick: { show: false }, + axisLine: { + lineStyle: { + width: 2, + color: "#5982B2", + }, + }, + }, + yAxis: { + name: "单位/%", + min: 50, + nameTextStyle: { + color: "#fff", + fontSize: 14, + }, + type: "value", + axisLabel: { + color: "#fff", + fontSize: 14, + formatter: "{value}", + }, + axisLine: { + show: true, + lineStyle: { + width: 2, + color: "#5982B2", + }, + }, + splitLine: { + lineStyle: { + width: 2, + color: "#5982B2", + }, + }, + }, + tooltip: { + trigger: "axis", + className: "luoyang-chart-tooltip", + show: false, + }, + series: [ + { + name: "产线1", + type: "line", + symbol: "circle", + symbolSize: 4, + data: chartData.yData1, + }, + { + name: "产线2", + type: "line", + symbol: "circle", + symbolSize: 4, + data: chartData.yData2, + }, + { + name: "产线3", + type: "line", + symbol: "circle", + symbolSize: 4, + data: chartData.yData3, + }, + { + name: "产线4", + type: "line", + symbol: "circle", + symbolSize: 4, + data: chartData.yData4, + }, + { + name: "产线5", + type: "line", + symbol: "circle", + symbolSize: 4, + data: chartData.yData5, + }, + ], + }; +} diff --git a/src/page/LinePage/Center/index.tsx b/src/page/LinePage/Center/index.tsx new file mode 100644 index 0000000..14d5036 --- /dev/null +++ b/src/page/LinePage/Center/index.tsx @@ -0,0 +1,12 @@ +import CenterDown from "./CenterDown"; +import CenterUp from "./CenterUp"; + +function Center() { + return ( +
+ + +
+ ); +} +export default Center; diff --git a/src/page/LinePage/Component/SwitchButton/index.css b/src/page/LinePage/Component/SwitchButton/index.css new file mode 100644 index 0000000..604d81a --- /dev/null +++ b/src/page/LinePage/Component/SwitchButton/index.css @@ -0,0 +1,19 @@ +.switch-button { + height: 33px; +} +.switch-button button { + color: #fff; + font-size: 18px; + padding: 4px 10px; + background-color: rgba(49, 135, 140, 0.3); + cursor: pointer; +} +.switch-button button:first-child { + border-radius: 5px 0 0 5px; +} +.switch-button button:last-child { + border-radius: 0 5px 5px 0; +} +.switch-button button.active { + background-color: rgba(86, 244, 231, 0.7); +} diff --git a/src/page/LinePage/Component/SwitchButton/index.tsx b/src/page/LinePage/Component/SwitchButton/index.tsx new file mode 100644 index 0000000..9209c06 --- /dev/null +++ b/src/page/LinePage/Component/SwitchButton/index.tsx @@ -0,0 +1,65 @@ +import { useEffect, useState } from "react"; +import "./index.css"; +interface Name { + name: string; + ename: string; +} +interface nameListProps { + nameList: Name[]; + onChange: (value: 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) { + const [activeName, setActiveName] = useState(props.nameList[0].ename); + const [timerId, setTimerId] = useState(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 ( +
+ {props.nameList.map((item, index) => { + return ( + + ); + })} +
+ ); +} +export default SwitchButton; diff --git a/src/page/LinePage/Component/TitleBox/index.css b/src/page/LinePage/Component/TitleBox/index.css new file mode 100644 index 0000000..3ae06db --- /dev/null +++ b/src/page/LinePage/Component/TitleBox/index.css @@ -0,0 +1,13 @@ +.title_box { + font-size: 24px; + color: #52fff1; + padding: 10px 0 0 15px; +} +.title_box img { + width: 33px; + height: 33px; + vertical-align: bottom; + margin-right: 3px; + position: relative; + top: 3px; +} diff --git a/src/page/LinePage/Component/TitleBox/index.tsx b/src/page/LinePage/Component/TitleBox/index.tsx new file mode 100644 index 0000000..dd43a66 --- /dev/null +++ b/src/page/LinePage/Component/TitleBox/index.tsx @@ -0,0 +1,53 @@ +import Defect from "./../../assets/icon/defect.png"; +import Alarm from "./../../assets/icon/alarm.png"; +import Finished from "./../../assets/icon/finished.png"; +import InputAndOutput from "./../../assets/icon/inputAndOutput.png"; +import Num from "./../../assets/icon/num.png"; +import Record from "./../../assets/icon/record.png"; +import "./index.css"; +interface titleProps { + title: string; +} +function TitleBox(props: titleProps) { + const filteredTitles = () => { + switch (props.title) { + case "left_up": + return { + img: Defect, + title: "产线报废汇总", + }; + case "left_down": + return { + img: Record, + title: "当前产线报废情况", + }; + case "center_down_left": + return { + img: Alarm, + title: "异常报警", + }; + case "center_down_right": + return { + img: Finished, + title: "产线成品率", + }; + case "right_up": + return { + img: Num, + title: "各产线总投入和产出", + }; + default: + return { + img: InputAndOutput, + title: "当前产线投入和产出", + }; + } + }; + return ( +
+ title + {filteredTitles().title} +
+ ); +} +export default TitleBox; diff --git a/src/page/LinePage/Left/BarChart/chart.config.ts b/src/page/LinePage/Left/BarChart/chart.config.ts new file mode 100644 index 0000000..87857fc --- /dev/null +++ b/src/page/LinePage/Left/BarChart/chart.config.ts @@ -0,0 +1,79 @@ +import * as echarts from "echarts"; +export default function getOptions(dataProps: number[], color: string[]) { + if (dataProps.length === 0) return null; + return { + grid: { top: 30, right: 12, bottom: 26, left: 48 }, + legend: { + show: false, + }, + xAxis: { + type: "category", + data: ["磨边后", "包装1", "包装2"], + axisLabel: { + color: "#fff", + fontSize: 14, + interval: 0, + }, + axisTick: { show: false }, + axisLine: { + lineStyle: { + width: 2, + color: "#5982B2", + }, + }, + }, + yAxis: { + name: "单位/片", + nameTextStyle: { + color: "#fff", + fontSize: 14, + }, + type: "value", + axisLabel: { + color: "#fff", + fontSize: 14, + formatter: "{value}", + }, + axisLine: { + show: true, + lineStyle: { + width: 2, + color: "#5982B2", + }, + }, + splitLine: { + lineStyle: { + width: 2, + color: "#5982B2", + }, + }, + }, + tooltip: { + trigger: "axis", + axisPointer: { + type: "shadow", + }, + className: "luoyang-chart-tooltip", + show: false, + }, + series: [ + { + data: dataProps, + type: "bar", + barWidth: 10, + label: { + show: true, + fontSize: 12, + color: "#9CD4FF", + position: "top", + }, + itemStyle: { + color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ + { offset: 0, color: color[0] }, + { offset: 1, color: color[1] }, + ]), + }, + }, + ], + }; +} diff --git a/src/page/LinePage/Left/LeftDown.tsx b/src/page/LinePage/Left/LeftDown.tsx new file mode 100644 index 0000000..9ecd183 --- /dev/null +++ b/src/page/LinePage/Left/LeftDown.tsx @@ -0,0 +1,183 @@ +import ReactECharts from "echarts-for-react"; +import TitleBox from "../Component/TitleBox"; +import SwitchButton from "../Component/SwitchButton"; +import ScrollBoard from "./../../Component/ScrollBoard"; +import { useState } from "react"; +import getOptions from "./BarChart/chart.config"; +function LeftDown() { + const nameList = [ + { name: "表单", ename: "table" }, + { name: "柱状", ename: "chart" }, + ]; + const [activeName, setActiveName] = useState(nameList[0].ename); + const handleButtonChange = (activeName: string) => { + setActiveName(activeName); + }; + const config = { + 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列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"], + ], + }; + 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 ( +
+ +
+ +
+
+
+
+ 当天 +
+
+
+ {activeName === "table" ? ( + + ) : options1 ? ( + + ) : ( +

+ 暂无数据 +

+ )} +
+
+
+ 本周 +
+
+
+ {activeName === "table" ? ( + + ) : options2 ? ( + + ) : ( +

+ 暂无数据 +

+ )} +
+
+
+ 本月 +
+
+
+ {activeName === "table" ? ( + + ) : options3 ? ( + + ) : ( +

+ 暂无数据 +

+ )} +
+
+
+ ); +} +export default LeftDown; diff --git a/src/page/LinePage/Left/LeftUp.tsx b/src/page/LinePage/Left/LeftUp.tsx new file mode 100644 index 0000000..0cd8b82 --- /dev/null +++ b/src/page/LinePage/Left/LeftUp.tsx @@ -0,0 +1,69 @@ +import ReactECharts from "echarts-for-react"; +import TitleBox from "../Component/TitleBox"; +import SwitchButton from "../Component/SwitchButton"; +import getOptions from "./SummaryBarChart/chart.config"; +import { useState } from "react"; +function LeftUp() { + // 假数据 + 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(nameList[0].ename); + let chartData = (dataSource as { [key: string]: any })[activeName]; + const handleButtonChange = (activeName: string) => { + setActiveName(activeName); + }; + const options = getOptions(chartData); + return ( +
+ +
+ +
+ {options && ( +
+ {} +
+ )} + {!options && ( +

+ 暂无数据 +

+ )} +
+ ); +} +export default LeftUp; diff --git a/src/page/LinePage/Left/SummaryBarChart/chart.config.ts b/src/page/LinePage/Left/SummaryBarChart/chart.config.ts new file mode 100644 index 0000000..4707a61 --- /dev/null +++ b/src/page/LinePage/Left/SummaryBarChart/chart.config.ts @@ -0,0 +1,149 @@ +export default function getOptions(chartData: any) { + if (Object.keys(chartData).length === 0) { + return null; + } + const colors = ["#2760FF", "#8167F6", "#5B9BFF", "#99D66C", "#FFD160"]; + let sum = chartData.sumData; + return { + color: colors, + grid: { top: 48, right: 20, bottom: 5, left: 15, containLabel: true }, + legend: { + show: true, + icon: "roundRect", + top: 10, + right: 20, + padding: 0, + itemWidth: 10, + itemHeight: 10, + itemGap: 15, + height: 10, + textStyle: { + color: "#DFF1FE", + fontSize: 14, + }, + }, + xAxis: { + type: "category", + data: chartData.xData, + axisLabel: { + color: "#fff", + fontSize: 16, + }, + axisTick: { show: false }, + axisLine: { + lineStyle: { + width: 2, + color: "#5982B2", + }, + }, + }, + yAxis: { + name: "单位/片", + nameTextStyle: { + color: "#fff", + fontSize: 14, + }, + type: "value", + axisLabel: { + color: "#fff", + fontSize: 16, + formatter: "{value}", + }, + axisLine: { + show: true, + lineStyle: { + width: 2, + color: "#5982B2", + }, + }, + splitLine: { + lineStyle: { + width: 2, + color: "#5982B2", + }, + }, + }, + tooltip: { + show: false, + trigger: "axis", + axisPointer: { + type: "shadow", + }, + className: "luoyang-chart-tooltip", + }, + // Declare several bar series, each will be mapped + // to a column of dataset.source by default. + series: [ + { + data: chartData.yData1, + type: "bar", + stack: "a", + name: "磨边后", + barWidth: 14, + label: { + show: true, + position: "right", + color: "inherit", + }, + }, + { + data: chartData.yData2, + type: "bar", + stack: "a", + name: "包装1", + label: { + show: true, + position: "right", + color: "inherit", + }, + }, + { + data: chartData.yData3, + type: "bar", + stack: "a", + name: "包装2", + label: { + show: true, + 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", + stack: "a", + name: "", + label: { + show: true, + position: "top", + color: "#fff", + formatter: function (params: any) { + return sum[params.dataIndex]; + }, + }, + }, + ], + }; +} diff --git a/src/page/LinePage/Left/Table/index.tsx b/src/page/LinePage/Left/Table/index.tsx new file mode 100644 index 0000000..6abcea0 --- /dev/null +++ b/src/page/LinePage/Left/Table/index.tsx @@ -0,0 +1,4 @@ +function Table() { + return
111
; +} +export default Table; diff --git a/src/page/LinePage/Left/index.tsx b/src/page/LinePage/Left/index.tsx new file mode 100644 index 0000000..6524b82 --- /dev/null +++ b/src/page/LinePage/Left/index.tsx @@ -0,0 +1,11 @@ +import LeftUp from "./LeftUp"; +import LeftDown from "./LeftDown"; +function Left() { + return ( +
+ + +
+ ); +} +export default Left; diff --git a/src/page/LinePage/Right/LineChart/chart.config.ts b/src/page/LinePage/Right/LineChart/chart.config.ts new file mode 100644 index 0000000..18bd639 --- /dev/null +++ b/src/page/LinePage/Right/LineChart/chart.config.ts @@ -0,0 +1,99 @@ +import * as echarts from "echarts"; +export default function getOptions(tempData: any) { + if (Object.keys(tempData).length === 0) { + return null; + } + const colors = ["#1A99FF", "#50F4E3"]; + return { + color: colors, + grid: { top: 30, right: 12, bottom: 10, left: 10, containLabel: true }, + legend: { + show: true, + icon: "roundRect", + top: 10, + right: 10, + padding: 0, + itemWidth: 10, + itemHeight: 10, + itemGap: 3, + height: 10, + textStyle: { + color: "#DFF1FE", + fontSize: 14, + }, + }, + xAxis: { + type: "category", + data: tempData.time, + // data: Array(7) + // .fill(1) + // .map((_, index) => { + // const today = new Date(); + // const dtimestamp = + // today.getTime() - (index + 1) * 24 * 60 * 60 * 1000; + // return `${new Date(dtimestamp).getMonth() + 1}.${new Date( + // dtimestamp + // ).getDate()}`; + // }) + // .reverse(), + axisLabel: { + color: "#fff", + fontSize: 14, + }, + axisTick: { show: false }, + axisLine: { + lineStyle: { + width: 2, + color: "#5982B2", + }, + }, + }, + yAxis: { + name: "单位/千片", + nameTextStyle: { + color: "#fff", + fontSize: 14, + }, + type: "value", + axisLabel: { + color: "#fff", + fontSize: 14, + formatter: "{value}", + }, + axisLine: { + show: true, + lineStyle: { + width: 2, + color: "#5982B2", + }, + }, + splitLine: { + lineStyle: { + width: 2, + color: "#5982B2", + }, + }, + }, + series: [ + { + name: "投入", + type: "line", + symbol: "circle", + symbolSize: 4, + data: tempData.input, + }, + { + name: "产出", + type: "line", + symbol: "circle", + symbolSize: 4, + data: tempData.output, + }, + ], + tooltip: { + trigger: "axis", + className: "luoyang-chart-tooltip", + show: false, + }, + }; +} diff --git a/src/page/LinePage/Right/RightDown.tsx b/src/page/LinePage/Right/RightDown.tsx new file mode 100644 index 0000000..b4b3954 --- /dev/null +++ b/src/page/LinePage/Right/RightDown.tsx @@ -0,0 +1,294 @@ +import ReactECharts from "echarts-for-react"; +import TitleBox from "../Component/TitleBox"; +import SwitchButton from "../Component/SwitchButton"; +import ScrollBoard from "./../../Component/ScrollBoard"; +import { useState } from "react"; +import getOptions from "./LineChart/chart.config"; +function RightDown() { + // 假数据 + 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(nameList[0].ename); + const handleButtonChange = (activeName: string) => { + setActiveName(activeName); + }; + 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"], + ], + }; + 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 ( +
+ +
+ +
+
+
+
+ 当天 +
+
+
+ {activeName === "table" ? ( + + ) : options1 ? ( + + ) : ( +

+ 暂无数据 +

+ )} +
+
+
+ 本周 +
+
+
+ {activeName === "table" ? ( + + ) : options2 ? ( + + ) : ( +

+ 暂无数据 +

+ )} +
+
+
+ 本月 +
+
+
+ {activeName === "table" ? ( + + ) : options3 ? ( + + ) : ( +

+ 暂无数据 +

+ )} +
+
+
+ ); +} +export default RightDown; diff --git a/src/page/LinePage/Right/RightUp.tsx b/src/page/LinePage/Right/RightUp.tsx new file mode 100644 index 0000000..9107cbc --- /dev/null +++ b/src/page/LinePage/Right/RightUp.tsx @@ -0,0 +1,33 @@ +import TitleBox from "../Component/TitleBox"; +import ScrollBoard from "./../../Component/ScrollBoard"; +function RightUp() { + const config = { + header: ["序号", "产线", "上片数据量", "成品下片数量"], + headerHeight: 32, + rowNum: 5, + 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: [70, 90, 106, 114], + data: [ + ["1", "钢1线", "82315", "64268"], + ["2", "钢2线", "78246", "61235"], + ["3", "钢3线", "79092", "63562"], + ["4", "钢4线", "84125", "66789"], + ["5", "钢5线", "85223", "68246"], + ], + }; + return ( +
+ +
+ +
+
+ ); +} +export default RightUp; diff --git a/src/page/LinePage/Right/index.tsx b/src/page/LinePage/Right/index.tsx new file mode 100644 index 0000000..53c802a --- /dev/null +++ b/src/page/LinePage/Right/index.tsx @@ -0,0 +1,12 @@ +import RightDown from "./RightDown"; +import RightUp from "./RightUp"; + +function Right() { + return ( +
+ + +
+ ); +} +export default Right; diff --git a/src/page/LinePage/TopP.tsx b/src/page/LinePage/TopP.tsx new file mode 100644 index 0000000..e7c7a64 --- /dev/null +++ b/src/page/LinePage/TopP.tsx @@ -0,0 +1,14 @@ +import '../../lanhuapp/common.css'; +import "./index.css"; + +function TopP() { + return ( +
+
+
+
+
+ ); +} + +export default TopP; \ No newline at end of file diff --git a/src/page/LinePage/assets/icon/alarm.png b/src/page/LinePage/assets/icon/alarm.png new file mode 100644 index 0000000..eb335f3 Binary files /dev/null and b/src/page/LinePage/assets/icon/alarm.png differ diff --git a/src/page/LinePage/assets/icon/defect.png b/src/page/LinePage/assets/icon/defect.png new file mode 100644 index 0000000..76ed17c Binary files /dev/null and b/src/page/LinePage/assets/icon/defect.png differ diff --git a/src/page/LinePage/assets/icon/finished.png b/src/page/LinePage/assets/icon/finished.png new file mode 100644 index 0000000..99b411b Binary files /dev/null and b/src/page/LinePage/assets/icon/finished.png differ diff --git a/src/page/LinePage/assets/icon/g.png b/src/page/LinePage/assets/icon/g.png new file mode 100644 index 0000000..bf1b107 Binary files /dev/null and b/src/page/LinePage/assets/icon/g.png differ diff --git a/src/page/LinePage/assets/icon/inputAndOutput.png b/src/page/LinePage/assets/icon/inputAndOutput.png new file mode 100644 index 0000000..113ed13 Binary files /dev/null and b/src/page/LinePage/assets/icon/inputAndOutput.png differ diff --git a/src/page/LinePage/assets/icon/num.png b/src/page/LinePage/assets/icon/num.png new file mode 100644 index 0000000..e77c409 Binary files /dev/null and b/src/page/LinePage/assets/icon/num.png differ diff --git a/src/page/LinePage/assets/icon/r.png b/src/page/LinePage/assets/icon/r.png new file mode 100644 index 0000000..d11591e Binary files /dev/null and b/src/page/LinePage/assets/icon/r.png differ diff --git a/src/page/LinePage/assets/icon/record.png b/src/page/LinePage/assets/icon/record.png new file mode 100644 index 0000000..4622f01 Binary files /dev/null and b/src/page/LinePage/assets/icon/record.png differ diff --git a/src/page/LinePage/assets/icon/y.png b/src/page/LinePage/assets/icon/y.png new file mode 100644 index 0000000..72c796a Binary files /dev/null and b/src/page/LinePage/assets/icon/y.png differ diff --git a/src/page/LinePage/index.css b/src/page/LinePage/index.css new file mode 100644 index 0000000..1a28491 --- /dev/null +++ b/src/page/LinePage/index.css @@ -0,0 +1,264 @@ +/* 顶部 */ +.block_top { + width: 1920px; + height: 94px; + background: url(/public/svg/topback.svg) 100% no-repeat; + background-size: 100% 100%; + opacity: 1; + display: flex; + justify-content: center; +} + +.block_top_title { + width: 651px; + height: 77px; + background: url(/public/png/topTiltle.png) 100% no-repeat; + background-size: 100% 100%; + margin-top: 18px; +} +/* 中部 */ +.block_bottom { + width: 1920px; + height: 966px; + padding-top: 20px; +} + +.group_left { + width: 402px; + height: 966px; + margin: 0 0 0 24px; +} + +.group_center { + width: 1041px; + height: 966px; + margin: 0 0 0 15px; +} + +.group_right { + width: 401px; + height: 966px; + margin-left: 15px; +} + +.left_up { + width: 402px; + height: 332px; + background: url(../../../public/png/rect/lp_left_up.png) no-repeat; + background-size: 100% 100%; + background-position: 0 0; + position: relative; +} +.left_down { + width: 402px; + height: 599px; + background: url(../../../public/png/rect/lp_left_down.png) no-repeat; + background-size: 100% 100%; + background-position: 0 0; + margin-top: 14px; + position: relative; +} +.center_up { + width: 1041px; + height: 562px; + background: url(../../../public/png/rect/lp_center_up.png) no-repeat; + background-size: 100% 100%; + background-position: 0 0; + position: relative; +} +.center_down { + width: 1041px; + height: 368px; + margin-top: 17px; +} +.center_down_inner { + width: 513px; + height: 366px; + 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; + position: relative; +} +.center_down .left-box .alarm_num_title { + position: absolute; + left: 220px; + top: 22px; + font-size: 13px; + letter-spacing: 3px; + color: #fff; +} +.center_down .left-box .alarm_num { + color: #52fff1; + font-size: 40px; + text-align: center; + font-family: PingFangSC, PingFang SC; +} +.center_down .right_box .chart_box { + width: 100%; + height: 310px; + margin-top: 10px; +} +.right_up { + width: 401px; + height: 257px; + background: url(../../../public/png/rect/lp_right_up.png) no-repeat; + background-size: 100% 100%; + background-position: 0 0; +} +.right_down { + width: 401px; + height: 673px; + background: url(../../../public/png/rect/lp_right_down.png) no-repeat; + background-size: 100% 100%; + background-position: 0 0; + margin-top: 14px; + position: relative; +} +.left_up_switch { + position: absolute; + right: 10px; + top: 12px; +} +.left_up_chart { + height: 275px; + margin-top: 10px; +} +/* 左侧 */ +.left_down_title { + height: 18px; + justify-content: center; + margin-bottom: 4px; +} +.left_down_box1 { + width: 56px; + height: 13px; + background: url(/public/png/leftbar.png) 100% no-repeat; + background-size: 100% 100%; + margin-top: 2px; +} +.left_down_box2 { + width: 56px; + height: 13px; + background: url(/public/png/rightbar.png) 100% no-repeat; + background-size: 100% 100%; + margin: 2px 0 0 0px; +} +.left_down_text { + /*width: 40px;*/ + height: 18px; + overflow-wrap: break-word; + color: rgba(1, 207, 204, 1); + font-size: 18px; + letter-spacing: 5px; + font-family: PingFangSC-Regular; + white-space: nowrap; + line-height: 18px; + margin-left: 18px; + margin-right: 16px; + text-align: center; +} +.left_down_content { + height: 160px; + /* padding-bottom: 5px; */ +} +.right_down_content { + 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; +} +/* chart图部分 */ +.luoyang-chart-tooltip { + background: #0a2b4f77 !important; + border: none !important; + backdrop-filter: blur(12px); +} + +.luoyang-chart-tooltip * { + 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: 24px; + font-size: 17px; + white-space: nowrap; +} diff --git a/src/page/LinePage/index.tsx b/src/page/LinePage/index.tsx new file mode 100644 index 0000000..daf9389 --- /dev/null +++ b/src/page/LinePage/index.tsx @@ -0,0 +1,18 @@ +import React from "react"; +import TopP from "./TopP"; +import Left from "./Left"; +import Right from "./Right"; +import Center from "./Center"; +function LinePage() { + return ( + + +
+ +
+ +
+
+ ); +} +export default LinePage; diff --git a/src/page/MainE/CenterUpE.tsx b/src/page/MainE/CenterUpE.tsx index a93b01b..66aef0f 100644 --- a/src/page/MainE/CenterUpE.tsx +++ b/src/page/MainE/CenterUpE.tsx @@ -1,12 +1,15 @@ import React from "react"; import LineBabylon from "../../babylonjs/LineBabylon"; +import MybabylonJS_1 from "../../babylonjs/MybabylonJS_1"; import {Observable} from "@babylonjs/core"; +// import LineID from "../../store/ChangeLineID"; function CenterUpE() { return (
- + + {/* */}
) } diff --git a/src/page/MainE/MainE.tsx b/src/page/MainE/MainE.tsx index 972fbf9..9b886f6 100644 --- a/src/page/MainE/MainE.tsx +++ b/src/page/MainE/MainE.tsx @@ -15,6 +15,7 @@ import {MyObservable} from "../../context/MyObservable"; import {ThisLineID} from "../../context/ThisLineID"; + function MainE() { const contextLineID = useContext(ThisLineID); const {LineID} = useParams() @@ -26,7 +27,6 @@ function MainE() { } const dispatch = useAppDispatch(); dispatch(UpdateChangeLineID(NowThisLineID)); - return ( diff --git a/src/page/TestPage/CenterUp.tsx b/src/page/TestPage/CenterUp.tsx new file mode 100644 index 0000000..1388c2d --- /dev/null +++ b/src/page/TestPage/CenterUp.tsx @@ -0,0 +1,41 @@ +import React, { useState } from "react"; // 使用useState钩子来管理状态 +import intl from "react-intl-universal"; +import '../../lanhuapp/common.css'; +import "../../lanhuapp/index.css"; +import "../style/standard.css" +import MybabylonJS_1 from "../../babylonjs/MybabylonJS_1"; +import MybabylonJS_2 from "../../babylonjs/MybabylonJS_2"; +import { number } from "echarts"; +import { firePixelShader } from "@babylonjs/materials/fire/fire.fragment"; + +function CenterUp() { + +// 使用 useState 钩子来管理当前的序号状态 +const [modelIndex, setModelIndex] = useState(1); // 默认序号为 1 + +// 定义切换模型序号的函数 +const prevModelIndex = () => { + // 当前序号减 1,如果小于 1,则变为 5 + setModelIndex((currentModelIndex) => (currentModelIndex - 1 + 5) % 5); +}; + +const nextModelIndex = () => { + // 当前序号加 1,如果大于 5,则变为 1 + setModelIndex((currentModelIndex) => (currentModelIndex + 1) % 5); +}; + + + + return ( +
+
+ + {/* 添加按钮来切换组件 */} + + +
{modelIndex}
+
+ ); +} + +export default CenterUp; \ No newline at end of file diff --git a/src/page/TestPage/index.css b/src/page/TestPage/index.css new file mode 100644 index 0000000..dcf01e1 --- /dev/null +++ b/src/page/TestPage/index.css @@ -0,0 +1,4 @@ +.main-box { + font-size: 50px; + color: #fff; +} \ No newline at end of file diff --git a/src/page/TestPage/index.tsx b/src/page/TestPage/index.tsx new file mode 100644 index 0000000..8e28e48 --- /dev/null +++ b/src/page/TestPage/index.tsx @@ -0,0 +1,38 @@ +import "./index.css" +import MainE from "../MainE/MainE"; +import {useParams,useNavigate} from "react-router-dom"; +import {useEffect} from 'react'; +function TestPage() { + const {LineID} = useParams() + const navigate = useNavigate(); + console.log("TestPage被加载了") +useEffect(() => { + const handleKeyDown = (event:any) => { + if (event.key === 'ArrowUp') { + console.log('TestPage向上键被按下'); + // 执行向上键的逻辑 + } else if (event.key === 'ArrowDown') { + console.log('TestPage向下键被按下'); + // 执行向下键的逻辑 + navigate('/LD',{ state: { LineID: LineID} }); + + } + }; + + window.addEventListener('keydown', handleKeyDown); + + return () => { + window.removeEventListener('keydown', handleKeyDown); + }; +}, []); + + return ( + <> +
TestPage Line{LineID}
+
3434
+ + + ); +} + +export default TestPage; \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index d938e0a..cc0a000 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -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"] }