Compare commits
17 Commits
3c8c7e497b
...
zjl
| Author | SHA1 | Date | |
|---|---|---|---|
| ebe2a03023 | |||
| 40791bc619 | |||
| 45c8563892 | |||
| 288e2c8e04 | |||
| 84b34d7b79 | |||
| 1812afd680 | |||
| 128b362587 | |||
| e8ca7d16ee | |||
| 1f7b867dc5 | |||
| 022bf57feb | |||
| d142b16df3 | |||
| 0dcff0c256 | |||
| b6fb156c2c | |||
| 2bc9908f62 | |||
| 2cb5c7fcd2 | |||
| bbb7de918e | |||
| bda855430d |
25369
package-lock.json
generated
@@ -22,6 +22,7 @@
|
||||
"@types/node": "^16.11.56",
|
||||
"@types/react": "^18.0.17",
|
||||
"@types/react-dom": "^18.0.6",
|
||||
"antd": "^5.22.2",
|
||||
"axios": "^1.3.3",
|
||||
"babel-jest": "^27.4.2",
|
||||
"babel-loader": "^8.2.3",
|
||||
@@ -31,11 +32,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",
|
||||
@@ -78,7 +81,7 @@
|
||||
"workbox-webpack-plugin": "^6.4.1"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "node scripts/start.js",
|
||||
"start": "node --max-old-space-size=4096 scripts/start.js",
|
||||
"build": "node scripts/build.js",
|
||||
"test": "node scripts/test.js"
|
||||
},
|
||||
|
||||
@@ -1,177 +0,0 @@
|
||||
{
|
||||
"accessors": [
|
||||
{
|
||||
"bufferView": 0,
|
||||
"componentType": 5126,
|
||||
"count": 3575,
|
||||
"type": "VEC2"
|
||||
},
|
||||
{
|
||||
"bufferView": 1,
|
||||
"componentType": 5126,
|
||||
"count": 3575,
|
||||
"type": "VEC3"
|
||||
},
|
||||
{
|
||||
"bufferView": 2,
|
||||
"componentType": 5126,
|
||||
"count": 3575,
|
||||
"type": "VEC4"
|
||||
},
|
||||
{
|
||||
"bufferView": 3,
|
||||
"componentType": 5126,
|
||||
"count": 3575,
|
||||
"type": "VEC3",
|
||||
"max": [
|
||||
0.009921154,
|
||||
0.00977163,
|
||||
0.0100762453
|
||||
],
|
||||
"min": [
|
||||
-0.009921154,
|
||||
-0.00977163,
|
||||
-0.0100762453
|
||||
]
|
||||
},
|
||||
{
|
||||
"bufferView": 4,
|
||||
"componentType": 5123,
|
||||
"count": 18108,
|
||||
"type": "SCALAR"
|
||||
}
|
||||
],
|
||||
"asset": {
|
||||
"generator": "glTF Tools for Unity",
|
||||
"version": "2.0"
|
||||
},
|
||||
"bufferViews": [
|
||||
{
|
||||
"buffer": 0,
|
||||
"byteLength": 28600
|
||||
},
|
||||
{
|
||||
"buffer": 0,
|
||||
"byteOffset": 28600,
|
||||
"byteLength": 42900
|
||||
},
|
||||
{
|
||||
"buffer": 0,
|
||||
"byteOffset": 71500,
|
||||
"byteLength": 57200
|
||||
},
|
||||
{
|
||||
"buffer": 0,
|
||||
"byteOffset": 128700,
|
||||
"byteLength": 42900
|
||||
},
|
||||
{
|
||||
"buffer": 0,
|
||||
"byteOffset": 171600,
|
||||
"byteLength": 36216
|
||||
}
|
||||
],
|
||||
"buffers": [
|
||||
{
|
||||
"uri": "BoomBox.bin",
|
||||
"byteLength": 207816
|
||||
}
|
||||
],
|
||||
"images": [
|
||||
{
|
||||
"uri": "BoomBox_baseColor.png"
|
||||
},
|
||||
{
|
||||
"uri": "BoomBox_occlusionRoughnessMetallic.png"
|
||||
},
|
||||
{
|
||||
"uri": "BoomBox_normal.png"
|
||||
},
|
||||
{
|
||||
"uri": "BoomBox_emissive.png"
|
||||
}
|
||||
],
|
||||
"meshes": [
|
||||
{
|
||||
"primitives": [
|
||||
{
|
||||
"attributes": {
|
||||
"TEXCOORD_0": 0,
|
||||
"NORMAL": 1,
|
||||
"TANGENT": 2,
|
||||
"POSITION": 3
|
||||
},
|
||||
"indices": 4,
|
||||
"material": 0
|
||||
}
|
||||
],
|
||||
"name": "BoomBox"
|
||||
}
|
||||
],
|
||||
"materials": [
|
||||
{
|
||||
"pbrMetallicRoughness": {
|
||||
"baseColorTexture": {
|
||||
"index": 0
|
||||
},
|
||||
"metallicRoughnessTexture": {
|
||||
"index": 1
|
||||
}
|
||||
},
|
||||
"normalTexture": {
|
||||
"index": 2
|
||||
},
|
||||
"occlusionTexture": {
|
||||
"index": 1
|
||||
},
|
||||
"emissiveFactor": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"emissiveTexture": {
|
||||
"index": 3
|
||||
},
|
||||
"name": "BoomBox_Mat"
|
||||
}
|
||||
],
|
||||
"nodes": [
|
||||
{
|
||||
"mesh": 0,
|
||||
"rotation": [
|
||||
0.0,
|
||||
1.0,
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"scale": [ 1, 1, 1 ],
|
||||
"name": "BoomBox"
|
||||
}
|
||||
],
|
||||
"scene": 0,
|
||||
"scenes": [
|
||||
{
|
||||
"nodes": [
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"textures": [
|
||||
{
|
||||
"name": "baseColor",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"name": "occlusionRoughnessMetallic",
|
||||
"source": 1
|
||||
},
|
||||
{
|
||||
"name": "normal",
|
||||
"source": 2
|
||||
},
|
||||
{
|
||||
"name": "emissive",
|
||||
"source": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
|
Before Width: | Height: | Size: 3.1 MiB |
|
Before Width: | Height: | Size: 130 KiB |
|
Before Width: | Height: | Size: 2.7 MiB |
|
Before Width: | Height: | Size: 4.6 MiB |
@@ -1,183 +0,0 @@
|
||||
{
|
||||
"accessors": [
|
||||
{
|
||||
"bufferView": 0,
|
||||
"componentType": 5126,
|
||||
"count": 3575,
|
||||
"type": "VEC2"
|
||||
},
|
||||
{
|
||||
"bufferView": 1,
|
||||
"componentType": 5126,
|
||||
"count": 3575,
|
||||
"type": "VEC3"
|
||||
},
|
||||
{
|
||||
"bufferView": 2,
|
||||
"componentType": 5126,
|
||||
"count": 3575,
|
||||
"type": "VEC4"
|
||||
},
|
||||
{
|
||||
"bufferView": 3,
|
||||
"componentType": 5126,
|
||||
"count": 3575,
|
||||
"type": "VEC3",
|
||||
"max": [
|
||||
0.009921154,
|
||||
0.00977163,
|
||||
0.0100762453
|
||||
],
|
||||
"min": [
|
||||
-0.009921154,
|
||||
-0.00977163,
|
||||
-0.0100762453
|
||||
]
|
||||
},
|
||||
{
|
||||
"bufferView": 4,
|
||||
"componentType": 5123,
|
||||
"count": 18108,
|
||||
"type": "SCALAR"
|
||||
}
|
||||
],
|
||||
"asset": {
|
||||
"generator": "glTF Tools for Unity",
|
||||
"version": "2.0"
|
||||
},
|
||||
"bufferViews": [
|
||||
{
|
||||
"buffer": 0,
|
||||
"byteLength": 28600
|
||||
},
|
||||
{
|
||||
"buffer": 0,
|
||||
"byteOffset": 28600,
|
||||
"byteLength": 42900
|
||||
},
|
||||
{
|
||||
"buffer": 0,
|
||||
"byteOffset": 71500,
|
||||
"byteLength": 57200
|
||||
},
|
||||
{
|
||||
"buffer": 0,
|
||||
"byteOffset": 128700,
|
||||
"byteLength": 42900
|
||||
},
|
||||
{
|
||||
"buffer": 0,
|
||||
"byteOffset": 171600,
|
||||
"byteLength": 36216
|
||||
}
|
||||
],
|
||||
"buffers": [
|
||||
{
|
||||
"uri": "BoomBox.bin",
|
||||
"byteLength": 207816
|
||||
}
|
||||
],
|
||||
"extensionsUsed": [
|
||||
"KHR_materials_unlit"
|
||||
],
|
||||
"images": [
|
||||
{
|
||||
"uri": "BoomBox_baseColor.png"
|
||||
},
|
||||
{
|
||||
"uri": "BoomBox_occlusionRoughnessMetallic.png"
|
||||
},
|
||||
{
|
||||
"uri": "BoomBox_normal.png"
|
||||
},
|
||||
{
|
||||
"uri": "BoomBox_emissive.png"
|
||||
}
|
||||
],
|
||||
"meshes": [
|
||||
{
|
||||
"primitives": [
|
||||
{
|
||||
"attributes": {
|
||||
"TEXCOORD_0": 0,
|
||||
"NORMAL": 1,
|
||||
"TANGENT": 2,
|
||||
"POSITION": 3
|
||||
},
|
||||
"indices": 4,
|
||||
"material": 0
|
||||
}
|
||||
],
|
||||
"name": "BoomBox"
|
||||
}
|
||||
],
|
||||
"materials": [
|
||||
{
|
||||
"pbrMetallicRoughness": {
|
||||
"baseColorTexture": {
|
||||
"index": 0
|
||||
},
|
||||
"metallicRoughnessTexture": {
|
||||
"index": 1
|
||||
}
|
||||
},
|
||||
"normalTexture": {
|
||||
"index": 2
|
||||
},
|
||||
"occlusionTexture": {
|
||||
"index": 1
|
||||
},
|
||||
"emissiveFactor": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"emissiveTexture": {
|
||||
"index": 3
|
||||
},
|
||||
"name": "BoomBox_Mat",
|
||||
"extensions": {
|
||||
"KHR_materials_unlit": {}
|
||||
}
|
||||
}
|
||||
],
|
||||
"nodes": [
|
||||
{
|
||||
"mesh": 0,
|
||||
"rotation": [
|
||||
0.0,
|
||||
1.0,
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"scale": [ 1, 1, 1 ],
|
||||
"name": "BoomBox"
|
||||
}
|
||||
],
|
||||
"scene": 0,
|
||||
"scenes": [
|
||||
{
|
||||
"nodes": [
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"textures": [
|
||||
{
|
||||
"name": "baseColor",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"name": "occlusionRoughnessMetallic",
|
||||
"source": 1
|
||||
},
|
||||
{
|
||||
"name": "normal",
|
||||
"source": 2
|
||||
},
|
||||
{
|
||||
"name": "emissive",
|
||||
"source": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 4.2 KiB |
@@ -14,7 +14,7 @@
|
||||
manifest.json provides metadata used when your web app is installed on a
|
||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||
-->
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||
<!-- <link rel="manifest" href="%PUBLIC_URL%/manifest.json" /> -->
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
@@ -24,7 +24,7 @@
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>React App</title>
|
||||
<title>数智工厂生产监控驾驶舱</title>
|
||||
</head>
|
||||
<body style="overflow: hidden">
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
|
||||
|
Before Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
@@ -1,25 +0,0 @@
|
||||
{
|
||||
"short_name": "React App",
|
||||
"name": "Create React App Sample",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
},
|
||||
{
|
||||
"src": "logo192.png",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192"
|
||||
},
|
||||
{
|
||||
"src": "logo512.png",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
}
|
||||
|
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/numberBox.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
public/png/rect/ld_center_down.png
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
public/png/rect/ld_left_up_innerbox.png
Normal file
|
After Width: | Height: | Size: 113 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,3 +0,0 @@
|
||||
# https://www.robotstxt.org/robotstxt.html
|
||||
User-agent: *
|
||||
Disallow:
|
||||
@@ -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 |
75
public/svg/topbackLD.svg
Normal file
@@ -0,0 +1,75 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="1920px" height="93.0031818px" viewBox="0 0 1920 93.0031818" 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.8254916%" x2="-6.66133815e-14%" y2="49.7796521%" 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.6276601%" x2="-6.66133815e-14%" y2="49.5379248%" id="linearGradient-3">
|
||||
<stop stop-color="#31A6AE" stop-opacity="0" offset="0%"></stop>
|
||||
<stop stop-color="#31A6AE" offset="100%"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient x1="98.361014%" y1="49.8437805%" x2="-6.66133815e-14%" y2="49.8027451%" id="linearGradient-4">
|
||||
<stop stop-color="#3797C6" stop-opacity="0.31441215" offset="0%"></stop>
|
||||
<stop stop-color="#52FFF1" offset="100%"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient x1="103.601203%" y1="51.0279165%" x2="-6.66133815e-14%" y2="49.2432614%" id="linearGradient-5">
|
||||
<stop stop-color="#3797C6" stop-opacity="0" offset="0%"></stop>
|
||||
<stop stop-color="#31A6AE" offset="100%"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient x1="103.601203%" y1="50.0057357%" x2="-6.66133815e-14%" y2="49.9957774%" id="linearGradient-6">
|
||||
<stop stop-color="#31A6AE" offset="0%"></stop>
|
||||
<stop stop-color="#3797C6" stop-opacity="0" offset="100%"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient x1="103.601203%" y1="50.03033%" x2="-6.66133815e-14%" y2="49.9776715%" id="linearGradient-7">
|
||||
<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">
|
||||
<polygon id="路径-5" fill="url(#linearGradient-1)" points="1.90545852e-13 -4.50993001e-15 2.88853814e-14 31.7045455 82.7768328 31.7045455 120.694098 57.9834285 585.064327 57.9834285 633.594326 93 1284.71703 93 1333.41502 57.5262217 1517.36351 57.5262217 1554.66659 31.7045455 1866 31.7045455 1866 1.08915917e-12"></polygon>
|
||||
<g id="编组-12">
|
||||
<g id="编组-8" transform="translate(711.263222, 24.306818)"></g>
|
||||
<g id="编组-4" transform="translate(0.750956, 31.704545)">
|
||||
<polyline id="路径-9" stroke="url(#linearGradient-2)" stroke-width="2.12" points="1866.47546 1.64272616e-13 1556.20507 -1.48645149e-14 1518.30238 26.2788831 1332.03314 26.2788831 1284.10896 60.2386364 959.060954 60.2386364"></polyline>
|
||||
<g id="编组-29" transform="translate(1426.559836, 49.142045) scale(-1, 1) translate(-1426.559836, -49.142045) translate(1331.116205, 38.045455)">
|
||||
<polyline id="路径-10" stroke="url(#linearGradient-3)" stroke-width="2.12" points="190.887262 22.1931818 166.031081 4.22727273 4.00078371 4.22727273"></polyline>
|
||||
<ellipse id="椭圆形" fill="#31A6AE" cx="4.00078371" cy="4.22727273" rx="4.00078371" ry="4.22727273"></ellipse>
|
||||
</g>
|
||||
<polyline id="路径-9" stroke="url(#linearGradient-4)" stroke-width="2.12" transform="translate(479.530477, 30.119318) scale(-1, 1) translate(-479.530477, -30.119318) " points="959.060954 -1.33756642e-14 876.066883 -4.67997966e-14 838.164187 26.2788831 373.972385 26.2788831 326.048198 60.2386364 -4.54174955e-13 60.2386364"></polyline>
|
||||
<g id="编组-28" transform="translate(114.894416, 36.988636)">
|
||||
<polyline id="路径-10" stroke="url(#linearGradient-5)" stroke-width="2.12" points="472.111287 23.25 447.255105 5.28409091 326.074844 5.28409091"></polyline>
|
||||
<ellipse id="椭圆形" fill="#31A6AE" cx="321.073864" cy="5.28409091" rx="4.00078371" ry="4.22727273"></ellipse>
|
||||
<ellipse id="椭圆形备份" fill="#31A6AE" cx="233.056623" cy="5.28409091" rx="4.00078371" ry="4.22727273"></ellipse>
|
||||
<g id="编组-2" transform="translate(247.059366, 0.000000)" fill="#31A6AE">
|
||||
<polygon id="路径-11" points="51.8543795 6.33584094e-14 48.0094045 0 56.5647535 10.5681818 60.0117556 10.5681818"></polygon>
|
||||
<polygon id="路径-11备份" opacity="0.8" points="39.8520284 6.33584094e-14 36.0070534 0 44.5624024 10.5681818 48.0094045 10.5681818"></polygon>
|
||||
<polygon id="路径-11备份-3" opacity="0.4" points="15.8473261 6.33584094e-14 12.0023511 0 20.5577001 10.5681818 24.0047022 10.5681818"></polygon>
|
||||
<polygon id="路径-11备份-2" opacity="0.601434" points="27.8496773 6.33584094e-14 24.0047022 0 32.5600513 10.5681818 36.0070534 10.5681818"></polygon>
|
||||
<polygon id="路径-11备份-4" opacity="0.201434" points="3.84497501 6.33584094e-14 4.67611706e-16 0 8.55534901 10.5681818 12.0023511 10.5681818"></polygon>
|
||||
</g>
|
||||
<line x1="229.055839" y1="4.75568182" x2="0.354627912" y2="5.28409091" id="路径-12" stroke="url(#linearGradient-6)" stroke-width="2.12"></line>
|
||||
</g>
|
||||
<g id="编组-3" transform="translate(117.896179, 0.000000)">
|
||||
<g id="编组-2备份" fill="#31A6AE">
|
||||
<polygon id="路径-11" points="77.7815693 9.50376141e-14 72.0141067 0 84.8471303 15.8522727 90.0176334 15.8522727"></polygon>
|
||||
<polygon id="路径-11备份" opacity="0.8" points="59.7780426 9.50376141e-14 54.0105801 0 66.8436036 15.8522727 72.0141067 15.8522727"></polygon>
|
||||
<polygon id="路径-11备份-3" opacity="0.4" points="23.7709892 9.50376141e-14 18.0035267 0 30.8365502 15.8522727 36.0070534 15.8522727"></polygon>
|
||||
<polygon id="路径-11备份-2" opacity="0.601434" points="41.7745159 9.50376141e-14 36.0070534 0 48.8400769 15.8522727 54.0105801 15.8522727"></polygon>
|
||||
<polygon id="路径-11备份-4" opacity="0.201434" points="5.76746252 9.50376141e-14 7.01417559e-16 0 12.8330235 15.8522727 18.0035267 15.8522727"></polygon>
|
||||
</g>
|
||||
<line x1="103.02018" y1="7.92613636" x2="203.018671" y2="8.45454545" id="路径-13" stroke="url(#linearGradient-7)" stroke-width="2.12"></line>
|
||||
</g>
|
||||
</g>
|
||||
<rect id="矩形" stroke="#979797" stroke-width="1.06" opacity="0" x="0.53" y="0.53" width="1918.94" height="91.94"></rect>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 971 KiB |
|
Before Width: | Height: | Size: 5.6 MiB |
|
Before Width: | Height: | Size: 4.1 MiB |
|
Before Width: | Height: | Size: 644 KiB |
|
Before Width: | Height: | Size: 90 B |
|
Before Width: | Height: | Size: 401 KiB |
|
Before Width: | Height: | Size: 79 KiB |
|
Before Width: | Height: | Size: 942 KiB |
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"url": "india.mes.picaiba.com/api/"
|
||||
"url": "192.168.8.22"
|
||||
}
|
||||
136
src/App.tsx
@@ -1,89 +1,97 @@
|
||||
import React, {useEffect, useState, useContext} from 'react';
|
||||
import intl from 'react-intl-universal';
|
||||
import locales from "./locales/locales";
|
||||
import './App.css';
|
||||
import {useAppSelector} from "./store/hooks";
|
||||
import {selectChangeLangAndCss} from "./store/ChangeLangAndCss";
|
||||
import {createBrowserRouter, RouterProvider,} from "react-router-dom";
|
||||
import { useEffect } from "react";
|
||||
import "./App.css";
|
||||
import { createHashRouter, RouterProvider } from "react-router-dom";
|
||||
|
||||
import ErrorPage from "./page/ErrorPage";
|
||||
import MainP from "./page/MainP/MainP";
|
||||
import MainE from "./page/MainE/MainE";
|
||||
import MainQ from "./page/MainQ/MainQ";
|
||||
import SwitchAll from "./page/AutoSwitch/SwitchAll";
|
||||
import SwitchLine from "./page/AutoSwitch/SwitchLine";
|
||||
import {MyObservable} from "./context/MyObservable";
|
||||
import {Observable} from "@babylonjs/core";
|
||||
import {selectGlassStatus} from "./store/ProductionMonitoringEntity";
|
||||
|
||||
// const LOCALES_LIST = [
|
||||
// {
|
||||
// label: "English",
|
||||
// value: "en-US",
|
||||
// },
|
||||
// {
|
||||
// label: "简体中文",
|
||||
// value: "zh-CN",
|
||||
// },
|
||||
// ];
|
||||
import { MyObservable } from "./context/MyObservable";
|
||||
import { Observable } from "@babylonjs/core";
|
||||
import LDPage from "./page/LDPage";
|
||||
import LinePageOneOne from "./page/LinePage1-1";
|
||||
import LinePageOneTwo from "./page/LinePage1-2";
|
||||
import LinePageTwoOne from "./page/LinePage2-1";
|
||||
import LinePageTwoTwo from "./page/LinePage2-2";
|
||||
import LinePageThreeOne from "./page/LinePage3-1";
|
||||
import LinePageThreeTwo from "./page/LinePage3-2";
|
||||
import LinePageFourOne from "./page/LinePage4-1";
|
||||
import LinePageFourTwo from "./page/LinePage4-2";
|
||||
import LinePageFiveOne from "./page/LinePage5-1";
|
||||
import LinePageFiveTwo from "./page/LinePage5-2";
|
||||
|
||||
const onGlassObservable = new Observable();
|
||||
|
||||
function App() {
|
||||
const thisLineGlassStatus = useAppSelector(selectGlassStatus)
|
||||
onGlassObservable.notifyObservers(thisLineGlassStatus)
|
||||
|
||||
const Locale = useAppSelector(selectChangeLangAndCss).Locale;
|
||||
|
||||
const setCurrentLocale = (currentLocale: string) => {
|
||||
intl.init({
|
||||
currentLocale,
|
||||
locales: locales,
|
||||
}).then(() => {
|
||||
console.log('Language Changed to ' + currentLocale);
|
||||
});
|
||||
};
|
||||
|
||||
setCurrentLocale(Locale);
|
||||
|
||||
const router = createBrowserRouter([
|
||||
const router = createHashRouter([
|
||||
{
|
||||
path: "/",
|
||||
element: <MainP/>,
|
||||
errorElement: <ErrorPage/>
|
||||
path: "/LD",
|
||||
element: <LDPage />,
|
||||
errorElement: <ErrorPage />,
|
||||
},
|
||||
{
|
||||
path: "/P",
|
||||
element: <MainP/>,
|
||||
errorElement: <ErrorPage/>
|
||||
path: "/LP/1-1",
|
||||
element: <LinePageOneOne />,
|
||||
errorElement: <ErrorPage />,
|
||||
},
|
||||
{
|
||||
path: "/Q",
|
||||
element: <MainQ/>,
|
||||
errorElement: <ErrorPage/>
|
||||
path: "/LP/1-2",
|
||||
element: <LinePageOneTwo />,
|
||||
errorElement: <ErrorPage />,
|
||||
},
|
||||
{
|
||||
path: "/E/:LineID?",
|
||||
element: <MainE/>,
|
||||
errorElement: <ErrorPage/>
|
||||
},
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
{
|
||||
path: "/SA",
|
||||
element: <SwitchAll/>,
|
||||
errorElement: <ErrorPage/>
|
||||
path: "/LP/2-1",
|
||||
element: <LinePageTwoOne />,
|
||||
errorElement: <ErrorPage />,
|
||||
},
|
||||
{
|
||||
path: "/SL/:LineID?",
|
||||
element: <SwitchLine/>,
|
||||
errorElement: <ErrorPage/>
|
||||
path: "/LP/2-2",
|
||||
element: <LinePageTwoTwo />,
|
||||
errorElement: <ErrorPage />,
|
||||
},
|
||||
{
|
||||
path: "/LP/3-1",
|
||||
element: <LinePageThreeOne />,
|
||||
errorElement: <ErrorPage />,
|
||||
},
|
||||
{
|
||||
path: "/LP/3-2",
|
||||
element: <LinePageThreeTwo />,
|
||||
errorElement: <ErrorPage />,
|
||||
},
|
||||
{
|
||||
path: "/LP/4-1",
|
||||
element: <LinePageFourOne />,
|
||||
errorElement: <ErrorPage />,
|
||||
},
|
||||
{
|
||||
path: "/LP/4-2",
|
||||
element: <LinePageFourTwo />,
|
||||
errorElement: <ErrorPage />,
|
||||
},
|
||||
{
|
||||
path: "/LP/5-1",
|
||||
element: <LinePageFiveOne />,
|
||||
errorElement: <ErrorPage />,
|
||||
},
|
||||
{
|
||||
path: "/LP/5-2",
|
||||
element: <LinePageFiveTwo />,
|
||||
errorElement: <ErrorPage />,
|
||||
},
|
||||
]);
|
||||
useEffect(() => {
|
||||
const timerId = setInterval(() => {
|
||||
window.location.reload();
|
||||
}, 43200000);
|
||||
|
||||
return () => {
|
||||
clearInterval(timerId);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<MyObservable.Provider value={onGlassObservable}>
|
||||
<div className="background">
|
||||
<RouterProvider router={router}/>
|
||||
<RouterProvider router={router} />
|
||||
</div>
|
||||
</MyObservable.Provider>
|
||||
);
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Babylon.js Product Page Demo</title>
|
||||
|
||||
<!-- <link rel="stylesheet" href="https://use.typekit.net/pyp7dhw.css"> -->
|
||||
<link href='https://d33wubrfki0l68.cloudfront.net/css/c204e345dce3e9e660ec5e23ae93696b9c5b9d42/demos/productpage/styles.css'
|
||||
rel='stylesheet' type='text/css'/>
|
||||
|
||||
<script src="https://use.typekit.net/pyp7dhw.js"></script>
|
||||
<script>try {
|
||||
Typekit.load({async: false});
|
||||
} catch (e) {
|
||||
}</script>
|
||||
|
||||
<script src="https://preview.babylonjs.com/babylon.js"></script>
|
||||
<script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.min.js"></script>
|
||||
<script src="https://preview.babylonjs.com/nodeEditor/babylon.nodeEditor.js"></script>
|
||||
<script src="https://preview.babylonjs.com/gui/babylon.gui.js"></script>
|
||||
<script src="https://code.jquery.com/pep/0.4.3/pep.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<canvas id="renderCanvas" touch-action="none"></canvas> <!-- touch-action="none" for best results from PEP -->
|
||||
|
||||
<script src='https://d33wubrfki0l68.cloudfront.net/bundles/67cad91c66fe8e5633757e23e16f4220bf108fb5.js'></script>
|
||||
<div id="header">
|
||||
<div class="headerContent">
|
||||
<a href="https://www.babylonjs.com/"><img src="assets/textures/babylonLogo_48px.svg"/></a><span id="headerType">eCommerce Product Demo</span>
|
||||
</div>
|
||||
</div>
|
||||
<div id="htmlLayer">
|
||||
<div id="loader">
|
||||
<div class="lds-ripple">
|
||||
<div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div id="loadingText">
|
||||
<h1>Loading...</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div id="block_1">
|
||||
<h1 id="head_1" class="track">Interactive Product Pages</h1>
|
||||
<p>Babylon.js gives you all the power you need to create realistic interactive experiences for your product's
|
||||
audience. Leverage the power of 3D rendering empowered by animation,
|
||||
behaviors, audio, video, and a full GUI layer.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div id="bg1">
|
||||
<div id="block_2">
|
||||
<h1 id="head_2" class="track">PBR Node Materials</h1>
|
||||
<p>Create custom shaders for your assets using the node materials with full support for physically based
|
||||
rendering materials. This includes support for
|
||||
image-based lighting, real-time environment probes, subsurface translucency, refraction, and more!
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div id="block_3">
|
||||
<h1 id="head_3" class="track">Advanced PBR Features</h1>
|
||||
<p>Node material's physically-based rendering supports advanced features like clearcoat and sheen. Enjoy the
|
||||
flexibility of creating custom shaders to unlock complete creative freedom while retaining the ability
|
||||
to
|
||||
render a wide range of materials accurately.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bg2">
|
||||
<div id="block_4">
|
||||
<h1 id="head_4" class="track">Procedural Textures</h1>
|
||||
<p>Node materials can now create procedural textures to be used as you wish. A custom procedural texture
|
||||
created in the node material editor is being used to morph between materials on this asset. Notice
|
||||
how the morph is always different due to our custom shader allowing us to change the procedural texture
|
||||
every time we use it.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bg3">
|
||||
<div id="block_5">
|
||||
<h1 id="head_5" class="track">Animating Material Parameters</h1>
|
||||
<p>Node materials allow us to manipulate parameters directly or through animation. This enables interations
|
||||
such as the animated ring light in the demo asset. We are also able to tie this animation into our post
|
||||
processing like the glow layer you see here. And we still retain the ability to add all of this
|
||||
functionality to PBR materials for the best possible rendering.
|
||||
</p>
|
||||
</div>
|
||||
<div id="block_6">
|
||||
<h1 id="head_6" class="track">GUI Controls in Materials</h1>
|
||||
<p>Babylon.js also allows you to put GUI controls directly into our materials used on a mesh. You can see
|
||||
how we can make a fully function product demo by displaying the actual time and date on the device
|
||||
screen.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
1183
src/Test/Test3.js
@@ -1,14 +0,0 @@
|
||||
import React from 'react'
|
||||
import intl from 'react-intl-universal';
|
||||
|
||||
const BasicComponent: React.FC<any> = () => {
|
||||
return (
|
||||
<div>
|
||||
<div className="title">Basic Examples:</div>
|
||||
<div>{intl.get('SIMPLE')}</div>
|
||||
<div>{intl.get('HELLO', { name: 'Tony', where: 'Alibaba' })}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default BasicComponent;
|
||||
@@ -1,14 +0,0 @@
|
||||
import React from 'react'
|
||||
import intl from 'react-intl-universal';
|
||||
|
||||
const CurrencyComponent: React.FC<any> = () => {
|
||||
let price = 123456.78;
|
||||
return (
|
||||
<div>
|
||||
<div className="title">Currency Example:</div>
|
||||
<div>{intl.get('SALE_PRICE', { price })}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default CurrencyComponent;
|
||||
@@ -1,18 +0,0 @@
|
||||
import React from 'react'
|
||||
import intl from 'react-intl-universal';
|
||||
|
||||
const DateComponent: React.FC<any> = () => {
|
||||
const start = new Date();
|
||||
const end = new Date();
|
||||
const expires = new Date();
|
||||
return (
|
||||
<div>
|
||||
<div className="title">Date Examples:</div>
|
||||
<div>{intl.get('SALE_START', { start })}</div>
|
||||
<div>{intl.get('SALE_END', { end })}</div>
|
||||
<div>{intl.get('COUPON', { expires })}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default DateComponent;
|
||||
@@ -1,15 +0,0 @@
|
||||
import React from 'react'
|
||||
import intl from 'react-intl-universal';
|
||||
|
||||
const HtmlComponent: React.FC<any> = () => {
|
||||
return (
|
||||
<div>
|
||||
<div className="title">Html Examples:</div>
|
||||
<div>{intl.getHTML('TIP')}</div>
|
||||
<div>{intl.getHTML('TIP_VAR', { message: 'HTML with variables' })}</div>
|
||||
<div>{intl.getHTML('TIP_VAR', { message: '<script>alert("ReactIntlUniversal prevents from xss attack")</script>' })}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default HtmlComponent;
|
||||
@@ -1,13 +0,0 @@
|
||||
import React from 'react';
|
||||
import util from '../core/util';
|
||||
|
||||
const MessageNotInComponent: React.FC<any> = () => {
|
||||
return (
|
||||
<div>
|
||||
<div className="title">Message Not in Component Example:</div>
|
||||
<div>{util.getMessage()}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default MessageNotInComponent;
|
||||
@@ -1,15 +0,0 @@
|
||||
import React from 'react'
|
||||
import intl from 'react-intl-universal';
|
||||
|
||||
const PluralComponent: React.FC<any> = () => {
|
||||
return (
|
||||
<div>
|
||||
<div className="title">Plural Examples:</div>
|
||||
<div>{intl.get("PHOTO", { photoNum: 0 })}</div>
|
||||
<div>{intl.get("PHOTO", { photoNum: 1 })}</div>
|
||||
<div>{intl.get("PHOTO", { photoNum: 1000000 })}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default PluralComponent;
|
||||
@@ -1,7 +0,0 @@
|
||||
import intl from 'react-intl-universal';
|
||||
|
||||
const util = {
|
||||
getMessage: () => intl.get('MESSAGE_NOT_IN_COMPONENT'),
|
||||
};
|
||||
|
||||
export default util;
|
||||
@@ -1,41 +0,0 @@
|
||||
import React, {useEffect, useState} from "react";
|
||||
import intl from 'react-intl-universal';
|
||||
import locales from "../locales/locales";
|
||||
import useForceUpdate from 'use-force-update';
|
||||
import BasicComponent from "./components/basic";
|
||||
|
||||
function Test() {
|
||||
const forceUpdate = useForceUpdate();
|
||||
useEffect(() => {
|
||||
setthetext();
|
||||
})
|
||||
const setthetext = ()=>{
|
||||
let currenttext = "zh-CN";
|
||||
setCurrentLocale(currenttext);
|
||||
};
|
||||
|
||||
const setCurrentLocale = (currentLocale: string) => {
|
||||
intl.init({
|
||||
currentLocale,
|
||||
locales: locales,
|
||||
});
|
||||
};
|
||||
|
||||
const OnChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
|
||||
setCurrentLocale(e.target.value)
|
||||
forceUpdate();
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<select onChange={OnChange}>
|
||||
<option value={"zh-CN"}>中文</option>
|
||||
<option value={"en-US"}>英文</option>
|
||||
</select>
|
||||
<div id='name'>{intl.get('SIMPLE')}</div>
|
||||
<BasicComponent/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Test;
|
||||
@@ -1,77 +0,0 @@
|
||||
import React, {useEffect, useState} from "react";
|
||||
import intl from 'react-intl-universal';
|
||||
import useForceUpdate from 'use-force-update';
|
||||
import locales from "../locales/locales";
|
||||
|
||||
import BasicComponent from "./components/basic";
|
||||
|
||||
const LOCALES_LIST = [
|
||||
{
|
||||
label: "English",
|
||||
value: "en-US",
|
||||
},
|
||||
{
|
||||
label: "简体中文",
|
||||
value: "zh-CN",
|
||||
},
|
||||
];
|
||||
|
||||
function Test2() {
|
||||
const forceUpdate = useForceUpdate();
|
||||
const [initDone, setInitDone] = React.useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
initializeIntl();
|
||||
})
|
||||
|
||||
const initializeIntl = () => {
|
||||
// 1. Get the currentLocale from url, cookie, or browser setting
|
||||
let currentLocale = intl.determineLocale({
|
||||
urlLocaleKey: 'lang', // Example: https://fe-tool.com/react-intl-universal?lang=en-US
|
||||
cookieLocaleKey: 'lang', // Example: "lang=en-US" in cookie
|
||||
});
|
||||
|
||||
// 2. Fallback to "en-US" if the currentLocale isn't supported in LOCALES_LIST
|
||||
if (!LOCALES_LIST.some(item => item.value === currentLocale)) {
|
||||
currentLocale = "en-US"
|
||||
}
|
||||
|
||||
// 3. Set currentLocale and load locale data
|
||||
setCurrentLocale(currentLocale);
|
||||
|
||||
// 4. After loading locale data, start to render
|
||||
setInitDone(true);
|
||||
}
|
||||
|
||||
const setCurrentLocale = (currentLocale: string) => {
|
||||
intl.init({
|
||||
currentLocale,
|
||||
locales: locales,
|
||||
});
|
||||
};
|
||||
|
||||
const onLocaleChange = (e: React.ChangeEvent<HTMLSelectElement>)=>{
|
||||
setCurrentLocale(e.target.value);
|
||||
forceUpdate();
|
||||
}
|
||||
const localeSelector = (
|
||||
<select onChange={onLocaleChange} defaultValue="">
|
||||
<option value="" disabled>Change Language</option>
|
||||
{LOCALES_LIST.map(locale=>(
|
||||
<option key={locale.value} value={locale.value}>{locale.label}</option>
|
||||
))}
|
||||
</select>
|
||||
);
|
||||
return (
|
||||
<div>
|
||||
{initDone && (
|
||||
<div className="react-intl-universal-example">
|
||||
{localeSelector}
|
||||
<BasicComponent/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Test2;
|
||||
441
src/babylonjs/AllLinePageBabylon.tsx
Normal file
@@ -0,0 +1,441 @@
|
||||
import { useEffect, useRef, useState } 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 { HemisphericLight, Vector3 } from "@babylonjs/core";
|
||||
import { useAppSelector } from "../store/hooks";
|
||||
import "../page/style/standard.css";
|
||||
import AlarmTipGreen from "./../page/assets/icon/g.png";
|
||||
import AlarmTipYellow from "./../page/assets/icon/y.png";
|
||||
import AlarmTipRed from "./../page/assets/icon/r.png";
|
||||
import { selectLine1Before } from "../store/LinePageSlice";
|
||||
import { selectAllLine } from "../store/LeaderPageSlice";
|
||||
|
||||
const myStyle = {
|
||||
width: "1041px",
|
||||
height: "599px",
|
||||
outline: "none",
|
||||
};
|
||||
interface MybabylonJSProps {
|
||||
modelPath: string; // 明确 modelPath 属性的类型为 string
|
||||
}
|
||||
interface EqListType {
|
||||
[key: string]: EqMsg
|
||||
}
|
||||
interface EqMsg {
|
||||
equipmentName?:string;
|
||||
run?:boolean;
|
||||
error?:boolean;
|
||||
inputNum?:number;
|
||||
outputNum?:number;
|
||||
quantityTime?:number;
|
||||
status?:string;
|
||||
statusTime?:number;
|
||||
localDateTime?:number;
|
||||
equipmentCode?:string;
|
||||
equipmentId?:number;
|
||||
num?:number;
|
||||
}
|
||||
function MybabylonJS({ modelPath }: MybabylonJSProps) {
|
||||
const [eqList, setEqList] = useState<EqListType>({});
|
||||
const allEquStatus = useAppSelector(selectLine1Before) as any;
|
||||
const allData = useAppSelector(selectAllLine) as any; // 使用`any`来绕过类型检查
|
||||
const canvasRef = useRef(null);
|
||||
const resetRef = useRef<(() => void) | null>(null);
|
||||
const [numAlarm, setNumAlarm] = useState('0');
|
||||
const [monthNum, setMonthNum] = useState('0');
|
||||
const [todayNum, setTodayNum] = useState('0');
|
||||
const [yieldNum, setYieldNum] = useState('0');
|
||||
const [selectedMeshName, setSelectedMeshName] = useState<string | null>(null);
|
||||
const [selectedMeshId, setSelectedMeshId] = useState<string | null>(null);
|
||||
const [selectedMeshObj, setSelectedMeshObj] = useState<EqMsg>({
|
||||
equipmentName: "",
|
||||
run: true,
|
||||
error: false,
|
||||
num: 0,
|
||||
});
|
||||
// 使用 useRef 来存储当前加载的模型引用
|
||||
const currentMeshesRef = useRef<Array<BABYLON.AbstractMesh>>([]);
|
||||
useEffect(() => {
|
||||
const equStatus = allEquStatus?.equStatus;
|
||||
if (equStatus) {
|
||||
setEqList(equStatus);
|
||||
}
|
||||
},[allEquStatus])
|
||||
// 中间顶部数据
|
||||
useEffect(() => {
|
||||
const numAlarm = allData?.numAlarm;
|
||||
setNumAlarm(numAlarm || '0');
|
||||
const monthMap = allData?.monthMap;
|
||||
setMonthNum(monthMap?.output || '0');
|
||||
const todayMap = allData?.todayMap;
|
||||
setTodayNum(todayMap?.output || '0');
|
||||
setYieldNum(todayMap?.Yield || '0');
|
||||
},[allData])
|
||||
useEffect(() => {
|
||||
if (selectedMeshId && eqList[selectedMeshId]) {
|
||||
setSelectedMeshObj({
|
||||
equipmentName:eqList[selectedMeshId].equipmentName,
|
||||
run:eqList[selectedMeshId].run ? eqList[selectedMeshId].run : true,
|
||||
error:eqList[selectedMeshId].error ? eqList[selectedMeshId].error : false,
|
||||
num:eqList[selectedMeshId].inputNum ? eqList[selectedMeshId].inputNum : (eqList[selectedMeshId].outputNum ? eqList[selectedMeshId].outputNum : 0),
|
||||
});
|
||||
}
|
||||
},[selectedMeshId])
|
||||
useEffect(() => {
|
||||
// 确保 canvas 引用存在
|
||||
if (!canvasRef.current) return;
|
||||
const canvas = canvasRef.current;
|
||||
const engine = new BABYLON.Engine(canvas, true, {
|
||||
preserveDrawingBuffer: true,
|
||||
stencil: true,
|
||||
});
|
||||
|
||||
const createScene = async function () {
|
||||
// This creates a basic Babylon Scene object (non-mesh)
|
||||
const scene = new BABYLON.Scene(engine);
|
||||
scene.clearColor = new BABYLON.Color4(0, 0, 0, 0);
|
||||
const baseLight = new HemisphericLight(
|
||||
"hemiLight",
|
||||
new Vector3(-1, 1, 0),
|
||||
scene
|
||||
);
|
||||
baseLight.intensity = 1;
|
||||
baseLight.diffuse = new BABYLON.Color3(1, 1, 1);
|
||||
baseLight.specular = new BABYLON.Color3(0.25, 0.25, 0.25);
|
||||
baseLight.groundColor = new BABYLON.Color3(0.5, 0.5, 0.5);
|
||||
|
||||
//add an arcRotateCamera to the scene
|
||||
const camera = new BABYLON.ArcRotateCamera(
|
||||
"camera",
|
||||
BABYLON.Tools.ToRadians(270),
|
||||
BABYLON.Tools.ToRadians(25),
|
||||
220,
|
||||
new BABYLON.Vector3(0, 0, 10)
|
||||
);
|
||||
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);
|
||||
|
||||
// 定义一个函数来加载或重新加载模型
|
||||
const loadOrReloadModel = async () => {
|
||||
// 在加载新模型之前卸载已加载的模型
|
||||
currentMeshesRef.current.forEach((mesh) => {
|
||||
if (mesh && mesh.parent) {
|
||||
scene.removeMesh(mesh, true);
|
||||
}
|
||||
});
|
||||
currentMeshesRef.current = []; // 重置模型数组
|
||||
try {
|
||||
// 使用 ImportMeshAsync 加载新模型
|
||||
var LOD0MESH1 = await BABYLON.SceneLoader.ImportMeshAsync(
|
||||
"",
|
||||
"/Line/",
|
||||
"part1.babylon",
|
||||
scene
|
||||
);
|
||||
// 将新加载的模型添加到 currentMeshesRef 中
|
||||
currentMeshesRef.current.push(...LOD0MESH1.meshes);
|
||||
var LOD0MESH2 = await BABYLON.SceneLoader.ImportMeshAsync(
|
||||
"",
|
||||
"/Line/",
|
||||
"part2.babylon",
|
||||
scene
|
||||
);
|
||||
currentMeshesRef.current.push(...LOD0MESH2.meshes);
|
||||
// ...为新加载的模型设置交互逻辑
|
||||
|
||||
LOD0MESH1.meshes.forEach((mesh) => {
|
||||
mesh.isPickable = true;
|
||||
mesh.actionManager = new BABYLON.ActionManager(scene);
|
||||
if (modelPath.slice(-1) === "1") {
|
||||
if (
|
||||
mesh.name.includes("磨边") ||
|
||||
mesh.name.includes("清洗") ||
|
||||
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._scene.onPointerDown = async (event, _pickResult) => {
|
||||
console.log('_pickResult',_pickResult)
|
||||
const pickInfo = mesh._scene.pick(
|
||||
mesh._scene.pointerX,
|
||||
mesh._scene.pointerY
|
||||
);
|
||||
//判断是否是右键
|
||||
if (!(event.buttons === 1 && pickInfo.pickedMesh)) return;
|
||||
const MeshName = pickInfo.pickedMesh.name;
|
||||
const MeshNameId = pickInfo.pickedMesh.metadata.tags;
|
||||
|
||||
setSelectedMeshName(MeshName);
|
||||
setSelectedMeshId(MeshNameId);
|
||||
};
|
||||
});
|
||||
LOD0MESH2.meshes.forEach((mesh) => {
|
||||
mesh.isPickable = true;
|
||||
mesh.actionManager = new BABYLON.ActionManager(scene);
|
||||
if (modelPath.slice(-1) === "1") {
|
||||
if (
|
||||
mesh.name.includes("磨边") ||
|
||||
mesh.name.includes("清洗") ||
|
||||
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._scene.onPointerDown = async (event, _pickResult) => {
|
||||
console.log('_pickResult',_pickResult)
|
||||
const pickInfo = mesh._scene.pick(
|
||||
mesh._scene.pointerX,
|
||||
mesh._scene.pointerY
|
||||
);
|
||||
//判断是否是右键
|
||||
if (!(event.buttons === 1 && pickInfo.pickedMesh)) return;
|
||||
const MeshName = pickInfo.pickedMesh.name;
|
||||
const MeshNameId = pickInfo.pickedMesh.metadata.tags;
|
||||
|
||||
setSelectedMeshName(MeshName);
|
||||
setSelectedMeshId(MeshNameId);
|
||||
};
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("加载模型失败:", error);
|
||||
}
|
||||
};
|
||||
|
||||
// 调用函数以加载或重新加载模型
|
||||
loadOrReloadModel();
|
||||
|
||||
function reset() {
|
||||
camera.target = new BABYLON.Vector3(0, 0, 10);
|
||||
camera.alpha = BABYLON.Tools.ToRadians(270);
|
||||
camera.beta = BABYLON.Tools.ToRadians(25);
|
||||
camera.radius = 220;
|
||||
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);
|
||||
}
|
||||
});
|
||||
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 = () => {
|
||||
//模型初始位置
|
||||
if (resetRef.current) {
|
||||
resetRef.current();
|
||||
}
|
||||
};
|
||||
function formatNumber(str: string, separator = ',') {
|
||||
// 使用正则表达式从右到左每隔3位添加分隔符
|
||||
str = str.toString();
|
||||
return str.replace(/\B(?=(\d{3})+(?!\d))/g, separator);
|
||||
}
|
||||
function toPercentage(decimalStr: string) {
|
||||
let decimal = parseFloat(decimalStr);
|
||||
if (isNaN(decimal)) {
|
||||
throw new Error('Invalid decimal number provided.');
|
||||
}
|
||||
let percent = decimal * 100;
|
||||
let formattedPercent = percent.toFixed(2);
|
||||
return formattedPercent + '%';
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={myStyle}>
|
||||
<div className="model_top_container">
|
||||
<div className="model_top_style1">
|
||||
<div className="model_top_num">{toPercentage(yieldNum)}</div>
|
||||
<div className="model_top_text">成品率</div>
|
||||
</div>
|
||||
<div className="model_top_style2">
|
||||
<div className="model_top_num">{formatNumber(todayNum)}</div>
|
||||
<div className="model_top_text">今日产量</div>
|
||||
</div>
|
||||
<div className="model_top_style2">
|
||||
<div className="model_top_num">{formatNumber(monthNum)}</div>
|
||||
<div className="model_top_text">本月产量</div>
|
||||
</div>
|
||||
<div className="model_top_style1">
|
||||
<div className="model_top_num">{formatNumber(numAlarm)}</div>
|
||||
<div className="model_top_text">设备报警数</div>
|
||||
</div>
|
||||
</div>
|
||||
{selectedMeshName && (
|
||||
<div className="eq_detail_info">
|
||||
<div>
|
||||
<span className="left_name">设备名称:</span>
|
||||
<span className="right_value">{selectedMeshObj.equipmentName}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span className="left_name">进/出口数量:</span>
|
||||
<span className="right_value">{selectedMeshObj.num}</span>
|
||||
</div>
|
||||
{/* <div>
|
||||
<span className="left_name">出口数量:</span>
|
||||
<span className="right_value">1,312</span>
|
||||
</div> */}
|
||||
<div>
|
||||
<span className="left_name">报警状态:</span>
|
||||
<span className="right_value">
|
||||
{selectedMeshObj.error ? (
|
||||
<>
|
||||
<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.run ? (
|
||||
<>
|
||||
<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>
|
||||
)}
|
||||
<canvas ref={canvasRef} style={myStyle} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default MybabylonJS;
|
||||
445
src/babylonjs/EqInfoData.ts
Normal file
@@ -0,0 +1,445 @@
|
||||
interface EqInfoInterface {
|
||||
name: string;
|
||||
data: Array<{ name: string; value: number, code:string, label:string}>;
|
||||
position: Array<number>;
|
||||
}
|
||||
interface EqInfoDataInterface {
|
||||
[key: string]: Array<EqInfoInterface>;
|
||||
}
|
||||
const EqInfoData:EqInfoDataInterface = {
|
||||
"Line1-1": [
|
||||
{
|
||||
name: "磨边进口",
|
||||
data: [
|
||||
{ name: "1支线", value: 0, code:'1-edge1', label:'inputNum' },
|
||||
{ name: "2支线", value: 0, code:'1-edge2', label:'inputNum' },
|
||||
{ name: "3支线", value: 0, code:'1-edge3', label:'inputNum' },
|
||||
],
|
||||
position: [180, 210],
|
||||
},
|
||||
{
|
||||
name: "磨边清洗出口",
|
||||
data: [
|
||||
{ name: "1支线", value: 0, code:'1-edgeclean1', label:'outputNum' },
|
||||
{ name: "2支线", value: 0, code:'1-edgeclean2', label:'outputNum' },
|
||||
{ name: "3支线", value: 0, code:'1-edgeclean3', label:'outputNum' },
|
||||
],
|
||||
position: [340, 130],
|
||||
},
|
||||
{
|
||||
name: "打孔出口",
|
||||
data: [
|
||||
{ name: "1支线", value: 0, code:'1-punch1', label:'outputNum' },
|
||||
{ name: "2支线", value: 0, code:'1-punch2', label:'outputNum' },
|
||||
{ name: "3支线", value: 0, code:'1-punch3', label:'outputNum' },
|
||||
],
|
||||
position: [590, 300],
|
||||
},
|
||||
{
|
||||
name: "丝印进口",
|
||||
data: [
|
||||
{ name: "1支线", value: 0, code:'1-silk1', label:'inputNum' },
|
||||
{ name: "2支线", value: 0, code:'1-silk2', label:'inputNum' },
|
||||
{ name: "3支线", value: 0, code:'1-silk3', label:'inputNum' },
|
||||
],
|
||||
position: [510, 65],
|
||||
},
|
||||
{
|
||||
name: "二次固化出口",
|
||||
data: [
|
||||
{ name: "1支线", value: 0, code:'1-secsolid1', label:'outputNum' },
|
||||
{ name: "2支线", value: 0, code:'1-secsolid2', label:'outputNum' },
|
||||
{ name: "3支线", value: 0, code:'1-secsolid3', label:'outputNum' },
|
||||
],
|
||||
position: [850, 190],
|
||||
},
|
||||
{
|
||||
name: "钢化进口",
|
||||
data: [{ name: "钢化进口", value: 0, code:'1-temper1', label:'inputNum' }],
|
||||
position: [750, 10],
|
||||
},
|
||||
],
|
||||
"Line1-2": [
|
||||
{
|
||||
name: "钢化出口",
|
||||
data: [{ name: "钢化出口", value: 0, code:'1-temper1', label:'outputNum' }],
|
||||
position: [140, 250],
|
||||
},
|
||||
{
|
||||
name: "包装清洗机入口",
|
||||
data: [
|
||||
{ name: "包装清洗机1_1", value: 0, code:'1-packclean1', label:'inputNum' },
|
||||
{ name: "包装清洗机1_2", value: 0, code:'1-packclean2', label:'inputNum' },
|
||||
],
|
||||
position: [450, 320],
|
||||
},
|
||||
{
|
||||
name: "包装清洗机出口",
|
||||
data: [
|
||||
{ name: "包装清洗机1_1", value: 0, code:'1-packclean1', label:'outputNum' },
|
||||
{ name: "包装清洗机1_2", value: 0, code:'1-packclean2', label:'outputNum' },
|
||||
],
|
||||
position: [350, 130],
|
||||
},
|
||||
{
|
||||
name: "铺纸机",
|
||||
data: [
|
||||
{ name: "铺纸机1_1", value: 0, code:'1-paper1', label:'outputNum' },
|
||||
{ name: "铺纸机1_2", value: 0, code:'1-paper2', label:'outputNum' },
|
||||
],
|
||||
position: [640, 240],
|
||||
},
|
||||
{
|
||||
name: "下片机械手",
|
||||
data: [
|
||||
{ name: "下片机械手1_1", value: 0, code:'1-down1', label:'outputNum'},
|
||||
{ name: "下片机械手1_2", value: 0, code:'1-down2', label:'outputNum'},
|
||||
{ name: "下片机械手1_3", value: 0, code:'1-down3', label:'outputNum'},
|
||||
],
|
||||
position: [570, 10],
|
||||
},
|
||||
],
|
||||
"Line2-1": [
|
||||
{
|
||||
name: "磨边进口",
|
||||
data: [
|
||||
{ name: "1支线", value: 0, code:'2-edge1', label:'inputNum' },
|
||||
{ name: "2支线", value: 0, code:'2-edge2', label:'inputNum' },
|
||||
],
|
||||
position: [150, 245],
|
||||
},
|
||||
{
|
||||
name: "磨边清洗出口",
|
||||
data: [
|
||||
{ name: "1支线", value: 0, code:'2-edgeclean1', label:'outputNum' },
|
||||
{ name: "2支线", value: 0, code:'2-edgeclean2', label:'outputNum' },
|
||||
],
|
||||
position: [310, 180],
|
||||
},
|
||||
{
|
||||
name: "打孔出口",
|
||||
data: [
|
||||
{ name: "1支线", value: 0, code:'2-punch1', label:'outputNum' },
|
||||
{ name: "2支线", value: 0, code:'2-punch2', label:'outputNum' },
|
||||
],
|
||||
position: [540, 300],
|
||||
},
|
||||
{
|
||||
name: "丝印进口",
|
||||
data: [
|
||||
{ name: "1支线", value: 0, code:'2-silk1', label:'inputNum' },
|
||||
{ name: "2支线", value: 0, code:'2-silk2', label:'inputNum' },
|
||||
],
|
||||
position: [530, 100],
|
||||
},
|
||||
{
|
||||
name: "二次固化出口",
|
||||
data: [
|
||||
{ name: "1支线", value: 0, code:'2-secsolid1', label:'outputNum' },
|
||||
{ name: "2支线", value: 0, code:'2-secsolid2', label:'outputNum' },
|
||||
],
|
||||
position: [850, 170],
|
||||
},
|
||||
{
|
||||
name: "钢化进口",
|
||||
data: [{ name: "钢化进口", value: 0, code:'2-temper1', label:'inputNum' }],
|
||||
position: [810, 10],
|
||||
},
|
||||
],
|
||||
"Line2-2": [
|
||||
{
|
||||
name: "钢化出口",
|
||||
data: [{ name: "钢化出口", value: 0, code:'2-temper1', label:'outputNum' }],
|
||||
position: [305, 260],
|
||||
},
|
||||
{
|
||||
name: "包装清洗机入口",
|
||||
data: [
|
||||
{ name: "包装清洗机", value: 0, code:'2-packclean1', label:'inputNum' },
|
||||
],
|
||||
position: [640, 270],
|
||||
},
|
||||
{
|
||||
name: "包装清洗机出口",
|
||||
data: [
|
||||
{ name: "包装清洗机", value: 0, code:'2-packclean1', label:'outputNum' },
|
||||
],
|
||||
position: [550, 140],
|
||||
},
|
||||
{
|
||||
name: "铺纸机",
|
||||
data: [
|
||||
{ name: "铺纸机", value: 0, code:'2-paper1', label:'outputNum' },
|
||||
],
|
||||
position: [810, 210],
|
||||
},
|
||||
{
|
||||
name: "下片机械手",
|
||||
data: [
|
||||
{ name: "下片机械手2_1", value: 0, code:'2-down1', label:'outputNum'},
|
||||
{ name: "下片机械手2_2", value: 0, code:'2-down2', label:'outputNum'},
|
||||
],
|
||||
position: [630, 10],
|
||||
},
|
||||
],
|
||||
"Line3-1": [
|
||||
{
|
||||
name: "磨边进口",
|
||||
data: [
|
||||
{ name: "1支线", value: 0, code:'3-edge1', label:'inputNum' },
|
||||
{ name: "2支线", value: 0, code:'3-edge2', label:'inputNum' },
|
||||
],
|
||||
position: [150, 225],
|
||||
},
|
||||
{
|
||||
name: "磨边清洗出口",
|
||||
data: [
|
||||
{ name: "1支线", value: 0, code:'3-edgeclean1', label:'outputNum' },
|
||||
{ name: "2支线", value: 0, code:'3-edgeclean2', label:'outputNum' },
|
||||
],
|
||||
position: [380, 150],
|
||||
},
|
||||
{
|
||||
name: "打孔出口",
|
||||
data: [
|
||||
{ name: "1支线", value: 0, code:'3-punch1', label:'outputNum' },
|
||||
{ name: "2支线", value: 0, code:'3-punch2', label:'outputNum' },
|
||||
],
|
||||
position: [620, 280],
|
||||
},
|
||||
{
|
||||
name: "丝印进口",
|
||||
data: [
|
||||
{ name: "1支线", value: 0, code:'3-silk1', label:'inputNum' },
|
||||
{ name: "2支线", value: 0, code:'3-silk2', label:'inputNum' },
|
||||
],
|
||||
position: [560, 90],
|
||||
},
|
||||
{
|
||||
name: "二次固化出口",
|
||||
data: [
|
||||
{ name: "1支线", value: 0, code:'3-secsolid1', label:'outputNum' },
|
||||
{ name: "2支线", value: 0, code:'3-secsolid2', label:'outputNum' },
|
||||
],
|
||||
position: [870, 170],
|
||||
},
|
||||
{
|
||||
name: "钢化进口",
|
||||
data: [{ name: "钢化进口", value: 0, code:'3-temper1', label:'inputNum' }],
|
||||
position: [820, 28],
|
||||
},
|
||||
],
|
||||
"Line3-2": [
|
||||
{
|
||||
name: "钢化出口",
|
||||
data: [{ name: "钢化出口", value: 0, code:'3-temper1', label:'outputNum' }],
|
||||
position: [300, 190],
|
||||
},
|
||||
{
|
||||
name: "包装清洗机入口",
|
||||
data: [
|
||||
{ name: "包装清洗机", value: 0, code:'3-packclean1', label:'inputNum' },
|
||||
],
|
||||
position: [580, 250],
|
||||
},
|
||||
{
|
||||
name: "包装清洗机出口",
|
||||
data: [
|
||||
{ name: "包装清洗机", value: 0, code:'3-packclean1', label:'outputNum' },
|
||||
],
|
||||
position: [520, 100],
|
||||
},
|
||||
{
|
||||
name: "铺纸机",
|
||||
data: [
|
||||
{ name: "铺纸机", value: 0, code:'3-paper1', label:'outputNum' },
|
||||
],
|
||||
position: [760, 190],
|
||||
},
|
||||
{
|
||||
name: "下片机械手",
|
||||
data: [
|
||||
{ name: "下片机械手3_1", value: 0, code:'3-down1', label:'outputNum'},
|
||||
{ name: "下片机械手3_2", value: 0, code:'3-down2', label:'outputNum'},
|
||||
],
|
||||
position: [670, 10],
|
||||
},
|
||||
],
|
||||
"Line4-1": [
|
||||
{
|
||||
name: "磨边进口",
|
||||
data: [
|
||||
{ name: "1支线", value: 0, code:'4-edge1', label:'inputNum' },
|
||||
{ name: "2支线", value: 0, code:'4-edge2', label:'inputNum' },
|
||||
],
|
||||
position: [200, 150],
|
||||
},
|
||||
{
|
||||
name: "磨边清洗出口",
|
||||
data: [
|
||||
{ name: "1支线", value: 0, code:'4-edgeclean1', label:'outputNum' },
|
||||
{ name: "2支线", value: 0, code:'4-edgeclean2', label:'outputNum' },
|
||||
],
|
||||
position: [420, 150],
|
||||
},
|
||||
{
|
||||
name: "一次镀膜进口",
|
||||
data: [
|
||||
{ name: "1支线", value: 0, code:'4-fircoat1', label:'inputNum' },
|
||||
{ name: "2支线", value: 0, code:'4-fircoat2', label:'inputNum' },
|
||||
],
|
||||
position: [650, 290],
|
||||
},
|
||||
{
|
||||
name: "二次镀膜进口",
|
||||
data: [
|
||||
{ name: "1支线", value: 0, code:'4-seccoat1', label:'inputNum' },
|
||||
{ name: "2支线", value: 0, code:'4-seccoat2', label:'inputNum' },
|
||||
],
|
||||
position: [640, 60],
|
||||
},
|
||||
{
|
||||
name: "二次固化出口",
|
||||
data: [
|
||||
{ name: "1支线", value: 0, code:'4-secsolid1', label:'outputNum' },
|
||||
{ name: "2支线", value: 0, code:'4-secsolid2', label:'outputNum' },
|
||||
],
|
||||
position: [860, 190],
|
||||
},
|
||||
{
|
||||
name: "钢化进口",
|
||||
data: [{ name: "钢化进口", value: 0, code:'4-temper1', label:'inputNum' }],
|
||||
position: [820, 20],
|
||||
},
|
||||
],
|
||||
"Line4-2": [
|
||||
{
|
||||
name: "钢化出口",
|
||||
data: [{ name: "钢化出口", value: 0, code:'4-temper1', label:'outputNum' }],
|
||||
position: [290, 230],
|
||||
},
|
||||
{
|
||||
name: "包装清洗机入口",
|
||||
data: [
|
||||
{ name: "包装清洗机", value: 0, code:'4-packclean1', label:'inputNum' },
|
||||
],
|
||||
position: [550, 280],
|
||||
},
|
||||
{
|
||||
name: "包装清洗机出口",
|
||||
data: [
|
||||
{ name: "包装清洗机", value: 0, code:'4-packclean1', label:'outputNum' },
|
||||
],
|
||||
position: [500, 130],
|
||||
},
|
||||
{
|
||||
name: "铺纸机",
|
||||
data: [
|
||||
{ name: "铺纸机4_1", value: 0, code:'4-paper1', label:'outputNum'},
|
||||
{ name: "铺纸机4_2", value: 0, code:'4-paper2', label:'outputNum'},
|
||||
],
|
||||
position: [765, 210],
|
||||
},
|
||||
{
|
||||
name: "下片机械手",
|
||||
data: [
|
||||
{ name: "下片机械手4_1", value: 0, code:'4-down1', label:'outputNum' },
|
||||
{ name: "下片机械手4_2", value: 0, code:'4-down2', label:'outputNum' },
|
||||
],
|
||||
position: [560, 10],
|
||||
},
|
||||
],
|
||||
"Line5-1": [
|
||||
{
|
||||
name: "磨边进口",
|
||||
data: [
|
||||
{ name: "1支线", value: 0, code:'5-edge1', label:'inputNum' },
|
||||
{ name: "2支线", value: 0, code:'5-edge2', label:'inputNum' },
|
||||
{ name: "3支线", value: 0, code:'5-edge3', label:'inputNum' },
|
||||
],
|
||||
position: [150, 370],
|
||||
},
|
||||
{
|
||||
name: "磨边清洗出口",
|
||||
data: [
|
||||
{ name: "1支线", value: 0, code:'5-edgeclean1', label:'outputNum' },
|
||||
{ name: "2支线", value: 0, code:'5-edgeclean2', label:'outputNum' },
|
||||
{ name: "3支线", value: 0, code:'5-edgeclean3', label:'outputNum' },
|
||||
],
|
||||
position: [380, 130],
|
||||
},
|
||||
{
|
||||
name: "一次镀膜进口",
|
||||
data: [
|
||||
{ name: "1支线", value: 0, code:'5-fircoat1', label:'inputNum' },
|
||||
{ name: "2支线", value: 0, code:'5-fircoat2', label:'inputNum' },
|
||||
{ name: "3支线", value: 0, code:'5-fircoat3', label:'inputNum' },
|
||||
],
|
||||
position: [650, 310],
|
||||
},
|
||||
{
|
||||
name: "二次镀膜进口",
|
||||
data: [
|
||||
{ name: "1支线", value: 0, code:'5-seccoat1', label:'inputNum' },
|
||||
{ name: "2支线", value: 0, code:'5-seccoat2', label:'inputNum' },
|
||||
{ name: "3支线", value: 0, code:'5-seccoat3', label:'inputNum' },
|
||||
],
|
||||
position: [640, 20],
|
||||
},
|
||||
{
|
||||
name: "二次固化出口",
|
||||
data: [
|
||||
{ name: "1支线", value: 0, code:'5-secsolid1', label:'outputNum' },
|
||||
{ name: "2支线", value: 0, code:'5-secsolid2', label:'outputNum' },
|
||||
{ name: "3支线", value: 0, code:'5-secsolid3', label:'outputNum' },
|
||||
],
|
||||
position: [850, 220],
|
||||
},
|
||||
{
|
||||
name: "钢化进口",
|
||||
data: [{ name: "钢化进口", value: 0, code:'5-temper1', label:'inputNum' }],
|
||||
position: [830, 10],
|
||||
},
|
||||
],
|
||||
"Line5-2": [
|
||||
{
|
||||
name: "钢化出口",
|
||||
data: [{ name: "钢化出口", value: 0, code:'5-temper1', label:'outputNum' }],
|
||||
position: [260, 255],
|
||||
},
|
||||
{
|
||||
name: "包装清洗机入口",
|
||||
data: [
|
||||
{ name: "包装清洗机5_1", value: 0, code:'5-packclean1', label:'inputNum' },
|
||||
{ name: "包装清洗机5_2", value: 0, code:'5-packclean2', label:'inputNum' },
|
||||
],
|
||||
position: [508, 350],
|
||||
},
|
||||
{
|
||||
name: "包装清洗机出口",
|
||||
data: [
|
||||
{ name: "包装清洗机5_1", value: 0, code:'5-packclean1', label:'outputNum' },
|
||||
{ name: "包装清洗机5_2", value: 0, code:'5-packclean2', label:'outputNum' },
|
||||
],
|
||||
position: [444, 120],
|
||||
},
|
||||
{
|
||||
name: "铺纸机",
|
||||
data: [
|
||||
{ name: "铺纸机5_1", value: 0, code:'5-paper1', label:'outputNum' },
|
||||
{ name: "铺纸机5_2", value: 0, code:'5-paper2', label:'outputNum' },
|
||||
],
|
||||
position: [710, 272],
|
||||
},
|
||||
{
|
||||
name: "下片机械手",
|
||||
data: [
|
||||
{ name: "下片机械手5_1", value: 0, code:'5-down1', label:'outputNum'},
|
||||
{ name: "下片机械手5_2", value: 0, code:'5-down2', label:'outputNum'},
|
||||
{ name: "下片机械手5_3", value: 0, code:'5-down3', label:'outputNum'},
|
||||
],
|
||||
position: [700, 10],
|
||||
},
|
||||
],
|
||||
}
|
||||
export default EqInfoData
|
||||
@@ -1,59 +0,0 @@
|
||||
const EquMap = {
|
||||
CleanAfterEdge1_1: ['object_1_003'],
|
||||
CleanAfterEdge1_2: ['object_1_004'],
|
||||
CleanAfterEdge2_1: ['object_2_003'],
|
||||
CleanAfterEdge2_2: ['object_2_004'],
|
||||
CleanAfterEdge3_1: ['object_3_003'],
|
||||
CleanAfterEdge3_2: ['object_3_004'],
|
||||
CleanAfterEdge4_1: ['object_4_003'],
|
||||
CleanAfterEdge4_2: ['object_4_004'],
|
||||
CleanAfterTemper1_1: ['object_1_026', 'object_1_027'],
|
||||
CleanAfterTemper2_1: ['object_2_022', 'object_2_023'],
|
||||
CleanAfterTemper3_1: ['object_3_022', 'object_3_023'],
|
||||
CleanAfterTemper4_1: ['object_4_026', 'object_4_027'],
|
||||
CleanBeforCoat1_1: ['object_1_009'],
|
||||
CleanBeforCoat1_2: ['object_1_010'],
|
||||
CleanBeforCoat4_1: ['object_4_009'],
|
||||
CleanBeforCoat4_2: ['object_4_010'],
|
||||
Edge1_1: ['object_1_001'],
|
||||
Edge1_2: ['object_1_002'],
|
||||
Edge2_1: ['object_2_001'],
|
||||
Edge2_2: ['object_2_002'],
|
||||
Edge3_1: ['object_3_001'],
|
||||
Edge3_2: ['object_3_002'],
|
||||
Edge4_1: ['object_4_001'],
|
||||
Edge4_2: ['object_4_002'],
|
||||
FirstCoat1_1: ['object_1_011'],
|
||||
FirstCoat1_2: ['object_1_012'],
|
||||
FirstCoat2_1: ['object_2_007'],
|
||||
FirstCoat2_2: ['object_2_008'],
|
||||
FirstCoat3_1: ['object_3_007'],
|
||||
FirstCoat3_2: ['object_3_008'],
|
||||
FirstCoat4_1: ['object_4_011'],
|
||||
FirstCoat4_2: ['object_4_012'],
|
||||
Punch1_1: ['object_1_007'],
|
||||
Punch1_2: ['object_1_008'],
|
||||
Punch4_1: ['object_4_007'],
|
||||
Punch4_2: ['object_4_008'],
|
||||
SecondCoat1_1: ['object_1_013'],
|
||||
SecondCoat1_2: ['object_1_014'],
|
||||
SecondCoat2_1: ['object_2_009'],
|
||||
SecondCoat2_2: ['object_2_010'],
|
||||
SecondCoat3_1: ['object_3_009'],
|
||||
SecondCoat3_2: ['object_3_010'],
|
||||
SecondCoat4_1: ['object_4_013'],
|
||||
SecondCoat4_2: ['object_4_014'],
|
||||
Temper1_1: ['object_1_017', 'object_1_018', 'object_1_019', 'object_1_020', 'object_1_021', 'object_1_022', 'object_1_023', 'object_1_024', 'object_1_025'],
|
||||
Temper2_1: ['object_2_013', 'object_2_014', 'object_2_015', 'object_2_016', 'object_2_017', 'object_2_018', 'object_2_019', 'object_2_020', 'object_2_021'],
|
||||
Temper3_1: ['object_3_013', 'object_3_014', 'object_3_015', 'object_3_016', 'object_3_017', 'object_3_018', 'object_3_019', 'object_3_020', 'object_3_021'],
|
||||
Temper4_1: ['object_4_017', 'object_4_018', 'object_4_019', 'object_4_020', 'object_4_021', 'object_4_022', 'object_4_023', 'object_4_024', 'object_4_025'],
|
||||
Unload1_1: ['object_1_028'],
|
||||
Unload1_2: ['object_1_029'],
|
||||
Unload2_1: ['object_2_024'],
|
||||
Unload2_2: ['object_2_025'],
|
||||
Unload3_1: ['object_3_024'],
|
||||
Unload3_2: ['object_3_025'],
|
||||
Unload4_1: ['object_4_028'],
|
||||
Unload4_2: ['object_4_029']
|
||||
}
|
||||
export default EquMap;
|
||||
421
src/babylonjs/LinePageBabylonNew.tsx
Normal file
@@ -0,0 +1,421 @@
|
||||
import { useEffect, useRef, useState } 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 { HemisphericLight, Vector3 } from "@babylonjs/core";
|
||||
import { useAppSelector } from "../store/hooks";
|
||||
import "../page/style/standard.css";
|
||||
import EqInfoData from "./EqInfoData";
|
||||
import AlarmTipGreen from "./../page/assets/icon/g.png";
|
||||
import AlarmTipYellow from "./../page/assets/icon/y.png";
|
||||
import AlarmTipRed from "./../page/assets/icon/r.png";
|
||||
import {selectLine1Before} from "../store/LinePageSlice";
|
||||
import {selectLine1After} from "../store/LinePageSlice";
|
||||
import {selectLine2Before} from "../store/LinePageSlice";
|
||||
import {selectLine2After} from "../store/LinePageSlice";
|
||||
import {selectLine3Before} from "../store/LinePageSlice";
|
||||
import {selectLine3After} from "../store/LinePageSlice";
|
||||
import {selectLine4Before} from "../store/LinePageSlice";
|
||||
import {selectLine4After} from "../store/LinePageSlice";
|
||||
import {selectLine5Before} from "../store/LinePageSlice";
|
||||
import {selectLine5After} from "../store/LinePageSlice";
|
||||
|
||||
const lineNameNo = ["一","二","三","四","五"]
|
||||
const myStyle = {
|
||||
width: "1041px",
|
||||
height: "562px",
|
||||
outline: "none",
|
||||
};
|
||||
interface MybabylonJSProps {
|
||||
modelPath: string; // 明确 modelPath 属性的类型为 string
|
||||
}
|
||||
interface EqListType {
|
||||
[key: string]: EqMsg
|
||||
}
|
||||
interface EqMsg {
|
||||
equipmentName?:string;
|
||||
run?:boolean;
|
||||
error?:boolean;
|
||||
inputNum?:number;
|
||||
outputNum?:number;
|
||||
quantityTime?:number;
|
||||
status?:string;
|
||||
statusTime?:number;
|
||||
localDateTime?:number;
|
||||
equipmentCode?:string;
|
||||
equipmentId?:number;
|
||||
}
|
||||
function MybabylonJS({ modelPath }: MybabylonJSProps) {
|
||||
const [eqList, setEqList] = useState<EqListType>({});
|
||||
const canvasRef = useRef(null);
|
||||
const resetRef = useRef<(() => void) | null>(null);
|
||||
const [selectedMeshName, setSelectedMeshName] = useState<string | null>(null);
|
||||
const [selectedMeshId, setSelectedMeshId] = useState<string | null>(null);
|
||||
const [selectedMeshObj, setSelectedMeshObj] = useState<EqMsg>({
|
||||
equipmentName: "",
|
||||
run: true,
|
||||
error: false,
|
||||
});
|
||||
const [showInfo, setShowInfo] = useState(true);
|
||||
|
||||
const selectorMap: Record<string, (state: any) => any> = {
|
||||
"Line1-1": selectLine1Before,
|
||||
"Line1-2": selectLine1After,
|
||||
"Line2-1": selectLine2Before,
|
||||
"Line2-2": selectLine2After,
|
||||
"Line3-1": selectLine3Before,
|
||||
"Line3-2": selectLine3After,
|
||||
"Line4-1": selectLine4Before,
|
||||
"Line4-2": selectLine4After,
|
||||
"Line5-1": selectLine5Before,
|
||||
"Line5-2": selectLine5After
|
||||
};
|
||||
const selectedSelector = selectorMap[modelPath];
|
||||
const allData = useAppSelector(selectedSelector);
|
||||
// const allData = useAppSelector(selectLine1Before) as any;
|
||||
|
||||
|
||||
// 使用 useRef 来存储当前加载的模型引用
|
||||
const currentMeshesRef = useRef<Array<BABYLON.AbstractMesh>>([]);
|
||||
useEffect(() => {
|
||||
const equStatus = allData?.equStatus;
|
||||
if (equStatus) {
|
||||
setEqList(equStatus);
|
||||
}
|
||||
},[allData])
|
||||
useEffect(() => {
|
||||
const equStatus = allData?.equStatus;
|
||||
if (equStatus) {
|
||||
for (let i = 0; i < EqInfoData[modelPath].length; i++) {
|
||||
for (let j = 0; j < EqInfoData[modelPath][i].data.length; j++) {
|
||||
EqInfoData[modelPath][i].data[j].value = equStatus[EqInfoData[modelPath][i].data[j].code][EqInfoData[modelPath][i].data[j].label] ? equStatus[EqInfoData[modelPath][i].data[j].code][EqInfoData[modelPath][i].data[j].label] : 0
|
||||
}
|
||||
}
|
||||
}
|
||||
},[allData,modelPath])
|
||||
useEffect(() => {
|
||||
if (selectedMeshId && eqList[selectedMeshId]) {
|
||||
setSelectedMeshObj({
|
||||
equipmentName:eqList[selectedMeshId].equipmentName,
|
||||
run:eqList[selectedMeshId].run ? eqList[selectedMeshId].run : true,
|
||||
error:eqList[selectedMeshId].error ? eqList[selectedMeshId].error : false,
|
||||
});
|
||||
}
|
||||
},[selectedMeshId])
|
||||
useEffect(() => {
|
||||
// 确保 canvas 引用存在
|
||||
if (!canvasRef.current) return;
|
||||
const canvas = canvasRef.current;
|
||||
const engine = new BABYLON.Engine(canvas, true, {
|
||||
preserveDrawingBuffer: true,
|
||||
stencil: true,
|
||||
});
|
||||
|
||||
const createScene = async function () {
|
||||
// This creates a basic Babylon Scene object (non-mesh)
|
||||
const scene = new BABYLON.Scene(engine);
|
||||
scene.clearColor = new BABYLON.Color4(0, 0, 0, 0);
|
||||
const baseLight = new HemisphericLight(
|
||||
"hemiLight",
|
||||
new Vector3(-1, 1, 0),
|
||||
scene
|
||||
);
|
||||
baseLight.intensity = 1;
|
||||
baseLight.diffuse = new BABYLON.Color3(1, 1, 1);
|
||||
baseLight.specular = new BABYLON.Color3(0.25, 0.25, 0.25);
|
||||
baseLight.groundColor = new BABYLON.Color3(0.5, 0.5, 0.5);
|
||||
|
||||
//add an arcRotateCamera to the scene
|
||||
const camera = new BABYLON.ArcRotateCamera(
|
||||
"camera",
|
||||
BABYLON.Tools.ToRadians(245),
|
||||
BABYLON.Tools.ToRadians(25),
|
||||
modelPath.slice(-3) === "2-1"
|
||||
? 120
|
||||
: modelPath.slice(-1) === "1"
|
||||
? 110
|
||||
: modelPath.slice(-3) === "5-2"
|
||||
? 100
|
||||
: modelPath.slice(-3) === "1-2"
|
||||
? 90
|
||||
: 65,
|
||||
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.forEach((mesh) => {
|
||||
mesh.isPickable = true;
|
||||
mesh.actionManager = new BABYLON.ActionManager(scene);
|
||||
if (modelPath.slice(-1) === "1") {
|
||||
if (
|
||||
mesh.name.includes("磨边") ||
|
||||
mesh.name.includes("清洗") ||
|
||||
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._scene.onPointerDown = async (event, _pickResult) => {
|
||||
console.log('_pickResult',_pickResult)
|
||||
const pickInfo = mesh._scene.pick(
|
||||
mesh._scene.pointerX,
|
||||
mesh._scene.pointerY
|
||||
);
|
||||
//判断是否是右键
|
||||
if (!(event.buttons === 1 && pickInfo.pickedMesh)) return;
|
||||
const MeshName = pickInfo.pickedMesh.name;
|
||||
const MeshNameId = pickInfo.pickedMesh.metadata.tags;
|
||||
|
||||
setSelectedMeshName(MeshName);
|
||||
setSelectedMeshId(MeshNameId);
|
||||
};
|
||||
});
|
||||
} 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(-3) === "2-1"
|
||||
? 120
|
||||
: modelPath.slice(-1) === "1"
|
||||
? 110
|
||||
: modelPath.slice(-3) === "5-2"
|
||||
? 100
|
||||
: modelPath.slice(-3) === "1-2"
|
||||
? 90
|
||||
: 65
|
||||
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 = () => {
|
||||
//模型初始位置
|
||||
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">
|
||||
第{lineNameNo[Number(modelPath.slice(-3,-2))-1]}产线钢化{modelPath.slice(-1) === "1" ? "前段" : "后段"}
|
||||
</span>
|
||||
</div>
|
||||
{selectedMeshName && (
|
||||
<div className="eq_detail_info">
|
||||
<div>
|
||||
<span className="left_name">设备名称:</span>
|
||||
<span className="right_value">{selectedMeshObj.equipmentName}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span className="left_name">报警状态:</span>
|
||||
<span className="right_value">
|
||||
{selectedMeshObj.error ? (
|
||||
<>
|
||||
<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.run ? (
|
||||
<>
|
||||
<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) => {
|
||||
return (
|
||||
<div
|
||||
className="eq_info"
|
||||
key={item.data[0].code+item.data[0].label}
|
||||
style={{ left: item.position[0], top: item.position[1] }}
|
||||
>
|
||||
<div className="eq_info_inner" style={{ color: "#00FFF0" }}>
|
||||
{item.name}
|
||||
</div>
|
||||
{item.data.map((info) => {
|
||||
return (
|
||||
<div className="eq_info_inner" key={info.code+info.label}>
|
||||
{info.name}:{info.value}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
||||
<canvas ref={canvasRef} style={myStyle} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default MybabylonJS;
|
||||
@@ -1,363 +0,0 @@
|
||||
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 {
|
||||
GlassAnimation1_1, GlassAnimation1_2D, GlassAnimation1_2U, GlassAnimation1_3, GlassAnimation1_4,
|
||||
GlassAnimation2_1, GlassAnimation2_2D, GlassAnimation2_2U, GlassAnimation2_3, GlassAnimation2_4,
|
||||
GlassAnimation3_1, GlassAnimation3_2D, GlassAnimation3_2U, GlassAnimation3_3, GlassAnimation3_4,
|
||||
GlassAnimation4_1, GlassAnimation4_2D, GlassAnimation4_2U, GlassAnimation4_3, GlassAnimation4_4
|
||||
} from "./GlassAnimation";
|
||||
import { useAppSelector } from "../store/hooks";
|
||||
import { GlassStatus, selectGlassStatus } from "../store/ProductionMonitoringEntity";
|
||||
import '../page/style/standard.css';
|
||||
import { MyObservable } from "../context/MyObservable";
|
||||
import { Button, ButtonGroup } from "@mui/material";
|
||||
import intl from "react-intl-universal";
|
||||
import { EquStatusInterface, selectEquStatus } from "../store/EquStatusEntity";
|
||||
import EquMap from "./EquMap";
|
||||
|
||||
const onMainCamObservable = new Observable();
|
||||
const onEquObservable = new Observable();
|
||||
|
||||
|
||||
|
||||
const myStyle = {
|
||||
width: '1036px',
|
||||
height: '666px',
|
||||
outline: 'none',
|
||||
}
|
||||
|
||||
|
||||
|
||||
const DetailCamera = {
|
||||
Part_1: {
|
||||
alpha: BABYLON.Tools.ToRadians(270),
|
||||
beta: BABYLON.Tools.ToRadians(25),
|
||||
radius: 85,
|
||||
target: new BABYLON.Vector3(-110, 0, -8)
|
||||
},
|
||||
Part_2: {
|
||||
alpha: BABYLON.Tools.ToRadians(270),
|
||||
beta: BABYLON.Tools.ToRadians(25),
|
||||
radius: 85,
|
||||
target: new BABYLON.Vector3(-40, 0, -8)
|
||||
},
|
||||
Part_3: {
|
||||
alpha: BABYLON.Tools.ToRadians(270),
|
||||
beta: BABYLON.Tools.ToRadians(25),
|
||||
radius: 85,
|
||||
target: new BABYLON.Vector3(0, 0, -8)
|
||||
},
|
||||
Part_4: {
|
||||
alpha: BABYLON.Tools.ToRadians(270),
|
||||
beta: BABYLON.Tools.ToRadians(25),
|
||||
radius: 85,
|
||||
target: new BABYLON.Vector3(110, 0, -8)
|
||||
},
|
||||
}
|
||||
|
||||
interface MybabylonJSProps {
|
||||
modelPath: string; // 明确 modelPath 属性的类型为 string
|
||||
}
|
||||
|
||||
|
||||
function MybabylonJS({ modelPath }: MybabylonJSProps) {
|
||||
const onGlassObservable = useContext(MyObservable);
|
||||
const EquStatus = useAppSelector(selectEquStatus);
|
||||
const canvasRef = useRef(null);
|
||||
onEquObservable.notifyObservers(EquStatus);
|
||||
// const thisLineGlassStatus = useAppSelector(selectGlassStatus)
|
||||
// onGlassObservable.notifyObservers(thisLineGlassStatus)
|
||||
const [SelectedMeshName, setSelectedMeshName] = useState<string | null>(null);
|
||||
|
||||
|
||||
interface MybabylonJSProps {
|
||||
modelPath: string;
|
||||
}
|
||||
|
||||
// 使用 useRef 来存储当前加载的模型引用
|
||||
const currentMeshesRef = useRef<Array<BABYLON.AbstractMesh>>([]);
|
||||
|
||||
|
||||
|
||||
|
||||
useEffect(
|
||||
() => {
|
||||
// 确保 canvas 引用存在
|
||||
if (!canvasRef.current) return;
|
||||
|
||||
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 light = new BABYLON.DirectionalLight('light', new BABYLON.Vector3(20, 20, 100), scene);
|
||||
const light2 = new BABYLON.PointLight('light2', new BABYLON.Vector3(20, 20, 100), scene);
|
||||
|
||||
const Glass1_1 = new BABYLON.TransformNode('Glass1_1')
|
||||
|
||||
const baseLight = new HemisphericLight('hemiLight', new Vector3(-1, 1, 0), 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), 215, new BABYLON.Vector3(-2, 0, -8));
|
||||
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 = .3
|
||||
grid.gridRatio = .04
|
||||
grid.backFaceCulling = !1
|
||||
grid.mainColor = new BABYLON.Color3(1, 1, 1)
|
||||
grid.lineColor = new BABYLON.Color3(1, 1, 1)
|
||||
grid.opacity = .8
|
||||
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);
|
||||
|
||||
|
||||
// var LOD0MESH = await BABYLON.SceneLoader.ImportMeshAsync('', '/test/', `${modelPath}.babylon`, 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('', '/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);
|
||||
// var LOD4MESH = await BABYLON.SceneLoader.ImportMeshAsync('', '/test/', `line5.babylon`, scene);
|
||||
// 将新加载的模型添加到 currentMeshesRef 中
|
||||
currentMeshesRef.current.push(...LOD0MESH.meshes);
|
||||
|
||||
|
||||
// ...为新加载的模型设置交互逻辑
|
||||
|
||||
LOD0MESH.meshes.map((mesh) => {
|
||||
mesh.isPickable = true;
|
||||
mesh.actionManager = new BABYLON.ActionManager(scene);
|
||||
//鼠标移动到物体上亮显
|
||||
mesh.actionManager.registerAction(new BABYLON.ExecuteCodeAction(BABYLON.ActionManager.OnPointerOverTrigger, () => {
|
||||
// @ts-ignore
|
||||
hl.addMesh(mesh, BABYLON.Color3.Green());
|
||||
|
||||
}));
|
||||
mesh.actionManager.registerAction(new BABYLON.ExecuteCodeAction(BABYLON.ActionManager.OnPointerOutTrigger, () => {
|
||||
// @ts-ignore
|
||||
hl.removeMesh(mesh)
|
||||
|
||||
}));
|
||||
|
||||
|
||||
mesh._scene.onPointerDown = async (event, _pickResult) => {
|
||||
const pickInfo = mesh._scene.pick(mesh._scene.pointerX, mesh._scene.pointerY)
|
||||
|
||||
const clickedPosition = _pickResult.pickedPoint
|
||||
//如果需要获取吗模型根节点,而不是模型中某个组件,请用一下方法
|
||||
// getRootNode(pickInfo.pickedMesh as BABYLON.Node) 如上篇文章getRootNode函数
|
||||
|
||||
//判断是否是右键
|
||||
if (!(event.buttons === 1 && pickInfo.pickedMesh)) return
|
||||
const MeshName1 = pickInfo.pickedMesh.name.split(".")[0]
|
||||
|
||||
setSelectedMeshName(MeshName1)
|
||||
|
||||
|
||||
} })
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
onEquObservable.add((eventData, eventState) => {
|
||||
LOD0MESH.meshes.find((mesh) => {
|
||||
// @ts-ignore
|
||||
hl2.removeMesh(mesh);
|
||||
|
||||
})
|
||||
Object.keys(eventData as EquStatusInterface).map((key) => {
|
||||
// @ts-ignore
|
||||
if (eventData[key] == 2) {
|
||||
// @ts-ignore
|
||||
EquMap[key].map((name) => {
|
||||
LOD0MESH.meshes.find((mesh) => {
|
||||
if (mesh.name == name) {
|
||||
// @ts-ignore
|
||||
hl2.addMesh(mesh, BABYLON.Color3.Red());
|
||||
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
} catch (error) {
|
||||
console.error('加载模型失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 调用函数以加载或重新加载模型
|
||||
loadOrReloadModel();
|
||||
|
||||
function reset() {
|
||||
camera.target = new BABYLON.Vector3(-2, 0, -8);
|
||||
camera.alpha = BABYLON.Tools.ToRadians(245);
|
||||
camera.beta = BABYLON.Tools.ToRadians(25);
|
||||
camera.radius = 215;
|
||||
}
|
||||
|
||||
let resetCamera = setTimeout(reset, 15000)
|
||||
scene.onPointerObservable.add((pointerInfo) => {
|
||||
// console.log(camera.target, camera.alpha * 180 / 3.14, camera.beta * 180 / 3.14, camera.radius)
|
||||
switch (pointerInfo.type) {
|
||||
case BABYLON.PointerEventTypes.POINTERMOVE:
|
||||
clearTimeout(resetCamera);
|
||||
resetCamera = setTimeout(reset, 15000)
|
||||
}
|
||||
})
|
||||
|
||||
onMainCamObservable.add((eventData, eventState) => {
|
||||
clearTimeout(resetCamera);
|
||||
resetCamera = setTimeout(reset, 5000);
|
||||
switch (eventData) {
|
||||
case 1:
|
||||
camera.target = DetailCamera.Part_1.target;
|
||||
camera.alpha = DetailCamera.Part_1.alpha;
|
||||
camera.beta = DetailCamera.Part_1.beta;
|
||||
camera.radius = DetailCamera.Part_1.radius;
|
||||
break;
|
||||
case 2:
|
||||
camera.target = DetailCamera.Part_2.target;
|
||||
camera.alpha = DetailCamera.Part_2.alpha;
|
||||
camera.beta = DetailCamera.Part_2.beta;
|
||||
camera.radius = DetailCamera.Part_2.radius;
|
||||
break;
|
||||
case 3:
|
||||
camera.target = DetailCamera.Part_3.target;
|
||||
camera.alpha = DetailCamera.Part_3.alpha;
|
||||
camera.beta = DetailCamera.Part_3.beta;
|
||||
camera.radius = DetailCamera.Part_3.radius;
|
||||
break;
|
||||
case 4:
|
||||
camera.target = DetailCamera.Part_4.target;
|
||||
camera.alpha = DetailCamera.Part_4.alpha;
|
||||
camera.beta = DetailCamera.Part_4.beta;
|
||||
camera.radius = DetailCamera.Part_4.radius;
|
||||
break;
|
||||
}
|
||||
})
|
||||
|
||||
return scene;
|
||||
};
|
||||
|
||||
// call the createScene function
|
||||
const scene = createScene();
|
||||
|
||||
scene.then((scene) => {
|
||||
|
||||
|
||||
})
|
||||
|
||||
// run the render loop
|
||||
scene.then((scene) => {
|
||||
engine.runRenderLoop(function () {
|
||||
scene.render()
|
||||
});
|
||||
},
|
||||
(reason) => {
|
||||
console.log(reason);
|
||||
}
|
||||
);
|
||||
|
||||
// Resize
|
||||
window.addEventListener("resize", function () {
|
||||
engine.resize();
|
||||
});
|
||||
|
||||
// 组件卸载时的清理逻辑
|
||||
return () => {
|
||||
// 清理场景和引擎资源
|
||||
engine.dispose();
|
||||
};
|
||||
},
|
||||
[modelPath]
|
||||
);
|
||||
|
||||
|
||||
const handleClick1 = () => {
|
||||
onMainCamObservable.notifyObservers(1)
|
||||
}
|
||||
const handleClick2 = () => {
|
||||
onMainCamObservable.notifyObservers(2)
|
||||
}
|
||||
const handleClick3 = () => {
|
||||
onMainCamObservable.notifyObservers(3)
|
||||
}
|
||||
const handleClick4 = () => {
|
||||
onMainCamObservable.notifyObservers(4)
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<div style={myStyle}>
|
||||
|
||||
<ButtonGroup variant="contained" aria-label="outlined button group" className={'btnArea'}>
|
||||
<h2>当前选择: {SelectedMeshName}</h2>
|
||||
<Button sx={{ backgroundColor: 'rgba(86, 244, 231, 0.69)' }} onClick={handleClick1}>{intl.get('Part1')}</Button>
|
||||
<Button sx={{ backgroundColor: 'rgba(86, 244, 231, 0.69)' }} onClick={handleClick2}>{intl.get('Part2')}</Button>
|
||||
<Button sx={{ backgroundColor: 'rgba(86, 244, 231, 0.69)' }} onClick={handleClick3}>{intl.get('Part3')}</Button>
|
||||
<Button sx={{ backgroundColor: 'rgba(86, 244, 231, 0.69)' }} onClick={handleClick4}>{intl.get('Part4')}</Button>
|
||||
</ButtonGroup>
|
||||
<canvas ref={canvasRef} style={myStyle} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default MybabylonJS;
|
||||
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"><g fill="#61DAFB"><path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/><circle cx="420.9" cy="296.5" r="45.7"/><path d="M520.5 78.1z"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 2.6 KiB |
@@ -1,65 +0,0 @@
|
||||
import React, {useContext, useEffect, useState} from "react";
|
||||
import intl from "react-intl-universal";
|
||||
import MainP from "../MainP/MainP";
|
||||
import MainE from "../MainE/MainE";
|
||||
import MainQ from "../MainQ/MainQ";
|
||||
import TabPanel from "../Component/TabPanel";
|
||||
import SwitchOnOff from "../Component/SwitchOnOff";
|
||||
import {useAppSelector} from "../../store/hooks";
|
||||
import {selectSwitchState} from "../../store/ChangeSwitchState";
|
||||
import {ThisLineID} from "../../context/ThisLineID";
|
||||
|
||||
function SwitchAll() {
|
||||
const [PageIndex, setPageIndex] = useState(1)
|
||||
const state = useAppSelector(selectSwitchState)
|
||||
useEffect(() => {
|
||||
let timerId: NodeJS.Timer;
|
||||
|
||||
function StartSwitch() {
|
||||
timerId = setTimeout(() => {
|
||||
if (PageIndex < 6) {
|
||||
setPageIndex(PageIndex + 1)
|
||||
} else {
|
||||
setPageIndex(1)
|
||||
}
|
||||
}, 30000)
|
||||
}
|
||||
|
||||
function StopSwitch() {
|
||||
clearInterval(timerId)
|
||||
}
|
||||
|
||||
if (state) {
|
||||
StartSwitch()
|
||||
} else {
|
||||
StopSwitch()
|
||||
}
|
||||
|
||||
window.dispatchEvent(new Event('resize'))
|
||||
return () => {
|
||||
clearInterval(timerId)
|
||||
}
|
||||
}, [PageIndex, state]
|
||||
)
|
||||
return (
|
||||
<div>
|
||||
<SwitchOnOff/>
|
||||
<TabPanel index={1} value={PageIndex}><MainP/></TabPanel>
|
||||
<TabPanel index={2} value={PageIndex}><MainQ/></TabPanel>
|
||||
<ThisLineID.Provider value={'1'}>
|
||||
<TabPanel index={3} value={PageIndex}><MainE/></TabPanel>
|
||||
</ThisLineID.Provider>
|
||||
<ThisLineID.Provider value={'2'}>
|
||||
<TabPanel index={4} value={PageIndex}><MainE/></TabPanel>
|
||||
</ThisLineID.Provider>
|
||||
<ThisLineID.Provider value={'3'}>
|
||||
<TabPanel index={5} value={PageIndex}><MainE/></TabPanel>
|
||||
</ThisLineID.Provider>
|
||||
<ThisLineID.Provider value={'4'}>
|
||||
<TabPanel index={6} value={PageIndex}><MainE/></TabPanel>
|
||||
</ThisLineID.Provider>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default SwitchAll;
|
||||
@@ -1,53 +0,0 @@
|
||||
import React, {useContext, useEffect, useState} from "react";
|
||||
import intl from "react-intl-universal";
|
||||
import MainP from "../MainP/MainP";
|
||||
import MainE from "../MainE/MainE";
|
||||
import MainQ from "../MainQ/MainQ";
|
||||
import TabPanel from "../Component/TabPanel";
|
||||
import SwitchOnOff from "../Component/SwitchOnOff";
|
||||
import {useAppSelector} from "../../store/hooks";
|
||||
import {selectSwitchState} from "../../store/ChangeSwitchState";
|
||||
|
||||
function SwitchLine() {
|
||||
const [PageIndex, setPageIndex] = useState(1)
|
||||
const state = useAppSelector(selectSwitchState)
|
||||
useEffect(() => {
|
||||
let timerId: NodeJS.Timer;
|
||||
|
||||
function StartSwitch() {
|
||||
timerId = setInterval(() => {
|
||||
if (PageIndex < 3) {
|
||||
setPageIndex(PageIndex + 1)
|
||||
} else {
|
||||
setPageIndex(1)
|
||||
}
|
||||
}, 30000)
|
||||
}
|
||||
|
||||
function StopSwitch() {
|
||||
clearInterval(timerId)
|
||||
}
|
||||
|
||||
if (state) {
|
||||
StartSwitch()
|
||||
} else {
|
||||
StopSwitch()
|
||||
}
|
||||
|
||||
window.dispatchEvent(new Event('resize'))
|
||||
return () => {
|
||||
clearInterval(timerId)
|
||||
}
|
||||
}, [PageIndex, state]
|
||||
)
|
||||
return (
|
||||
<div>
|
||||
<SwitchOnOff/>
|
||||
<TabPanel index={1} value={PageIndex}><MainP/></TabPanel>
|
||||
<TabPanel index={2} value={PageIndex}><MainQ/></TabPanel>
|
||||
<TabPanel index={3} value={PageIndex}><MainE/></TabPanel>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default SwitchLine;
|
||||
81
src/page/Component/BarChart/chart.config.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import * as echarts from "echarts";
|
||||
export default function getOptions(dataProps: number[],xData:string[], color: string[]) {
|
||||
if (dataProps.length === 0) return null;
|
||||
return {
|
||||
grid: { top: 30, right: 10, bottom: 5, left: 10, containLabel: true },
|
||||
legend: {
|
||||
show: false,
|
||||
},
|
||||
xAxis: {
|
||||
type: "category",
|
||||
data: xData,
|
||||
axisLabel: {
|
||||
color: "#fff",
|
||||
fontSize: 10,
|
||||
interval: 0,
|
||||
rotate:20
|
||||
|
||||
},
|
||||
axisTick: { show: false },
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
width: 2,
|
||||
color: "#5982B2",
|
||||
},
|
||||
},
|
||||
},
|
||||
yAxis: {
|
||||
name: "单位/片",
|
||||
nameTextStyle: {
|
||||
color: "#fff",
|
||||
fontSize: 12,
|
||||
},
|
||||
type: "value",
|
||||
axisLabel: {
|
||||
color: "#fff",
|
||||
fontSize: 12,
|
||||
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] },
|
||||
]),
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
126
src/page/Component/BarLineChart/chart.config.ts
Normal file
@@ -0,0 +1,126 @@
|
||||
import * as echarts from "echarts";
|
||||
export default function getOptions(dataProps:any) {
|
||||
if (dataProps.length === 0) return null;
|
||||
return {
|
||||
grid: { top: 40, right: 10, bottom: 5, left: 10, containLabel: true },
|
||||
legend: {
|
||||
show: false,
|
||||
},
|
||||
xAxis: {
|
||||
type: "category",
|
||||
data: dataProps.time,
|
||||
axisLabel: {
|
||||
color: "#fff",
|
||||
fontSize: 12,
|
||||
interval: 0,
|
||||
rotate:20
|
||||
},
|
||||
axisTick: { show: false },
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
width: 2,
|
||||
color: "#5982B2",
|
||||
},
|
||||
},
|
||||
},
|
||||
yAxis: [{
|
||||
name: "单位/片",
|
||||
nameTextStyle: {
|
||||
color: "#fff",
|
||||
fontSize: 12,
|
||||
},
|
||||
type: "value",
|
||||
axisLabel: {
|
||||
color: "#fff",
|
||||
fontSize: 12,
|
||||
formatter: "{value}",
|
||||
},
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
width: 2,
|
||||
color: "#5982B2",
|
||||
},
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
width: 2,
|
||||
color: "#5982B2",
|
||||
},
|
||||
},
|
||||
},{
|
||||
name: "良品率/%",
|
||||
nameTextStyle: {
|
||||
color: "#fff",
|
||||
fontSize: 12,
|
||||
},
|
||||
type: "value",
|
||||
axisLabel: {
|
||||
color: "#fff",
|
||||
fontSize: 12,
|
||||
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.input,
|
||||
type: "bar",
|
||||
barWidth: 10,
|
||||
barGap:0,
|
||||
itemStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{ offset: 0, color: 'rgba(157, 234, 245, 1)' },
|
||||
{ offset: 1, color: 'rgba(110, 249, 222, 1)' },
|
||||
]),
|
||||
},
|
||||
},
|
||||
{
|
||||
data:dataProps.output,
|
||||
type: "bar",
|
||||
barWidth: 10,
|
||||
itemStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{ offset: 0, color: 'rgba(92, 183, 255, 1)' },
|
||||
{ offset: 1, color: 'rgba(54, 75, 254, 1)' },
|
||||
]),
|
||||
},
|
||||
},
|
||||
{
|
||||
data: dataProps.yield,
|
||||
type: "line",
|
||||
yAxisIndex: 1,
|
||||
symbol:'circle',
|
||||
symbolSize: 7,
|
||||
color:'rgba(18, 255, 245, 1)',
|
||||
areaStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{ offset: 0, color: 'rgba(18, 255, 245, 0.8)' },
|
||||
{ offset: 0.2, color: 'rgba(18, 255, 245, 0.2)' },
|
||||
{ offset: 0.4, color: 'rgba(18, 255, 245, 0)' },
|
||||
]),
|
||||
}
|
||||
}
|
||||
],
|
||||
};
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
import React, {useState} from "react";
|
||||
import intl from "react-intl-universal";
|
||||
import '../../lanhuapp/common.css';
|
||||
import "../../lanhuapp/index.css";
|
||||
|
||||
function ChangeFullButton() {
|
||||
const [isFull, setIsFull] = useState(false);
|
||||
|
||||
function fullExit() {
|
||||
let element = document.documentElement;
|
||||
|
||||
//HTML5 W3C 提议
|
||||
document.exitFullscreen();
|
||||
|
||||
setIsFull(false)
|
||||
}
|
||||
|
||||
function fullScreen() {
|
||||
let element = document.documentElement;
|
||||
|
||||
//HTML W3C 提议
|
||||
element.requestFullscreen();
|
||||
|
||||
setIsFull(true)
|
||||
}
|
||||
|
||||
const click = () => {
|
||||
isFull ? fullExit() : fullScreen();
|
||||
}
|
||||
|
||||
return (
|
||||
<button className="section_1 flex-col" onClick={click}/>
|
||||
)
|
||||
}
|
||||
|
||||
export default ChangeFullButton;
|
||||
@@ -1,19 +0,0 @@
|
||||
import React from "react";
|
||||
import intl from "react-intl-universal";
|
||||
import '../../lanhuapp/common.css';
|
||||
import "../../lanhuapp/index.css";
|
||||
import {useAppDispatch} from "../../store/hooks";
|
||||
import {UpdateChangeLangAndCss} from "../../store/ChangeLangAndCss";
|
||||
|
||||
function ChangeLangButton() {
|
||||
const dispatch = useAppDispatch();
|
||||
const changeTitle = () => {
|
||||
dispatch(UpdateChangeLangAndCss())
|
||||
}
|
||||
|
||||
return (
|
||||
<button className="box_76 flex-col" onClick={changeTitle}/>
|
||||
)
|
||||
}
|
||||
|
||||
export default ChangeLangButton;
|
||||
121
src/page/Component/LineChart/chart.config.ts
Normal file
@@ -0,0 +1,121 @@
|
||||
export default function getOptions(chartData: any) {
|
||||
if (Object.keys(chartData).length === 0) {
|
||||
return null;
|
||||
}
|
||||
const colors = ["#2760FF", "#8167F6", "#5B9BFF", "#99D66C", "#FFD160","#D680FF","#FF6860"];
|
||||
return {
|
||||
color: colors,
|
||||
grid: { top: 50, right: 12, bottom: 5, left: 15, containLabel: true },
|
||||
legend: {
|
||||
show: true,
|
||||
top: 5,
|
||||
right: 10,
|
||||
padding: 0,
|
||||
itemWidth: 14,
|
||||
itemHeight: 10,
|
||||
itemGap: 8,
|
||||
height: 10,
|
||||
textStyle: {
|
||||
color: "#DFF1FE",
|
||||
fontSize: 12,
|
||||
},
|
||||
},
|
||||
xAxis: {
|
||||
type: "category",
|
||||
data: chartData.xData,
|
||||
// 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: 12,
|
||||
},
|
||||
axisTick: { show: false },
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
width: 2,
|
||||
color: "#5982B2",
|
||||
},
|
||||
},
|
||||
},
|
||||
yAxis: {
|
||||
name: "单位/%",
|
||||
min: 50,
|
||||
nameTextStyle: {
|
||||
color: "#fff",
|
||||
fontSize: 12,
|
||||
},
|
||||
type: "value",
|
||||
axisLabel: {
|
||||
color: "#fff",
|
||||
fontSize: 12,
|
||||
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:chartData.series
|
||||
// series: [
|
||||
// {
|
||||
// name: "产线1",
|
||||
// type: "line",
|
||||
// symbol: "circle",
|
||||
// symbolSize: 4,
|
||||
// data: chartData.yData[0],
|
||||
// },
|
||||
// {
|
||||
// name: "产线2",
|
||||
// type: "line",
|
||||
// symbol: "circle",
|
||||
// symbolSize: 4,
|
||||
// data: chartData.yData[1],
|
||||
// },
|
||||
// {
|
||||
// name: "产线3",
|
||||
// type: "line",
|
||||
// symbol: "circle",
|
||||
// symbolSize: 4,
|
||||
// data: chartData.yData[2],
|
||||
// },
|
||||
// {
|
||||
// name: "产线4",
|
||||
// type: "line",
|
||||
// symbol: "circle",
|
||||
// symbolSize: 4,
|
||||
// data: chartData.yData[3],
|
||||
// },
|
||||
// {
|
||||
// name: "产线5",
|
||||
// type: "line",
|
||||
// symbol: "circle",
|
||||
// symbolSize: 4,
|
||||
// data: chartData.yData[4],
|
||||
// },
|
||||
// ],
|
||||
};
|
||||
}
|
||||
98
src/page/Component/LineChartRight/chart.config.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
|
||||
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: 5, containLabel: true },
|
||||
legend: {
|
||||
show: true,
|
||||
top: 10,
|
||||
right: 10,
|
||||
padding: 0,
|
||||
itemWidth: 14,
|
||||
itemHeight: 10,
|
||||
itemGap: 8,
|
||||
height: 10,
|
||||
textStyle: {
|
||||
color: "#DFF1FE",
|
||||
fontSize: 12,
|
||||
},
|
||||
},
|
||||
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: 12,
|
||||
},
|
||||
axisTick: { show: false },
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
width: 2,
|
||||
color: "#5982B2",
|
||||
},
|
||||
},
|
||||
},
|
||||
yAxis: {
|
||||
name: "单位/千片",
|
||||
nameTextStyle: {
|
||||
color: "#fff",
|
||||
fontSize: 12,
|
||||
},
|
||||
type: "value",
|
||||
axisLabel: {
|
||||
color: "#fff",
|
||||
fontSize: 12,
|
||||
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,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
import React from "react";
|
||||
import intl from "react-intl-universal";
|
||||
import '../../lanhuapp/common.css';
|
||||
import "../../lanhuapp/index.css";
|
||||
import {useAppSelector} from "../../store/hooks";
|
||||
import {Quality, selectQualityMonitorEntity} from "../../store/QualityMonitorEntity";
|
||||
import {Table, TableBody, TableHead} from "@mui/material";
|
||||
import {StyledTableCell, StyledTableContainer, StyledTableRow} from "./StyledTable";
|
||||
|
||||
interface param {
|
||||
timeName: "todayQualityLineAll" | "weekQualityLineAll" | "monthQualityLineAll";
|
||||
lineName: "Line_1" | "Line_2" | "Line_3" | "Line_4";
|
||||
}
|
||||
|
||||
function QualityRightTable(props: param) {
|
||||
const AllData = useAppSelector(selectQualityMonitorEntity);
|
||||
const TimeData = AllData[props.timeName];
|
||||
const LineData = TimeData[props.lineName];
|
||||
const SlicedLineData = LineData.slice(0, 6);
|
||||
return (
|
||||
<div className="rightTableAreaQ">
|
||||
<StyledTableContainer>
|
||||
<Table>
|
||||
<TableHead>
|
||||
<StyledTableRow>
|
||||
<StyledTableCell align="center" sx={{width: 100}}>{intl.get('serialNo')}</StyledTableCell>
|
||||
<StyledTableCell align="center" sx={{width: 250}}>{intl.get('DefectType')}</StyledTableCell>
|
||||
<StyledTableCell align="center" sx={{width: 120}}>{intl.get('DefectNumber')}</StyledTableCell>
|
||||
</StyledTableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{SlicedLineData.map((item: Quality, index: number) => (
|
||||
<StyledTableRow key={index}>
|
||||
<StyledTableCell align="center">{item.sort}</StyledTableCell>
|
||||
<StyledTableCell align="center" sx={{
|
||||
maxWidth: 250,
|
||||
overflow: 'hidden',
|
||||
whiteSpace: 'nowrap',
|
||||
textOverflow: 'ellipsis'
|
||||
}}>{item.content}</StyledTableCell>
|
||||
<StyledTableCell align="center">{item.num}</StyledTableCell>
|
||||
</StyledTableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</StyledTableContainer>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default QualityRightTable;
|
||||
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;
|
||||
}
|
||||
439
src/page/Component/ScrollBoard/index.tsx
Normal file
@@ -0,0 +1,439 @@
|
||||
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";
|
||||
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;
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
import React from "react";
|
||||
import {styled, TableCell, tableCellClasses, TableContainer, TableRow, ToggleButton} from "@mui/material";
|
||||
|
||||
export const StyledTableCell = styled(TableCell)(({theme}) => ({
|
||||
[`&.${tableCellClasses.head}`]: {
|
||||
backgroundColor: 'rgba(32, 55, 96, 0.7)',
|
||||
color: theme.palette.common.white,
|
||||
fontSize: 14,
|
||||
padding: 0,
|
||||
border: 0,
|
||||
height: 28,
|
||||
},
|
||||
[`&.${tableCellClasses.body}`]: {
|
||||
fontSize: 12,
|
||||
color: theme.palette.common.white,
|
||||
padding: 0,
|
||||
border: 0,
|
||||
height: 26
|
||||
},
|
||||
}));
|
||||
|
||||
export const StyledTableRow = styled(TableRow)(({theme}) => ({
|
||||
'&:nth-of-type(odd)': {
|
||||
backgroundColor: 'rgba(14, 32, 62, 0.7)',
|
||||
},
|
||||
backgroundColor: 'rgba(32, 55, 96, 0.7)',
|
||||
}));
|
||||
|
||||
export const StyledTableContainer = styled(TableContainer)(({theme}) => ({
|
||||
overflow: 'auto hidden',
|
||||
'&::-webkit-scrollbar': {
|
||||
height: 8,
|
||||
WebkitAppearance: 'none'
|
||||
},
|
||||
'&::-webkit-scrollbar-thumb': {
|
||||
borderRadius: 2,
|
||||
backgroundColor: 'rgba(91, 196, 190, 0.5)',
|
||||
},
|
||||
'&::-webkit-scrollbar-button': {
|
||||
width: 8,
|
||||
borderBottomLeftRadius: 2,
|
||||
borderBottomRightRadius: 2,
|
||||
backgroundColor: 'rgba(91, 196, 190, 1)',
|
||||
},
|
||||
'&::-webkit-scrollbar-track': {
|
||||
backgroundColor: 'rgba(12, 32, 67, 1)',
|
||||
}
|
||||
}));
|
||||
|
||||
export const StyledToggleButton = styled(ToggleButton)({
|
||||
width: 120,
|
||||
height: 24,
|
||||
backgroundColor: 'rgba(49, 135, 140, 0.29)',
|
||||
color: "white",
|
||||
'&.Mui-selected': {
|
||||
backgroundColor: 'rgba(86, 244, 231, 0.69)',
|
||||
color: "white",
|
||||
'&:hover': {
|
||||
backgroundColor: 'rgba(86, 244, 231, 0.5)',
|
||||
color: "white",
|
||||
},
|
||||
},
|
||||
'&:hover': {
|
||||
backgroundColor: 'rgba(86, 244, 231, 0.5)',
|
||||
color: "white",
|
||||
},
|
||||
'&:active': {
|
||||
backgroundColor: 'rgba(86, 244, 231, 0.69)',
|
||||
color: "white",
|
||||
},
|
||||
});
|
||||
75
src/page/Component/SummaryBarChart/chart.config.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
export default function getOptions(chartData: any) {
|
||||
if (Object.keys(chartData).length === 0) {
|
||||
return null;
|
||||
}
|
||||
const colors = ["#2760FF", "#8167F6", "#5B9BFF", "#99D66C", "#FFD160","#D680FF","#FF6860"];
|
||||
return {
|
||||
color: colors,
|
||||
grid: { top: 48, right: 20, bottom: 5, left: 10, containLabel: true },
|
||||
legend: {
|
||||
show: true,
|
||||
icon: "roundRect",
|
||||
top: 5,
|
||||
right: 20,
|
||||
padding: 0,
|
||||
itemWidth: 10,
|
||||
itemHeight: 10,
|
||||
itemGap: 15,
|
||||
height: 10,
|
||||
textStyle: {
|
||||
color: "#DFF1FE",
|
||||
fontSize: 12,
|
||||
},
|
||||
},
|
||||
xAxis: {
|
||||
type: "category",
|
||||
data: chartData.xData,
|
||||
axisLabel: {
|
||||
color: "#fff",
|
||||
fontSize: 12,
|
||||
},
|
||||
axisTick: { show: false },
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
width: 2,
|
||||
color: "#5982B2",
|
||||
},
|
||||
},
|
||||
},
|
||||
yAxis: {
|
||||
name: "单位/片",
|
||||
nameTextStyle: {
|
||||
color: "#fff",
|
||||
fontSize: 12,
|
||||
},
|
||||
type: "value",
|
||||
axisLabel: {
|
||||
color: "#fff",
|
||||
fontSize: 12,
|
||||
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",
|
||||
},
|
||||
series:chartData.series
|
||||
};
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
import React, {useState} from "react";
|
||||
import intl from "react-intl-universal";
|
||||
import '../../lanhuapp/common.css';
|
||||
import "../../lanhuapp/index.css";
|
||||
import {FormControlLabel, Switch} from "@mui/material";
|
||||
import {useAppSelector, useAppDispatch} from "../../store/hooks";
|
||||
import {selectSwitchState,ChangeSwitch} from "../../store/ChangeSwitchState";
|
||||
|
||||
function SwitchOnOff() {
|
||||
const dispatch = useAppDispatch();
|
||||
const [isSwitch, setIsSwitch] = useState(useAppSelector(selectSwitchState));
|
||||
|
||||
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
dispatch(ChangeSwitch())
|
||||
setIsSwitch(event.target.checked);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={'switchBtn'}>
|
||||
<FormControlLabel control={<Switch color={'warning'} checked={isSwitch} onChange={handleChange}/>}
|
||||
label={intl.get('AutoSwitch')}/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default SwitchOnOff;
|
||||
@@ -1,19 +0,0 @@
|
||||
import React from "react";
|
||||
import "../style/standard.css"
|
||||
|
||||
interface TabPanelProps {
|
||||
children?: React.ReactNode;
|
||||
index: number;
|
||||
value: number;
|
||||
}
|
||||
|
||||
function TabPanel(props: TabPanelProps) {
|
||||
const {children, value, index, ...other} = props;
|
||||
return (
|
||||
<div hidden={value !== index}>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default TabPanel;
|
||||
@@ -1,6 +1,4 @@
|
||||
import React from "react";
|
||||
import "./style/standard.css"
|
||||
import intl from "react-intl-universal";
|
||||
|
||||
|
||||
function ErrorPage() {
|
||||
|
||||
73
src/page/LDPage/Center/CenterDown.tsx
Normal file
@@ -0,0 +1,73 @@
|
||||
import TitleBox from "../Component/TitleBox";
|
||||
import NumberBox from "../Component/NumberBox";
|
||||
import {useAppSelector} from "./../../../store/hooks"
|
||||
import { selectAllLine } from "./../../../store/LeaderPageSlice";
|
||||
import { formatNumberWithCommas } from './../../../utils/index';
|
||||
function CenterDown() {
|
||||
interface mapInterface {
|
||||
inputRate:string,
|
||||
outputRate:string,
|
||||
input:string,
|
||||
output:string
|
||||
}
|
||||
let monthMap = {
|
||||
inputRate:'',
|
||||
outputRate:'',
|
||||
input:'',
|
||||
output:''
|
||||
}
|
||||
let lastMonthMap = {
|
||||
input:'',
|
||||
output:''
|
||||
}
|
||||
let yearMap = {
|
||||
inputRate:'',
|
||||
outputRate:'',
|
||||
input:'',
|
||||
output:''
|
||||
}
|
||||
const data = useAppSelector(selectAllLine);
|
||||
if (data.monthMap) {
|
||||
monthMap = data.monthMap as mapInterface
|
||||
lastMonthMap = data.lastMonthMap as mapInterface
|
||||
yearMap = data.yearMap as mapInterface
|
||||
}
|
||||
return(
|
||||
<div className="ld_center_down flex-row">
|
||||
<div className="ld_center_down_inner flex-col ld_left-box">
|
||||
<TitleBox title={"center_down_left"} />
|
||||
<div style={{padding:'10px 0px 0px 20px'}}>
|
||||
<div style={{width:'300px',height:'128px',marginBottom:'5px'}}>
|
||||
<NumberBox num={monthMap.inputRate?monthMap.inputRate:'-'} show={true} title={'总投入片数'} bigNum={monthMap.input?formatNumberWithCommas(monthMap.input):'-'}/>
|
||||
</div>
|
||||
<div style={{width:'300px',height:'128px'}}>
|
||||
<NumberBox num={monthMap.outputRate || '-'} show={true} title={'总生产片数'} bigNum={monthMap.output?formatNumberWithCommas(monthMap.output):'-'}/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="ld_center_down_inner flex-col ld_center-box">
|
||||
<TitleBox title={"center_down_center"} />
|
||||
<div style={{padding:'10px 0px 0px 20px'}}>
|
||||
<div style={{width:'300px',height:'128px',marginBottom:'5px'}}>
|
||||
<NumberBox num={''} show={false} title={'总投入片数'} bigNum={lastMonthMap.input?formatNumberWithCommas(lastMonthMap.input):'-'}/>
|
||||
</div>
|
||||
<div style={{width:'300px',height:'128px'}}>
|
||||
<NumberBox num={''} show={false} title={'总生产片数'} bigNum={lastMonthMap.output?formatNumberWithCommas(lastMonthMap.output):'-'}/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="ld_center_down_inner flex-col ld_right-box">
|
||||
<TitleBox title={"center_down_right"} />
|
||||
<div style={{padding:'10px 0px 0px 20px'}}>
|
||||
<div style={{width:'300px',height:'128px',marginBottom:'5px'}}>
|
||||
<NumberBox num={yearMap.inputRate || '_'} show={true} title={'总投入片数/万'} bigNum={monthMap.input?formatNumberWithCommas(monthMap.input):'-'}/>
|
||||
</div>
|
||||
<div style={{width:'300px',height:'128px'}}>
|
||||
<NumberBox num={yearMap.outputRate || '_'} show={true} title={'总生产片数/万'} bigNum={yearMap.output?formatNumberWithCommas(yearMap.output):'-'}/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default CenterDown;
|
||||
10
src/page/LDPage/Center/CenterUp.tsx
Normal file
@@ -0,0 +1,10 @@
|
||||
import LinePageBabylon from "../../../babylonjs/AllLinePageBabylon";
|
||||
function CenterUp() {
|
||||
const lineID = "1-1"
|
||||
return(
|
||||
<div className="ld_center_up">
|
||||
<LinePageBabylon modelPath={`Line${lineID}`} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default CenterUp;
|
||||
12
src/page/LDPage/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;
|
||||
27
src/page/LDPage/Component/NumberBox/index.css
Normal file
@@ -0,0 +1,27 @@
|
||||
.number_box_container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: url(../../../../../public/png/numberBox.png) no-repeat;
|
||||
background-size: 100% 100%;
|
||||
background-position: 0 0;
|
||||
margin:0 auto;
|
||||
padding: 25px 20px 20px;
|
||||
}
|
||||
.number_box_container .big_number {
|
||||
font-size:38px;
|
||||
color: #fff;
|
||||
}
|
||||
.number_box_container .big_number_title {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.number_box_container .big_number_title_left {
|
||||
font-size: 20px;
|
||||
color: #fff;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
.number_box_container .big_number_title_right {
|
||||
font-size: 18px;
|
||||
position: relative;
|
||||
top: 6px;
|
||||
left:10px;
|
||||
}
|
||||
35
src/page/LDPage/Component/NumberBox/index.tsx
Normal file
@@ -0,0 +1,35 @@
|
||||
import './index.css';
|
||||
import a_r from './../../../assets/icon/a_r.png';
|
||||
import a_g from './../../../assets/icon/a_g.png';
|
||||
interface boxProps {
|
||||
num:string | number,
|
||||
show?:boolean,
|
||||
title:string,
|
||||
lastYear?:boolean,
|
||||
bigNum:string | number
|
||||
}
|
||||
function NumberBox(props: boxProps) {
|
||||
return (
|
||||
<div className="number_box_container" style={{paddingLeft:props.lastYear?'45px':'25px'}}>
|
||||
<div className='flex-row big_number_title'>
|
||||
<div className='big_number_title_left'>{props.title}</div>
|
||||
{
|
||||
props.show?(
|
||||
<div className='big_number_title_right' style={{color:Number(props.num)>0?'#FF0000':'#00FF00'}}>
|
||||
{Number(props.num)>0?'+':''}{props.num}%
|
||||
{
|
||||
Number(props.num)>0?(
|
||||
<img src={a_r} alt="" width='5px'/>
|
||||
):(
|
||||
<img src={a_g} alt="" width='5px'/>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
):''
|
||||
}
|
||||
</div>
|
||||
<div className='big_number'>{props.bigNum}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default NumberBox;
|
||||
13
src/page/LDPage/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;
|
||||
}
|
||||
56
src/page/LDPage/Component/TitleBox/index.tsx
Normal file
@@ -0,0 +1,56 @@
|
||||
import Defect from "./../../../assets/icon/defect.png";
|
||||
import NumBar from "./../../../assets/icon/numBar.png";
|
||||
import Defe from "./../../../assets/icon/defe.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: Record,
|
||||
title: "近期数据对比",
|
||||
};
|
||||
case "left_down":
|
||||
return {
|
||||
img: NumBar,
|
||||
title: "投入产出及良品率",
|
||||
};
|
||||
case "center_down_left":
|
||||
return {
|
||||
img: Defect,
|
||||
title: "本月数据",
|
||||
};
|
||||
case "center_down_center":
|
||||
return {
|
||||
img: Defect,
|
||||
title: "上月数据",
|
||||
};
|
||||
case "center_down_right":
|
||||
return {
|
||||
img: Defect,
|
||||
title: "本年数据",
|
||||
};
|
||||
case "right_up":
|
||||
return {
|
||||
img: Defe,
|
||||
title: "缺陷情况",
|
||||
};
|
||||
default:
|
||||
return {
|
||||
img: Defect,
|
||||
title: "上年数据",
|
||||
};
|
||||
}
|
||||
};
|
||||
return (
|
||||
<div className="title_box">
|
||||
<img src={filteredTitles().img} alt="title" />
|
||||
<span>{filteredTitles().title}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
export default TitleBox;
|
||||
164
src/page/LDPage/Component/pieChart/chart.config.ts
Normal file
@@ -0,0 +1,164 @@
|
||||
function getCoordinates(startArc: number, endArc: number) {
|
||||
const posi = [
|
||||
Math.sin(startArc),
|
||||
-Math.cos(startArc),
|
||||
Math.sin(endArc),
|
||||
-Math.cos(endArc),
|
||||
];
|
||||
const dx = posi[2] - posi[0];
|
||||
const dy = posi[3] - posi[1];
|
||||
|
||||
return getLocation(dx, dy);
|
||||
}
|
||||
function getLocation(dx: number, dy: number) {
|
||||
const tanV = dx / dy;
|
||||
const directSign = Math.abs(tanV) < 1;
|
||||
const t = directSign ? tanV : 1 / tanV;
|
||||
|
||||
const sign1 = t > 0 ? 1 : -1;
|
||||
const sign2 = dx > 0 ? 1 : -1;
|
||||
const sign = directSign ? sign1 * sign2 : sign2;
|
||||
|
||||
const group1 = [0.5 - (sign * t) / 2, 0.5 + (sign * t) / 2];
|
||||
const group2 = sign > 0 ? [0, 1] : [1, 0];
|
||||
const group = [...group1, ...group2];
|
||||
const keys = directSign ? ["x", "x2", "y", "y2"] : ["y", "y2", "x", "x2"];
|
||||
|
||||
let res: { [key: string]: any } = {};
|
||||
keys.forEach((k, idx) => {
|
||||
res[k] = group[idx];
|
||||
});
|
||||
return res;
|
||||
}
|
||||
// 数据格式
|
||||
// const dataProps = [
|
||||
// {value: 14,name:'缺陷1'},
|
||||
// {value: 20,name:'缺陷2'},
|
||||
// {value: 22,name:'缺陷3'},
|
||||
// {value: 14,name:'缺陷4'},
|
||||
// {value: 30,name:'缺陷5'}
|
||||
// ]
|
||||
let rangArrValue: any[] = [];
|
||||
let dataList: any = [];
|
||||
let totalValue = 0;
|
||||
const colors = [
|
||||
"rgb(39, 96, 255)",
|
||||
"rgb(91, 155, 255)",
|
||||
"rgb(153, 214, 108)",
|
||||
"rgb(18, 255, 245)",
|
||||
"rgb(221, 177, 18)",
|
||||
];
|
||||
const getPersonnelList = async (dataProps: any) => {
|
||||
totalValue = dataProps.reduce(
|
||||
(total: any, value: any) => total + value.value,
|
||||
0
|
||||
);
|
||||
let cacheNum = 0;
|
||||
for (let i = 0; i < dataProps.length; i++) {
|
||||
const endNum = cacheNum + dataProps[i].value;
|
||||
rangArrValue.push([cacheNum, endNum]);
|
||||
cacheNum = endNum;
|
||||
}
|
||||
const angleArr = rangArrValue.map((arr) =>
|
||||
arr.map((num: any) => (num / totalValue) * Math.PI * 2)
|
||||
);
|
||||
dataList = dataProps.map((item: any, index: any) => {
|
||||
const range = getCoordinates(angleArr[index][0], angleArr[index][1]);
|
||||
const startColor = colors[index%5];
|
||||
const color = {
|
||||
type: "linear",
|
||||
x: range.x,
|
||||
x2: range.x2,
|
||||
y: range.y,
|
||||
y2: range.y2,
|
||||
colorStops: [
|
||||
{
|
||||
offset: 0,
|
||||
color: startColor, // 起始颜色
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: `${startColor.substring(0, startColor.length - 1)}, 0.2)`, // 终点颜色
|
||||
},
|
||||
],
|
||||
global: false,
|
||||
};
|
||||
|
||||
return {
|
||||
name: item.name,
|
||||
value: item.value,
|
||||
itemStyle: {
|
||||
color: color,
|
||||
},
|
||||
};
|
||||
});
|
||||
};
|
||||
export default function getOptions(dataProps: any) {
|
||||
if (dataProps.length === 0) return null;
|
||||
getPersonnelList(dataProps);
|
||||
return {
|
||||
color: colors,
|
||||
graphic: [
|
||||
{
|
||||
type: "text",
|
||||
left: "center",
|
||||
top: "44%",
|
||||
style: {
|
||||
text: totalValue,
|
||||
fill: "#fff",
|
||||
width: 150,
|
||||
height: 44,
|
||||
fontSize: 31,
|
||||
fontWeight: 400,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "text",
|
||||
left: "center",
|
||||
top: "55%",
|
||||
style: {
|
||||
text: "总数/件",
|
||||
fill: "rgba(255, 255, 255, 0.70)",
|
||||
width: 32,
|
||||
height: 16,
|
||||
fontSize: 16,
|
||||
fontWeight: 400,
|
||||
},
|
||||
},
|
||||
],
|
||||
series: [
|
||||
{
|
||||
name: "产线缺陷分类",
|
||||
type: "pie",
|
||||
radius: ["45%", "60%"],
|
||||
center: ["50%", "50%"],
|
||||
// label: {
|
||||
// formatter: "{d}%",
|
||||
// color: "#fff",
|
||||
// },
|
||||
label:{
|
||||
formatter:function(params:any){
|
||||
return `{color${params.dataIndex}|${params.percent}%}\n{style2|${params.name}}`
|
||||
},
|
||||
rich:{
|
||||
color0:{color:'rgb(39, 96, 255)',fontSize:22},
|
||||
color1:{color:'rgb(91, 155, 255)',fontSize:22},
|
||||
color2:{color:'rgb(153, 214, 108)',fontSize:22},
|
||||
color3:{color:'rgb(18, 255, 245)',fontSize:22},
|
||||
color4:{color:'rgb(221, 177, 18)',fontSize:22},
|
||||
color5:{color:'rgb(39, 96, 255)',fontSize:22},
|
||||
color6:{color:'rgb(91, 155, 255)',fontSize:22},
|
||||
color7:{color:'rgb(153, 214, 108)',fontSize:22},
|
||||
color8:{color:'rgb(18, 255, 245)',fontSize:22},
|
||||
color9:{color:'rgb(221, 177, 18)',fontSize:22},
|
||||
style2:{
|
||||
color:'#fff',
|
||||
fontSize:14
|
||||
}
|
||||
}
|
||||
},
|
||||
data: dataList,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||