5 Commits be61ed31d3 ... 558fb129cc

Author SHA1 Message Date
  fbw 558fb129cc 增加照片回显 1 week ago
  fbw 756a0bb52c test前 2 weeks ago
  fan 57719399c9 增加访客人员根据是否有工号判断照片更新逻辑 3 weeks ago
  fan ea663cab6d 上传照片增加时间戳,每次绑卡施工人员更新照片,登记记录增加领队人员带时间戳照片 3 weeks ago
  fan b23e75805b 每次登记已绑定部门信息保持 3 weeks ago

+ 369 - 44
package-lock.json

@@ -1386,6 +1386,155 @@
       "integrity": "sha1-pTUV2yXYA4N0OBtzryC7Ty5QjYc=",
       "dev": true
     },
+    "@tensorflow-models/body-pix": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmmirror.com/@tensorflow-models/body-pix/-/body-pix-2.2.1.tgz",
+      "integrity": "sha512-JeZHcpVMR0mW2znmF0FpZ0f7zpSY7c6+A7FBOmcIyZupTkXmG3MwGGqFPsVjRBwfqaKa4qYCJd7Svqo6rMzJYw=="
+    },
+    "@tensorflow/tfjs": {
+      "version": "4.22.0",
+      "resolved": "https://registry.npmmirror.com/@tensorflow/tfjs/-/tfjs-4.22.0.tgz",
+      "integrity": "sha512-0TrIrXs6/b7FLhLVNmfh8Sah6JgjBPH4mZ8JGb7NU6WW+cx00qK5BcAZxw7NCzxj6N8MRAIfHq+oNbPUNG5VAg==",
+      "requires": {
+        "@tensorflow/tfjs-backend-cpu": "4.22.0",
+        "@tensorflow/tfjs-backend-webgl": "4.22.0",
+        "@tensorflow/tfjs-converter": "4.22.0",
+        "@tensorflow/tfjs-core": "4.22.0",
+        "@tensorflow/tfjs-data": "4.22.0",
+        "@tensorflow/tfjs-layers": "4.22.0",
+        "argparse": "^1.0.10",
+        "chalk": "^4.1.0",
+        "core-js": "3.29.1",
+        "regenerator-runtime": "^0.13.5",
+        "yargs": "^16.0.3"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "4.3.0",
+          "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz",
+          "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+          "requires": {
+            "color-convert": "^2.0.1"
+          }
+        },
+        "chalk": {
+          "version": "4.1.2",
+          "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz",
+          "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "color-name": {
+          "version": "1.1.4",
+          "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz",
+          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+        },
+        "core-js": {
+          "version": "3.29.1",
+          "resolved": "https://registry.npmmirror.com/core-js/-/core-js-3.29.1.tgz",
+          "integrity": "sha512-+jwgnhg6cQxKYIIjGtAHq2nwUOolo9eoFZ4sHfUH09BLXBgxnH4gA0zEd+t+BO2cNB8idaBtZFcFTRjQJRJmAw=="
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
+        },
+        "supports-color": {
+          "version": "7.2.0",
+          "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz",
+          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        }
+      }
+    },
+    "@tensorflow/tfjs-backend-cpu": {
+      "version": "4.22.0",
+      "resolved": "https://registry.npmmirror.com/@tensorflow/tfjs-backend-cpu/-/tfjs-backend-cpu-4.22.0.tgz",
+      "integrity": "sha512-1u0FmuLGuRAi8D2c3cocHTASGXOmHc/4OvoVDENJayjYkS119fcTcQf4iHrtLthWyDIPy3JiPhRrZQC9EwnhLw==",
+      "requires": {
+        "@types/seedrandom": "^2.4.28",
+        "seedrandom": "^3.0.5"
+      }
+    },
+    "@tensorflow/tfjs-backend-webgl": {
+      "version": "4.22.0",
+      "resolved": "https://registry.npmmirror.com/@tensorflow/tfjs-backend-webgl/-/tfjs-backend-webgl-4.22.0.tgz",
+      "integrity": "sha512-H535XtZWnWgNwSzv538czjVlbJebDl5QTMOth4RXr2p/kJ1qSIXE0vZvEtO+5EC9b00SvhplECny2yDewQb/Yg==",
+      "requires": {
+        "@tensorflow/tfjs-backend-cpu": "4.22.0",
+        "@types/offscreencanvas": "~2019.3.0",
+        "@types/seedrandom": "^2.4.28",
+        "seedrandom": "^3.0.5"
+      }
+    },
+    "@tensorflow/tfjs-converter": {
+      "version": "4.22.0",
+      "resolved": "https://registry.npmmirror.com/@tensorflow/tfjs-converter/-/tfjs-converter-4.22.0.tgz",
+      "integrity": "sha512-PT43MGlnzIo+YfbsjM79Lxk9lOq6uUwZuCc8rrp0hfpLjF6Jv8jS84u2jFb+WpUeuF4K33ZDNx8CjiYrGQ2trQ=="
+    },
+    "@tensorflow/tfjs-core": {
+      "version": "4.22.0",
+      "resolved": "https://registry.npmmirror.com/@tensorflow/tfjs-core/-/tfjs-core-4.22.0.tgz",
+      "integrity": "sha512-LEkOyzbknKFoWUwfkr59vSB68DMJ4cjwwHgicXN0DUi3a0Vh1Er3JQqCI1Hl86GGZQvY8ezVrtDIvqR1ZFW55A==",
+      "requires": {
+        "@types/long": "^4.0.1",
+        "@types/offscreencanvas": "~2019.7.0",
+        "@types/seedrandom": "^2.4.28",
+        "@webgpu/types": "0.1.38",
+        "long": "4.0.0",
+        "node-fetch": "~2.6.1",
+        "seedrandom": "^3.0.5"
+      },
+      "dependencies": {
+        "@types/offscreencanvas": {
+          "version": "2019.7.3",
+          "resolved": "https://registry.npmmirror.com/@types/offscreencanvas/-/offscreencanvas-2019.7.3.tgz",
+          "integrity": "sha512-ieXiYmgSRXUDeOntE1InxjWyvEelZGP63M+cGuquuRLuIKKT1osnkXjxev9B7d1nXSug5vpunx+gNlbVxMlC9A=="
+        }
+      }
+    },
+    "@tensorflow/tfjs-data": {
+      "version": "4.22.0",
+      "resolved": "https://registry.npmmirror.com/@tensorflow/tfjs-data/-/tfjs-data-4.22.0.tgz",
+      "integrity": "sha512-dYmF3LihQIGvtgJrt382hSRH4S0QuAp2w1hXJI2+kOaEqo5HnUPG0k5KA6va+S1yUhx7UBToUKCBHeLHFQRV4w==",
+      "requires": {
+        "@types/node-fetch": "^2.1.2",
+        "node-fetch": "~2.6.1",
+        "string_decoder": "^1.3.0"
+      },
+      "dependencies": {
+        "safe-buffer": {
+          "version": "5.2.1",
+          "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz",
+          "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
+        },
+        "string_decoder": {
+          "version": "1.3.0",
+          "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.3.0.tgz",
+          "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+          "requires": {
+            "safe-buffer": "~5.2.0"
+          }
+        }
+      }
+    },
+    "@tensorflow/tfjs-layers": {
+      "version": "4.22.0",
+      "resolved": "https://registry.npmmirror.com/@tensorflow/tfjs-layers/-/tfjs-layers-4.22.0.tgz",
+      "integrity": "sha512-lybPj4ZNj9iIAPUj7a8ZW1hg8KQGfqWLlCZDi9eM/oNKCCAgchiyzx8OrYoWmRrB+AM6VNEeIT+2gZKg5ReihA=="
+    },
     "@types/body-parser": {
       "version": "1.19.2",
       "resolved": "https://registry.npmmirror.com/@types/body-parser/download/@types/body-parser-1.19.2.tgz",
@@ -1463,6 +1612,11 @@
       "integrity": "sha1-l+3JA36gw4WFMgsolk3eOznkZg0=",
       "dev": true
     },
+    "@types/long": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmmirror.com/@types/long/-/long-4.0.2.tgz",
+      "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA=="
+    },
     "@types/mime": {
       "version": "1.3.2",
       "resolved": "https://registry.npmmirror.com/@types/mime/download/@types/mime-1.3.2.tgz",
@@ -1484,8 +1638,30 @@
     "@types/node": {
       "version": "17.0.10",
       "resolved": "https://registry.npmmirror.com/@types/node/download/@types/node-17.0.10.tgz",
-      "integrity": "sha512-S/3xB4KzyFxYGCppyDt68yzBU9ysL88lSdIah4D6cptdcltc4NCPCAMc0+PCpg/lLIyC7IPvj2Z52OJWeIUkog==",
-      "dev": true
+      "integrity": "sha512-S/3xB4KzyFxYGCppyDt68yzBU9ysL88lSdIah4D6cptdcltc4NCPCAMc0+PCpg/lLIyC7IPvj2Z52OJWeIUkog=="
+    },
+    "@types/node-fetch": {
+      "version": "2.6.12",
+      "resolved": "https://registry.npmmirror.com/@types/node-fetch/-/node-fetch-2.6.12.tgz",
+      "integrity": "sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==",
+      "requires": {
+        "@types/node": "*",
+        "form-data": "^4.0.0"
+      },
+      "dependencies": {
+        "form-data": {
+          "version": "4.0.3",
+          "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.3.tgz",
+          "integrity": "sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==",
+          "requires": {
+            "asynckit": "^0.4.0",
+            "combined-stream": "^1.0.8",
+            "es-set-tostringtag": "^2.1.0",
+            "hasown": "^2.0.2",
+            "mime-types": "^2.1.12"
+          }
+        }
+      }
     },
     "@types/normalize-package-data": {
       "version": "2.4.1",
@@ -1493,6 +1669,11 @@
       "integrity": "sha1-0zV0eaD9/dWQf+Z+F+CoXJBuEwE=",
       "dev": true
     },
+    "@types/offscreencanvas": {
+      "version": "2019.3.0",
+      "resolved": "https://registry.npmmirror.com/@types/offscreencanvas/-/offscreencanvas-2019.3.0.tgz",
+      "integrity": "sha512-esIJx9bQg+QYF0ra8GnvfianIY8qWB0GBx54PK5Eps6m+xTj86KLavHv6qDhzKcu5UUOgNfJ2pWaIIV7TRUd9Q=="
+    },
     "@types/q": {
       "version": "1.5.5",
       "resolved": "https://registry.npmmirror.com/@types/q/download/@types/q-1.5.5.tgz",
@@ -1511,6 +1692,11 @@
       "integrity": "sha1-zWZ7z90CUhOq+3ylkVqTJZCs3Nw=",
       "dev": true
     },
+    "@types/seedrandom": {
+      "version": "2.4.34",
+      "resolved": "https://registry.npmmirror.com/@types/seedrandom/-/seedrandom-2.4.34.tgz",
+      "integrity": "sha512-ytDiArvrn/3Xk6/vtylys5tlY6eo7Ane0hvcx++TKo6RxQXuVfW0AF/oeWqAj9dN29SyhtawuXstgmPlwNcv/A=="
+    },
     "@types/serve-static": {
       "version": "1.13.10",
       "resolved": "https://registry.npmmirror.com/@types/serve-static/download/@types/serve-static-1.13.10.tgz",
@@ -2328,6 +2514,11 @@
         "@xtuc/long": "4.2.2"
       }
     },
+    "@webgpu/types": {
+      "version": "0.1.38",
+      "resolved": "https://registry.npmmirror.com/@webgpu/types/-/types-0.1.38.tgz",
+      "integrity": "sha512-7LrhVKz2PRh+DD7+S+PVaFd5HxaWQvoMqBbsV9fNJO1pjUs1P8bM2vQVNfk+3URTqbuTI7gkXi0rfsN0IadoBA=="
+    },
     "@xtuc/ieee754": {
       "version": "1.2.0",
       "resolved": "https://registry.nlark.com/@xtuc/ieee754/download/@xtuc/ieee754-1.2.0.tgz",
@@ -2514,7 +2705,6 @@
       "version": "1.0.10",
       "resolved": "https://registry.nlark.com/argparse/download/argparse-1.0.10.tgz",
       "integrity": "sha1-vNZ5HqWuCXJeF+WtmIE0zUCz2RE=",
-      "dev": true,
       "requires": {
         "sprintf-js": "~1.0.2"
       }
@@ -2670,8 +2860,7 @@
     "asynckit": {
       "version": "0.4.0",
       "resolved": "https://registry.nlark.com/asynckit/download/asynckit-0.4.0.tgz",
-      "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
-      "dev": true
+      "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
     },
     "atob": {
       "version": "2.1.2",
@@ -3302,6 +3491,22 @@
         "get-intrinsic": "^1.0.2"
       }
     },
+    "call-bind-apply-helpers": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+      "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+      "requires": {
+        "es-errors": "^1.3.0",
+        "function-bind": "^1.1.2"
+      },
+      "dependencies": {
+        "function-bind": {
+          "version": "1.1.2",
+          "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz",
+          "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="
+        }
+      }
+    },
     "call-me-maybe": {
       "version": "1.0.1",
       "resolved": "https://registry.npmmirror.com/call-me-maybe/download/call-me-maybe-1.0.1.tgz",
@@ -3761,7 +3966,6 @@
       "version": "1.0.8",
       "resolved": "https://registry.nlark.com/combined-stream/download/combined-stream-1.0.8.tgz",
       "integrity": "sha1-w9RaizT9cwYxoRCoolIGgrMdWn8=",
-      "dev": true,
       "requires": {
         "delayed-stream": "~1.0.0"
       }
@@ -4754,8 +4958,7 @@
     "delayed-stream": {
       "version": "1.0.0",
       "resolved": "https://registry.nlark.com/delayed-stream/download/delayed-stream-1.0.0.tgz",
-      "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
-      "dev": true
+      "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
     },
     "depd": {
       "version": "1.1.2",
@@ -4934,6 +5137,16 @@
       "integrity": "sha1-P7rwIL/XlIhAcuomsel5HUWmKfA=",
       "dev": true
     },
+    "dunder-proto": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz",
+      "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+      "requires": {
+        "call-bind-apply-helpers": "^1.0.1",
+        "es-errors": "^1.3.0",
+        "gopd": "^1.2.0"
+      }
+    },
     "duplexer": {
       "version": "0.1.2",
       "resolved": "https://registry.nlark.com/duplexer/download/duplexer-0.1.2.tgz",
@@ -5032,8 +5245,7 @@
     "emoji-regex": {
       "version": "8.0.0",
       "resolved": "https://registry.npmmirror.com/emoji-regex/download/emoji-regex-8.0.0.tgz",
-      "integrity": "sha1-6Bj9ac5cz8tARZT4QpY79TFkzDc=",
-      "dev": true
+      "integrity": "sha1-6Bj9ac5cz8tARZT4QpY79TFkzDc="
     },
     "emojis-list": {
       "version": "3.0.0",
@@ -5162,6 +5374,72 @@
         "unbox-primitive": "^1.0.1"
       }
     },
+    "es-define-property": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz",
+      "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="
+    },
+    "es-errors": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz",
+      "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="
+    },
+    "es-object-atoms": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+      "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+      "requires": {
+        "es-errors": "^1.3.0"
+      }
+    },
+    "es-set-tostringtag": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+      "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+      "requires": {
+        "es-errors": "^1.3.0",
+        "get-intrinsic": "^1.2.6",
+        "has-tostringtag": "^1.0.2",
+        "hasown": "^2.0.2"
+      },
+      "dependencies": {
+        "function-bind": {
+          "version": "1.1.2",
+          "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz",
+          "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="
+        },
+        "get-intrinsic": {
+          "version": "1.3.0",
+          "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+          "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+          "requires": {
+            "call-bind-apply-helpers": "^1.0.2",
+            "es-define-property": "^1.0.1",
+            "es-errors": "^1.3.0",
+            "es-object-atoms": "^1.1.1",
+            "function-bind": "^1.1.2",
+            "get-proto": "^1.0.1",
+            "gopd": "^1.2.0",
+            "has-symbols": "^1.1.0",
+            "hasown": "^2.0.2",
+            "math-intrinsics": "^1.1.0"
+          }
+        },
+        "has-symbols": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz",
+          "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="
+        },
+        "has-tostringtag": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+          "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+          "requires": {
+            "has-symbols": "^1.0.3"
+          }
+        }
+      }
+    },
     "es-to-primitive": {
       "version": "1.2.1",
       "resolved": "https://registry.nlark.com/es-to-primitive/download/es-to-primitive-1.2.1.tgz",
@@ -5189,8 +5467,7 @@
     "escalade": {
       "version": "3.1.1",
       "resolved": "https://registry.nlark.com/escalade/download/escalade-3.1.1.tgz",
-      "integrity": "sha1-2M/ccACWXFoBdLSoLqpcBVJ0LkA=",
-      "dev": true
+      "integrity": "sha1-2M/ccACWXFoBdLSoLqpcBVJ0LkA="
     },
     "escape-html": {
       "version": "1.0.3",
@@ -6100,8 +6377,7 @@
     "get-caller-file": {
       "version": "2.0.5",
       "resolved": "https://registry.nlark.com/get-caller-file/download/get-caller-file-2.0.5.tgz",
-      "integrity": "sha1-T5RBKoLbMvNuOwuXQfipf+sDH34=",
-      "dev": true
+      "integrity": "sha1-T5RBKoLbMvNuOwuXQfipf+sDH34="
     },
     "get-intrinsic": {
       "version": "1.1.1",
@@ -6114,6 +6390,15 @@
         "has-symbols": "^1.0.1"
       }
     },
+    "get-proto": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/get-proto/-/get-proto-1.0.1.tgz",
+      "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+      "requires": {
+        "dunder-proto": "^1.0.1",
+        "es-object-atoms": "^1.0.0"
+      }
+    },
     "get-stdin": {
       "version": "6.0.0",
       "resolved": "https://registry.nlark.com/get-stdin/download/get-stdin-6.0.0.tgz",
@@ -6203,6 +6488,11 @@
         "slash": "^2.0.0"
       }
     },
+    "gopd": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz",
+      "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="
+    },
     "graceful-fs": {
       "version": "4.2.9",
       "resolved": "https://registry.npmmirror.com/graceful-fs/download/graceful-fs-4.2.9.tgz",
@@ -6353,6 +6643,21 @@
         "minimalistic-assert": "^1.0.1"
       }
     },
+    "hasown": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz",
+      "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+      "requires": {
+        "function-bind": "^1.1.2"
+      },
+      "dependencies": {
+        "function-bind": {
+          "version": "1.1.2",
+          "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz",
+          "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="
+        }
+      }
+    },
     "he": {
       "version": "1.2.0",
       "resolved": "https://registry.npmmirror.com/he/download/he-1.2.0.tgz",
@@ -7256,8 +7561,7 @@
     "is-fullwidth-code-point": {
       "version": "3.0.0",
       "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/download/is-fullwidth-code-point-3.0.0.tgz",
-      "integrity": "sha1-8Rb4Bk/pCz94RKOJl8C3UFEmnx0=",
-      "dev": true
+      "integrity": "sha1-8Rb4Bk/pCz94RKOJl8C3UFEmnx0="
     },
     "is-glob": {
       "version": "4.0.3",
@@ -7866,6 +8170,11 @@
       "integrity": "sha512-G6A/nJLRgWOuuwdNuA6koovfEV1YpqqAG4pRUlFaz3jj2QNZ8M4vBqnVA+HBTmU/AMNUtlOsMmSpF6NyOjztbA==",
       "dev": true
     },
+    "long": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmmirror.com/long/-/long-4.0.0.tgz",
+      "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA=="
+    },
     "lower-case": {
       "version": "1.1.4",
       "resolved": "https://registry.nlark.com/lower-case/download/lower-case-1.1.4.tgz",
@@ -7942,6 +8251,11 @@
         "zousan": "^2.3.3"
       }
     },
+    "math-intrinsics": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+      "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="
+    },
     "md5": {
       "version": "2.3.0",
       "resolved": "https://registry.npmmirror.com/md5/-/md5-2.3.0.tgz",
@@ -8074,14 +8388,12 @@
     "mime-db": {
       "version": "1.51.0",
       "resolved": "https://registry.npmmirror.com/mime-db/download/mime-db-1.51.0.tgz?cache=0&sync_timestamp=1636425985504&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fmime-db%2Fdownload%2Fmime-db-1.51.0.tgz",
-      "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==",
-      "dev": true
+      "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g=="
     },
     "mime-types": {
       "version": "2.1.34",
       "resolved": "https://registry.npmmirror.com/mime-types/download/mime-types-2.1.34.tgz?cache=0&sync_timestamp=1636432301104&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fmime-types%2Fdownload%2Fmime-types-2.1.34.tgz",
       "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==",
-      "dev": true,
       "requires": {
         "mime-db": "1.51.0"
       }
@@ -8439,6 +8751,14 @@
         "lower-case": "^1.1.1"
       }
     },
+    "node-fetch": {
+      "version": "2.6.13",
+      "resolved": "https://registry.npmmirror.com/node-fetch/-/node-fetch-2.6.13.tgz",
+      "integrity": "sha512-StxNAxh15zr77QvvkmveSQ8uCQ4+v5FkvNTj0OESmiHu+VRi/gXArXtkWMElOsOUNLtUEvI4yS+rdtOHZTwlQA==",
+      "requires": {
+        "whatwg-url": "^5.0.0"
+      }
+    },
     "node-fetch-npm": {
       "version": "2.0.4",
       "resolved": "https://registry.npmjs.org/node-fetch-npm/-/node-fetch-npm-2.0.4.tgz",
@@ -10157,8 +10477,7 @@
     "regenerator-runtime": {
       "version": "0.13.9",
       "resolved": "https://registry.npmmirror.com/regenerator-runtime/download/regenerator-runtime-0.13.9.tgz",
-      "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==",
-      "dev": true
+      "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
     },
     "regenerator-transform": {
       "version": "0.14.5",
@@ -10378,8 +10697,7 @@
     "require-directory": {
       "version": "2.1.1",
       "resolved": "https://registry.npmmirror.com/require-directory/download/require-directory-2.1.1.tgz",
-      "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
-      "dev": true
+      "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="
     },
     "require-main-filename": {
       "version": "2.0.0",
@@ -10558,10 +10876,10 @@
         "typescript": "^3.6.3"
       }
     },
-    "screenfull": {
-      "version": "6.0.2",
-      "resolved": "https://registry.npmmirror.com/screenfull/-/screenfull-6.0.2.tgz",
-      "integrity": "sha512-AQdy8s4WhNvUZ6P8F6PB21tSPIYKniic+Ogx0AacBMjKP1GUHN2E9URxQHtCusiwxudnCKkdy4GrHXPPJSkCCw=="
+    "seedrandom": {
+      "version": "3.0.5",
+      "resolved": "https://registry.npmmirror.com/seedrandom/-/seedrandom-3.0.5.tgz",
+      "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg=="
     },
     "select-hose": {
       "version": "2.0.0",
@@ -11233,8 +11551,7 @@
     "sprintf-js": {
       "version": "1.0.3",
       "resolved": "https://registry.nlark.com/sprintf-js/download/sprintf-js-1.0.3.tgz",
-      "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
-      "dev": true
+      "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
     },
     "sshpk": {
       "version": "1.17.0",
@@ -11347,7 +11664,6 @@
       "version": "4.2.3",
       "resolved": "https://registry.npmmirror.com/string-width/download/string-width-4.2.3.tgz",
       "integrity": "sha1-JpxxF9J7Ba0uU2gwqOyJXvnG0BA=",
-      "dev": true,
       "requires": {
         "emoji-regex": "^8.0.0",
         "is-fullwidth-code-point": "^3.0.0",
@@ -11386,7 +11702,6 @@
       "version": "6.0.1",
       "resolved": "https://registry.npmmirror.com/strip-ansi/download/strip-ansi-6.0.1.tgz?cache=0&sync_timestamp=1632432619223&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fstrip-ansi%2Fdownload%2Fstrip-ansi-6.0.1.tgz",
       "integrity": "sha1-nibGPTD1NEPpSJSVshBdN7Z6hdk=",
-      "dev": true,
       "requires": {
         "ansi-regex": "^5.0.1"
       },
@@ -11394,8 +11709,7 @@
         "ansi-regex": {
           "version": "5.0.1",
           "resolved": "https://registry.nlark.com/ansi-regex/download/ansi-regex-5.0.1.tgz?cache=0&sync_timestamp=1631634988487&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fansi-regex%2Fdownload%2Fansi-regex-5.0.1.tgz",
-          "integrity": "sha1-CCyyyJyf6GWaMRpTvWpNxTAdswQ=",
-          "dev": true
+          "integrity": "sha1-CCyyyJyf6GWaMRpTvWpNxTAdswQ="
         }
       }
     },
@@ -11864,6 +12178,11 @@
         "punycode": "^2.1.1"
       }
     },
+    "tr46": {
+      "version": "0.0.3",
+      "resolved": "https://registry.npmmirror.com/tr46/-/tr46-0.0.3.tgz",
+      "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
+    },
     "tryer": {
       "version": "1.0.1",
       "resolved": "https://registry.npmmirror.com/tryer/download/tryer-1.0.1.tgz",
@@ -12623,6 +12942,11 @@
         "defaults": "^1.0.3"
       }
     },
+    "webidl-conversions": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+      "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
+    },
     "webpack": {
       "version": "4.46.0",
       "resolved": "https://registry.npmmirror.com/webpack/download/webpack-4.46.0.tgz",
@@ -13132,6 +13456,15 @@
       "integrity": "sha1-f4RzvIOd/YdgituV1+sHUhFXikI=",
       "dev": true
     },
+    "whatwg-url": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-5.0.0.tgz",
+      "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+      "requires": {
+        "tr46": "~0.0.3",
+        "webidl-conversions": "^3.0.0"
+      }
+    },
     "which": {
       "version": "1.3.1",
       "resolved": "https://registry.nlark.com/which/download/which-1.3.1.tgz",
@@ -13178,7 +13511,6 @@
       "version": "7.0.0",
       "resolved": "https://registry.nlark.com/wrap-ansi/download/wrap-ansi-7.0.0.tgz",
       "integrity": "sha1-Z+FFz/UQpqaYS98RUpEdadLrnkM=",
-      "dev": true,
       "requires": {
         "ansi-styles": "^4.0.0",
         "string-width": "^4.1.0",
@@ -13189,7 +13521,6 @@
           "version": "4.3.0",
           "resolved": "https://registry.npmmirror.com/ansi-styles/download/ansi-styles-4.3.0.tgz",
           "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-          "dev": true,
           "requires": {
             "color-convert": "^2.0.1"
           }
@@ -13198,7 +13529,6 @@
           "version": "2.0.1",
           "resolved": "https://registry.npmmirror.com/color-convert/download/color-convert-2.0.1.tgz",
           "integrity": "sha1-ctOmjVmMm9s68q0ehPIdiWq9TeM=",
-          "dev": true,
           "requires": {
             "color-name": "~1.1.4"
           }
@@ -13206,8 +13536,7 @@
         "color-name": {
           "version": "1.1.4",
           "resolved": "https://registry.nlark.com/color-name/download/color-name-1.1.4.tgz",
-          "integrity": "sha1-wqCah6y95pVD3m9j+jmVyCbFNqI=",
-          "dev": true
+          "integrity": "sha1-wqCah6y95pVD3m9j+jmVyCbFNqI="
         }
       }
     },
@@ -13253,7 +13582,6 @@
       "version": "16.2.0",
       "resolved": "https://registry.npmmirror.com/yargs/download/yargs-16.2.0.tgz",
       "integrity": "sha1-HIK/D2tqZur85+8w43b0mhJHf2Y=",
-      "dev": true,
       "requires": {
         "cliui": "^7.0.2",
         "escalade": "^3.1.1",
@@ -13268,7 +13596,6 @@
           "version": "7.0.4",
           "resolved": "https://registry.nlark.com/cliui/download/cliui-7.0.4.tgz",
           "integrity": "sha1-oCZe5lVHb8gHrqnfPfjfd4OAi08=",
-          "dev": true,
           "requires": {
             "string-width": "^4.2.0",
             "strip-ansi": "^6.0.0",
@@ -13278,16 +13605,14 @@
         "y18n": {
           "version": "5.0.8",
           "resolved": "https://registry.nlark.com/y18n/download/y18n-5.0.8.tgz",
-          "integrity": "sha1-f0k00PfKjFb5UxSTndzS3ZHOHVU=",
-          "dev": true
+          "integrity": "sha1-f0k00PfKjFb5UxSTndzS3ZHOHVU="
         }
       }
     },
     "yargs-parser": {
       "version": "20.2.9",
       "resolved": "https://registry.npmmirror.com/yargs-parser/download/yargs-parser-20.2.9.tgz?cache=0&sync_timestamp=1637031214824&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fyargs-parser%2Fdownload%2Fyargs-parser-20.2.9.tgz",
-      "integrity": "sha1-LrfcOwKJcY/ClfNidThFxBoMlO4=",
-      "dev": true
+      "integrity": "sha1-LrfcOwKJcY/ClfNidThFxBoMlO4="
     },
     "yorkie": {
       "version": "2.0.0",

+ 2 - 0
package.json

@@ -10,6 +10,8 @@
   },
   "dependencies": {
     "@datorama/akita": "^7.1.1",
+    "@tensorflow-models/body-pix": "^2.2.1",
+    "@tensorflow/tfjs": "^4.22.0",
     "animate.css": "^3.5.1",
     "axios": "^0.25.0",
     "cesium": "^1.84.0",

BIN
public/imgs/personLK.png


+ 1 - 1
public/index.html

@@ -5,7 +5,7 @@
   <meta charset="utf-8" />
   <meta http-equiv="X-UA-Compatible" content="IE=edge" />
   <meta name="viewport" content="width=device-width,initial-scale=1.0" />
-  <link rel="icon" href="<static/setting/favicon.ico" />
+  <link rel="icon" href="static/setting/favicon.ico" />
   <script src="js/config.js?"></script>
   <script src="js/station.js"></script>
 </head>

+ 8 - 0
src/API/custom.js

@@ -102,6 +102,14 @@ export const savePerson = data =>
     data,
     notShowLoading: true,
   })
+//检索人员信息
+export const GetPersonList = data =>
+  $http({
+    method: 'post',
+    url: '/System/Person/GetPageListJson',
+    data,
+    notShowLoading: true,
+  })
 //人员绑定标签信息
 export const bindingCard = data =>
   $http({

+ 18 - 0
src/API/report.js

@@ -7,4 +7,22 @@ export const getMileageList = data =>
     url: 'customPage/page/getList',
     data,
     notShowLoading: true,
+  })
+
+  // 获取通用报表信息
+export const getDataList = data =>
+  $http({
+    method: 'POST',
+    url: 'Report/Data/GetList',
+    data,
+    notShowLoading: true,
+  })
+
+  // 更新通用报表信息
+export const updateDataList = data =>
+  $http({
+    method: 'POST',
+    url: 'customPage/Page/Update',
+    data,
+    notShowLoading: true,
   })

+ 6 - 2
src/components/IdReader/index.vue

@@ -36,6 +36,7 @@ export default {
   },
   watch: {
     enable(newValue, oldValue) {
+      console.log("启动项", newValue, oldValue);
       if (!oldValue && newValue) {
         this.OcrRecognition();
         this.timer = setInterval(() => {
@@ -43,6 +44,7 @@ export default {
           this.ReadIDCardNoJudge();
         }, 3000);
       } else if (oldValue && !newValue) {
+        this.timer = null;
         this.closeConnect();
       }
     },
@@ -95,7 +97,7 @@ export default {
           //   document.all["BackPhotoDisplay"].src =
           //     "data:image/jpeg;base64," + alldata[21];//反面
           // }
-          //回传 
+          //回传
           this.$emit("output", this.response);
         } else {
           console.log("读取数据信息", res.data);
@@ -109,7 +111,9 @@ export default {
       paramTimeOut = "timeout=" + paramTimeOut;
       var parameterAll = paramTimeOut;
       let val = "04?" + parameterAll;
-      this.websockets.send(val);
+      if (this.websockets !== null) {
+        this.websockets.send(val);
+      }
     },
     //关闭连接
     closeConnect() {

+ 5 - 0
src/router/index.js

@@ -38,6 +38,11 @@ const routes = [
     name: 'leave',
     component: () => import('@/views/leave/index.vue'),
   },
+  {
+    path: '/test',
+    name: 'test',
+    component: () => import('@/views/test/index.vue'),
+  },
 ]
 
 const router = new VueRouter({

+ 12 - 0
src/utils/request.js

@@ -66,6 +66,18 @@ $http.interceptors.response.use(
     // if (res.code === 200) return res;
     if ((res.code + "").startsWith("2")) {
       return res;
+    } else if (res.code === 40000) {
+      // console.log("ERROR:", response, res, localStorage.getItem("token"));
+      Message({
+        message: "登录超时,请重新登录",
+        type: "error",
+        duration: 800,
+      });
+      localStorage.clear();
+      // setTimeout(() => {
+      //   window.location.reload();
+      // }, 500);
+      // this.$router.push("/login");
     } else {
       // Message({
       //   message: res?.msg || "连接错误",

+ 12 - 7
src/views/components/baseHeader/left.vue

@@ -111,12 +111,22 @@ export default {
           name: "首页",
           path: "/basePage",
         },
+        // {
+        //   id: "2",
+        //   name: "今日进站",
+        //   path: "/leave",
+        // },
         {
-          id: "1",
+          id: "3",
           name: "退出登记",
           path: "/basePage",
         },
         // {
+        //   id: "4",
+        //   name: "退出登记",
+        //   path: "/test",
+        // },
+        // {
         //   id: "2",
         //   name: "关闭弹窗",
         //   path: "/basePage",
@@ -127,11 +137,6 @@ export default {
         //   name: "绑卡记录",
         //   path: "/Page1?path=custompage%2Fpage?pageId=839895523707068416",
         // },
-        // {
-        //   id: "3",
-        //   name: "还卡记录",
-        //   path: "/leave",
-        // },
       ],
       activeSubNav: "",
       datetimeData: {
@@ -167,11 +172,11 @@ export default {
     },
   },
   created() {
+    this.refreshTime();
     // this.getMenuList();
   },
   mounted() {
     this.title = SYSTEM_TITLE;
-    this.refreshTime();
     this.$EventBus.$on("alarmCount", (data) => {
       this.alarmCount = +data;
     });

+ 29 - 16
src/views/components/dialog/RiskTipDialog.vue

@@ -379,23 +379,31 @@ export default {
           this.person = { cardNo: 0 };
         }
       } catch (err) {
-        console.log(err, 123);
+        this.$message.error(err.msg);
+        console.log(err, "RFID查询");
       }
     },
     async savePersonInfo(person) {
       try {
-        const res = await savePerson(person);
-        this.response = res;
-        if (this.dialogConfig.type == 1) {
-          console.log("绑定成功");
-          this.bindRecord(person);
-        }
-        if (this.dialogConfig.type == 2) {
-          console.log("解绑成功");
-          this.unbindRecord(person);
+        if (person.name !== "") {
+          const res = await savePerson(person);
+          this.response = res;
+          if (this.dialogConfig.type == 1) {
+            console.log("绑定成功");
+            this.bindRecord(person);
+          }
+          if (this.dialogConfig.type == 2) {
+            console.log("解绑成功");
+            this.unbindRecord(person);
+          }
+        } else {
+          if (this.dialogConfig.type == 2) {
+            this.$message.error("请将需要解绑的卡片贴近感应区");
+          }
         }
       } catch (err) {
         console.log(err);
+        this.$message.error(err.msg);
         console.log("绑定失败");
         this.enable = true;
         this.info = err.msg;
@@ -414,12 +422,14 @@ export default {
           field004: person.cardNo, //卡号
           field005: Dayjs(new Date()).format("YYYY-MM-DD HH:mm:ss"), //绑卡时间
           field006: person.cause, //进站目的
+          field007: person.photoPath, //人员照片
           pageId: "839895523707068416", //绑卡
         };
         const res = await bindAndUnbindrecord(record);
         console.log("绑定记录反馈信息:", res);
       } catch (err) {
-        console.log(err);
+        this.$message.error(err.msg);
+        console.log(err, "基础信息绑定错误");
       }
     },
     async unbindRecord(person) {
@@ -439,7 +449,8 @@ export default {
           this.unbindNumber = "";
         }, 500);
       } catch (err) {
-        console.log(err);
+        this.$message.error(err.msg);
+        console.log(err, "基础信息解绑错误");
       }
     },
     checkrecognizedNumberBind() {
@@ -505,7 +516,7 @@ export default {
           this.dialogConfig.data.accessControlIds = [
             "789185403352522752", // 进站识别
             "789185626355277824", // 出站识别
-            "833420345783361536", 
+            "833420345783361536",
             "830088938663190528",
             "833426645288230912",
           ];
@@ -539,8 +550,9 @@ export default {
             this.info = "刷卡识别中。。。请刷卡";
           }, 1000);
         }
-      } catch (error) {
-        console.log(error);
+      } catch (err) {
+        this.$message.error(err.msg);
+        console.log(er, "绑卡操作");
       }
     },
     setZIndex(val) {
@@ -742,7 +754,7 @@ export default {
           height: 60px;
           text-align: center;
           position: absolute;
-          bottom: 40px;
+          bottom: 50px;
           left: 50%;
           transform: translate(-50%, 0);
           .el-button {
@@ -759,6 +771,7 @@ export default {
             }
           }
           .btn-handle.el-button {
+            margin-left: 40px;
             background: rgba(0, 159, 221, 0.8);
           }
           .btn-cancel.el-button {

+ 204 - 52
src/views/leave/index.vue

@@ -2,51 +2,103 @@
   <div class="recognize-main">
     <template>
       <!-- 退卡人员信息 -->
-      <div class="infomation_content">
+      <div>
         <div>
-          <div class="infomation_prompt">
-            人员信息(请依次,点击退卡-再刷卡-确认退卡。):
-          </div>
-          <div class="infomation_data_line"></div>
-          <div class="infomation_data">
-            <div
-              class="infomation_data_content"
-              v-for="(item, index) in stepProcessInfomation"
-              :key="item.step"
-            >
-              <span class="infomation_data_prop">{{ item.propName }}</span>
-              <span>
-                <el-input
-                  ref="dealContent"
-                  v-model="infomation[item.prop]"
-                  rows="1"
-                  type="textarea"
-                  style="
-                    font-size: 40px;
-                    font-family: 'Microsoft YaHei';
-                    width: 380px;
-                    height: 68px;
-                  "
-                />
-              </span>
-            </div>
-          </div>
-          <div class="infomation_button">
-            <el-button
-              style="width: 160px; height: 80px; font-size: xx-large"
-              type="primary "
-              size="medium "
-              @click="handleClick(infomation, 1)"
-              >退卡</el-button
-            >
-            <el-button
-              style="width: 160px; height: 80px; font-size: xx-large"
-              type="primary "
-              size="medium "
-              @click="handleClick(infomation, 2)"
-              >确认</el-button
-            >
-          </div>
+          <el-row>
+            <el-col class="infomation_content" :span="18">
+              <div class="infomation_prompt">
+                今日进站信息概览:登记信息共计{{ companyCount }}条,人数共计{{
+                  personsCount
+                }}人次
+              </div>
+              <div class="infomation_data_line"></div>
+              <div>
+                <el-table
+                  height="70vh"
+                  :data="personComingList"
+                  style="width: 100%"
+                  :key="refreKey"
+                  :default-sort="{ prop: 'field001', order: 'descending' }"
+                >
+                  <el-table-column align="center" prop="field003" label="单位">
+                  </el-table-column>
+                  <el-table-column
+                    align="center"
+                    prop="field006"
+                    label="进站目的"
+                  >
+                  </el-table-column>
+                  <el-table-column align="center" prop="field002" label="领队">
+                  </el-table-column>
+                  <el-table-column
+                    align="center"
+                    prop="field005"
+                    label="联系电话"
+                  >
+                  </el-table-column>
+                  <el-table-column
+                    sortable
+                    align="center"
+                    prop="field001"
+                    label="进站时间"
+                  >
+                  </el-table-column>
+                  <el-table-column
+                    sortable
+                    align="center"
+                    prop="field013"
+                    label="离站时间"
+                  >
+                  </el-table-column>
+                  <el-table-column
+                    align="center"
+                    prop="field007"
+                    label="总人数"
+                  >
+                  </el-table-column>
+                  <el-table-column
+                    align="center"
+                    prop="field008"
+                    label="同行人员"
+                  >
+                  </el-table-column>
+                  <el-table-column align="center" label="操作">
+                    <template slot-scope="scope">
+                      <el-button
+                        v-if="!scope.row.field013"
+                        type="primary"
+                        size="medium "
+                        @click="handleClick(scope.row, 3)"
+                        >离站</el-button
+                      >
+                    </template>
+                  </el-table-column>
+                </el-table>
+              </div>
+            </el-col>
+            <el-col class="infomation_content" :span="6">
+              <div class="infomation_prompt">
+                今日发出未收回卡{{ inList.length }}张
+              </div>
+              <div class="infomation_data_line"></div>
+              <div>
+                <el-table
+                  height="70vh"
+                  :data="inList"
+                  style="width: 100%"
+                  :key="refreKey"
+                >
+                  <el-table-column align="center" prop="field001" label="姓名">
+                  </el-table-column>
+                  <el-table-column align="center" label="在站">
+                    <template slot-scope="scope">
+                      {{ scope.row ? "未还卡" : "还卡" }}
+                    </template>
+                  </el-table-column>
+                </el-table>
+              </div>
+            </el-col>
+          </el-row>
         </div>
       </div>
     </template>
@@ -55,6 +107,8 @@
 
 <script>
 import BaseTableList from "@/views/components/base/BaseTableList";
+import { getDataList, updateDataList } from "@/API/report";
+import Dayjs from "dayjs";
 
 export default {
   name: "recognize",
@@ -107,6 +161,13 @@ export default {
       cameraInfo: {
         id: "1",
       },
+      personComingList: [{}],
+      personBindList: [{}],
+      personUnbindList: [{}],
+      inList: [{}],
+      refreKey: 1,
+      companyCount: 0,
+      personsCount: 0,
     };
   },
   watch: {
@@ -125,8 +186,88 @@ export default {
       immediate: true,
     },
   },
-  mounted() {},
+  mounted() {
+    this.getComingDataList();
+    this.getBindList().then(() => {
+      this.getUnbindList();
+    });
+  },
   methods: {
+    async getComingDataList() {
+      try {
+        const params = {
+          sql: "select CAST(id as char) as id,field001,field002,field003,field004,field005,field006,field007,field008,field009,field010,field011,field012,field013 from custom_table_person_coming_records where TO_DAYS(field001) = TO_DAYS(NOW())", //登记时间
+        };
+        const res = await getDataList(params);
+        this.personComingList = res.data.content;
+        this.companyCount = this.personComingList.length;
+        this.personsCount = 0;
+        this.personComingList.forEach((e) => {
+          this.personsCount += Number(e.field007);
+        });
+        // console.log("入场登记报表sql", params, res);
+        this.refreKey++;
+      } catch (err) {
+        console.log(err);
+      }
+    },
+    async getBindList() {
+      try {
+        const params = {
+          sql: "select CAST(id as char) as id,field001,field002,field003,field004,field005,field006,field007 from custom_table_bind_card_records where TO_DAYS(BaseCreateTime) = TO_DAYS(NOW())", //登记时间
+        };
+        const res = await getDataList(params);
+        this.personBindList = res.data.content;
+        // this.companyCount = this.personComingList.length;
+        // this.personsCount = 0;
+        // this.personComingList.forEach((e) => {
+        //   this.personsCount += Number(e.field007);
+        // });
+        // console.log("今日绑卡", params, res);
+        this.refreKey++;
+      } catch (err) {
+        console.log(err);
+      }
+    },
+    async getUnbindList() {
+      try {
+        const params = {
+          sql: "select CAST(id as char) as id,field001,field002,field003,field004,field005 from custom_table_unbind_card_records where TO_DAYS(BaseCreateTime) = TO_DAYS(NOW())", //登记时间
+        };
+        const res = await getDataList(params);
+        this.personUnbindList = res.data.content;
+        // 过滤标记
+        for (let i = 0; i < this.personUnbindList.length; i++) {
+          const e = this.personUnbindList[i];
+          for (let j = 0; j < this.personBindList.length; j++) {
+            const bind = this.personBindList[j];
+            if (bind.field001 === e.field001 && bind.field004 === e.field004) {
+              this.personBindList[j].in = true;
+            }
+          }
+        }
+        //过滤显示
+        this.inList = this.personBindList.filter((e) => !e.in);
+        // console.log(
+        //   "在站",
+        //   this.personBindList,
+        //   this.personUnbindList,
+        //   this.inList
+        // );
+        this.refreKey++;
+      } catch (err) {
+        console.log(err);
+      }
+    },
+    async saveComingRecord(data) {
+      try {
+        const res = await updateDataList(data);
+        console.log("入场登记报表保存离站时间", data, res);
+        this.refreKey++;
+      } catch (err) {
+        console.log(err);
+      }
+    },
     handleClick(data, type) {
       console.log("退卡了哦!", data);
       if (type) {
@@ -149,7 +290,12 @@ export default {
             console.log("确认退卡", data);
             this.$store.dispatch("dialog/addRiskDialog", dialogConfig);
             break;
-
+          case 3:
+            data.pageId = "842348058862690304";
+            data.field013 = Dayjs(new Date()).format("YYYY-MM-DD HH:mm:ss");
+            console.log("确认离站", data);
+            this.saveComingRecord(data);
+            break;
           default:
             break;
         }
@@ -160,7 +306,7 @@ export default {
 </script>
 <style>
 .el-input__inner {
-  height: 120px;
+  height: 40px;
 }
 </style>
 <style lang="less" scoped>
@@ -172,13 +318,15 @@ export default {
   color: #fff;
   .infomation_content {
     color: #fff;
+    padding: 6px;
+    height: 100%;
     .infomation_prompt {
-      font-size: 60px;
-      margin-top: 2%;
-      margin-left: 2%;
+      font-size: 40px;
+      margin-top: 20px;
+      margin-left: 20px;
     }
     .infomation_prop {
-      margin-top: 14%;
+      margin-top: 100px;
       width: 100%;
       height: 100px;
       display: flex;
@@ -187,7 +335,11 @@ export default {
       font-size: 60px;
     }
     .infomation_data_line {
-      margin-top: 5%;
+      margin-top: 20px;
+    }
+    .infomation_table {
+      height: 195px;
+      overflow-y: scroll;
     }
     .infomation_data {
       width: 100%;

+ 235 - 0
src/views/recognize/components/VideoLocalWindow copy.vue

@@ -0,0 +1,235 @@
+<template>
+  <div>
+    <video ref="video" autoplay muted playsinline></video>
+    <!-- <el-button @click="startCamera">开启摄像头</el-button>
+    <el-button @click="stopCamera" :disabled="!isCameraActive"
+      >关闭摄像头</el-button
+    > -->
+  </div>
+</template>
+
+
+<script>
+import { GetPersonByFace, GetPersonByFaceBase64 } from "@/API/custom";
+export default {
+  props: {
+    processStep: {
+      type: String,
+      require: true,
+    },
+    isUpload: {
+      type: String,
+      require: false,
+    },
+    cameraData: {
+      type: Object,
+      default: () => ({}),
+    },
+  },
+  watch: {
+    processStep: {
+      handler(step) {
+        if (step == 0 || step == 9) {
+          this.startCamera();
+        } else {
+          this.stopCamera();
+        }
+      },
+      deep: true,
+      immediate: true,
+    },
+    isUpload: {
+      handler(val) {
+        console.log("上传子级开关", val);
+        if (val) {
+          this.uploadImage();
+        } else {
+          this.isUpload = false;
+        }
+      },
+      deep: true,
+      immediate: true,
+    },
+  },
+  data() {
+    return {
+      isCameraActive: false,
+      stream: null,
+      captureInterval: null, // 新增定时器变量
+    };
+  },
+  methods: {
+    async startCamera() {
+      try {
+        const stream = await navigator.mediaDevices.getUserMedia({
+          video: {
+            width: { ideal: 1280 },
+            height: { ideal: 800 },
+            facingMode: "user",
+          },
+        });
+        this.stream = stream;
+        this.isCameraActive = true;
+        this.$refs.video.srcObject = stream;
+
+        if (this.isUpload) {
+          setTimeout(() => {
+            this.uploadImage();
+          }, 1000);
+        } else {
+          // 新增定时截图功能
+          this.captureInterval = setInterval(() => {
+            this.captureImage();
+          }, 3000);
+        }
+      } catch (err) {
+        console.error("摄像头访问错误:", err);
+        alert(`摄像头访问失败: ${err.message}`);
+      }
+    },
+    stopCamera() {
+      if (this.stream) {
+        this.stream.getTracks().forEach((track) => track.stop());
+        this.isCameraActive = false;
+        this.$refs.video.srcObject = null;
+        this.stream = null;
+
+        // 停止定时器
+        if (this.captureInterval) {
+          clearInterval(this.captureInterval);
+          this.captureInterval = null;
+        }
+      }
+    },
+    // 新增截图方法
+    // async captureImage() {
+    //   const video = this.$refs.video;
+    //   video.currentTime = 1;
+    //   const canvas = document.createElement("canvas");
+    //   canvas.width = video.videoWidth;
+    //   canvas.height = video.videoHeight;
+    //   canvas
+    //     .getContext("2d")
+    //     .drawImage(video, 0, 0, canvas.width, canvas.height);
+    //   // 下载到本地
+    //   // const link = document.createElement("a");
+    //   // link.download = `capture_${new Date()
+    //   //   .toISOString()
+    //   //   .replace(/[:.]/g, "-")}.png`;
+    //   // link.href = canvas.toDataURL("image/png");
+    //   // link.click();
+
+    //   // 将canvas转为Blob对象
+    //   canvas.toBlob(async (blob) => {
+    //     if (blob) {
+    //       console.log("blob数据", blob);
+    //       const formData = new FormData();
+    //       formData.append("timestamp", new Date().toISOString());
+    //       formData.append("file", blob, "screenshot.png");
+    //       console.log("上传数据", formData);
+    //       try {
+    //         // const res = await GetPersonByFace(formData);
+    //         // console.log("上传反馈", res);
+    //         // const response = await fetch("System/Person/GetPersonByFace", {
+    //         //   method: "POST",
+    //         //   body: formData,
+    //         // });
+    //       } catch (err) {
+    //         console.error("上传过程中出错:", err);
+    //       }
+    //     }
+    //   }, "image/png");
+    // },
+
+    async captureImage() {
+      const video = this.$refs.video;
+      const canvas = document.createElement("canvas");
+      canvas.width = video.videoWidth;
+      canvas.height = video.videoHeight;
+      canvas.getContext("2d").drawImage(video, 0, 0);
+
+      try {
+        const base64Data = canvas.toDataURL("image/png");
+        // console.log("上传数据:Base64", base64Data);
+        // 替换YOUR_SERVER_URL为你的实际服务器地址
+        const response = await fetch(
+          "/yapi/System/Person/GetPersonByFaceBase64",
+          {
+            method: "POST",
+            headers: {
+              token: localStorage.getItem("token"),
+              "Content-Type": "application/json",
+            },
+            body: JSON.stringify({
+              data: base64Data,
+              fileModule: 2,
+            }),
+          }
+        );
+        const result = await response.json();
+        // console.log("上传反馈", response, result);
+        if (result.code === 20000) {
+          console.log("服务器返回数据:", result);
+          this.$emit("output", result.data);
+          setTimeout(() => {
+            this.stopCamera();
+          }, 200);
+        }
+      } catch (err) {
+        console.error("上传过程中出错:", err);
+      }
+    },
+    async uploadImage() {
+      const video = this.$refs.video;
+      const canvas = document.createElement("canvas");
+      canvas.width = video.videoWidth;
+      canvas.height = video.videoHeight;
+      canvas.getContext("2d").drawImage(video, 0, 0);
+      try {
+        const base64Data = canvas.toDataURL("image/png");
+        // console.log("上传数据:Base64", base64Data);
+        // 替换YOUR_SERVER_URL为你的实际服务器地址
+        const response = await fetch("/yapi/File/UploadBase64", {
+          method: "POST",
+          headers: {
+            token: localStorage.getItem("token"),
+            "Content-Type": "application/json",
+          },
+          body: JSON.stringify({
+            data: base64Data,
+            fileModule: 1,
+          }),
+        });
+        const result = await response.json();
+        console.log("上传反馈", response, result);
+        if (result.code === 20000) {
+          console.log("服务器上传返回数据:", result);
+          this.$emit("outputPath", result.data);
+          setTimeout(() => {
+            this.stopCamera();
+          }, 200);
+        }
+        this.isUpload = false;
+      } catch (err) {
+        console.error("上传过程中出错:", err);
+      }
+    },
+  },
+  created() {
+    this.startCamera();
+  },
+  beforeDestroy() {
+    this.stopCamera();
+  },
+};
+</script>
+
+<style scoped>
+video {
+  height: 800px;
+  width: 1280px;
+  /* width: 100%;
+  max-width: 500px; */
+  background: #000;
+}
+</style>

+ 110 - 13
src/views/recognize/components/VideoLocalWindow.vue

@@ -1,6 +1,9 @@
 <template>
-  <div>
+  <div class="videoContainer">
     <video ref="video" autoplay muted playsinline></video>
+    <div id="timestamp" v-show="false">
+      {{ datetimeData.date + " " + datetimeData.time }}
+    </div>
     <!-- <el-button @click="startCamera">开启摄像头</el-button>
     <el-button @click="stopCamera" :disabled="!isCameraActive"
       >关闭摄像头</el-button
@@ -11,6 +14,8 @@
 
 <script>
 import { GetPersonByFace, GetPersonByFaceBase64 } from "@/API/custom";
+import Dayjs from "dayjs";
+
 export default {
   props: {
     processStep: {
@@ -56,9 +61,29 @@ export default {
       isCameraActive: false,
       stream: null,
       captureInterval: null, // 新增定时器变量
+      datetimeData: {
+        date: Dayjs(new Date()).format("YYYY-MM-DD"),
+        time: Dayjs(new Date()).format("HH:mm:ss"),
+        week: Dayjs(new Date()).format("dddd"),
+      },
     };
   },
   methods: {
+    refreshTime() {
+      let speed = 1000;
+      let timer = null;
+      let theNowTime = () => {
+        // this.datePersonData.time = Dayjs(new Date()).format('HH:mm:ss')
+        this.datetimeData.time = Dayjs(new Date()).format("HH:mm:ss");
+        this.datetimeData.date = Dayjs(new Date()).format("YYYY-MM-DD");
+        this.datetimeData.week = Dayjs(new Date()).format("dddd");
+      };
+      timer = setInterval(theNowTime, speed);
+      this.$once("hook:beforeDestroy", () => {
+        clearInterval(timer);
+        timer = null;
+      });
+    },
     async startCamera() {
       try {
         const stream = await navigator.mediaDevices.getUserMedia({
@@ -80,7 +105,8 @@ export default {
           // 新增定时截图功能
           this.captureInterval = setInterval(() => {
             this.captureImage();
-          }, 3000);
+            console.log("截图上传");
+          }, 2500);
         }
       } catch (err) {
         console.error("摄像头访问错误:", err);
@@ -143,11 +169,36 @@ export default {
 
     async captureImage() {
       const video = this.$refs.video;
+      if (video.paused) return;
       const canvas = document.createElement("canvas");
-      canvas.width = video.videoWidth;
-      canvas.height = video.videoHeight;
-      canvas.getContext("2d").drawImage(video, 0, 0);
 
+      const cropWidth = video.videoWidth * 0.5;
+      const cropHeight = video.videoHeight * 0.98;
+
+      // 设置canvas尺寸为选择区域大小
+      canvas.width = cropWidth;
+      canvas.height = cropHeight;
+
+      const x = (video.videoWidth - cropWidth) / 2;
+      const y = (video.videoHeight - cropHeight) / 2;
+
+      const ctx = canvas.getContext("2d");
+      //中心60%区域
+      ctx.drawImage(
+        video,
+        x,
+        y,
+        cropWidth,
+        cropHeight,
+        0,
+        0,
+        cropWidth,
+        cropHeight
+      );
+      // canvas.width = video.videoWidth;
+      // canvas.height = video.videoHeight;
+      // const ctx = canvas.getContext("2d");
+      // ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
       try {
         const base64Data = canvas.toDataURL("image/png");
         // console.log("上传数据:Base64", base64Data);
@@ -169,11 +220,12 @@ export default {
         const result = await response.json();
         // console.log("上传反馈", response, result);
         if (result.code === 20000) {
-          console.log("服务器返回数据:", result);
+          // console.log("服务器返回数据:", result);
           this.$emit("output", result.data);
-          setTimeout(() => {
-            this.stopCamera();
-          }, 200);
+          this.uploadImage();
+          // setTimeout(() => {
+          //   this.stopCamera();
+          // }, 200);
         }
       } catch (err) {
         console.error("上传过程中出错:", err);
@@ -182,9 +234,36 @@ export default {
     async uploadImage() {
       const video = this.$refs.video;
       const canvas = document.createElement("canvas");
-      canvas.width = video.videoWidth;
-      canvas.height = video.videoHeight;
-      canvas.getContext("2d").drawImage(video, 0, 0);
+
+      const cropWidth = video.videoWidth * 0.5;
+      const cropHeight = video.videoHeight * 0.98;
+
+      // 设置canvas尺寸为选择区域大小
+      canvas.width = cropWidth;
+      canvas.height = cropHeight;
+
+      const x = (video.videoWidth - cropWidth) / 2;
+      const y = (video.videoHeight - cropHeight) / 2;
+
+      const ctx = canvas.getContext("2d");
+      //中心60%区域
+      ctx.drawImage(
+        video,
+        x,
+        y,
+        cropWidth,
+        cropHeight,
+        0,
+        0,
+        cropWidth,
+        cropHeight
+      );
+      // ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
+      const timestampDiv = document.getElementById("timestamp");
+      // 在canvas上绘制时间戳
+      ctx.font = "24px Arial";
+      ctx.fillStyle = "white";
+      ctx.fillText(timestampDiv.textContent, 20, canvas.height - 20);
       try {
         const base64Data = canvas.toDataURL("image/png");
         // console.log("上传数据:Base64", base64Data);
@@ -201,7 +280,7 @@ export default {
           }),
         });
         const result = await response.json();
-        console.log("上传反馈", response, result);
+        // console.log("上传反馈", response, result);
         if (result.code === 20000) {
           console.log("服务器上传返回数据:", result);
           this.$emit("outputPath", result.data);
@@ -217,6 +296,7 @@ export default {
   },
   created() {
     this.startCamera();
+    this.refreshTime();
   },
   beforeDestroy() {
     this.stopCamera();
@@ -225,11 +305,28 @@ export default {
 </script>
 
 <style scoped>
+.videoContainer {
+  position: relative;
+  width: 50%; /* 容器宽度设为50% */
+  height: 100%; /* 容器高度设为100% */
+  margin: 0 auto; /* 居中显示 */
+  overflow: hidden; /* 隐藏溢出部分 */
+}
 video {
   height: 800px;
   width: 1280px;
+  transform: translate(-25%, 0%);
   /* width: 100%;
   max-width: 500px; */
   background: #000;
 }
+#timestamp {
+  position: absolute;
+  bottom: 20px;
+  left: 20px;
+  color: white;
+  font-size: 24px;
+  background-color: rgba(0, 0, 0, 0.5);
+  padding: 5px;
+}
 </style>

+ 371 - 0
src/views/recognize/components/VideoLocalWindowBack.vue

@@ -0,0 +1,371 @@
+<template>
+  <div class="videoContainer">
+    <img id="background-image" :src="backgroundImageSrc" alt="背景图片" />
+    <video ref="video" autoplay muted playsinline></video>
+    <div id="timestamp" v-show="false">
+      {{ datetimeData.date + " " + datetimeData.time }}
+    </div>
+    <!-- <el-button @click="startCamera">开启摄像头</el-button>
+    <el-button @click="stopCamera" :disabled="!isCameraActive"
+      >关闭摄像头</el-button
+    > -->
+  </div>
+</template>
+
+
+<script>
+import { GetPersonByFace, GetPersonByFaceBase64 } from "@/API/custom";
+import Dayjs from "dayjs";
+
+export default {
+  props: {
+    processStep: {
+      type: String,
+      require: true,
+    },
+    isUpload: {
+      type: String,
+      require: false,
+    },
+    cameraData: {
+      type: Object,
+      default: () => ({}),
+    },
+  },
+  watch: {
+    processStep: {
+      handler(step) {
+        if (step == 0 || step == 9) {
+          this.startCamera();
+        } else {
+          this.stopCamera();
+        }
+      },
+      deep: true,
+      immediate: true,
+    },
+    isUpload: {
+      handler(val) {
+        console.log("上传子级开关", val);
+        if (val) {
+          this.uploadImage();
+        } else {
+          this.isUpload = false;
+        }
+      },
+      deep: true,
+      immediate: true,
+    },
+  },
+  data() {
+    return {
+      backgroundImageSrc: "/imgs/personLK.png",
+      isCameraActive: false,
+      stream: null,
+      captureInterval: null, // 新增定时器变量
+      datetimeData: {
+        date: Dayjs(new Date()).format("YYYY-MM-DD"),
+        time: Dayjs(new Date()).format("HH:mm:ss"),
+        week: Dayjs(new Date()).format("dddd"),
+      },
+    };
+  },
+  methods: {
+    refreshTime() {
+      let speed = 1000;
+      let timer = null;
+      let theNowTime = () => {
+        // this.datePersonData.time = Dayjs(new Date()).format('HH:mm:ss')
+        this.datetimeData.time = Dayjs(new Date()).format("HH:mm:ss");
+        this.datetimeData.date = Dayjs(new Date()).format("YYYY-MM-DD");
+        this.datetimeData.week = Dayjs(new Date()).format("dddd");
+      };
+      timer = setInterval(theNowTime, speed);
+      this.$once("hook:beforeDestroy", () => {
+        clearInterval(timer);
+        timer = null;
+      });
+    },
+    async startCamera() {
+      try {
+        const stream = await navigator.mediaDevices.getUserMedia({
+          video: {
+            width: { ideal: 1280 },
+            height: { ideal: 800 },
+            facingMode: "user",
+          },
+        });
+        this.stream = stream;
+        this.isCameraActive = true;
+        this.$refs.video.srcObject = stream;
+
+        if (this.isUpload) {
+          setTimeout(() => {
+            this.uploadImage();
+          }, 1000);
+        } else {
+          // 新增定时截图功能
+          this.captureInterval = setInterval(() => {
+            this.captureImage();
+            console.log("截图上传");
+          }, 2500);
+        }
+      } catch (err) {
+        console.error("摄像头访问错误:", err);
+        alert(`摄像头访问失败: ${err.message}`);
+      }
+    },
+    stopCamera() {
+      if (this.stream) {
+        this.stream.getTracks().forEach((track) => track.stop());
+        this.isCameraActive = false;
+        this.$refs.video.srcObject = null;
+        this.stream = null;
+
+        // 停止定时器
+        if (this.captureInterval) {
+          clearInterval(this.captureInterval);
+          this.captureInterval = null;
+        }
+      }
+    },
+    // 新增截图方法
+    // async captureImage() {
+    //   const video = this.$refs.video;
+    //   video.currentTime = 1;
+    //   const canvas = document.createElement("canvas");
+    //   canvas.width = video.videoWidth;
+    //   canvas.height = video.videoHeight;
+    //   canvas
+    //     .getContext("2d")
+    //     .drawImage(video, 0, 0, canvas.width, canvas.height);
+    //   // 下载到本地
+    //   // const link = document.createElement("a");
+    //   // link.download = `capture_${new Date()
+    //   //   .toISOString()
+    //   //   .replace(/[:.]/g, "-")}.png`;
+    //   // link.href = canvas.toDataURL("image/png");
+    //   // link.click();
+
+    //   // 将canvas转为Blob对象
+    //   canvas.toBlob(async (blob) => {
+    //     if (blob) {
+    //       console.log("blob数据", blob);
+    //       const formData = new FormData();
+    //       formData.append("timestamp", new Date().toISOString());
+    //       formData.append("file", blob, "screenshot.png");
+    //       console.log("上传数据", formData);
+    //       try {
+    //         // const res = await GetPersonByFace(formData);
+    //         // console.log("上传反馈", res);
+    //         // const response = await fetch("System/Person/GetPersonByFace", {
+    //         //   method: "POST",
+    //         //   body: formData,
+    //         // });
+    //       } catch (err) {
+    //         console.error("上传过程中出错:", err);
+    //       }
+    //     }
+    //   }, "image/png");
+    // },
+
+    async captureImage() {
+      const video = this.$refs.video;
+      if (video.paused) return;
+      const canvas = document.createElement("canvas");
+
+      const cropWidth = video.videoWidth * 0.5;
+      const cropHeight = video.videoHeight * 0.98;
+
+      // 设置canvas尺寸为选择区域大小
+      canvas.width = cropWidth;
+      canvas.height = cropHeight;
+
+      const x = (video.videoWidth - cropWidth) / 2;
+      const y = (video.videoHeight - cropHeight) / 2;
+
+      const ctx = canvas.getContext("2d");
+      //中心60%区域
+      ctx.drawImage(
+        video,
+        x,
+        y,
+        cropWidth,
+        cropHeight,
+        0,
+        0,
+        cropWidth,
+        cropHeight
+      );
+      // 获取背景图片元素
+      const backgroundImage = document.getElementById("background-image");
+      console.log("背景图片", backgroundImage.complete);
+      // 等待背景图片加载完成
+      if (!backgroundImage.complete) {
+        backgroundImage.onload = () => {
+          // 绘制背景图片
+          ctx.drawImage(backgroundImage, 0, 0, canvas.width, canvas.height);
+        };
+      } else {
+        // 绘制背景图片
+        ctx.drawImage(backgroundImage, 0, 0, canvas.width, canvas.height);
+      }
+      // canvas.width = video.videoWidth;
+      // canvas.height = video.videoHeight;
+      // const ctx = canvas.getContext("2d");
+      // ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
+      try {
+        const base64Data = canvas.toDataURL("image/png");
+        // console.log("上传数据:Base64", base64Data);
+        // 替换YOUR_SERVER_URL为你的实际服务器地址
+        const response = await fetch(
+          "/yapi/System/Person/GetPersonByFaceBase64",
+          {
+            method: "POST",
+            headers: {
+              token: localStorage.getItem("token"),
+              "Content-Type": "application/json",
+            },
+            body: JSON.stringify({
+              data: base64Data,
+              fileModule: 2,
+            }),
+          }
+        );
+        const result = await response.json();
+        // console.log("上传反馈", response, result);
+        if (result.code === 20000) {
+          // console.log("服务器返回数据:", result);
+          this.$emit("output", result.data);
+          this.uploadImage();
+          // setTimeout(() => {
+          //   this.stopCamera();
+          // }, 200);
+        }
+      } catch (err) {
+        console.error("上传过程中出错:", err);
+      }
+    },
+    async uploadImage() {
+      const video = this.$refs.video;
+      const canvas = document.createElement("canvas");
+
+      const cropWidth = video.videoWidth * 0.5;
+      const cropHeight = video.videoHeight * 0.98;
+
+      // 设置canvas尺寸为选择区域大小
+      canvas.width = cropWidth;
+      canvas.height = cropHeight;
+
+      const x = (video.videoWidth - cropWidth) / 2;
+      const y = (video.videoHeight - cropHeight) / 2;
+
+      const ctx = canvas.getContext("2d");
+      //中心60%区域
+      ctx.drawImage(
+        video,
+        x,
+        y,
+        cropWidth,
+        cropHeight,
+        0,
+        0,
+        cropWidth,
+        cropHeight
+      );
+
+      // 获取背景图片元素
+      const backgroundImage = document.getElementById("background-image");
+      console.log("背景图片", backgroundImage.complete);
+      // 等待背景图片加载完成
+      if (!backgroundImage.complete) {
+        backgroundImage.onload = () => {
+          // 绘制背景图片
+          ctx.drawImage(backgroundImage, 0, 0, canvas.width, canvas.height);
+        };
+      } else {
+        // 绘制背景图片
+        ctx.drawImage(backgroundImage, 0, 0, canvas.width, canvas.height);
+      }
+      // ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
+      const timestampDiv = document.getElementById("timestamp");
+      // 在canvas上绘制时间戳
+      ctx.font = "24px Arial";
+      ctx.fillStyle = "white";
+      ctx.fillText(timestampDiv.textContent, 20, canvas.height - 20);
+      try {
+        const base64Data = canvas.toDataURL("image/png");
+        // console.log("上传数据:Base64", base64Data);
+        // 替换YOUR_SERVER_URL为你的实际服务器地址
+        const response = await fetch("/yapi/File/UploadBase64", {
+          method: "POST",
+          headers: {
+            token: localStorage.getItem("token"),
+            "Content-Type": "application/json",
+          },
+          body: JSON.stringify({
+            data: base64Data,
+            fileModule: 1,
+          }),
+        });
+        const result = await response.json();
+        // console.log("上传反馈", response, result);
+        if (result.code === 20000) {
+          console.log("服务器上传返回数据:", result);
+          this.$emit("outputPath", result.data);
+          setTimeout(() => {
+            this.stopCamera();
+          }, 200);
+        }
+        this.isUpload = false;
+      } catch (err) {
+        console.error("上传过程中出错:", err);
+      }
+    },
+  },
+  created() {
+    this.startCamera();
+    this.refreshTime();
+  },
+  beforeDestroy() {
+    this.stopCamera();
+  },
+};
+</script>
+
+<style scoped>
+.videoContainer {
+  position: relative;
+  width: 50%; /* 容器宽度设为50% */
+  height: 100%; /* 容器高度设为100% */
+  margin: 0 auto; /* 居中显示 */
+  overflow: hidden; /* 隐藏溢出部分 */
+}
+
+#background-image {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  z-index: 1;
+}
+video {
+  height: 800px;
+  width: 1280px;
+  transform: translate(-25%, 0%);
+  /* width: 100%;
+  max-width: 500px; */
+  background: #000;
+  z-index: 0;
+}
+#timestamp {
+  position: absolute;
+  bottom: 20px;
+  left: 20px;
+  color: white;
+  font-size: 24px;
+  background-color: rgba(0, 0, 0, 0.5);
+  padding: 5px;
+}
+</style>

+ 373 - 0
src/views/recognize/components/VideoLocalWindowTest.vue

@@ -0,0 +1,373 @@
+<template>
+  <div class="videoContainer">
+    <video
+      ref="video"
+      id="video"
+      :width="1280"
+      :height="800"
+      autoplay
+      muted
+      playsinline
+    ></video>
+    <div id="timestamp" v-show="false">
+      {{ datetimeData.date + " " + datetimeData.time }}
+    </div>
+    <canvas id="blurred-canvas" :width="1280" :height="800"></canvas>
+    <!-- <el-button @click="startCamera">开启摄像头</el-button>
+    <el-button @click="stopCamera" :disabled="!isCameraActive"
+      >关闭摄像头</el-button
+    > -->
+  </div>
+</template>
+
+
+<script>
+/* eslint-disable */
+import * as tf from "@tensorflow/tfjs";
+import * as bodyPix from "@tensorflow-models/body-pix";
+import { GetPersonByFace, GetPersonByFaceBase64 } from "@/API/custom";
+import Dayjs from "dayjs";
+
+export default {
+  props: {
+    processStep: {
+      type: String,
+      require: true,
+    },
+    isUpload: {
+      type: String,
+      require: false,
+    },
+    cameraData: {
+      type: Object,
+      default: () => ({}),
+    },
+  },
+  watch: {
+    processStep: {
+      handler(step) {
+        if (step == 0 || step == 9) {
+          this.startCamera();
+        } else {
+          this.stopCamera();
+        }
+      },
+      deep: true,
+      immediate: true,
+    },
+    isUpload: {
+      handler(val) {
+        console.log("上传子级开关", val);
+        if (val) {
+          this.uploadImage();
+        } else {
+          this.isUpload = false;
+        }
+      },
+      deep: true,
+      immediate: true,
+    },
+  },
+  data() {
+    return {
+      isCameraActive: false,
+      video: null,
+      stream: null,
+      captureInterval: null, // 新增定时器变量
+      datetimeData: {
+        date: Dayjs(new Date()).format("YYYY-MM-DD"),
+        time: Dayjs(new Date()).format("HH:mm:ss"),
+        week: Dayjs(new Date()).format("dddd"),
+      },
+      // BodyPix模型加载
+      net: null,
+      // 修改默认值为 true,自动开启背景虚化
+      showBlurred: true,
+      loading: true,
+    };
+  },
+  methods: {
+    refreshTime() {
+      let speed = 1000;
+      let timer = null;
+      let theNowTime = () => {
+        // this.datePersonData.time = Dayjs(new Date()).format('HH:mm:ss')
+        this.datetimeData.time = Dayjs(new Date()).format("HH:mm:ss");
+        this.datetimeData.date = Dayjs(new Date()).format("YYYY-MM-DD");
+        this.datetimeData.week = Dayjs(new Date()).format("dddd");
+      };
+      timer = setInterval(theNowTime, speed);
+      this.$once("hook:beforeDestroy", () => {
+        clearInterval(timer);
+        timer = null;
+      });
+    },
+    async loadBodyPix() {
+      this.net = await bodyPix.load();
+      this.processVideoFrame();
+    },
+    async processVideoFrame() {
+      // 确保 video 和 blurredCanvas 存在
+      if (this.showBlurred && this.video && this.blurredCanvas) {
+        try {
+          const segmentation = await this.net.segmentPerson(this.video);
+          const backgroundBlurAmount = 5;
+          const edgeBlurAmount = 3;
+          const flipHorizontal = false;
+
+          bodyPix.drawBokehEffect(
+            this.blurredCanvas,
+            this.video,
+            segmentation,
+            backgroundBlurAmount,
+            edgeBlurAmount,
+            flipHorizontal
+          );
+        } catch (err) {
+          console.error("处理视频帧时出错:", err);
+        }
+      }
+
+      requestAnimationFrame(() => this.processVideoFrame());
+    },
+    async startCamera() {
+      try {
+        this.stream = await navigator.mediaDevices.getUserMedia({
+          video: true,
+        });
+        this.video = document.getElementById("video");
+        this.isCameraActive = true;
+
+        if (this.video) {
+          this.video.srcObject = this.stream;
+          this.loading = false;
+          this.loadBodyPix();
+        } else {
+          this.error = "未能找到视频元素,请检查 HTML 结构。";
+          this.loading = false;
+        }
+
+        if (this.isUpload) {
+          setTimeout(() => {
+            this.uploadImage();
+          }, 1000);
+        } else {
+          // 新增定时截图功能
+          this.captureInterval = setInterval(() => {
+            this.captureImage();
+            console.log("截图上传");
+          }, 2500);
+        }
+      } catch (err) {
+        console.error("摄像头访问错误:", err);
+        alert(`摄像头访问失败: ${err.message}`);
+        this.loading = false;
+      }
+    },
+    stopCamera() {
+      if (this.stream) {
+        this.stream.getTracks().forEach((track) => track.stop());
+        this.isCameraActive = false;
+        this.video.srcObject = null;
+        this.stream = null;
+
+        // 停止定时器
+        if (this.captureInterval) {
+          clearInterval(this.captureInterval);
+          this.captureInterval = null;
+        }
+      }
+    },
+    async captureImage() {
+      if (this.video.paused) return;
+      const canvas = document.createElement("canvas");
+
+      const cropWidth = this.video.videoWidth * 0.5;
+      const cropHeight = this.video.videoHeight * 0.98;
+
+      // 设置canvas尺寸为选择区域大小
+      canvas.width = cropWidth;
+      canvas.height = cropHeight;
+
+      const x = (this.video.videoWidth - cropWidth) / 2;
+      const y = (this.video.videoHeight - cropHeight) / 2;
+
+      const ctx = canvas.getContext("2d");
+      //中心60%区域
+      ctx.drawImage(
+        this.video,
+        x,
+        y,
+        cropWidth,
+        cropHeight,
+        0,
+        0,
+        cropWidth,
+        cropHeight
+      );
+      // canvas.width = video.videoWidth;
+      // canvas.height = video.videoHeight;
+      // const ctx = canvas.getContext("2d");
+      // ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
+      try {
+        const base64Data = canvas.toDataURL("image/png");
+        // console.log("上传数据:Base64", base64Data);
+        // 替换YOUR_SERVER_URL为你的实际服务器地址
+        const response = await fetch(
+          "/yapi/System/Person/GetPersonByFaceBase64",
+          {
+            method: "POST",
+            headers: {
+              token: localStorage.getItem("token"),
+              "Content-Type": "application/json",
+            },
+            body: JSON.stringify({
+              data: base64Data,
+              fileModule: 2,
+            }),
+          }
+        );
+        const result = await response.json();
+        // console.log("上传反馈", response, result);
+        if (result.code === 20000) {
+          // console.log("服务器返回数据:", result);
+          this.$emit("output", result.data);
+          this.uploadImage();
+          // setTimeout(() => {
+          //   this.stopCamera();
+          // }, 200);
+        }
+      } catch (err) {
+        console.error("上传过程中出错:", err);
+      }
+    },
+    async uploadImage() {
+      const canvas = document.createElement("canvas");
+
+      const cropWidth = this.video.videoWidth * 0.5;
+      const cropHeight = this.video.videoHeight * 0.98;
+
+      // 设置canvas尺寸为选择区域大小
+      canvas.width = cropWidth;
+      canvas.height = cropHeight;
+
+      const x = (this.video.videoWidth - cropWidth) / 2;
+      const y = (this.video.videoHeight - cropHeight) / 2;
+
+      const ctx = canvas.getContext("2d");
+      console.log(
+        "???????????????????",
+        x,
+        y,
+        cropWidth,
+        cropHeight,
+        this.video,
+        this.blurredCanvas,
+        canvas
+      );
+      //中心60%区域
+      ctx.drawImage(
+        this.video,
+        x,
+        y,
+        cropWidth,
+        cropHeight,
+        0,
+        0,
+        cropWidth,
+        cropHeight
+      );
+      ctx.drawImage(
+        this.showBlurred ? this.blurredCanvas : this.video,
+        x,
+        y,
+        this.blurredCanvas.width,
+        this.blurredCanvas.height,
+        0,
+        0,
+        cropWidth,
+        cropHeight
+      );
+      // ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
+      const timestampDiv = document.getElementById("timestamp");
+      // 在canvas上绘制时间戳
+      ctx.font = "24px Arial";
+      ctx.fillStyle = "white";
+      ctx.fillText(timestampDiv.textContent, 20, canvas.height - 20);
+      try {
+        const base64Data = canvas.toDataURL("image/png");
+        // console.log("上传数据:Base64", base64Data);
+        // 替换YOUR_SERVER_URL为你的实际服务器地址
+        const response = await fetch("/yapi/File/UploadBase64", {
+          method: "POST",
+          headers: {
+            token: localStorage.getItem("token"),
+            "Content-Type": "application/json",
+          },
+          body: JSON.stringify({
+            data: base64Data,
+            fileModule: 1,
+          }),
+        });
+        const result = await response.json();
+        // console.log("上传反馈", response, result);
+        if (result.code === 20000) {
+          console.log("服务器上传返回数据:", result);
+          this.$emit("outputPath", result.data);
+          setTimeout(() => {
+            this.stopCamera();
+          }, 200);
+        }
+        this.isUpload = false;
+      } catch (err) {
+        console.error("上传过程中出错:", err);
+      }
+    },
+  },
+  mounted() {
+    if (this.loading) {
+      this.blurredCanvas = document.getElementById("blurred-canvas");
+      if (this.blurredCanvas) {
+        this.ctx = this.blurredCanvas.getContext("2d");
+      }
+    }
+  },
+  created() {
+    this.startCamera();
+    this.refreshTime();
+  },
+  beforeDestroy() {
+    this.stopCamera();
+  },
+};
+</script>
+
+<style scoped>
+.videoContainer {
+  position: relative;
+  width: 50%; /* 容器宽度设为50% */
+  height: 100%; /* 容器高度设为100% */
+  margin: 0 auto; /* 居中显示 */
+  overflow: hidden; /* 隐藏溢出部分 */
+}
+video {
+  height: 800px;
+  width: 1280px;
+  transform: translate(-25%, 0%);
+  /* width: 100%;
+  max-width: 500px; */
+  background: #000;
+}
+#timestamp {
+  position: absolute;
+  bottom: 20px;
+  left: 20px;
+  color: white;
+  font-size: 24px;
+  background-color: rgba(0, 0, 0, 0.5);
+  padding: 5px;
+}
+#blurred-video {
+  display: none;
+}
+</style>

+ 332 - 0
src/views/recognize/components/VideoLocalWindowTimestamp.vue

@@ -0,0 +1,332 @@
+<template>
+  <div class="videoContainer">
+    <video ref="video" autoplay muted playsinline></video>
+    <div id="timestamp" v-show="false">
+      {{ datetimeData.date + " " + datetimeData.time }}
+    </div>
+    <!-- <el-button @click="startCamera">开启摄像头</el-button>
+    <el-button @click="stopCamera" :disabled="!isCameraActive"
+      >关闭摄像头</el-button
+    > -->
+  </div>
+</template>
+
+
+<script>
+import { GetPersonByFace, GetPersonByFaceBase64 } from "@/API/custom";
+import Dayjs from "dayjs";
+
+export default {
+  props: {
+    processStep: {
+      type: String,
+      require: true,
+    },
+    isUpload: {
+      type: String,
+      require: false,
+    },
+    cameraData: {
+      type: Object,
+      default: () => ({}),
+    },
+  },
+  watch: {
+    processStep: {
+      handler(step) {
+        if (step == 0 || step == 9) {
+          this.startCamera();
+        } else {
+          this.stopCamera();
+        }
+      },
+      deep: true,
+      immediate: true,
+    },
+    isUpload: {
+      handler(val) {
+        console.log("上传子级开关", val);
+        if (val) {
+          this.uploadImage();
+        } else {
+          this.isUpload = false;
+        }
+      },
+      deep: true,
+      immediate: true,
+    },
+  },
+  data() {
+    return {
+      isCameraActive: false,
+      stream: null,
+      captureInterval: null, // 新增定时器变量
+      datetimeData: {
+        date: Dayjs(new Date()).format("YYYY-MM-DD"),
+        time: Dayjs(new Date()).format("HH:mm:ss"),
+        week: Dayjs(new Date()).format("dddd"),
+      },
+    };
+  },
+  methods: {
+    refreshTime() {
+      let speed = 1000;
+      let timer = null;
+      let theNowTime = () => {
+        // this.datePersonData.time = Dayjs(new Date()).format('HH:mm:ss')
+        this.datetimeData.time = Dayjs(new Date()).format("HH:mm:ss");
+        this.datetimeData.date = Dayjs(new Date()).format("YYYY-MM-DD");
+        this.datetimeData.week = Dayjs(new Date()).format("dddd");
+      };
+      timer = setInterval(theNowTime, speed);
+      this.$once("hook:beforeDestroy", () => {
+        clearInterval(timer);
+        timer = null;
+      });
+    },
+    async startCamera() {
+      try {
+        const stream = await navigator.mediaDevices.getUserMedia({
+          video: {
+            width: { ideal: 1280 },
+            height: { ideal: 800 },
+            facingMode: "user",
+          },
+        });
+        this.stream = stream;
+        this.isCameraActive = true;
+        this.$refs.video.srcObject = stream;
+
+        if (this.isUpload) {
+          setTimeout(() => {
+            this.uploadImage();
+          }, 1000);
+        } else {
+          // 新增定时截图功能
+          this.captureInterval = setInterval(() => {
+            this.captureImage();
+            console.log("截图上传");
+          }, 2500);
+        }
+      } catch (err) {
+        console.error("摄像头访问错误:", err);
+        alert(`摄像头访问失败: ${err.message}`);
+      }
+    },
+    stopCamera() {
+      if (this.stream) {
+        this.stream.getTracks().forEach((track) => track.stop());
+        this.isCameraActive = false;
+        this.$refs.video.srcObject = null;
+        this.stream = null;
+
+        // 停止定时器
+        if (this.captureInterval) {
+          clearInterval(this.captureInterval);
+          this.captureInterval = null;
+        }
+      }
+    },
+    // 新增截图方法
+    // async captureImage() {
+    //   const video = this.$refs.video;
+    //   video.currentTime = 1;
+    //   const canvas = document.createElement("canvas");
+    //   canvas.width = video.videoWidth;
+    //   canvas.height = video.videoHeight;
+    //   canvas
+    //     .getContext("2d")
+    //     .drawImage(video, 0, 0, canvas.width, canvas.height);
+    //   // 下载到本地
+    //   // const link = document.createElement("a");
+    //   // link.download = `capture_${new Date()
+    //   //   .toISOString()
+    //   //   .replace(/[:.]/g, "-")}.png`;
+    //   // link.href = canvas.toDataURL("image/png");
+    //   // link.click();
+
+    //   // 将canvas转为Blob对象
+    //   canvas.toBlob(async (blob) => {
+    //     if (blob) {
+    //       console.log("blob数据", blob);
+    //       const formData = new FormData();
+    //       formData.append("timestamp", new Date().toISOString());
+    //       formData.append("file", blob, "screenshot.png");
+    //       console.log("上传数据", formData);
+    //       try {
+    //         // const res = await GetPersonByFace(formData);
+    //         // console.log("上传反馈", res);
+    //         // const response = await fetch("System/Person/GetPersonByFace", {
+    //         //   method: "POST",
+    //         //   body: formData,
+    //         // });
+    //       } catch (err) {
+    //         console.error("上传过程中出错:", err);
+    //       }
+    //     }
+    //   }, "image/png");
+    // },
+
+    async captureImage() {
+      const video = this.$refs.video;
+      if (video.paused) return;
+      const canvas = document.createElement("canvas");
+
+      const cropWidth = video.videoWidth * 0.5;
+      const cropHeight = video.videoHeight * 0.98;
+
+      // 设置canvas尺寸为选择区域大小
+      canvas.width = cropWidth;
+      canvas.height = cropHeight;
+
+      const x = (video.videoWidth - cropWidth) / 2;
+      const y = (video.videoHeight - cropHeight) / 2;
+
+      const ctx = canvas.getContext("2d");
+      //中心60%区域
+      ctx.drawImage(
+        video,
+        x,
+        y,
+        cropWidth,
+        cropHeight,
+        0,
+        0,
+        cropWidth,
+        cropHeight
+      );
+      // canvas.width = video.videoWidth;
+      // canvas.height = video.videoHeight;
+      // const ctx = canvas.getContext("2d");
+      // ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
+      try {
+        const base64Data = canvas.toDataURL("image/png");
+        // console.log("上传数据:Base64", base64Data);
+        // 替换YOUR_SERVER_URL为你的实际服务器地址
+        const response = await fetch(
+          "/yapi/System/Person/GetPersonByFaceBase64",
+          {
+            method: "POST",
+            headers: {
+              token: localStorage.getItem("token"),
+              "Content-Type": "application/json",
+            },
+            body: JSON.stringify({
+              data: base64Data,
+              fileModule: 2,
+            }),
+          }
+        );
+        const result = await response.json();
+        // console.log("上传反馈", response, result);
+        if (result.code === 20000) {
+          // console.log("服务器返回数据:", result);
+          this.$emit("output", result.data);
+          this.uploadImage();
+          // setTimeout(() => {
+          //   this.stopCamera();
+          // }, 200);
+        }
+      } catch (err) {
+        console.error("上传过程中出错:", err);
+      }
+    },
+    async uploadImage() {
+      const video = this.$refs.video;
+      const canvas = document.createElement("canvas");
+
+      const cropWidth = video.videoWidth * 0.5;
+      const cropHeight = video.videoHeight * 0.98;
+
+      // 设置canvas尺寸为选择区域大小
+      canvas.width = cropWidth;
+      canvas.height = cropHeight;
+
+      const x = (video.videoWidth - cropWidth) / 2;
+      const y = (video.videoHeight - cropHeight) / 2;
+
+      const ctx = canvas.getContext("2d");
+      //中心60%区域
+      ctx.drawImage(
+        video,
+        x,
+        y,
+        cropWidth,
+        cropHeight,
+        0,
+        0,
+        cropWidth,
+        cropHeight
+      );
+      // ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
+      const timestampDiv = document.getElementById("timestamp");
+      // 在canvas上绘制时间戳
+      ctx.font = "24px Arial";
+      ctx.fillStyle = "white";
+      ctx.fillText(timestampDiv.textContent, 20, canvas.height - 20);
+      try {
+        const base64Data = canvas.toDataURL("image/png");
+        // console.log("上传数据:Base64", base64Data);
+        // 替换YOUR_SERVER_URL为你的实际服务器地址
+        const response = await fetch("/yapi/File/UploadBase64", {
+          method: "POST",
+          headers: {
+            token: localStorage.getItem("token"),
+            "Content-Type": "application/json",
+          },
+          body: JSON.stringify({
+            data: base64Data,
+            fileModule: 1,
+          }),
+        });
+        const result = await response.json();
+        // console.log("上传反馈", response, result);
+        if (result.code === 20000) {
+          console.log("服务器上传返回数据:", result);
+          this.$emit("outputPath", result.data);
+          setTimeout(() => {
+            this.stopCamera();
+          }, 200);
+        }
+        this.isUpload = false;
+      } catch (err) {
+        console.error("上传过程中出错:", err);
+      }
+    },
+  },
+  created() {
+    this.startCamera();
+    this.refreshTime();
+  },
+  beforeDestroy() {
+    this.stopCamera();
+  },
+};
+</script>
+
+<style scoped>
+.videoContainer {
+  position: relative;
+  width: 50%; /* 容器宽度设为50% */
+  height: 100%; /* 容器高度设为100% */
+  margin: 0 auto; /* 居中显示 */
+  overflow: hidden; /* 隐藏溢出部分 */
+}
+video {
+  height: 800px;
+  width: 1280px;
+  transform: translate(-25%, 0%);
+  /* width: 100%;
+  max-width: 500px; */
+  background: #000;
+}
+#timestamp {
+  position: absolute;
+  bottom: 20px;
+  left: 20px;
+  color: white;
+  font-size: 24px;
+  background-color: rgba(0, 0, 0, 0.5);
+  padding: 5px;
+}
+</style>

+ 219 - 34
src/views/recognize/index.vue

@@ -96,6 +96,20 @@
               />
             </span>
           </div>
+          <div class="infomation_data" v-if="processStep.num == 1">
+            <el-image
+              :key="refreshKey"
+              style="
+                width: 300px;
+                height: 400px;
+                top: 340px;
+                left: 260px;
+                position: absolute;
+              "
+              :src="tempPhotoPath"
+            >
+            </el-image>
+          </div>
           <div class="infomation_button">
             <el-button
               style="width: 160px; height: 80px; font-size: xx-large"
@@ -205,6 +219,32 @@
               </span>
             </div>
           </div>
+          <div class="infomation_data">
+            <el-image
+              v-if="personType == 1"
+              :key="refreshKey"
+              style="
+                width: 200px;
+                height: 300px;
+                top: 340px;
+                position: absolute;
+              "
+              :src="tempPhotoPath"
+            >
+            </el-image>
+            <el-image
+              v-if="personType == 2"
+              :key="refreshKey"
+              style="
+                width: 200px;
+                height: 300px;
+                top: 380px;
+                position: absolute;
+              "
+              :src="tempPhotoPath"
+            >
+            </el-image>
+          </div>
           <div class="infomation_button">
             <el-button
               style="
@@ -394,6 +434,20 @@
               />
             </span>
           </div>
+          <div class="infomation_data">
+            <el-image
+              :key="refreshKey"
+              style="
+                width: 300px;
+                height: 400px;
+                top: 340px;
+                left: 260px;
+                position: absolute;
+              "
+              :src="tempPhotoPath"
+            >
+            </el-image>
+          </div>
           <div class="infomation_button">
             <el-button
               style="width: 160px; height: 80px; font-size: xx-large"
@@ -576,6 +630,7 @@ import {
   personComingTagUpdate,
   RefreshDriver,
   bindAndUnbindrecord,
+  GetPersonList,
 } from "@/API/custom";
 import Dayjs from "dayjs";
 
@@ -590,10 +645,15 @@ export default {
   },
   data() {
     return {
+      tempPhotoPath: "",
       refreshKey: 0, //页面刷新
       cardEnable: false, //rfid刷卡
       idEnable: false, //身份证刷卡
       uploadPic: false, //上传录入
+      recognizeSuccess: false, //识别成功
+      finallySet: false, //最终修改
+      nameEnbale: false, //最终修改
+      tempList: [],
       fullLoading: null,
       rfid: "",
       idCardData: {},
@@ -793,6 +853,7 @@ export default {
         ],
         tableData: [],
       },
+      pPath: "~@/assets/imgs/stationMap/default_0.png",
     };
   },
   watch: {
@@ -871,12 +932,43 @@ export default {
       deep: true,
       immediate: true,
     },
+    tempPhotoPath: {
+      handler(newVal, oldVal) {
+        console.log("照片路径:", newVal);
+        this.refresh();
+      },
+      deep: true,
+      immediate: true,
+    },
+    nameEnbale: {
+      handler(newVal) {
+        console.log("重名检测", newVal);
+        if (newVal) {
+          this.$alert("系统有同名人员,请加区分前缀、后缀修改名称", "提示", {
+            confirmButtonText: "返回修改",
+            callback: () => {
+              if (this.processStep.num == 2 || this.processStep.num == 11) {
+                this.processStep.num--;
+              } else if (this.processStep.num == 14) {
+                this.processStep.num = this.processStep.num - 4;
+                this.infomation.persons.pop();
+              }
+            },
+          });
+        }
+      },
+      deep: true,
+      immediate: true,
+    },
   },
   mounted() {
     this.init();
   },
   computed: {
     ...mapGetters(["personInfo"]),
+    VUE_APP_BASE_API() {
+      return process.env.VUE_APP_BASE_API;
+    },
   },
   methods: {
     init() {
@@ -912,7 +1004,7 @@ export default {
     },
     recognize() {
       if (this.recognizeEnable) {
-        console.log("人脸识别", this.processStep);
+        // console.log("人脸识别", this.processStep);
         // setTimeout(() => {
         //   this.processStep.num++;
         // }, 3000);
@@ -944,8 +1036,9 @@ export default {
           field007: person.count, //总计人数
           field008: this.names, //同行人员姓名
           field009: person.dangerousEnable ? "有" : "无", //危险品检查
-          field010: person.cause ? "是" : "否", //施工作业
+          field010: person.workerEnable ? "是" : "否", //施工作业
           field011: this.areas, //进站区域
+          field012: person.photoPath, //登记照片
           pageId: "842348058862690304", //入场登记
         };
         console.log("记录基础信息3:", record);
@@ -955,6 +1048,28 @@ export default {
         console.log(err);
       }
     },
+    async getPersonList(person) {
+      try {
+        const params = {
+          // pageSize: 10000,
+          // pageIndex: 1,
+          name: person.name, //登记时间
+        };
+        this.nameEnbale = false;
+        const res = await GetPersonList(params);
+        this.tempList = res.data.content;
+        console.log("名称信息", params);
+        for (let i = 0; i < this.tempList.length; i++) {
+          const p = this.tempList[i];
+          if (p.name === params.name) {
+            this.nameEnbale = true;
+          }
+        }
+        // console.log("名称检索数据表", this.tempList);
+      } catch (err) {
+        console.log(err);
+      }
+    },
     openFullScreen() {
       const loading = this.$loading({
         lock: true,
@@ -965,7 +1080,7 @@ export default {
       setTimeout(() => {
         loading.close();
         this.processStep.num++;
-      }, 2000);
+      }, 1000);
     },
     handleAudio(key, element = document) {
       const options = {
@@ -986,14 +1101,17 @@ export default {
         switch (type) {
           case 8:
             this.processStep.num--;
-            console.log("上一步");
+            // console.log("上一步");
             break;
           case 7:
             this.processStep.num++;
-            console.log("跳过人脸识别");
+            // console.log("跳过人脸识别");
             break;
           case 1:
-            console.log("人员登记信息流程");
+            // console.log("人员登记信息流程");
+            if (this.processStep.num === 1 && this.infomation.id === "") {
+              this.getPersonList({ name: this.infomation.name });
+            }
             if (this.personType == 1 && this.processStep.num === 2) {
               this.processStep.num += 3;
             } else {
@@ -1003,7 +1121,7 @@ export default {
           case 2:
             this.openFullScreen();
             // this.processStep.num++;
-            console.log("入场登记通知领导");
+            // console.log("入场登记通知领导");
             break;
           case 3:
             if (this.infomation.personEnable) {
@@ -1011,17 +1129,17 @@ export default {
             } else {
               this.processStep.num += 6;
             }
-            console.log("人脸识别");
+            // console.log("人脸识别");
             break;
           case 4:
             this.processStep.num++;
             this.initTableInfo();
-            console.log("登记绑卡");
+            // console.log("登记绑卡");
             break;
           case 6:
             this.checkPersonCardNo();
             this.bindInfoRecord(this.infomation);
-            console.log("完成登记");
+            // console.log("完成登记");
             break;
           case 5:
             if (this.personType == 1 && this.processStep.num === 11) {
@@ -1033,16 +1151,19 @@ export default {
               }
               this.processStep.num++;
             }
-            console.log("同行人员信息");
+            // console.log("同行人员信息");
             break;
           case 9:
             if (this.processStep.num === 10) {
+              if (this.person.id === "") {
+                this.getPersonList({ name: this.person.name }); //人员重名检测
+              }
+              this.person.department = this.infomation.department;
               this.processStep.num += 4;
               this.infomation.persons.push(this.person);
             }
             console.log("同行人员信息");
             break;
-
           default:
             break;
         }
@@ -1070,29 +1191,30 @@ export default {
         this.infomation.persons = this.infomation.persons.filter((e) => {
           return e.name !== data.name;
         });
+        this.person.id = "";
         this.tableConfig.tableData = this.infomation.persons;
-        console.log("删除", data, this.infomation.persons);
+        // console.log("删除", data, this.infomation.persons);
         this.refresh();
       }
       if (btnType === "close") {
-        console.log("解绑", data);
+        // console.log("解绑", data);
       }
       if (btnType === "input") {
-        console.log("录入人脸", data);
+        // console.log("录入人脸", data);
       }
     },
     addPerson() {
       this.infomation.personEnable = 1;
       this.person = {
         //初始化
+        id: "",
         name: "",
         company: this.infomation.company,
         idNumber: "",
         telephone: "",
         label: "",
         photoPath: "",
-        department:
-          this.personType === 1 ? "821025772184543232" : "821025720783347712",
+        department: this.infomation.department,
         position:
           this.personType === 1 ? "821073061166981120" : "821073092108361728",
         type:
@@ -1145,7 +1267,7 @@ export default {
     },
     handleByfaceUpload() {
       this.uploadPic = true;
-      console.log("上传父级开关", this.uploadPic);
+      // console.log("上传父级开关", this.uploadPic);
     },
     // 头像上传
     handleByfaceUploadPath(data) {
@@ -1153,14 +1275,48 @@ export default {
       if (data) {
         switch (this.processStep.num) {
           case 0:
-            this.processStep.num++;
-            this.infomation["photoPath"] = data;
+            if (this.recognizeSuccess) {
+              this.processStep.num += 5;
+            } else {
+              this.processStep.num++;
+            }
+            if (this.personType === 1) {
+              if (this.infomation.workNo === null) {
+                this.infomation["photoPath"] = data;
+              } else {
+                this.infomation["photoPath"] =
+                  this.infomation["photoPath"] !== ""
+                    ? this.infomation["photoPath"]
+                    : data;
+              }
+            } else {
+              this.infomation["photoPath"] = data;
+            }
+            this.tempPhotoPath = "https://10.0.0.201:8083" + "/yapi" + data;
             this.uploadPic = false;
+            this.recognizeSuccess = false;
             break;
           case 9:
-            this.processStep.num++;
-            this.person["photoPath"] = data;
+            if (this.recognizeSuccess) {
+              this.processStep.num += 5;
+            } else {
+              this.processStep.num++;
+            }
+            if (this.personType === 1) {
+              if (this.person.workNo === null) {
+                this.person["photoPath"] = data;
+              } else {
+                this.person["photoPath"] =
+                  this.person["photoPath"] !== ""
+                    ? this.person["photoPath"]
+                    : data;
+              }
+            } else {
+              this.person["photoPath"] = data;
+            }
+            this.tempPhotoPath = "https://10.0.0.201:8083" + "/yapi" + data;
             this.uploadPic = false;
+            this.recognizeSuccess = false;
             break;
           default:
             break;
@@ -1169,11 +1325,12 @@ export default {
     },
     // 人脸识别读取
     handleByfaceOut(data) {
-      console.log("人脸识别反馈", data);
+      // console.log("人脸识别反馈", data);
+      this.recognizeSuccess = true;
       if (data) {
         switch (this.processStep.num) {
           case 0:
-            this.processStep.num += 5;
+            // this.processStep.num += 5;
             this.infomation["id"] = data.id;
             this.infomation["name"] = data.name;
             this.infomation["companyName"] = data.companyName;
@@ -1183,14 +1340,28 @@ export default {
             this.infomation["idNumber"] = data.idNumber;
             this.infomation["telephone"] = data.telephone;
             this.infomation["cardNo"] = data.cardNo;
+            this.infomation["workNo"] = data.workNo;
             this.infomation["photoPath"] = data.photoPath;
-            this.infomation["department"] = this.personType === 1 ? "821025772184543232" : "821025720783347712";
-            this.infomation["position"] = this.personType === 1 ? "821073061166981120" : "821073092108361728";
-            this.infomation["type"] = this.personType === 1 ? "546093319541760000" : "403245878963347456";
+            if (data.department) {
+              this.infomation["department"] = data.department;
+            } else {
+              this.infomation["department"] =
+                this.personType === 1
+                  ? "821025772184543232"
+                  : "821025720783347712";
+            }
+            this.infomation["position"] =
+              this.personType === 1
+                ? "821073061166981120"
+                : "821073092108361728";
+            this.infomation["type"] =
+              this.personType === 1
+                ? "546093319541760000"
+                : "403245878963347456";
             this.infomation["accessControlIds"] = data.accessControlIds;
             break;
           case 9:
-            this.processStep.num += 5;
+            // this.processStep.num += 5;
             this.person["id"] = data.id;
             this.person["name"] = data.name;
             this.person["companyName"] = data.companyName;
@@ -1200,16 +1371,30 @@ export default {
             this.person["idNumber"] = data.idNumber;
             this.person["telephone"] = data.telephone;
             this.person["cardNo"] = data.cardNo;
+            this.person["workNo"] = data.workNo;
             this.person["photoPath"] = data.photoPath;
-            this.person["department"] = this.personType === 1 ? "821025772184543232" : "821025720783347712";
-            this.person["position"] = this.personType === 1 ? "821073061166981120" : "821073092108361728";
-            this.person["type"] = this.personType === 1 ? "546093319541760000" : "403245878963347456";
+            if (data.department) {
+              this.infomation["department"] = data.department;
+            } else {
+              this.infomation["department"] =
+                this.personType === 1
+                  ? "821025772184543232"
+                  : "821025720783347712";
+            }
+            this.person["position"] =
+              this.personType === 1
+                ? "821073061166981120"
+                : "821073092108361728";
+            this.person["type"] =
+              this.personType === 1
+                ? "546093319541760000"
+                : "403245878963347456";
             this.person["accessControlIds"] = data.typeBelong;
             if (!this.checkIn(data.id)) {
               this.infomation.persons.push(this.person);
-              console.log("添加", data.name);
+              // console.log("添加", data.name);
             } else {
-              console.log("人员已添加");
+              // console.log("人员已添加");
             }
             break;
           default:
@@ -1219,7 +1404,7 @@ export default {
     },
     // 读取身份证
     readIdCard(data) {
-      console.log("身份证信息", data);
+      // console.log("身份证信息", data);
       if (data) {
         switch (this.processStep.num) {
           case 3:

+ 183 - 0
src/views/test/index.vue

@@ -0,0 +1,183 @@
+<template>
+  <div class="recognize-main">
+    <div style="display: flex; gap: 20px">
+      <div id="video-container">
+        <video id="video" :width="640" :height="480" autoplay></video>
+      </div>
+      <!-- 新增虚化显示框 -->
+      <div>
+        <canvas
+          v-show="false"
+          id="blurred-canvas"
+          :width="640"
+          :height="480"
+        ></canvas>
+      </div>
+    </div>
+    <div>
+      <button id="capture-btn" @click="capture">截图</button>
+      <!-- 新增虚化背景按钮 -->
+      <button id="blur-btn" @click="toggleBlurred">
+        {{ showBlurred ? "隐藏虚化" : "显示虚化" }}
+      </button>
+    </div>
+    <div id="snapshot-container">
+      <canvas id="canvas" :width="640" :height="480"></canvas>
+    </div>
+  </div>
+</template>
+  
+  <script>
+/* eslint-disable */
+import * as tf from "@tensorflow/tfjs";
+import * as bodyPix from "@tensorflow-models/body-pix";
+
+export default {
+  name: "CameraCapture",
+  data() {
+    return {
+      video: null,
+      canvas: null,
+      captureBtn: null,
+      blurredCanvas: null,
+      ctx: null,
+      net: null,
+      // 修改默认值为 true,自动开启背景虚化
+      showBlurred: true,
+      loading: true,
+      error: null,
+      stream: null,
+    };
+  },
+  mounted() {
+    this.initializeCamera();
+    // 提前获取 canvas 元素
+    this.canvas = document.getElementById("canvas");
+    this.blurredCanvas = document.getElementById("blurred-canvas");
+    if (this.blurredCanvas) {
+      this.ctx = this.blurredCanvas.getContext("2d");
+    }
+  },
+  beforeDestroy() {
+    if (this.stream) {
+      this.stream.getTracks().forEach((track) => track.stop());
+    }
+  },
+  methods: {
+    async initializeCamera() {
+      try {
+        this.stream = await navigator.mediaDevices.getUserMedia({
+          video: true,
+        });
+        this.video = document.getElementById("video");
+        if (this.video) {
+          this.video.srcObject = this.stream;
+          this.loading = false;
+          this.loadBodyPix();
+        } else {
+          this.error = "未能找到视频元素,请检查 HTML 结构。";
+          this.loading = false;
+        }
+      } catch (err) {
+        console.error("访问摄像头失败:", err);
+        if (err.name === "NotAllowedError") {
+          this.error = "您拒绝了摄像头访问权限,请刷新页面并允许访问。";
+        } else if (err.name === "NotFoundError") {
+          this.error = "未检测到摄像头设备,请检查设备连接。";
+        } else {
+          this.error = "无法访问摄像头,请检查权限或设备连接。";
+        }
+        this.loading = false;
+      }
+    },
+    async loadBodyPix() {
+      this.net = await bodyPix.load();
+      this.processVideoFrame();
+    },
+    async processVideoFrame() {
+      // 确保 video 和 blurredCanvas 存在
+      if (this.showBlurred && this.video && this.blurredCanvas) {
+        try {
+          const segmentation = await this.net.segmentPerson(this.video);
+          const backgroundBlurAmount = 5;
+          const edgeBlurAmount = 3;
+          const flipHorizontal = false;
+
+          bodyPix.drawBokehEffect(
+            this.blurredCanvas,
+            this.video,
+            segmentation,
+            backgroundBlurAmount,
+            edgeBlurAmount,
+            flipHorizontal
+          );
+        } catch (err) {
+          console.error("处理视频帧时出错:", err);
+        }
+      }
+
+      requestAnimationFrame(() => this.processVideoFrame());
+    },
+    capture() {
+      if (this.canvas) {
+        const ctx = this.canvas.getContext("2d");
+        ctx.drawImage(
+          this.showBlurred ? this.blurredCanvas : this.video,
+          0,
+          0,
+          this.canvas.width,
+          this.canvas.height
+        );
+
+        const link = document.createElement("a");
+        link.download = "snapshot.png";
+        link.href = this.canvas.toDataURL();
+        link.click();
+      } else {
+        console.error("未能找到截图 canvas 元素");
+      }
+    },
+    toggleBlurred() {
+      this.showBlurred = !this.showBlurred;
+      // 确保在切换时 canvas 已正确获取上下文
+      if (this.showBlurred) {
+        this.blurredCanvas = document.getElementById("blurred-canvas");
+        if (this.blurredCanvas) {
+          this.ctx = this.blurredCanvas.getContext("2d");
+        } else {
+          console.error("未能找到虚化 canvas 元素");
+        }
+      }
+    },
+  },
+};
+</script>
+  
+  <style scoped>
+.recognize-main {
+  width: 100%;
+  height: 100%;
+  padding: 100px 30px 40px;
+  pointer-events: auto;
+  color: #fff;
+}
+#video-container {
+  margin-bottom: 20px;
+}
+#snapshot-container {
+  margin-top: 20px;
+}
+#capture-btn,
+#blur-btn {
+  backdrop-filter: blur(12px);
+  background-color: rgba(255, 255, 255, 0.5);
+  border: none;
+  padding: 10px 20px;
+  border-radius: 5px;
+  cursor: pointer;
+  margin-right: 10px;
+}
+#blurred-video {
+  display: none;
+}
+</style>

+ 2 - 2
vue.config.js

@@ -19,7 +19,7 @@ module.exports = {
       '/yapi': {
         target: 'https://10.0.0.201:8080/prod-api/', // 托克托现场
         // target: 'http://172.168.0.62:8080/prod-api/', // 托克托现场
-        // target: 'http://192.168.195.136:8080/prod-api/', // 托克托本地虚拟机
+        // target: 'https://192.168.195.136:8080/prod-api/', // 托克托本地虚拟机
         // target: "http://localhost:5002", // 远程服务器-赵哥
         changeOrigin: true,
         pathRewrite: {
@@ -29,7 +29,7 @@ module.exports = {
       '/model': {
         target: 'https://10.0.0.201:8081/model/', //托克托模型现场服务器
         // target: 'http://172.168.0.62:8081/model/', //托克托模型现场服务器
-        // target: 'http://192.168.195.136:8081/model/', //托克托模型虚拟机
+        // target: 'https://192.168.195.136:8081/model/', //托克托模型虚拟机
         changeOrigin: true,
         pathRewrite: {
           '^/model': '/',