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