|
@@ -1,244 +1,114 @@
|
|
|
<template>
|
|
|
- <el-form class="login-form" status-icon :rules="loginRules" ref="loginForm" :model="loginForm" label-width="0">
|
|
|
- <el-form-item prop="username" style="padding-left: 44px">
|
|
|
- <div class="video" style="z-index: 1">
|
|
|
- <video id="video" width="274" height="265" preload autoplay loop muted style="z-index: 1;"></video>
|
|
|
- </div>
|
|
|
- <!-- <div class="renlian" style="z-index: 999">
|
|
|
+ <div class="renlianBox">
|
|
|
+ <div class="videoBox">
|
|
|
+ <video id="video" width="290" height="300" preload autoplay loop muted></video>
|
|
|
+ <div class="renlian" style="z-index: 999">
|
|
|
<div class="box">
|
|
|
<div class="line"></div>
|
|
|
<div class="bottom"></div>
|
|
|
</div>
|
|
|
- </div> -->
|
|
|
+ </div>
|
|
|
<canvas id="canvas" width="500" height="500" style="position: fixed;top: -10000px"></canvas>
|
|
|
- </el-form-item>
|
|
|
- <!-- <a href="#" style="color: red;font-weight: bold">提示:如果未录入人脸请联系管理员进行录入</a>-->
|
|
|
- </el-form>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ </div>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
-import { mapGetters } from "vuex";
|
|
|
-// import { info } from "@/api/system/tenant";
|
|
|
-// import * as user from "@/api/user";
|
|
|
-// import { getTopUrl } from "@/util/util";
|
|
|
+import tracking from '@/api/tracking-min'
|
|
|
+import '@/api/face-min'
|
|
|
export default {
|
|
|
name: "renlian",
|
|
|
data () {
|
|
|
return {
|
|
|
- tenantMode: false,
|
|
|
- loginForm: {
|
|
|
- //租户ID
|
|
|
- tenantId: "000000",
|
|
|
- //用户名
|
|
|
- username: "",
|
|
|
- //密码
|
|
|
- password: "",
|
|
|
- //账号类型
|
|
|
- type: "account",
|
|
|
- //验证码的值
|
|
|
- code: "",
|
|
|
- //验证码的索引
|
|
|
- key: "",
|
|
|
- //预加载白色背景
|
|
|
- image: "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7",
|
|
|
- },
|
|
|
- loginRules: {
|
|
|
- tenantId: [
|
|
|
- { required: false, message: "请输入租户ID", trigger: "blur" }
|
|
|
- ],
|
|
|
- username: [
|
|
|
- { required: true, message: "请输入用户名", trigger: "blur" }
|
|
|
- ],
|
|
|
- password: [
|
|
|
- { required: true, message: "请输入密码", trigger: "blur" },
|
|
|
- { min: 1, message: "密码长度最少为6位", trigger: "blur" }
|
|
|
- ]
|
|
|
- },
|
|
|
- passwordType: "password"
|
|
|
+ video: null,
|
|
|
+ canvas: null,
|
|
|
+ uploadLock: true
|
|
|
};
|
|
|
},
|
|
|
- created () {
|
|
|
-
|
|
|
- },
|
|
|
mounted () {
|
|
|
- let that = this
|
|
|
- setTimeout(function () {
|
|
|
- that.openCamera()
|
|
|
- that.getTenant();
|
|
|
- that.refreshCode();
|
|
|
- }, 1000)
|
|
|
+ this.openCamera()
|
|
|
},
|
|
|
- destroyed () {
|
|
|
- // console.log(1111111111)
|
|
|
- // // 停止侦测
|
|
|
- this.trackerTask.stop()
|
|
|
- // // 关闭摄像头
|
|
|
- // window.tracking.closeCamera()
|
|
|
- },
|
|
|
- // computed: {
|
|
|
- // ...mapGetters(["tagWel"])
|
|
|
- // },
|
|
|
- props: [],
|
|
|
methods: {
|
|
|
- closeshexiangtou () {
|
|
|
- this.trackerTask.stop()
|
|
|
- },
|
|
|
- refreshCode () {
|
|
|
- user.getCaptcha().then(res => {
|
|
|
- const data = res.data;
|
|
|
- this.loginForm.key = data.key;
|
|
|
- this.loginForm.image = data.image;
|
|
|
- })
|
|
|
- },
|
|
|
- showPassword () {
|
|
|
- this.passwordType === ""
|
|
|
- ? (this.passwordType = "password")
|
|
|
- : (this.passwordType = "");
|
|
|
- },
|
|
|
- handleLogin () {
|
|
|
- this.$refs.loginForm.validate(valid => {
|
|
|
- if (valid) {
|
|
|
- const loading = this.$loading({
|
|
|
- lock: true,
|
|
|
- text: '登录中,请稍后。。。',
|
|
|
- spinner: "el-icon-loading"
|
|
|
- });
|
|
|
- this.$store.dispatch("LoginByUsername", this.loginForm).then(() => {
|
|
|
- // this.$router.push({ path: this.tagWel.value });
|
|
|
- loading.close();
|
|
|
- }).catch(() => {
|
|
|
- loading.close();
|
|
|
- this.refreshCode();
|
|
|
- });
|
|
|
- }
|
|
|
- });
|
|
|
- },
|
|
|
- getTenant () {
|
|
|
- let domain = getTopUrl();
|
|
|
- info(domain).then(res => {
|
|
|
- const data = res.data;
|
|
|
- if (data.success && data.data.tenantId) {
|
|
|
- this.tenantMode = false;
|
|
|
- this.loginForm.tenantId = data.data.tenantId;
|
|
|
- this.$parent.$refs.login.style.backgroundImage = `url(${data.data.backgroundUrl})`;
|
|
|
- }
|
|
|
- })
|
|
|
- },
|
|
|
-
|
|
|
-
|
|
|
+ // 初始化设置
|
|
|
openCamera () {
|
|
|
-
|
|
|
- console.log(new tracking)
|
|
|
-
|
|
|
- var video = document.getElementById('video');
|
|
|
- var canvas = document.getElementById('canvas');
|
|
|
- var context = canvas.getContext('2d');
|
|
|
-
|
|
|
-
|
|
|
- var tracker = new tracking.ObjectTracker('face'); // 引入第三方 库
|
|
|
- tracker.setInitialScale(1);
|
|
|
+ this.video = document.getElementById('video');
|
|
|
+ this.canvas = document.getElementById('canvas');
|
|
|
+ let canvas = document.getElementById('canvas');
|
|
|
+ let context = canvas.getContext('2d');
|
|
|
+
|
|
|
+ // 固定写法
|
|
|
+ let tracker = new window.tracking.ObjectTracker('face');
|
|
|
+ tracker.setInitialScale(4);
|
|
|
tracker.setStepSize(2);
|
|
|
tracker.setEdgesDensity(0.1);
|
|
|
-
|
|
|
- this.trackerTask = tracking.track('#video', tracker, { camera: true });
|
|
|
- //------- 指定 canvas 的宽高 ,auto 自动播放
|
|
|
- let constraints = {
|
|
|
- video: { width: 300, height: 300 },
|
|
|
- audio: true
|
|
|
- };
|
|
|
-
|
|
|
- let promise = navigator.mediaDevices.getUserMedia(constraints); // h5 新的API
|
|
|
-
|
|
|
- promise.then(function (MediaStream) {
|
|
|
- video.srcObject = MediaStream;
|
|
|
- video.play();
|
|
|
- }).catch(function (PermissionDeniedError) {
|
|
|
- console.log(PermissionDeniedError);
|
|
|
- })
|
|
|
- //--------------
|
|
|
- let that = this;
|
|
|
- that.tracker_fun(tracker, video, context, canvas); //open 摄像头,执行tracker_fun( 传入参数 )
|
|
|
-
|
|
|
- },
|
|
|
- tracker_fun (tracker, video, context, canvas) {
|
|
|
+ window.tracking.track('#video', tracker, {
|
|
|
+ camera: true
|
|
|
+ });
|
|
|
let that = this;
|
|
|
- let set_clear;
|
|
|
- set_clear = setInterval(function () { // 每秒 检测人脸 结果
|
|
|
- tracker.on('track', function (event) { // 视频流
|
|
|
- if (!that.first) { // if --- > else 检测到人脸 success() =>{}
|
|
|
- event.data.forEach(function (rect) {
|
|
|
- if (rect.x) {
|
|
|
- that.first = rect.x;
|
|
|
- // video.pause(); // success 将暂停 video
|
|
|
- context.drawImage(video, 0, 0, 500, 500); // 绘制到 canvas
|
|
|
- context.font = '11px Helvetica';
|
|
|
- context.fillText("", 100, 40);
|
|
|
- context.strokeStyle = '#a64ceb';
|
|
|
- context.strokeRect(rect.x, rect.y, rect.width, rect.height);
|
|
|
- var data_url = canvas.toDataURL('image/png'); //base64 request
|
|
|
- that.$store.dispatch("LoginByrenlian", data_url).then((res) => {
|
|
|
- if (res.error_code == 400) {
|
|
|
- setTimeout(function () {
|
|
|
- that.first = null;
|
|
|
- }, 3000)
|
|
|
- this.$message.error(res.error_msg);
|
|
|
- } else {
|
|
|
- const loading = that.$loading({
|
|
|
- lock: true,
|
|
|
- text: '登录中,请稍后。。。',
|
|
|
- spinner: "el-icon-loading"
|
|
|
- });
|
|
|
- clearInterval(set_clear)
|
|
|
- setTimeout(function () {
|
|
|
- loading.close();
|
|
|
- location.reload();
|
|
|
- // that.$router.resolve({path: that.tagWel.value});
|
|
|
- }, 3000)
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- }).catch(() => {
|
|
|
- setTimeout(function () {
|
|
|
- that.first = null;
|
|
|
- }, 3000)
|
|
|
- });
|
|
|
- // return;
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
+ tracker.on('track', (event) => {
|
|
|
+ // 检测出人脸 绘画人脸位置
|
|
|
+ context.clearRect(0, 0, canvas.width, canvas.height);
|
|
|
+ event.data.forEach((rect) => {
|
|
|
+ context.strokeStyle = '#0764B7';
|
|
|
+ context.strokeRect(rect.x, rect.y, rect.width, rect.height);
|
|
|
+ // 上传图片
|
|
|
+ that.uploadLock && that.screenshotAndUpload();
|
|
|
});
|
|
|
- // clearTimeout(set_clear)
|
|
|
- // console.log('-------')
|
|
|
- }, 3000)
|
|
|
-
|
|
|
- }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ // 上传图片
|
|
|
+ screenshotAndUpload () {
|
|
|
+ // 上锁避免重复发送请求
|
|
|
+ this.uploadLock = false;
|
|
|
+ // 绘制当前帧图片转换为base64格式
|
|
|
+ let canvas = this.canvas;
|
|
|
+ let video = this.video;
|
|
|
+ let ctx = canvas.getContext('2d');
|
|
|
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
|
+ ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
|
|
|
+ let base64Img = canvas.toDataURL('image/jpeg');
|
|
|
+ // 使用 base64Img 请求接口即可
|
|
|
+ console.log('base64Img:', base64Img)
|
|
|
+ // 三秒后重新检测人脸
|
|
|
+ // setTimeout(()=>{
|
|
|
+ // this.uploadLock = true
|
|
|
+ // },3000)
|
|
|
+ },
|
|
|
}
|
|
|
-};
|
|
|
+
|
|
|
+}
|
|
|
</script>
|
|
|
|
|
|
-<style>
|
|
|
+<style lang="scss">
|
|
|
+.renlianBox {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ .videoBox {
|
|
|
+ width: 290px;
|
|
|
+ height: 290px;
|
|
|
+ margin: 30px auto;
|
|
|
+ position: relative;
|
|
|
+ }
|
|
|
+}
|
|
|
.renlian {
|
|
|
- position: relative;
|
|
|
- height: 90px;
|
|
|
- width: 274px;
|
|
|
+ position: absolute;
|
|
|
+ left: 0;
|
|
|
+ top: 0;
|
|
|
background-size: 100% 100%;
|
|
|
}
|
|
|
.video {
|
|
|
position: relative;
|
|
|
- height: 90px;
|
|
|
- width: 274px;
|
|
|
+ // height: 90px;
|
|
|
+ // width: 274px;
|
|
|
background-size: 100% 100%;
|
|
|
}
|
|
|
|
|
|
.renlian .box {
|
|
|
- width: 30vw;
|
|
|
- height: 30vw;
|
|
|
- max-height: 30vh;
|
|
|
- max-width: 30vh;
|
|
|
- position: relative;
|
|
|
- left: 50%;
|
|
|
- top: 50%;
|
|
|
- transform: translate(-50%, -50%);
|
|
|
+ width: 300px;
|
|
|
+ height: 300px;
|
|
|
+ // max-height: 30vh;
|
|
|
+ // max-width: 30vh;
|
|
|
overflow: hidden;
|
|
|
border: 0.1rem solid rgba(3, 169, 244, 0.2);
|
|
|
}
|