diff --git a/package-lock.json b/package-lock.json index 83931df..f4b61c6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,9 @@ "antd": "^5.27.1", "chart.js": "^4.5.0", "electron-updater": "^6.3.9", - "react-chartjs-2": "^5.3.0" + "react": "^18.0.0", + "react-chartjs-2": "^5.3.0", + "react-dom": "^18.0.0" }, "devDependencies": { "@electron-toolkit/eslint-config": "^2.0.0", @@ -29,8 +31,6 @@ "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.20", "prettier": "^3.6.2", - "react": "^19.1.0", - "react-dom": "^19.1.0", "vite": "^7.0.5" } }, @@ -2038,9 +2038,9 @@ "license": "MIT" }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.49.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.49.0.tgz", - "integrity": "sha512-rlKIeL854Ed0e09QGYFlmDNbka6I3EQFw7iZuugQjMb11KMpJCLPFL4ZPbMfaEhLADEL1yx0oujGkBQ7+qW3eA==", + "version": "4.50.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.50.0.tgz", + "integrity": "sha512-lVgpeQyy4fWN5QYebtW4buT/4kn4p4IJ+kDNB4uYNT5b8c8DLJDg6titg20NIg7E8RWwdWZORW6vUFfrLyG3KQ==", "cpu": [ "arm" ], @@ -2052,9 +2052,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.49.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.49.0.tgz", - "integrity": "sha512-cqPpZdKUSQYRtLLr6R4X3sD4jCBO1zUmeo3qrWBCqYIeH8Q3KRL4F3V7XJ2Rm8/RJOQBZuqzQGWPjjvFUcYa/w==", + "version": "4.50.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.50.0.tgz", + "integrity": "sha512-2O73dR4Dc9bp+wSYhviP6sDziurB5/HCym7xILKifWdE9UsOe2FtNcM+I4xZjKrfLJnq5UR8k9riB87gauiQtw==", "cpu": [ "arm64" ], @@ -2066,9 +2066,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.49.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.49.0.tgz", - "integrity": "sha512-99kMMSMQT7got6iYX3yyIiJfFndpojBmkHfTc1rIje8VbjhmqBXE+nb7ZZP3A5skLyujvT0eIUCUsxAe6NjWbw==", + "version": "4.50.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.50.0.tgz", + "integrity": "sha512-vwSXQN8T4sKf1RHr1F0s98Pf8UPz7pS6P3LG9NSmuw0TVh7EmaE+5Ny7hJOZ0M2yuTctEsHHRTMi2wuHkdS6Hg==", "cpu": [ "arm64" ], @@ -2080,9 +2080,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.49.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.49.0.tgz", - "integrity": "sha512-y8cXoD3wdWUDpjOLMKLx6l+NFz3NlkWKcBCBfttUn+VGSfgsQ5o/yDUGtzE9HvsodkP0+16N0P4Ty1VuhtRUGg==", + "version": "4.50.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.50.0.tgz", + "integrity": "sha512-cQp/WG8HE7BCGyFVuzUg0FNmupxC+EPZEwWu2FCGGw5WDT1o2/YlENbm5e9SMvfDFR6FRhVCBePLqj0o8MN7Vw==", "cpu": [ "x64" ], @@ -2094,9 +2094,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.49.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.49.0.tgz", - "integrity": "sha512-3mY5Pr7qv4GS4ZvWoSP8zha8YoiqrU+e0ViPvB549jvliBbdNLrg2ywPGkgLC3cmvN8ya3za+Q2xVyT6z+vZqA==", + "version": "4.50.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.50.0.tgz", + "integrity": "sha512-UR1uTJFU/p801DvvBbtDD7z9mQL8J80xB0bR7DqW7UGQHRm/OaKzp4is7sQSdbt2pjjSS72eAtRh43hNduTnnQ==", "cpu": [ "arm64" ], @@ -2108,9 +2108,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.49.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.49.0.tgz", - "integrity": "sha512-C9KzzOAQU5gU4kG8DTk+tjdKjpWhVWd5uVkinCwwFub2m7cDYLOdtXoMrExfeBmeRy9kBQMkiyJ+HULyF1yj9w==", + "version": "4.50.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.50.0.tgz", + "integrity": "sha512-G/DKyS6PK0dD0+VEzH/6n/hWDNPDZSMBmqsElWnCRGrYOb2jC0VSupp7UAHHQ4+QILwkxSMaYIbQ72dktp8pKA==", "cpu": [ "x64" ], @@ -2122,9 +2122,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.49.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.49.0.tgz", - "integrity": "sha512-OVSQgEZDVLnTbMq5NBs6xkmz3AADByCWI4RdKSFNlDsYXdFtlxS59J+w+LippJe8KcmeSSM3ba+GlsM9+WwC1w==", + "version": "4.50.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.50.0.tgz", + "integrity": "sha512-u72Mzc6jyJwKjJbZZcIYmd9bumJu7KNmHYdue43vT1rXPm2rITwmPWF0mmPzLm9/vJWxIRbao/jrQmxTO0Sm9w==", "cpu": [ "arm" ], @@ -2136,9 +2136,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.49.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.49.0.tgz", - "integrity": "sha512-ZnfSFA7fDUHNa4P3VwAcfaBLakCbYaxCk0jUnS3dTou9P95kwoOLAMlT3WmEJDBCSrOEFFV0Y1HXiwfLYJuLlA==", + "version": "4.50.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.50.0.tgz", + "integrity": "sha512-S4UefYdV0tnynDJV1mdkNawp0E5Qm2MtSs330IyHgaccOFrwqsvgigUD29uT+B/70PDY1eQ3t40+xf6wIvXJyg==", "cpu": [ "arm" ], @@ -2150,9 +2150,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.49.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.49.0.tgz", - "integrity": "sha512-Z81u+gfrobVK2iV7GqZCBfEB1y6+I61AH466lNK+xy1jfqFLiQ9Qv716WUM5fxFrYxwC7ziVdZRU9qvGHkYIJg==", + "version": "4.50.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.50.0.tgz", + "integrity": "sha512-1EhkSvUQXJsIhk4msxP5nNAUWoB4MFDHhtc4gAYvnqoHlaL9V3F37pNHabndawsfy/Tp7BPiy/aSa6XBYbaD1g==", "cpu": [ "arm64" ], @@ -2164,9 +2164,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.49.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.49.0.tgz", - "integrity": "sha512-zoAwS0KCXSnTp9NH/h9aamBAIve0DXeYpll85shf9NJ0URjSTzzS+Z9evmolN+ICfD3v8skKUPyk2PO0uGdFqg==", + "version": "4.50.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.50.0.tgz", + "integrity": "sha512-EtBDIZuDtVg75xIPIK1l5vCXNNCIRM0OBPUG+tbApDuJAy9mKago6QxX+tfMzbCI6tXEhMuZuN1+CU8iDW+0UQ==", "cpu": [ "arm64" ], @@ -2178,9 +2178,9 @@ ] }, "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.49.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.49.0.tgz", - "integrity": "sha512-2QyUyQQ1ZtwZGiq0nvODL+vLJBtciItC3/5cYN8ncDQcv5avrt2MbKt1XU/vFAJlLta5KujqyHdYtdag4YEjYQ==", + "version": "4.50.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.50.0.tgz", + "integrity": "sha512-BGYSwJdMP0hT5CCmljuSNx7+k+0upweM2M4YGfFBjnFSZMHOLYR0gEEj/dxyYJ6Zc6AiSeaBY8dWOa11GF/ppQ==", "cpu": [ "loong64" ], @@ -2192,9 +2192,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.49.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.49.0.tgz", - "integrity": "sha512-k9aEmOWt+mrMuD3skjVJSSxHckJp+SiFzFG+v8JLXbc/xi9hv2icSkR3U7uQzqy+/QbbYY7iNB9eDTwrELo14g==", + "version": "4.50.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.50.0.tgz", + "integrity": "sha512-I1gSMzkVe1KzAxKAroCJL30hA4DqSi+wGc5gviD0y3IL/VkvcnAqwBf4RHXHyvH66YVHxpKO8ojrgc4SrWAnLg==", "cpu": [ "ppc64" ], @@ -2206,9 +2206,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.49.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.49.0.tgz", - "integrity": "sha512-rDKRFFIWJ/zJn6uk2IdYLc09Z7zkE5IFIOWqpuU0o6ZpHcdniAyWkwSUWE/Z25N/wNDmFHHMzin84qW7Wzkjsw==", + "version": "4.50.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.50.0.tgz", + "integrity": "sha512-bSbWlY3jZo7molh4tc5dKfeSxkqnf48UsLqYbUhnkdnfgZjgufLS/NTA8PcP/dnvct5CCdNkABJ56CbclMRYCA==", "cpu": [ "riscv64" ], @@ -2220,9 +2220,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.49.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.49.0.tgz", - "integrity": "sha512-FkkhIY/hYFVnOzz1WeV3S9Bd1h0hda/gRqvZCMpHWDHdiIHn6pqsY3b5eSbvGccWHMQ1uUzgZTKS4oGpykf8Tw==", + "version": "4.50.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.50.0.tgz", + "integrity": "sha512-LSXSGumSURzEQLT2e4sFqFOv3LWZsEF8FK7AAv9zHZNDdMnUPYH3t8ZlaeYYZyTXnsob3htwTKeWtBIkPV27iQ==", "cpu": [ "riscv64" ], @@ -2234,9 +2234,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.49.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.49.0.tgz", - "integrity": "sha512-gRf5c+A7QiOG3UwLyOOtyJMD31JJhMjBvpfhAitPAoqZFcOeK3Kc1Veg1z/trmt+2P6F/biT02fU19GGTS529A==", + "version": "4.50.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.50.0.tgz", + "integrity": "sha512-CxRKyakfDrsLXiCyucVfVWVoaPA4oFSpPpDwlMcDFQvrv3XY6KEzMtMZrA+e/goC8xxp2WSOxHQubP8fPmmjOQ==", "cpu": [ "s390x" ], @@ -2248,9 +2248,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.49.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.49.0.tgz", - "integrity": "sha512-BR7+blScdLW1h/2hB/2oXM+dhTmpW3rQt1DeSiCP9mc2NMMkqVgjIN3DDsNpKmezffGC9R8XKVOLmBkRUcK/sA==", + "version": "4.50.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.50.0.tgz", + "integrity": "sha512-8PrJJA7/VU8ToHVEPu14FzuSAqVKyo5gg/J8xUerMbyNkWkO9j2ExBho/68RnJsMGNJq4zH114iAttgm7BZVkA==", "cpu": [ "x64" ], @@ -2262,9 +2262,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.49.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.49.0.tgz", - "integrity": "sha512-hDMOAe+6nX3V5ei1I7Au3wcr9h3ktKzDvF2ne5ovX8RZiAHEtX1A5SNNk4zt1Qt77CmnbqT+upb/umzoPMWiPg==", + "version": "4.50.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.50.0.tgz", + "integrity": "sha512-SkE6YQp+CzpyOrbw7Oc4MgXFvTw2UIBElvAvLCo230pyxOLmYwRPwZ/L5lBe/VW/qT1ZgND9wJfOsdy0XptRvw==", "cpu": [ "x64" ], @@ -2275,10 +2275,24 @@ "linux" ] }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.50.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.50.0.tgz", + "integrity": "sha512-PZkNLPfvXeIOgJWA804zjSFH7fARBBCpCXxgkGDRjjAhRLOR8o0IGS01ykh5GYfod4c2yiiREuDM8iZ+pVsT+Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.49.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.49.0.tgz", - "integrity": "sha512-wkNRzfiIGaElC9kXUT+HLx17z7D0jl+9tGYRKwd8r7cUqTL7GYAvgUY++U2hK6Ar7z5Z6IRRoWC8kQxpmM7TDA==", + "version": "4.50.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.50.0.tgz", + "integrity": "sha512-q7cIIdFvWQoaCbLDUyUc8YfR3Jh2xx3unO8Dn6/TTogKjfwrax9SyfmGGK6cQhKtjePI7jRfd7iRYcxYs93esg==", "cpu": [ "arm64" ], @@ -2290,9 +2304,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.49.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.49.0.tgz", - "integrity": "sha512-gq5aW/SyNpjp71AAzroH37DtINDcX1Qw2iv9Chyz49ZgdOP3NV8QCyKZUrGsYX9Yyggj5soFiRCgsL3HwD8TdA==", + "version": "4.50.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.50.0.tgz", + "integrity": "sha512-XzNOVg/YnDOmFdDKcxxK410PrcbcqZkBmz+0FicpW5jtjKQxcW1BZJEQOF0NJa6JO7CZhett8GEtRN/wYLYJuw==", "cpu": [ "ia32" ], @@ -2304,9 +2318,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.49.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.49.0.tgz", - "integrity": "sha512-gEtqFbzmZLFk2xKh7g0Rlo8xzho8KrEFEkzvHbfUGkrgXOpZ4XagQ6n+wIZFNh1nTb8UD16J4nFSFKXYgnbdBg==", + "version": "4.50.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.50.0.tgz", + "integrity": "sha512-xMmiWRR8sp72Zqwjgtf3QbZfF1wdh8X2ABu3EaozvZcyHJeU0r+XAnXdKgs4cCAp6ORoYoCygipYP1mjmbjrsg==", "cpu": [ "x64" ], @@ -2671,9 +2685,9 @@ } }, "node_modules/antd": { - "version": "5.27.1", - "resolved": "https://registry.npmmirror.com/antd/-/antd-5.27.1.tgz", - "integrity": "sha512-jGMSdBN7hAMvPV27B4RhzZfL6n6yu8yDbo7oXrlJasaOqB7bSDPcjdEy1kXy3JPsny/Qazb1ykzRI4EfcByAPQ==", + "version": "5.27.2", + "resolved": "https://registry.npmmirror.com/antd/-/antd-5.27.2.tgz", + "integrity": "sha512-9pYRUTrumIEuulRwZijhcnL6ScBZ1X6Y3iJa67VyNhEZAiXtENA7AtggsnqdVclQIm0WL4ky76qUdWrVhDWF3g==", "license": "MIT", "dependencies": { "@ant-design/colors": "^7.2.1", @@ -3585,9 +3599,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001737", - "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001737.tgz", - "integrity": "sha512-BiloLiXtQNrY5UyF0+1nSJLXUENuhka2pzy2Fx5pGxqavdrxSCW4U6Pn/PoG3Efspi2frRbHpBV2XsrPE6EDlw==", + "version": "1.0.30001739", + "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001739.tgz", + "integrity": "sha512-y+j60d6ulelrNSwpPyrHdl+9mJnQzHBr08xm48Qno0nSk4h3Qojh+ziv2qE6rXf4k3tadF4o1J/1tAbVm1NtnA==", "dev": true, "funding": [ { @@ -4071,9 +4085,9 @@ } }, "node_modules/dayjs": { - "version": "1.11.15", - "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.15.tgz", - "integrity": "sha512-MC+DfnSWiM9APs7fpiurHGCoeIx0Gdl6QZBy+5lu8MbYKN5FZEXqOgrundfibdfhGZ15o9hzmZ2xJjZnbvgKXQ==", + "version": "1.11.18", + "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.18.tgz", + "integrity": "sha512-zFBQ7WFRvVRhKcWoUh+ZA1g2HVgUbsZm9sbddh8EC5iv93sui8DVVz1Npvz+r6meo9VKfa8NyLWBsQK1VvIKPA==", "license": "MIT" }, "node_modules/debug": { @@ -6748,7 +6762,6 @@ "version": "4.0.0", "resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, "license": "MIT" }, "node_modules/js-yaml": { @@ -7041,7 +7054,6 @@ "version": "1.4.0", "resolved": "https://registry.npmmirror.com/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, "license": "MIT", "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" @@ -8758,10 +8770,13 @@ } }, "node_modules/react": { - "version": "19.1.1", - "resolved": "https://registry.npmmirror.com/react/-/react-19.1.1.tgz", - "integrity": "sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==", + "version": "18.3.1", + "resolved": "https://registry.npmmirror.com/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, "engines": { "node": ">=0.10.0" } @@ -8777,15 +8792,16 @@ } }, "node_modules/react-dom": { - "version": "19.1.1", - "resolved": "https://registry.npmmirror.com/react-dom/-/react-dom-19.1.1.tgz", - "integrity": "sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw==", + "version": "18.3.1", + "resolved": "https://registry.npmmirror.com/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "license": "MIT", "dependencies": { - "scheduler": "^0.26.0" + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" }, "peerDependencies": { - "react": "^19.1.1" + "react": "^18.3.1" } }, "node_modules/react-is": { @@ -9053,9 +9069,9 @@ } }, "node_modules/rollup": { - "version": "4.49.0", - "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.49.0.tgz", - "integrity": "sha512-3IVq0cGJ6H7fKXXEdVt+RcYvRCt8beYY9K1760wGQwSAHZcS9eot1zDG5axUbcp/kWRi5zKIIDX8MoKv/TzvZA==", + "version": "4.50.0", + "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.50.0.tgz", + "integrity": "sha512-/Zl4D8zPifNmyGzJS+3kVoyXeDeT/GrsJM94sACNg9RtUE0hrHa1bNPtRSrfHTMH5HjRzce6K7rlTh3Khiw+pw==", "dev": true, "license": "MIT", "dependencies": { @@ -9069,26 +9085,27 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.49.0", - "@rollup/rollup-android-arm64": "4.49.0", - "@rollup/rollup-darwin-arm64": "4.49.0", - "@rollup/rollup-darwin-x64": "4.49.0", - "@rollup/rollup-freebsd-arm64": "4.49.0", - "@rollup/rollup-freebsd-x64": "4.49.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.49.0", - "@rollup/rollup-linux-arm-musleabihf": "4.49.0", - "@rollup/rollup-linux-arm64-gnu": "4.49.0", - "@rollup/rollup-linux-arm64-musl": "4.49.0", - "@rollup/rollup-linux-loongarch64-gnu": "4.49.0", - "@rollup/rollup-linux-ppc64-gnu": "4.49.0", - "@rollup/rollup-linux-riscv64-gnu": "4.49.0", - "@rollup/rollup-linux-riscv64-musl": "4.49.0", - "@rollup/rollup-linux-s390x-gnu": "4.49.0", - "@rollup/rollup-linux-x64-gnu": "4.49.0", - "@rollup/rollup-linux-x64-musl": "4.49.0", - "@rollup/rollup-win32-arm64-msvc": "4.49.0", - "@rollup/rollup-win32-ia32-msvc": "4.49.0", - "@rollup/rollup-win32-x64-msvc": "4.49.0", + "@rollup/rollup-android-arm-eabi": "4.50.0", + "@rollup/rollup-android-arm64": "4.50.0", + "@rollup/rollup-darwin-arm64": "4.50.0", + "@rollup/rollup-darwin-x64": "4.50.0", + "@rollup/rollup-freebsd-arm64": "4.50.0", + "@rollup/rollup-freebsd-x64": "4.50.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.50.0", + "@rollup/rollup-linux-arm-musleabihf": "4.50.0", + "@rollup/rollup-linux-arm64-gnu": "4.50.0", + "@rollup/rollup-linux-arm64-musl": "4.50.0", + "@rollup/rollup-linux-loongarch64-gnu": "4.50.0", + "@rollup/rollup-linux-ppc64-gnu": "4.50.0", + "@rollup/rollup-linux-riscv64-gnu": "4.50.0", + "@rollup/rollup-linux-riscv64-musl": "4.50.0", + "@rollup/rollup-linux-s390x-gnu": "4.50.0", + "@rollup/rollup-linux-x64-gnu": "4.50.0", + "@rollup/rollup-linux-x64-musl": "4.50.0", + "@rollup/rollup-openharmony-arm64": "4.50.0", + "@rollup/rollup-win32-arm64-msvc": "4.50.0", + "@rollup/rollup-win32-ia32-msvc": "4.50.0", + "@rollup/rollup-win32-x64-msvc": "4.50.0", "fsevents": "~2.3.2" } }, @@ -9192,10 +9209,13 @@ "license": "ISC" }, "node_modules/scheduler": { - "version": "0.26.0", - "resolved": "https://registry.npmmirror.com/scheduler/-/scheduler-0.26.0.tgz", - "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", - "license": "MIT" + "version": "0.23.2", + "resolved": "https://registry.npmmirror.com/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } }, "node_modules/scroll-into-view-if-needed": { "version": "3.1.0", @@ -10236,9 +10256,9 @@ } }, "node_modules/vite": { - "version": "7.1.3", - "resolved": "https://registry.npmmirror.com/vite/-/vite-7.1.3.tgz", - "integrity": "sha512-OOUi5zjkDxYrKhTV3V7iKsoS37VUM7v40+HuwEmcrsf11Cdx9y3DIr2Px6liIcZFwt3XSRpQvFpL3WVy7ApkGw==", + "version": "7.1.4", + "resolved": "https://registry.npmmirror.com/vite/-/vite-7.1.4.tgz", + "integrity": "sha512-X5QFK4SGynAeeIt+A7ZWnApdUyHYm+pzv/8/A57LqSGcI88U6R6ipOs3uCesdc6yl7nl+zNO0t8LmqAdXcQihw==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 4ab2316..600ed33 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,9 @@ "antd": "^5.27.1", "chart.js": "^4.5.0", "electron-updater": "^6.3.9", - "react-chartjs-2": "^5.3.0" + "react": "^18.0.0", + "react-chartjs-2": "^5.3.0", + "react-dom": "^18.0.0" }, "devDependencies": { "@electron-toolkit/eslint-config": "^2.0.0", @@ -38,8 +40,6 @@ "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.20", "prettier": "^3.6.2", - "react": "^19.1.0", - "react-dom": "^19.1.0", "vite": "^7.0.5" } } diff --git a/src/main/index.js b/src/main/index.js index 7eb5d25..2165aee 100644 --- a/src/main/index.js +++ b/src/main/index.js @@ -1,10 +1,9 @@ -import { app, shell, BrowserWindow, ipcMain } from 'electron' +import { app, shell, BrowserWindow } from 'electron' import { join } from 'path' import { electronApp, optimizer, is } from '@electron-toolkit/utils' import icon from '../../resources/icon.png?asset' - +import { registerIpRouter } from './ipcRouter' function createWindow() { - // Create the browser window. const mainWindow = new BrowserWindow({ width: 1440, height: 960, @@ -26,8 +25,6 @@ function createWindow() { return { action: 'deny' } }) - // HMR for renderer base on electron-vite cli. - // Load the remote URL for development or the local html file for production. if (is.dev && process.env['ELECTRON_RENDERER_URL']) { mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL']) } else { @@ -35,40 +32,23 @@ function createWindow() { } } -// This method will be called when Electron has finished -// initialization and is ready to create browser windows. -// Some APIs can only be used after this event occurs. app.whenReady().then(() => { - // Set app user model id for windows electronApp.setAppUserModelId('com.electron') - // Default open or close DevTools by F12 in development - // and ignore CommandOrControl + R in production. - // see https://github.com/alex8088/electron-toolkit/tree/master/packages/utils app.on('browser-window-created', (_, window) => { optimizer.watchWindowShortcuts(window) }) - - // IPC test - ipcMain.on('ping', () => console.log('pong')) - + // IPC处理函数注册 + registerIpRouter() createWindow() app.on('activate', function () { - // On macOS it's common to re-create a window in the app when the - // dock icon is clicked and there are no other windows open. if (BrowserWindow.getAllWindows().length === 0) createWindow() }) }) -// Quit when all windows are closed, except on macOS. There, it's common -// for applications and their menu bar to stay active until the user quits -// explicitly with Cmd + Q. app.on('window-all-closed', () => { if (process.platform !== 'darwin') { app.quit() } }) - -// In this file you can include the rest of your app's specific main process -// code. You can also put them in separate files and require them here. diff --git a/src/main/ipcRouter.js b/src/main/ipcRouter.js new file mode 100644 index 0000000..3c05edd --- /dev/null +++ b/src/main/ipcRouter.js @@ -0,0 +1,133 @@ +import { ipcMain } from 'electron' +import dgram from 'dgram' +import net from 'net' +import { IPC_EVENT } from '../renderer/src/common/ipcEvents.js' +import fs from 'fs' +// 全局保存所有TCP连接 +const tcpClients = new Map() +export function registerIpRouter() { + ipcMain.on(IPC_EVENT.DEVICE_SEARCH, searchDevice) // 设备搜索 + ipcMain.on(IPC_EVENT.DEVICE_CONNECT, connectDevice) // 设备连接 + ipcMain.on(IPC_EVENT.DEVICE_DISCONNECT, disconnectDevice) // 设备断开 +} + +const searchDevice = (event) => { + const message = Buffer.from(JSON.stringify({ command: 'name', type: 'get' })) + const PORT = 2230 + const BROADCAST_ADDR = '255.255.255.255' + const udpClient = dgram.createSocket('udp4') + + let timer = null + const resultMap = new Map() + + udpClient.bind(() => { + udpClient.setBroadcast(true) + udpClient.send(message, 0, message.length, PORT, BROADCAST_ADDR, (err) => { + if (err) { + console.error('UDP send failed', err) + udpClient.close() + } else { + console.log('UDP send successful') + } + }) + }) + + udpClient.on('message', (msg, rinfo) => { + try { + // 以 IP 为 key,自动去重 + resultMap.set(rinfo.address, { + from: rinfo.address, + data: msg.toString() + }) + } catch (e) { + console.error('parse UDP message failed:', e) + } + // 每收到一条消息就重置定时器 + if (timer) clearTimeout(timer) + timer = setTimeout(() => { + udpClient.close() + console.log('UDP socket closed after timeout') + // 关闭后统一回复所有结果(已去重) + event.reply && event.reply(IPC_EVENT.DEVICE_SEARCH_REPLY, Array.from(resultMap.values())) + }, 1000) // 1秒内没有新消息就关闭 + }) + + udpClient.on('error', (err) => { + console.error('UDP error:', err) + udpClient.close() + // 出错时也可以回复已收到的内容 + event.reply && event.reply(IPC_EVENT.DEVICE_SEARCH_REPLY, Array.from(resultMap.values())) + }) +} + +const connectDevice = (event, { ip, port }) => { + if (!ip || !port) { + event.reply(IPC_EVENT.DEVICE_CONNECT_REPLY, { success: false, error: '参数缺失' }) + return + } + if (tcpClients.has(ip)) { + event.reply(IPC_EVENT.DEVICE_CONNECT_REPLY, { success: false, error: '已连接' }) + return + } + const client = new net.Socket() + client.connect(Number(port), ip, () => { + event.reply(IPC_EVENT.DEVICE_CONNECT_REPLY, { success: true, ip }) + tcpClients.set(ip, client) + }) + + let buffer = '' + + client.on('data', (data) => { + buffer += data.toString() + let index + while ((index = buffer.indexOf('\n')) !== -1) { + const line = buffer.slice(0, index) + buffer = buffer.slice(index + 1) + if (!line.trim()) continue + let msg + try { + msg = JSON.parse(line) + console.log(msg.command) + } catch (e) { + console.error('TCP data parse error:', e) + fs.appendFileSync('error_log.txt', line + '\n') + continue + } + if (!msg || !msg.command) { + console.log('invalid msg format:', msg) + continue + } + switch (msg.command) { + case 'result': + event.sender.send(IPC_EVENT.SENSOR_DATA, { ip, ...msg }) + break + case 'image': + event.sender.send(IPC_EVENT.IMAGE_DATA, { ip, ...msg }) + break + case 'heartbeat': + break + default: + console.warn('unknow command type:', msg.command) + } + } + }) + client.on('error', (err) => { + event.reply(IPC_EVENT.DEVICE_CONNECT_REPLY, { success: false, error: err.message }) + client.destroy() + tcpClients.delete(ip) + }) + client.on('close', () => { + tcpClients.delete(ip) + }) +} + +const disconnectDevice = (event, { ip }) => { + const client = tcpClients.get(ip) + if (client) { + client.destroy() + tcpClients.delete(ip) + event.reply(IPC_EVENT.DEVICE_DISCONNECT_REPLY, { success: true }) + } else { + event.reply(IPC_EVENT.DEVICE_DISCONNECT_REPLY, { success: false, error: '未连接' }) + } +} diff --git a/src/preload/index.js b/src/preload/index.js index 8d62cb9..122fde5 100644 --- a/src/preload/index.js +++ b/src/preload/index.js @@ -1,12 +1,8 @@ import { contextBridge } from 'electron' import { electronAPI } from '@electron-toolkit/preload' -// Custom APIs for renderer const api = {} -// Use `contextBridge` APIs to expose Electron APIs to -// renderer only if context isolation is enabled, otherwise -// just add to the DOM global. if (process.contextIsolated) { try { contextBridge.exposeInMainWorld('electron', electronAPI) diff --git a/src/renderer/src/common/ipcEvents.js b/src/renderer/src/common/ipcEvents.js new file mode 100644 index 0000000..3e2263d --- /dev/null +++ b/src/renderer/src/common/ipcEvents.js @@ -0,0 +1,13 @@ +export const IPC_EVENT = { + //设备相关 + DEVICE_SEARCH: 'device:search', + DEVICE_SEARCH_REPLY: 'device:search:reply', + DEVICE_CONNECT: 'device:connect', + DEVICE_CONNECT_REPLY: 'device:connect:reply', + DEVICE_DISCONNECT: 'device:disconnect', + DEVICE_DISCONNECT_REPLY: 'device:disconnect:reply', + + SENSOR_DATA: 'sensor:data', // 传感器数据 + IMAGE_DATA: 'image:data', // 图像数据 + HEARTBEAT: 'heartbeat' // 心跳包(如需推送) +} diff --git a/src/renderer/src/components/ImageCollection/ImageCollection.jsx b/src/renderer/src/components/ImageCollection/ImageCollection.jsx index 8d9f702..8f7a24f 100644 --- a/src/renderer/src/components/ImageCollection/ImageCollection.jsx +++ b/src/renderer/src/components/ImageCollection/ImageCollection.jsx @@ -1,7 +1,40 @@ -import React from 'react' +import { useEffect, useState } from 'react' +import { IPC_EVENT } from '../../common/ipcEvents' -function ImageCollection() { - return
ImageCollection
+function ImagePreview() { + const [imgSrc, setImgSrc] = useState(null) + const [timestamp, setTimestamp] = useState(null) + + useEffect(() => { + // console.log('test') + const handler = (event, data) => { + // data.values.image 是 base64 字符串 + console.log(data) + setImgSrc(`data:image/png;base64,${data.values.image}`) + setTimestamp(data.values.timestamp) + } + window.electron.ipcRenderer.on(IPC_EVENT.IMAGE_DATA, handler) + return () => { + window.electron.ipcRenderer.removeListener(IPC_EVENT.IMAGE_DATA, handler) + } + }, []) + + return ( +
+ {imgSrc ? ( + <> + 设备图像 +
{timestamp}
+ + ) : ( +
暂无图像数据
+ )} +
+ ) } -export default ImageCollection +export default ImagePreview diff --git a/src/renderer/src/components/SiderHeader/SiderHeader.jsx b/src/renderer/src/components/SiderHeader/SiderHeader.jsx index 6d9f4fc..2352f84 100644 --- a/src/renderer/src/components/SiderHeader/SiderHeader.jsx +++ b/src/renderer/src/components/SiderHeader/SiderHeader.jsx @@ -1,6 +1,7 @@ +import { useState, useEffect } from 'react' import styles from './SiderHeader.module.css' -import { Flex } from 'antd' -import { Select, Button, Input } from 'antd' +import { Flex, Select, Button, Input, Spin, message } from 'antd' +import { IPC_EVENT } from '../../common/ipcEvents.js' import { VideoCameraFilled, GoldFilled, @@ -13,6 +14,93 @@ import MeasurementPointSetting from '../MeasurementPointSetting/MeasurementPoint import PropTypes from 'prop-types' function SiderHeader({ showSystemSettings = true }) { + const [searching, setSearching] = useState(false) + const [deviceList, setDeviceList] = useState([]) + const [selectedDevice, setSelectedDevice] = useState(undefined) + const [devicePort, setDevicePort] = useState('2230') + const [connected, setConnected] = useState(null) // 保存已连接设备IP + + // 监听设备搜索结果 + useEffect(() => { + const handler = (event, results) => { + setSearching(false) + if (Array.isArray(results) && results.length > 0) { + const ips = results.map((item) => item.from) + setDeviceList(ips.map((ip) => ({ value: ip, label: ip }))) + message.success(`发现${ips.length}台设备`) + } else { + setDeviceList([]) + message.warning('未发现设备') + } + } + window.electron.ipcRenderer.on(IPC_EVENT.DEVICE_SEARCH_REPLY, handler) + return () => { + window.electron.ipcRenderer.removeListener(IPC_EVENT.DEVICE_SEARCH_REPLY, handler) + } + }, []) + + // 监听设备连接/断开结果 + useEffect(() => { + const connectHandler = (event, result) => { + if (result.success) { + setConnected(result.ip) + message.success('设备连接成功') + } else { + setConnected(null) + message.error('设备连接失败: ' + (result.error || '未知错误')) + } + } + const disconnectHandler = (event, result) => { + setConnected(null) + if (result.success) { + message.success('设备已断开') + } else { + message.error('断开失败: ' + (result.error || '未知错误')) + } + } + window.electron.ipcRenderer.on(IPC_EVENT.DEVICE_CONNECT_REPLY, connectHandler) + window.electron.ipcRenderer.on(IPC_EVENT.DEVICE_DISCONNECT_REPLY, disconnectHandler) + return () => { + window.electron.ipcRenderer.removeListener(IPC_EVENT.DEVICE_CONNECT_REPLY, connectHandler) + window.electron.ipcRenderer.removeListener( + IPC_EVENT.DEVICE_DISCONNECT_REPLY, + disconnectHandler + ) + } + }, []) + + // 搜索设备 + const handleSearchDevice = () => { + setSearching(true) + setDeviceList([]) + setSelectedDevice(undefined) + window.electron.ipcRenderer.send(IPC_EVENT.DEVICE_SEARCH) + } + + // 连接/断开设备 + const handleConnectOrDisconnect = () => { + if (connected) { + // 已连接,断开 + window.electron.ipcRenderer.send(IPC_EVENT.DEVICE_DISCONNECT, { ip: connected }) + } else { + // 未连接,连接 + if (!selectedDevice || !devicePort) { + message.error('请选择设备并填写端口') + return + } + window.electron.ipcRenderer.send(IPC_EVENT.DEVICE_CONNECT, { + ip: selectedDevice, + port: devicePort + }) + } + } + + // 除断开连接按钮外,其他UI是否禁用 + const uiDisabled = !!connected + + // 调试信息 + console.log('connected:', connected, 'uiDisabled:', uiDisabled) + return ( @@ -24,21 +112,47 @@ function SiderHeader({ showSystemSettings = true }) { 设备列表: - : '无设备'} + disabled={searching || uiDisabled} + /> 设备端口: - + setDevicePort(e.target.value)} + disabled={uiDisabled} + /> - - diff --git a/src/renderer/src/main.jsx b/src/renderer/src/main.jsx index 9318a70..4a6f3a3 100644 --- a/src/renderer/src/main.jsx +++ b/src/renderer/src/main.jsx @@ -1,4 +1,3 @@ -import { StrictMode } from 'react' import { createRoot } from 'react-dom/client' import App from './App' import 'antd/dist/reset.css' @@ -8,8 +7,6 @@ import { ConfigProvider } from 'antd' import './assets/base.css' createRoot(document.getElementById('root')).render( - - - + )