zjl #1
44
package-lock.json
generated
@ -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",
|
||||
|
@ -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",
|
||||
|
Before Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 75 KiB |
Before Width: | Height: | Size: 2.7 MiB After Width: | Height: | Size: 8.9 MiB |
BIN
public/png/lp/eq_msg_always.png
Normal file
After Width: | Height: | Size: 7.6 KiB |
BIN
public/png/lp/eq_msg_detail.png
Normal file
After Width: | Height: | Size: 43 KiB |
BIN
public/png/lp/line_part.png
Normal file
After Width: | Height: | Size: 53 KiB |
BIN
public/png/rect/lp_center_down.png
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
public/png/rect/lp_center_up.png
Normal file
After Width: | Height: | Size: 89 KiB |
BIN
public/png/rect/lp_left_down.png
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
public/png/rect/lp_left_up.png
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
public/png/rect/lp_right_down.png
Normal file
After Width: | Height: | Size: 66 KiB |
BIN
public/png/rect/lp_right_up.png
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
public/png/topTiltle.png
Normal file
After Width: | Height: | Size: 82 KiB |
@ -1,100 +1,98 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="1921px" height="88px" viewBox="0 0 1921 88" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>编组 11</title>
|
||||
<defs>
|
||||
<linearGradient x1="50%" y1="-2.22044605e-14%" x2="50%" y2="100%" id="linearGradient-1">
|
||||
<stop stop-color="#081C43" stop-opacity="0" offset="0%"></stop>
|
||||
<stop stop-color="#27778E" stop-opacity="0.205883769" offset="57.0640297%"></stop>
|
||||
<stop stop-color="#37A5B4" stop-opacity="0.311188811" offset="100%"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient x1="98.361014%" y1="49.8607451%" x2="-6.66133815e-14%" y2="49.824166%" id="linearGradient-2">
|
||||
<stop stop-color="#3797C6" stop-opacity="0.31441215" offset="0%"></stop>
|
||||
<stop stop-color="#52FFF1" offset="100%"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient x1="103.601203%" y1="50.920359%" x2="-6.66133815e-14%" y2="49.3224437%" id="linearGradient-3">
|
||||
<stop stop-color="#31A6AE" stop-opacity="0" offset="0%"></stop>
|
||||
<stop stop-color="#31A6AE" offset="100%"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient x1="103.601203%" y1="50.0057165%" x2="-6.66133815e-14%" y2="49.9957916%" id="linearGradient-4">
|
||||
<stop stop-color="#31A6AE" offset="0%"></stop>
|
||||
<stop stop-color="#3797C6" stop-opacity="0" offset="100%"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient x1="98.361014%" y1="49.8601267%" x2="-6.66133815e-14%" y2="49.8233851%" id="linearGradient-5">
|
||||
<stop stop-color="#3797C6" stop-opacity="0.31441215" offset="0%"></stop>
|
||||
<stop stop-color="#52FFF1" offset="100%"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient x1="103.601203%" y1="50.920359%" x2="-6.66133815e-14%" y2="49.3224437%" id="linearGradient-6">
|
||||
<stop stop-color="#3797C6" stop-opacity="0" offset="0%"></stop>
|
||||
<stop stop-color="#31A6AE" offset="100%"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient x1="103.601203%" y1="50.0051355%" x2="-6.66133815e-14%" y2="49.9962193%" id="linearGradient-7">
|
||||
<stop stop-color="#31A6AE" offset="0%"></stop>
|
||||
<stop stop-color="#3797C6" stop-opacity="0" offset="100%"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient x1="103.601203%" y1="50.0271564%" x2="-6.66133815e-14%" y2="49.9800078%" id="linearGradient-8">
|
||||
<stop stop-color="#31A6AE" offset="0%"></stop>
|
||||
<stop stop-color="#3797C6" stop-opacity="0" offset="100%"></stop>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="现场看板_生产监控看板" transform="translate(1.000000, 0.000000)">
|
||||
<g id="编组-11" transform="translate(-1.000000, 0.000000)">
|
||||
<polygon id="路径-5" fill="url(#linearGradient-1)" points="1 -4.26746065e-15 1 30 83.7450271 30 121.647723 54.8660399 585.839525 54.8660399 634.350877 88 1285.2234 88 1333.90268 54.433414 1787.59181 54.433414 1824.88056 30 1921 30 1921 2.23106215e-13"></polygon>
|
||||
<g id="编组-12" transform="translate(0.000000, 0.000000)">
|
||||
<g id="编组-8" transform="translate(711.263222, 23.000000)"></g>
|
||||
<g id="编组-4" transform="translate(0.750956, 30.000000)">
|
||||
<polyline id="路径-9" stroke="url(#linearGradient-2)" stroke-width="2" points="1920.24904 5.66395583e-14 1824.1296 3.83165721e-14 1786.2269 24.8660399 1332.03314 24.8660399 1284.10896 57 959.060954 57"></polyline>
|
||||
<g id="编组-29" transform="translate(1561.171848, 46.000000) scale(-1, 1) translate(-1561.171848, -46.000000) translate(1331.116205, 35.000000)">
|
||||
<polyline id="路径-10" stroke="url(#linearGradient-3)" stroke-width="2" points="460.111287 22 435.255105 5 314.074844 5"></polyline>
|
||||
<ellipse id="椭圆形" fill="#31A6AE" cx="309.073864" cy="5" rx="4.00078371" ry="4"></ellipse>
|
||||
<ellipse id="椭圆形备份" fill="#31A6AE" cx="221.056623" cy="5" rx="4.00078371" ry="4"></ellipse>
|
||||
<g id="编组-2" transform="translate(235.059366, 0.000000)" fill="#31A6AE">
|
||||
<polygon id="路径-11" points="51.8543795 5.99520433e-14 48.0094045 0 56.5647535 10 60.0117556 10"></polygon>
|
||||
<polygon id="路径-11备份" opacity="0.8" points="39.8520284 5.99520433e-14 36.0070534 0 44.5624024 10 48.0094045 10"></polygon>
|
||||
<polygon id="路径-11备份-3" opacity="0.4" points="15.8473261 5.99520433e-14 12.0023511 0 20.5577001 10 24.0047022 10"></polygon>
|
||||
<polygon id="路径-11备份-2" opacity="0.601434" points="27.8496773 5.99520433e-14 24.0047022 0 32.5600513 10 36.0070534 10"></polygon>
|
||||
<polygon id="路径-11备份-4" opacity="0.201434" points="3.84497501 5.99520433e-14 4.67611706e-16 0 8.55534901 10 12.0023511 10"></polygon>
|
||||
</g>
|
||||
<line x1="217.055839" y1="4.5" x2="0.978448027" y2="5" id="路径-12" stroke="url(#linearGradient-4)" stroke-width="2"></line>
|
||||
</g>
|
||||
<polyline id="路径-9" stroke="url(#linearGradient-5)" stroke-width="2" transform="translate(479.530477, 28.500000) scale(-1, 1) translate(-479.530477, -28.500000) " points="959.060954 -1.26565425e-14 876.066883 -4.42836785e-14 838.164187 24.8660399 373.972385 24.8660399 326.048198 57 -4.54174955e-13 57"></polyline>
|
||||
<g id="编组-28" transform="translate(114.894416, 35.000000)">
|
||||
<polyline id="路径-10" stroke="url(#linearGradient-6)" stroke-width="2" points="472.111287 22 447.255105 5 326.074844 5"></polyline>
|
||||
<ellipse id="椭圆形" fill="#31A6AE" cx="321.073864" cy="5" rx="4.00078371" ry="4"></ellipse>
|
||||
<ellipse id="椭圆形备份" fill="#31A6AE" cx="233.056623" cy="5" rx="4.00078371" ry="4"></ellipse>
|
||||
<g id="编组-2" transform="translate(247.059366, 0.000000)" fill="#31A6AE">
|
||||
<polygon id="路径-11" points="51.8543795 5.99520433e-14 48.0094045 0 56.5647535 10 60.0117556 10"></polygon>
|
||||
<polygon id="路径-11备份" opacity="0.8" points="39.8520284 5.99520433e-14 36.0070534 0 44.5624024 10 48.0094045 10"></polygon>
|
||||
<polygon id="路径-11备份-3" opacity="0.4" points="15.8473261 5.99520433e-14 12.0023511 0 20.5577001 10 24.0047022 10"></polygon>
|
||||
<polygon id="路径-11备份-2" opacity="0.601434" points="27.8496773 5.99520433e-14 24.0047022 0 32.5600513 10 36.0070534 10"></polygon>
|
||||
<polygon id="路径-11备份-4" opacity="0.201434" points="3.84497501 5.99520433e-14 4.67611706e-16 0 8.55534901 10 12.0023511 10"></polygon>
|
||||
</g>
|
||||
<line x1="229.055839" y1="4.5" x2="0.354627912" y2="5" id="路径-12" stroke="url(#linearGradient-7)" stroke-width="2"></line>
|
||||
</g>
|
||||
<g id="编组-3" transform="translate(117.896179, 0.000000)">
|
||||
<g id="编组-2备份" fill="#31A6AE">
|
||||
<polygon id="路径-11" points="77.7815693 8.9928065e-14 72.0141067 0 84.8471303 15 90.0176334 15"></polygon>
|
||||
<polygon id="路径-11备份" opacity="0.8" points="59.7780426 8.9928065e-14 54.0105801 0 66.8436036 15 72.0141067 15"></polygon>
|
||||
<polygon id="路径-11备份-3" opacity="0.4" points="23.7709892 8.9928065e-14 18.0035267 0 30.8365502 15 36.0070534 15"></polygon>
|
||||
<polygon id="路径-11备份-2" opacity="0.601434" points="41.7745159 8.9928065e-14 36.0070534 0 48.8400769 15 54.0105801 15"></polygon>
|
||||
<polygon id="路径-11备份-4" opacity="0.201434" points="5.76746252 8.9928065e-14 7.01417559e-16 0 12.8330235 15 18.0035267 15"></polygon>
|
||||
</g>
|
||||
<line x1="103.02018" y1="7.5" x2="203.018671" y2="8" id="路径-13" stroke="url(#linearGradient-8)" stroke-width="2"></line>
|
||||
</g>
|
||||
<g id="编组-3备份" transform="translate(1678.705842, 7.500000) scale(-1, 1) translate(-1678.705842, -7.500000) translate(1577.185955, 0.000000)">
|
||||
<g id="编组-2备份" fill="#31A6AE">
|
||||
<polygon id="路径-11" points="77.7815693 8.9928065e-14 72.0141067 0 84.8471303 15 90.0176334 15"></polygon>
|
||||
<polygon id="路径-11备份" opacity="0.8" points="59.7780426 8.9928065e-14 54.0105801 0 66.8436036 15 72.0141067 15"></polygon>
|
||||
<polygon id="路径-11备份-3" opacity="0.4" points="23.7709892 8.9928065e-14 18.0035267 0 30.8365502 15 36.0070534 15"></polygon>
|
||||
<polygon id="路径-11备份-2" opacity="0.601434" points="41.7745159 8.9928065e-14 36.0070534 0 48.8400769 15 54.0105801 15"></polygon>
|
||||
<polygon id="路径-11备份-4" opacity="0.201434" points="5.76746252 8.9928065e-14 7.01417559e-16 0 12.8330235 15 18.0035267 15"></polygon>
|
||||
</g>
|
||||
<line x1="103.02018" y1="7.5" x2="203.018671" y2="8" id="路径-13" stroke="url(#linearGradient-8)" stroke-width="2"></line>
|
||||
</g>
|
||||
</g>
|
||||
<rect id="矩形" stroke="#979797" opacity="0" x="0.5" y="0.5" width="1919" height="87"></rect>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="1920px" height="93.28px" viewBox="0 0 1920 93.28" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title></title>
|
||||
<defs>
|
||||
<linearGradient x1="50%" y1="-2.22044605e-14%" x2="50%" y2="100%" id="linearGradient-1">
|
||||
<stop stop-color="#081C43" stop-opacity="0" offset="0%"></stop>
|
||||
<stop stop-color="#27778E" stop-opacity="0.205883769" offset="57.0640297%"></stop>
|
||||
<stop stop-color="#37A5B4" stop-opacity="0.311188811" offset="100%"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient x1="98.361014%" y1="49.8607451%" x2="-6.66133815e-14%" y2="49.824166%" id="linearGradient-2">
|
||||
<stop stop-color="#3797C6" stop-opacity="0.31441215" offset="0%"></stop>
|
||||
<stop stop-color="#52FFF1" offset="100%"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient x1="103.601203%" y1="50.920359%" x2="-6.66133815e-14%" y2="49.3224437%" id="linearGradient-3">
|
||||
<stop stop-color="#31A6AE" stop-opacity="0" offset="0%"></stop>
|
||||
<stop stop-color="#31A6AE" offset="100%"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient x1="103.601203%" y1="50.0057165%" x2="-6.66133815e-14%" y2="49.9957916%" id="linearGradient-4">
|
||||
<stop stop-color="#31A6AE" offset="0%"></stop>
|
||||
<stop stop-color="#3797C6" stop-opacity="0" offset="100%"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient x1="98.361014%" y1="49.8601267%" x2="-6.66133815e-14%" y2="49.8233851%" id="linearGradient-5">
|
||||
<stop stop-color="#3797C6" stop-opacity="0.31441215" offset="0%"></stop>
|
||||
<stop stop-color="#52FFF1" offset="100%"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient x1="103.601203%" y1="50.920359%" x2="-6.66133815e-14%" y2="49.3224437%" id="linearGradient-6">
|
||||
<stop stop-color="#3797C6" stop-opacity="0" offset="0%"></stop>
|
||||
<stop stop-color="#31A6AE" offset="100%"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient x1="103.601203%" y1="50.0051355%" x2="-6.66133815e-14%" y2="49.9962193%" id="linearGradient-7">
|
||||
<stop stop-color="#31A6AE" offset="0%"></stop>
|
||||
<stop stop-color="#3797C6" stop-opacity="0" offset="100%"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient x1="103.601203%" y1="50.0271564%" x2="-6.66133815e-14%" y2="49.9800078%" id="linearGradient-8">
|
||||
<stop stop-color="#31A6AE" offset="0%"></stop>
|
||||
<stop stop-color="#3797C6" stop-opacity="0" offset="100%"></stop>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g id="洛阳" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="编组-11" transform="translate(-58.630000, -0.000000)">
|
||||
<polygon id="路径-5" fill="url(#linearGradient-1)" points="1.06 -4.52350829e-15 1.06 31.8 88.7697287 31.8 128.946587 58.1580023 620.989897 58.1580023 672.41193 93.28 1362.3368 93.28 1413.93684 57.6994189 1894.84731 57.6994189 1934.37339 31.8 2036.26 31.8 2036.26 2.36492588e-13"></polygon>
|
||||
<g id="编组-12" transform="translate(0.000000, 0.000000)">
|
||||
<g id="编组-8" transform="translate(753.939016, 24.380000)"></g>
|
||||
<g id="编组-4" transform="translate(0.796014, 31.800000)">
|
||||
<polyline id="路径-9" stroke="url(#linearGradient-2)" stroke-width="2.12" points="2035.46399 6.00379318e-14 1933.57738 4.06155665e-14 1893.40052 26.3580023 1411.95513 26.3580023 1361.15549 60.42 1016.60461 60.42"></polyline>
|
||||
<g id="编组-29" transform="translate(1654.842159, 48.760000) scale(-1, 1) translate(-1654.842159, -48.760000) translate(1410.983177, 37.100000)">
|
||||
<polyline id="路径-10" stroke="url(#linearGradient-3)" stroke-width="2.12" points="487.717964 23.32 461.370411 5.3 332.919335 5.3"></polyline>
|
||||
<ellipse id="椭圆形" fill="#31A6AE" cx="327.618296" cy="5.3" rx="4.24083073" ry="4.24"></ellipse>
|
||||
<ellipse id="椭圆形备份" fill="#31A6AE" cx="234.32002" cy="5.3" rx="4.24083073" ry="4.24"></ellipse>
|
||||
<g id="编组-2" transform="translate(249.162928, 0.000000)" fill="#31A6AE">
|
||||
<polygon id="路径-11" points="54.9656423 6.35491659e-14 50.8899688 0 59.9586387 10.6 63.612461 10.6"></polygon>
|
||||
<polygon id="路径-11备份" opacity="0.8" points="42.2431501 6.35491659e-14 38.1674766 0 47.2361465 10.6 50.8899688 10.6"></polygon>
|
||||
<polygon id="路径-11备份-3" opacity="0.4" points="16.7981657 6.35491659e-14 12.7224922 0 21.7911621 10.6 25.4449844 10.6"></polygon>
|
||||
<polygon id="路径-11备份-2" opacity="0.601434" points="29.5206579 6.35491659e-14 25.4449844 0 34.5136543 10.6 38.1674766 10.6"></polygon>
|
||||
<polygon id="路径-11备份-4" opacity="0.201434" points="4.07567352 6.35491659e-14 4.95668408e-16 0 9.06866995 10.6 12.7224922 10.6"></polygon>
|
||||
</g>
|
||||
<line x1="230.07919" y1="4.77" x2="1.03715491" y2="5.3" id="路径-12" stroke="url(#linearGradient-4)" stroke-width="2.12"></line>
|
||||
</g>
|
||||
<polyline id="路径-9" stroke="url(#linearGradient-5)" stroke-width="2.12" transform="translate(508.302305, 30.210000) scale(-1, 1) translate(-508.302305, -30.210000) " points="1016.60461 -1.3415935e-14 928.630896 -4.69406992e-14 888.454038 26.3580023 396.410728 26.3580023 345.61109 60.42 -4.81425453e-13 60.42"></polyline>
|
||||
<g id="编组-28" transform="translate(121.788081, 37.100000)">
|
||||
<polyline id="路径-10" stroke="url(#linearGradient-6)" stroke-width="2.12" points="500.437964 23.32 474.090411 5.3 345.639335 5.3"></polyline>
|
||||
<ellipse id="椭圆形" fill="#31A6AE" cx="340.338296" cy="5.3" rx="4.24083073" ry="4.24"></ellipse>
|
||||
<ellipse id="椭圆形备份" fill="#31A6AE" cx="247.04002" cy="5.3" rx="4.24083073" ry="4.24"></ellipse>
|
||||
<g id="编组-2" transform="translate(261.882928, 0.000000)" fill="#31A6AE">
|
||||
<polygon id="路径-11" points="54.9656423 6.35491659e-14 50.8899688 0 59.9586387 10.6 63.612461 10.6"></polygon>
|
||||
<polygon id="路径-11备份" opacity="0.8" points="42.2431501 6.35491659e-14 38.1674766 0 47.2361465 10.6 50.8899688 10.6"></polygon>
|
||||
<polygon id="路径-11备份-3" opacity="0.4" points="16.7981657 6.35491659e-14 12.7224922 0 21.7911621 10.6 25.4449844 10.6"></polygon>
|
||||
<polygon id="路径-11备份-2" opacity="0.601434" points="29.5206579 6.35491659e-14 25.4449844 0 34.5136543 10.6 38.1674766 10.6"></polygon>
|
||||
<polygon id="路径-11备份-4" opacity="0.201434" points="4.07567352 6.35491659e-14 4.95668408e-16 0 9.06866995 10.6 12.7224922 10.6"></polygon>
|
||||
</g>
|
||||
<line x1="242.79919" y1="4.77" x2="0.375905586" y2="5.3" id="路径-12" stroke="url(#linearGradient-7)" stroke-width="2.12"></line>
|
||||
</g>
|
||||
<g id="编组-3" transform="translate(124.969950, 0.000000)">
|
||||
<g id="编组-2备份" fill="#31A6AE">
|
||||
<polygon id="路径-11" points="82.4484634 9.53237489e-14 76.3349532 0 89.9379581 15.9 95.4186914 15.9"></polygon>
|
||||
<polygon id="路径-11备份" opacity="0.8" points="63.3647251 9.53237489e-14 57.2512149 0 70.8542198 15.9 76.3349532 15.9"></polygon>
|
||||
<polygon id="路径-11备份-3" opacity="0.4" points="25.1972486 9.53237489e-14 19.0837383 0 32.6867432 15.9 38.1674766 15.9"></polygon>
|
||||
<polygon id="路径-11备份-2" opacity="0.601434" points="44.2809868 9.53237489e-14 38.1674766 0 51.7704815 15.9 57.2512149 15.9"></polygon>
|
||||
<polygon id="路径-11备份-4" opacity="0.201434" points="6.11351027 9.53237489e-14 7.43502613e-16 0 13.6030049 15.9 19.0837383 15.9"></polygon>
|
||||
</g>
|
||||
<line x1="109.201391" y1="7.95" x2="215.199791" y2="8.48" id="路径-13" stroke="url(#linearGradient-8)" stroke-width="2.12"></line>
|
||||
</g>
|
||||
<g id="编组-3备份" transform="translate(1779.428192, 7.950000) scale(-1, 1) translate(-1779.428192, -7.950000) translate(1671.817112, 0.000000)">
|
||||
<g id="编组-2备份" fill="#31A6AE">
|
||||
<polygon id="路径-11" points="82.4484634 9.53237489e-14 76.3349532 0 89.9379581 15.9 95.4186914 15.9"></polygon>
|
||||
<polygon id="路径-11备份" opacity="0.8" points="63.3647251 9.53237489e-14 57.2512149 0 70.8542198 15.9 76.3349532 15.9"></polygon>
|
||||
<polygon id="路径-11备份-3" opacity="0.4" points="25.1972486 9.53237489e-14 19.0837383 0 32.6867432 15.9 38.1674766 15.9"></polygon>
|
||||
<polygon id="路径-11备份-2" opacity="0.601434" points="44.2809868 9.53237489e-14 38.1674766 0 51.7704815 15.9 57.2512149 15.9"></polygon>
|
||||
<polygon id="路径-11备份-4" opacity="0.201434" points="6.11351027 9.53237489e-14 7.43502613e-16 0 13.6030049 15.9 19.0837383 15.9"></polygon>
|
||||
</g>
|
||||
<line x1="109.201391" y1="7.95" x2="215.199791" y2="8.48" id="路径-13" stroke="url(#linearGradient-8)" stroke-width="2.12"></line>
|
||||
</g>
|
||||
</g>
|
||||
<rect id="矩形" stroke="#979797" stroke-width="1.06" opacity="0" x="0.53" y="0.53" width="2034.14" height="92.22"></rect>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 9.9 KiB After Width: | Height: | Size: 9.7 KiB |
25
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: <SwitchLine/>,
|
||||
errorElement: <ErrorPage/>
|
||||
},
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
{
|
||||
path: "/TP/:LineID?",
|
||||
element: <TestPage/>,
|
||||
errorElement: <ErrorPage/>
|
||||
},
|
||||
{
|
||||
path: "/LD",
|
||||
element: <LDPage/>,
|
||||
errorElement: <ErrorPage/>
|
||||
},
|
||||
///////////////////////////////////////////////////////////////
|
||||
{
|
||||
path: "/LP/:LineID?",
|
||||
element: <LinePage/>,
|
||||
errorElement: <ErrorPage/>
|
||||
},
|
||||
// {
|
||||
// path: "/TP/:LineID?",
|
||||
// element: <TestPage/>,
|
||||
// errorElement: <ErrorPage/>
|
||||
// },
|
||||
]);
|
||||
|
||||
return (
|
||||
|
648
src/babylonjs/LinePageBabylon.tsx
Normal file
@ -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<number>;
|
||||
}
|
||||
interface EqInfoDataInterface {
|
||||
[key: string]: Array<EqInfoInterface>;
|
||||
}
|
||||
const eqInfoData: EqInfoDataInterface = {
|
||||
"Line5-1": [
|
||||
{
|
||||
name: "磨边进口",
|
||||
data: [
|
||||
{ name: "1支线", value: 413 },
|
||||
{ name: "2支线", value: 435 },
|
||||
{ name: "3支线", value: 397 },
|
||||
],
|
||||
position: [154, 266],
|
||||
},
|
||||
{
|
||||
name: "磨边清洗出口",
|
||||
data: [
|
||||
{ name: "1支线", value: 401 },
|
||||
{ name: "2支线", value: 418 },
|
||||
{ name: "3支线", value: 389 },
|
||||
],
|
||||
position: [331, 177],
|
||||
},
|
||||
{
|
||||
name: "一次镀膜进口",
|
||||
data: [
|
||||
{ name: "1支线", value: 400 },
|
||||
{ name: "2支线", value: 418 },
|
||||
{ name: "3支线", value: 388 },
|
||||
],
|
||||
position: [555, 329],
|
||||
},
|
||||
{
|
||||
name: "二次镀膜进口",
|
||||
data: [
|
||||
{ name: "1支线", value: 387 },
|
||||
{ name: "2支线", value: 399 },
|
||||
{ name: "3支线", value: 381 },
|
||||
],
|
||||
position: [550, 85],
|
||||
},
|
||||
{
|
||||
name: "二次固化出口",
|
||||
data: [
|
||||
{ name: "1支线", value: 384 },
|
||||
{ name: "2支线", value: 398 },
|
||||
{ name: "3支线", value: 377 },
|
||||
],
|
||||
position: [857, 184],
|
||||
},
|
||||
{
|
||||
name: "钢化进口",
|
||||
data: [{ name: "钢化进口", value: 1157 }],
|
||||
position: [870, 48],
|
||||
},
|
||||
],
|
||||
"Line5-2": [
|
||||
{
|
||||
name: "钢化出口",
|
||||
data: [{ name: "钢化出口", value: 1124 }],
|
||||
position: [305, 255],
|
||||
},
|
||||
{
|
||||
name: "包装清洗机入口",
|
||||
data: [
|
||||
{ name: "包装清洗机5_1", value: 515 },
|
||||
{ name: "包装清洗机5_2", value: 507 },
|
||||
],
|
||||
position: [508, 319],
|
||||
},
|
||||
{
|
||||
name: "包装清洗机出口",
|
||||
data: [
|
||||
{ name: "包装清洗机5_1", value: 515 },
|
||||
{ name: "包装清洗机5_2", value: 505 },
|
||||
],
|
||||
position: [444, 159],
|
||||
},
|
||||
{
|
||||
name: "铺纸机",
|
||||
data: [
|
||||
{ name: "铺纸机5_1", value: 509 },
|
||||
{ name: "铺纸机5_2", value: 504 },
|
||||
],
|
||||
position: [696, 272],
|
||||
},
|
||||
{
|
||||
name: "下片机械手",
|
||||
data: [
|
||||
{ name: "下片机械手5_1", value: 347 },
|
||||
{ name: "下片机械手5_2", value: 334 },
|
||||
{ name: "下片机械手5_3", value: 316 },
|
||||
],
|
||||
position: [712, 28],
|
||||
},
|
||||
],
|
||||
};
|
||||
interface EqStatusListInterface {
|
||||
[key: string]: Array<{
|
||||
equipment: string;
|
||||
alarm: boolean;
|
||||
online: boolean;
|
||||
}>;
|
||||
}
|
||||
const eqStatusList: EqStatusListInterface = {
|
||||
"Line5-1": [
|
||||
{ equipment: "磨边机5_1", alarm: false, online: true },
|
||||
{ equipment: "磨边机5_2", alarm: false, online: true },
|
||||
{ equipment: "磨边机5_3", alarm: false, online: true },
|
||||
{ equipment: "清洗机5_1", alarm: false, online: true },
|
||||
{ equipment: "清洗机5_2", alarm: false, online: true },
|
||||
{ equipment: "清洗机5_3", alarm: false, online: true },
|
||||
{ equipment: "一次镀膜5_2", alarm: false, online: true },
|
||||
{ equipment: "一次镀膜5_3", alarm: false, online: true },
|
||||
{ equipment: "一次固化5_1", alarm: false, online: true },
|
||||
{ equipment: "一次镀膜5_1", alarm: false, online: true },
|
||||
{ equipment: "一次固化5_2", alarm: false, online: true },
|
||||
{ equipment: "一次固化5_3", alarm: false, online: true },
|
||||
{ equipment: "二次镀膜5_1", alarm: false, online: true },
|
||||
{ equipment: "二次镀膜5_2", alarm: false, online: true },
|
||||
{ equipment: "二次镀膜5_3", alarm: false, online: true },
|
||||
{ equipment: "二次固化5_1", alarm: false, online: true },
|
||||
{ equipment: "二次固化5_2", alarm: false, online: true },
|
||||
{ equipment: "二次固化5_3", alarm: false, online: true },
|
||||
],
|
||||
"Line5-2": [
|
||||
{ equipment: "钢化炉5", alarm: false, online: true },
|
||||
{ equipment: "包装清洗机5_1", alarm: false, online: true },
|
||||
{ equipment: "包装清洗机5_2", alarm: false, online: true },
|
||||
{ equipment: "在线铺纸机5_1", alarm: false, online: true },
|
||||
{ equipment: "在线铺纸机5_2", alarm: false, online: true },
|
||||
{ equipment: "下片机械手5_1", alarm: false, online: true },
|
||||
{ equipment: "下片机械手5_2", alarm: false, online: true },
|
||||
{ equipment: "下片机械手5_3", alarm: false, online: true },
|
||||
],
|
||||
};
|
||||
function MybabylonJS({ modelPath }: MybabylonJSProps) {
|
||||
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<string | null>(null);
|
||||
const [selectedMeshObj, setSelectedMeshObj] = useState({
|
||||
equipment: "",
|
||||
alarm: false,
|
||||
online: true,
|
||||
});
|
||||
const [showInfo, setShowInfo] = useState(true);
|
||||
|
||||
// 使用 useRef 来存储当前加载的模型引用
|
||||
const currentMeshesRef = useRef<Array<BABYLON.AbstractMesh>>([]);
|
||||
|
||||
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 (
|
||||
<div style={myStyle}>
|
||||
{/* <h2 className="model_name">当前选择: {selectedMeshName}</h2> */}
|
||||
<div className="model_info">
|
||||
<span className="reset_btn" onClick={resetModel}></span>
|
||||
<span className="title">
|
||||
第五产线钢化{modelPath.slice(-1) === "1" ? "前段" : "后段"}
|
||||
</span>
|
||||
</div>
|
||||
{selectedMeshName && (
|
||||
<div className="eq_detail_info">
|
||||
<div>
|
||||
<span className="left_name">设备名称:</span>
|
||||
<span className="right_value">{selectedMeshObj.equipment}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span className="left_name">报警状态:</span>
|
||||
<span className="right_value">
|
||||
{selectedMeshObj.alarm ? (
|
||||
<>
|
||||
<img
|
||||
src={AlarmTipRed}
|
||||
alt=""
|
||||
width={17}
|
||||
style={{ position: "relative", top: "2px", marginRight: 5 }}
|
||||
/>
|
||||
<span>报警</span>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<img
|
||||
src={AlarmTipGreen}
|
||||
alt=""
|
||||
width={17}
|
||||
style={{ position: "relative", top: "2px", marginRight: 5 }}
|
||||
/>
|
||||
<span>正常</span>
|
||||
</>
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<span className="left_name">在线状态:</span>
|
||||
<span className="right_value">
|
||||
{selectedMeshObj.online ? (
|
||||
<>
|
||||
<img
|
||||
src={AlarmTipGreen}
|
||||
alt=""
|
||||
width={17}
|
||||
style={{ position: "relative", top: "2px", marginRight: 5 }}
|
||||
/>
|
||||
<span>在线</span>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<img
|
||||
src={AlarmTipYellow}
|
||||
alt=""
|
||||
width={17}
|
||||
style={{ position: "relative", top: "2px", marginRight: 5 }}
|
||||
/>
|
||||
<span>离线</span>
|
||||
</>
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{showInfo &&
|
||||
eqInfoData[modelPath] &&
|
||||
eqInfoData[modelPath].map((item, index) => {
|
||||
return (
|
||||
<div
|
||||
className="eq_info"
|
||||
key={index}
|
||||
style={{ left: item.position[0], top: item.position[1] }}
|
||||
>
|
||||
<div className="eq_info_inner" style={{ color: "#00FFF0" }}>
|
||||
{item.name}
|
||||
</div>
|
||||
{item.data.map((info, index) => {
|
||||
return (
|
||||
<div className="eq_info_inner">
|
||||
{info.name}:{info.value}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
||||
<canvas ref={canvasRef} style={myStyle} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default MybabylonJS;
|
@ -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);
|
||||
|
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
@ -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
@ -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
@ -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
@ -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
@ -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;
|
||||
}
|
4
src/page/LDPage/index.css
Normal file
@ -0,0 +1,4 @@
|
||||
.main-box {
|
||||
font-size: 50px;
|
||||
color: #fff;
|
||||
}
|
35
src/page/LDPage/index.tsx
Normal file
@ -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 (
|
||||
<>
|
||||
<div className="main-box">LDPage{state.LineID}</div>
|
||||
<div className="main-box" style={{display:'none'}}>3434</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default LDPage;
|
248
src/page/LinePage/Center/CenterDown.tsx
Normal file
@ -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<string>(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", "<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>",
|
||||
],
|
||||
],
|
||||
};
|
||||
const config1 = {
|
||||
header: ["序号", "报警时间", "报警设备", "报警内容"],
|
||||
headerHeight: 36,
|
||||
rowNum: 6,
|
||||
align: ["center", "left", "left", "left"],
|
||||
headerBGC: "rgba(79, 114, 136, 0.3)",
|
||||
oddRowBGC: "rgba(79, 114, 136, 0.3)",
|
||||
evenRowBGC: "rgba(76, 97, 123, 0.1)",
|
||||
columnWidth: [80, 137, 137, 137],
|
||||
data: [
|
||||
[
|
||||
"1",
|
||||
"2024/8/28 08:32",
|
||||
"清洗机5_1",
|
||||
"<span style='color:#FF1E1E'>故障</span>",
|
||||
],
|
||||
[
|
||||
"2",
|
||||
"2024/8/28 06:12",
|
||||
"清洗机5_1",
|
||||
"<span style='color:#FFB40F'>离线</span>",
|
||||
],
|
||||
[
|
||||
"3",
|
||||
"2024/8/28 06:05",
|
||||
"磨边机5_2",
|
||||
"<span style='color:#FFB40F'>离线</span>",
|
||||
],
|
||||
[
|
||||
"4",
|
||||
"2024/8/28 04:43",
|
||||
"二次镀膜机5_1",
|
||||
"<span style='color:#FFB40F'>离线</span>",
|
||||
],
|
||||
[
|
||||
"5",
|
||||
"2024/8/28 02:14",
|
||||
"磨边机5_1",
|
||||
"<span style='color:#FF1E1E'>故障</span>",
|
||||
],
|
||||
[
|
||||
"6",
|
||||
"2024/8/27 22:54",
|
||||
"磨边机5_2",
|
||||
"<span style='color:#FFB40F'>离线</span>",
|
||||
],
|
||||
[
|
||||
"7",
|
||||
"2024/8/27 21:55",
|
||||
"磨边机5_1",
|
||||
"<span style='color:#FFB40F'>离线</span>",
|
||||
],
|
||||
[
|
||||
"8",
|
||||
"2024/8/27 21:42",
|
||||
"一次镀膜机5_2",
|
||||
"<span style='color:#FFB40F'>离线</span>",
|
||||
],
|
||||
[
|
||||
"9",
|
||||
"2024/8/27 21:37",
|
||||
"磨边机5_1",
|
||||
"<span style='color:#FFB40F'>离线</span>",
|
||||
],
|
||||
],
|
||||
};
|
||||
const config2 = {
|
||||
header: ["序号", "报警时间", "报警设备", "报警内容"],
|
||||
headerHeight: 36,
|
||||
rowNum: 6,
|
||||
align: ["center", "left", "left", "left"],
|
||||
headerBGC: "rgba(79, 114, 136, 0.3)",
|
||||
oddRowBGC: "rgba(79, 114, 136, 0.3)",
|
||||
evenRowBGC: "rgba(76, 97, 123, 0.1)",
|
||||
columnWidth: [80, 137, 137, 137],
|
||||
data: [
|
||||
[
|
||||
"1",
|
||||
"2024/8/28 07:44",
|
||||
"下片机械手5_1",
|
||||
"<span style='color:#FF1E1E'>故障</span>",
|
||||
],
|
||||
[
|
||||
"2",
|
||||
"2024/8/28 07:35",
|
||||
"下片机械手5_1",
|
||||
"<span style='color:#FF1E1E'>故障</span>",
|
||||
],
|
||||
[
|
||||
"3",
|
||||
"2024/8/28 03:23",
|
||||
"在线铺纸机5_1",
|
||||
"<span style='color:#FFB40F'>离线</span>",
|
||||
],
|
||||
[
|
||||
"4",
|
||||
"2024/8/28 01:36",
|
||||
"下片机械手5_2",
|
||||
"<span style='color:#FF1E1E'>故障</span>",
|
||||
],
|
||||
[
|
||||
"5",
|
||||
"2024/8/28 00:38",
|
||||
"钢化炉5",
|
||||
"<span style='color:#FFB40F'>离线</span>",
|
||||
],
|
||||
[
|
||||
"6",
|
||||
"2024/8/27 23:58",
|
||||
"下片机械手5_3",
|
||||
"<span style='color:#FFB40F'>离线</span>",
|
||||
],
|
||||
[
|
||||
"7",
|
||||
"2024/8/27 23:45",
|
||||
"下片机械手5_2",
|
||||
"<span style='color:#FFB40F'>离线</span>",
|
||||
],
|
||||
[
|
||||
"8",
|
||||
"2024/8/27 22:34",
|
||||
"钢化炉5",
|
||||
"<span style='color:#FFB40F'>离线</span>",
|
||||
],
|
||||
[
|
||||
"9",
|
||||
"2024/8/27 20:31",
|
||||
"在线铺纸机5_1",
|
||||
"<span style='color:#FF1E1E'>故障</span>",
|
||||
],
|
||||
],
|
||||
};
|
||||
return (
|
||||
<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={lineID.slice(-1) === "1" ? config1 : config2}
|
||||
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} onChange={handleButtonChange} />
|
||||
</div> */}
|
||||
|
||||
{options && (
|
||||
<div className="chart_box">
|
||||
{<ReactECharts option={options} style={{ height: "100%" }} />}
|
||||
</div>
|
||||
)}
|
||||
{!options && (
|
||||
<p
|
||||
style={{
|
||||
color: "#cccf",
|
||||
fontSize: "24px",
|
||||
userSelect: "none",
|
||||
textAlign: "center",
|
||||
paddingTop: "72px",
|
||||
}}
|
||||
>
|
||||
暂无数据
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
export default CenterDown;
|
12
src/page/LinePage/Center/CenterUp.tsx
Normal file
@ -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 (
|
||||
<div className="center_up">
|
||||
<LinePageBabylon modelPath={`Line${lineID}`} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
export default CenterUp;
|
119
src/page/LinePage/Center/LineChart/chart.config.ts
Normal file
@ -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,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
12
src/page/LinePage/Center/index.tsx
Normal file
@ -0,0 +1,12 @@
|
||||
import CenterDown from "./CenterDown";
|
||||
import CenterUp from "./CenterUp";
|
||||
|
||||
function Center() {
|
||||
return (
|
||||
<div className="group_center flex-col">
|
||||
<CenterUp />
|
||||
<CenterDown />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
export default Center;
|
19
src/page/LinePage/Component/SwitchButton/index.css
Normal file
@ -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);
|
||||
}
|
65
src/page/LinePage/Component/SwitchButton/index.tsx
Normal file
@ -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<any>(null);
|
||||
let updateActiveName = createActiveNameUpdater(props.nameList, activeName);
|
||||
useEffect(() => {
|
||||
const timer = setInterval(() => {
|
||||
let active = updateActiveName();
|
||||
setActiveName(active);
|
||||
props.onChange(active);
|
||||
}, 60000);
|
||||
setTimerId(timer);
|
||||
return () => {
|
||||
if (timerId !== null) {
|
||||
clearInterval(timerId);
|
||||
}
|
||||
};
|
||||
}, [props.nameList.length]);
|
||||
const btnClick = (ename: string) => {
|
||||
if (timerId !== null) {
|
||||
clearInterval(timerId);
|
||||
}
|
||||
setActiveName(ename);
|
||||
props.onChange(ename); // 通知父组件
|
||||
const newTimer = setInterval(() => {
|
||||
let active = updateActiveName();
|
||||
setActiveName(active);
|
||||
props.onChange(active);
|
||||
}, 60000);
|
||||
setTimerId(newTimer);
|
||||
};
|
||||
return (
|
||||
<div className="switch-button">
|
||||
{props.nameList.map((item, index) => {
|
||||
return (
|
||||
<button
|
||||
key={item.ename}
|
||||
className={activeName === item.ename ? "active" : ""}
|
||||
onClick={() => btnClick(item.ename)}
|
||||
>
|
||||
{item.name}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
export default SwitchButton;
|
13
src/page/LinePage/Component/TitleBox/index.css
Normal file
@ -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;
|
||||
}
|
53
src/page/LinePage/Component/TitleBox/index.tsx
Normal file
@ -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 (
|
||||
<div className="title_box">
|
||||
<img src={filteredTitles().img} alt="title" />
|
||||
<span>{filteredTitles().title}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
export default TitleBox;
|
79
src/page/LinePage/Left/BarChart/chart.config.ts
Normal file
@ -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] },
|
||||
]),
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
183
src/page/LinePage/Left/LeftDown.tsx
Normal file
@ -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<string>(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 (
|
||||
<div className="left_down">
|
||||
<TitleBox title={"left_down"} />
|
||||
<div className="left_up_switch">
|
||||
<SwitchButton nameList={nameList} onChange={handleButtonChange} />
|
||||
</div>
|
||||
<div style={{ padding: "10px", height: "555px" }}>
|
||||
<div className="left_down_title flex-row">
|
||||
<div className="left_down_box1 flex-col" />
|
||||
<span className="left_down_text">当天</span>
|
||||
<div className="left_down_box2 flex-col" />
|
||||
</div>
|
||||
<div className="left_down_content">
|
||||
{activeName === "table" ? (
|
||||
<ScrollBoard
|
||||
config={config1}
|
||||
style={{ width: "380px", height: "150px" }}
|
||||
/>
|
||||
) : options1 ? (
|
||||
<ReactECharts option={options1} style={{ height: "100%" }} />
|
||||
) : (
|
||||
<p
|
||||
style={{
|
||||
color: "#cccf",
|
||||
fontSize: "24px",
|
||||
userSelect: "none",
|
||||
textAlign: "center",
|
||||
paddingTop: "72px",
|
||||
}}
|
||||
>
|
||||
暂无数据
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<div className="left_down_title flex-row">
|
||||
<div className="left_down_box1 flex-col" />
|
||||
<span className="left_down_text">本周</span>
|
||||
<div className="left_down_box2 flex-col" />
|
||||
</div>
|
||||
<div className="left_down_content">
|
||||
{activeName === "table" ? (
|
||||
<ScrollBoard
|
||||
config={config2}
|
||||
style={{ width: "380px", height: "150px" }}
|
||||
/>
|
||||
) : options2 ? (
|
||||
<ReactECharts option={options2} style={{ height: "100%" }} />
|
||||
) : (
|
||||
<p
|
||||
style={{
|
||||
color: "#cccf",
|
||||
fontSize: "24px",
|
||||
userSelect: "none",
|
||||
textAlign: "center",
|
||||
paddingTop: "72px",
|
||||
}}
|
||||
>
|
||||
暂无数据
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<div className="left_down_title flex-row">
|
||||
<div className="left_down_box1 flex-col" />
|
||||
<span className="left_down_text">本月</span>
|
||||
<div className="left_down_box2 flex-col" />
|
||||
</div>
|
||||
<div className="left_down_content">
|
||||
{activeName === "table" ? (
|
||||
<ScrollBoard
|
||||
config={config3}
|
||||
style={{ width: "380px", height: "150px" }}
|
||||
/>
|
||||
) : options3 ? (
|
||||
<ReactECharts option={options3} style={{ height: "100%" }} />
|
||||
) : (
|
||||
<p
|
||||
style={{
|
||||
color: "#cccf",
|
||||
fontSize: "24px",
|
||||
userSelect: "none",
|
||||
textAlign: "center",
|
||||
paddingTop: "72px",
|
||||
}}
|
||||
>
|
||||
暂无数据
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
export default LeftDown;
|
69
src/page/LinePage/Left/LeftUp.tsx
Normal file
@ -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<string>(nameList[0].ename);
|
||||
let chartData = (dataSource as { [key: string]: any })[activeName];
|
||||
const handleButtonChange = (activeName: string) => {
|
||||
setActiveName(activeName);
|
||||
};
|
||||
const options = getOptions(chartData);
|
||||
return (
|
||||
<div className="left_up">
|
||||
<TitleBox title={"left_up"} />
|
||||
<div className="left_up_switch">
|
||||
<SwitchButton nameList={nameList} onChange={handleButtonChange} />
|
||||
</div>
|
||||
{options && (
|
||||
<div className="left_up_chart">
|
||||
{<ReactECharts option={options} style={{ height: "100%" }} />}
|
||||
</div>
|
||||
)}
|
||||
{!options && (
|
||||
<p
|
||||
style={{
|
||||
color: "#cccf",
|
||||
fontSize: "24px",
|
||||
userSelect: "none",
|
||||
textAlign: "center",
|
||||
paddingTop: "72px",
|
||||
}}
|
||||
>
|
||||
暂无数据
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
export default LeftUp;
|
149
src/page/LinePage/Left/SummaryBarChart/chart.config.ts
Normal file
@ -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];
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
4
src/page/LinePage/Left/Table/index.tsx
Normal file
@ -0,0 +1,4 @@
|
||||
function Table() {
|
||||
return <div>111</div>;
|
||||
}
|
||||
export default Table;
|
11
src/page/LinePage/Left/index.tsx
Normal file
@ -0,0 +1,11 @@
|
||||
import LeftUp from "./LeftUp";
|
||||
import LeftDown from "./LeftDown";
|
||||
function Left() {
|
||||
return (
|
||||
<div className="group_left flex-col">
|
||||
<LeftUp />
|
||||
<LeftDown />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
export default Left;
|
99
src/page/LinePage/Right/LineChart/chart.config.ts
Normal file
@ -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,
|
||||
},
|
||||
};
|
||||
}
|
294
src/page/LinePage/Right/RightDown.tsx
Normal file
@ -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<string>(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 (
|
||||
<div className="right_down">
|
||||
<TitleBox title={"right_down"} />
|
||||
<div className="left_up_switch">
|
||||
<SwitchButton nameList={nameList} onChange={handleButtonChange} />
|
||||
</div>
|
||||
<div style={{ padding: "10px", height: "628px" }}>
|
||||
<div className="left_down_title flex-row">
|
||||
<div className="left_down_box1 flex-col" />
|
||||
<span className="left_down_text">当天</span>
|
||||
<div className="left_down_box2 flex-col" />
|
||||
</div>
|
||||
<div className="right_down_content">
|
||||
{activeName === "table" ? (
|
||||
<ScrollBoard
|
||||
config={config1}
|
||||
style={{ width: "380px", height: "180px" }}
|
||||
/>
|
||||
) : options1 ? (
|
||||
<ReactECharts option={options1} style={{ height: "100%" }} />
|
||||
) : (
|
||||
<p
|
||||
style={{
|
||||
color: "#cccf",
|
||||
fontSize: "24px",
|
||||
userSelect: "none",
|
||||
textAlign: "center",
|
||||
paddingTop: "72px",
|
||||
}}
|
||||
>
|
||||
暂无数据
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<div className="left_down_title flex-row">
|
||||
<div className="left_down_box1 flex-col" />
|
||||
<span className="left_down_text">本周</span>
|
||||
<div className="left_down_box2 flex-col" />
|
||||
</div>
|
||||
<div className="right_down_content">
|
||||
{activeName === "table" ? (
|
||||
<ScrollBoard
|
||||
config={config2}
|
||||
style={{ width: "380px", height: "180px" }}
|
||||
/>
|
||||
) : options2 ? (
|
||||
<ReactECharts option={options2} style={{ height: "100%" }} />
|
||||
) : (
|
||||
<p
|
||||
style={{
|
||||
color: "#cccf",
|
||||
fontSize: "24px",
|
||||
userSelect: "none",
|
||||
textAlign: "center",
|
||||
paddingTop: "72px",
|
||||
}}
|
||||
>
|
||||
暂无数据
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<div className="left_down_title flex-row">
|
||||
<div className="left_down_box1 flex-col" />
|
||||
<span className="left_down_text">本月</span>
|
||||
<div className="left_down_box2 flex-col" />
|
||||
</div>
|
||||
<div className="right_down_content">
|
||||
{activeName === "table" ? (
|
||||
<ScrollBoard
|
||||
config={config3}
|
||||
style={{ width: "380px", height: "180px" }}
|
||||
/>
|
||||
) : options3 ? (
|
||||
<ReactECharts option={options3} style={{ height: "100%" }} />
|
||||
) : (
|
||||
<p
|
||||
style={{
|
||||
color: "#cccf",
|
||||
fontSize: "24px",
|
||||
userSelect: "none",
|
||||
textAlign: "center",
|
||||
paddingTop: "72px",
|
||||
}}
|
||||
>
|
||||
暂无数据
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
export default RightDown;
|
33
src/page/LinePage/Right/RightUp.tsx
Normal file
@ -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 (
|
||||
<div className="right_up">
|
||||
<TitleBox title={"right_up"} />
|
||||
<div style={{ padding: "10px", height: "213px" }}>
|
||||
<ScrollBoard
|
||||
config={config}
|
||||
style={{ width: "380px", height: "193px" }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
export default RightUp;
|
12
src/page/LinePage/Right/index.tsx
Normal file
@ -0,0 +1,12 @@
|
||||
import RightDown from "./RightDown";
|
||||
import RightUp from "./RightUp";
|
||||
|
||||
function Right() {
|
||||
return (
|
||||
<div className="group_right flex-col">
|
||||
<RightUp />
|
||||
<RightDown />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
export default Right;
|
14
src/page/LinePage/TopP.tsx
Normal file
@ -0,0 +1,14 @@
|
||||
import '../../lanhuapp/common.css';
|
||||
import "./index.css";
|
||||
|
||||
function TopP() {
|
||||
return (
|
||||
<div className="flex-row">
|
||||
<div className="block_top flex-row">
|
||||
<div className='block_top_title'></div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default TopP;
|
BIN
src/page/LinePage/assets/icon/alarm.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
src/page/LinePage/assets/icon/defect.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
src/page/LinePage/assets/icon/finished.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
src/page/LinePage/assets/icon/g.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
src/page/LinePage/assets/icon/inputAndOutput.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
src/page/LinePage/assets/icon/num.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
src/page/LinePage/assets/icon/r.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
src/page/LinePage/assets/icon/record.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
src/page/LinePage/assets/icon/y.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
264
src/page/LinePage/index.css
Normal file
@ -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;
|
||||
}
|
18
src/page/LinePage/index.tsx
Normal file
@ -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 (
|
||||
<React.Fragment>
|
||||
<TopP />
|
||||
<div className="block_bottom flex-row">
|
||||
<Left />
|
||||
<Center />
|
||||
<Right />
|
||||
</div>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
export default LinePage;
|
@ -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 (
|
||||
<div className="block_16_E flex-col fineWin">
|
||||
<div className="fineWin-footer"/>
|
||||
<LineBabylon/>
|
||||
<LineBabylon />
|
||||
{/* <MybabylonJS_1 modelPath={`line${LineID}`} /> */}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -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 (
|
||||
<ThisLineID.Provider value={NowThisLineID}>
|
||||
<TopE/>
|
||||
|
41
src/page/TestPage/CenterUp.tsx
Normal file
@ -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 (
|
||||
<div className="block_16 flex-col fineWin">
|
||||
<div className="fineWin-footer"/>
|
||||
<MybabylonJS_1 modelPath={`line${modelIndex+1}`} />
|
||||
{/* 添加按钮来切换组件 */}
|
||||
<button className="centerButton_1" onClick={prevModelIndex}>上一个组件</button>
|
||||
<button className="centerButton_2" onClick={nextModelIndex}>下一个组件</button>
|
||||
<h5 className="centerButton_2" >{modelIndex}</h5>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default CenterUp;
|
4
src/page/TestPage/index.css
Normal file
@ -0,0 +1,4 @@
|
||||
.main-box {
|
||||
font-size: 50px;
|
||||
color: #fff;
|
||||
}
|
38
src/page/TestPage/index.tsx
Normal file
@ -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 (
|
||||
<>
|
||||
<div className="main-box">TestPage Line{LineID}</div>
|
||||
<div className="main-box" style={{display:'none'}}>3434</div>
|
||||
<MainE/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default TestPage;
|
@ -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"]
|
||||
}
|
||||
|