Compare commits

...

17 Commits

Author SHA1 Message Date
gtz
ebe2a03023 1 2025-08-25 15:21:36 +08:00
40791bc619 改变链接位置,改成在每个页面链接 2025-03-06 08:27:31 +08:00
45c8563892 接口后面加随机数 2025-02-27 08:54:31 +08:00
288e2c8e04 消除警告信息 2025-02-21 16:03:07 +08:00
84b34d7b79 删除多余代码 2025-02-21 13:26:56 +08:00
1812afd680 2.21日版 2025-02-21 11:10:35 +08:00
128b362587 1 2024-12-06 17:22:49 +08:00
e8ca7d16ee 修改 2024-11-29 10:34:06 +08:00
1f7b867dc5 三维接口调试 2024-11-01 10:35:32 +08:00
022bf57feb 5个页面的ws接口 2024-10-29 14:38:12 +08:00
d142b16df3 1-1对接接口 2024-09-12 16:14:54 +08:00
0dcff0c256 假数据版本 2024-09-11 10:16:17 +08:00
b6fb156c2c 修改 2024-08-29 15:12:39 +08:00
2bc9908f62 line5 2024-08-27 13:26:25 +08:00
2cb5c7fcd2 line5 2024-08-27 10:48:46 +08:00
bbb7de918e 大屏样式 2024-08-19 14:44:16 +08:00
bda855430d 1 2024-08-15 08:50:17 +08:00
347 changed files with 25953 additions and 32136 deletions

25369
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -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"
},

Binary file not shown.

Binary file not shown.

View File

@@ -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
}
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 MiB

View File

@@ -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
}
]
}

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

View File

@@ -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"
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 MiB

After

Width:  |  Height:  |  Size: 8.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

BIN
public/png/numberBox.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

BIN
public/png/topTiltle.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

View File

@@ -1,3 +0,0 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:

View File

@@ -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
View 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

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 971 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 644 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 401 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 942 KiB

View File

@@ -1,3 +1,3 @@
{
"url": "india.mes.picaiba.com/api/"
"url": "192.168.8.22"
}

View File

@@ -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>
);

View File

@@ -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">&nbsp;
<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>

File diff suppressed because it is too large Load Diff

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -1,7 +0,0 @@
import intl from 'react-intl-universal';
const util = {
getMessage: () => intl.get('MESSAGE_NOT_IN_COMPONENT'),
};
export default util;

View File

@@ -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;

View File

@@ -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;

View 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
View 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

View File

@@ -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;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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;

View File

@@ -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;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View 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] },
]),
},
},
],
};
}

View 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)' },
]),
}
}
],
};
}

View File

@@ -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;

View File

@@ -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;

View 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],
// },
// ],
};
}

View 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,
},
};
}

View File

@@ -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;

View 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;
}

View 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;

View 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 };
}

View 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 };
}

View 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;
}

View 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;
}

View File

@@ -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",
},
});

View 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
};
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -1,6 +1,4 @@
import React from "react";
import "./style/standard.css"
import intl from "react-intl-universal";
function ErrorPage() {

View 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;

View 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;

View 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;

View 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;
}

View 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;

View 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;
}

View 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;

View 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,
},
],
};
}

Some files were not shown because too many files have changed in this diff Show More