whychdw
2021-06-18 da664b75ddac09ef2f810c1331cbc033ce3edf3f
启动放电需要人脸识别
1个文件已添加
6个文件已修改
506 ■■■■ 已修改文件
package.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/js/config.js 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/FlexBox.vue 156 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/checkFace.vue 206 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/params/61850/DischargeParams.vue 54 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/params/BTS/DischargeParams.vue 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/dataTest/movingRingSystem/powerBox.vue 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json
@@ -1,6 +1,6 @@
{
  "name": "admin_manage",
  "version": "2.2.5",
  "version": "1.0.5",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve --mode dev",
src/assets/js/config.js
@@ -25,4 +25,9 @@
        des: '电池信息配置中点击编辑可以远程修改ip',
        value: false,
    },
    dischargeByFace: {
        label: '启动放电添加人脸识别',
        des: '启动充放电测试使用人脸识别',
        value: true,
    },
}
src/components/FlexBox.vue
@@ -6,11 +6,13 @@
        <div class="flex-box-border border-bottom-right"></div>
        <div class="flex-box-header" v-if="!noHeader" :class="{'no-header-bg':noHeaderBg}">
            <flex-layout direction="row" no-bg>
              <div slot="header">
                <i class="iconfont el-icon-fold"></i>
                <span class="header-text">{{title}}</span>
              </div>
              <div class="flex-header-tools"><slot name="tools"></slot></div>
                <div slot="header">
                    <i class="iconfont el-icon-fold"></i>
                    <span class="header-text">{{ title }}</span>
                </div>
                <div class="flex-header-tools">
                    <slot name="tools"></slot>
                </div>
            </flex-layout>
@@ -45,70 +47,82 @@
</script>
<style scoped>
    .flex-box {
        position: relative;
        display: flex;
        flex-direction: column;
        height: 100%;
    }
    .flex-box-border{
        position: absolute;
        display: inline-block;
        z-index: 9;
    }
    .flex-box-border.border-top-left {
        top: 0;
        left: 0;
        border-top: 2px solid #00FEFF;
        border-left: 2px solid #00FEFF;
    }
    .flex-box-border.border-top-right {
        top: 0;
        right: 0;
        border-top: 2px solid #00FEFF;
        border-right: 2px solid #00FEFF;
    }
    .flex-box-border.border-bottom-left {
        bottom: 0;
        left: 0;
        border-bottom: 2px solid #00FEFF;
        border-left: 2px solid #00FEFF;
    }
    .flex-box-border.border-bottom-right {
        bottom: 0;
        right: 0;
        border-bottom: 2px solid #00FEFF;
        border-right: 2px solid #00FEFF;
    }
    .flex-box-header {
        position: relative;
        padding: 12px 0;
        font-size: 14px;
        color: #00fefe;
        font-weight: bold;
    }
    .flex-box-header.no-header-bg {
        background: none;
        padding: 8px 0;
    }
    .flex-header-tools {
      position: absolute;
      top: 8px;
      right: 16px;
    }
    .flex-box-header .iconfont {
        font-size: 10px;
        margin-right: 8px;
        margin-left: 16px;
        transform: rotate(90deg);
    }
    .header-text {
        font-weight: bold;
    }
    .flex-box-body {
        position: relative;
        flex: 1;
        overflow: hidden;
        box-sizing: border-box;
    }
.flex-box {
    position: relative;
    display: flex;
    flex-direction: column;
    height: 100%;
}
.flex-box-border {
    position: absolute;
    display: inline-block;
    z-index: 9;
}
.flex-box-border.border-top-left {
    top: 0;
    left: 0;
    border-top: 2px solid #00FEFF;
    border-left: 2px solid #00FEFF;
}
.flex-box-border.border-top-right {
    top: 0;
    right: 0;
    border-top: 2px solid #00FEFF;
    border-right: 2px solid #00FEFF;
}
.flex-box-border.border-bottom-left {
    bottom: 0;
    left: 0;
    border-bottom: 2px solid #00FEFF;
    border-left: 2px solid #00FEFF;
}
.flex-box-border.border-bottom-right {
    bottom: 0;
    right: 0;
    border-bottom: 2px solid #00FEFF;
    border-right: 2px solid #00FEFF;
}
.flex-box-header {
    position: relative;
    padding: 12px 0;
    font-size: 14px;
    color: #00fefe;
    font-weight: bold;
}
.flex-box-header.no-header-bg {
    background: none;
    padding: 8px 0;
}
.flex-header-tools {
    position: absolute;
    top: 8px;
    right: 16px;
    z-index: 9;
}
.flex-box-header .iconfont {
    font-size: 10px;
    margin-right: 8px;
    margin-left: 16px;
    transform: rotate(90deg);
}
.header-text {
    font-weight: bold;
}
.flex-box-body {
    position: relative;
    flex: 1;
    overflow: hidden;
    box-sizing: border-box;
}
</style>
src/components/checkFace.vue
New file
@@ -0,0 +1,206 @@
<template>
    <div class="face-check">
        <video ref="video" width="480" height="320" style="display:none"></video>
        <canvas ref="canvas" width="480" height="320"></canvas>
        <p class="text">{{ faceDetect }}</p>
    </div>
</template>
<script>
import faceManager from '@/assets/js/apis/faceManager/faceManager.js'
import {uKeyLogin} from "@/assets/js/api";
export default {
    name: 'checkFace',
    props: {
        faceShow: {
            type: Boolean,
            default: false
        }
    },
    data() {
        return {
            status: true,
            faceDetect: '请将正脸对准摄像头',
            imageBase64: '',
            newstream: '',
            intTime: null,
            postTime: null,
            setTime: null
        }
    },
    mounted() {
        this.faceChange();
    },
    destroyed: function () {
        this.status = false;
        this.clearVideo();
    },
    methods: {
        // 关闭摄像头
        clearVideo: function () {
            // 关闭定时器
            clearInterval(this.intTime);
            clearInterval(this.postTime);
            clearTimeout(this.setTime);
            // 关闭摄像头
            for (let track of this.newstream.getTracks()) {
                track.stop()
            }
        },
        // 获取图片
        getImg: function () {
            let vm = this;
            let video = vm.$refs.video;
            let canvas = vm.$refs.canvas;
            let context = canvas.getContext('2d');
            context.drawImage(video, 0, 0, 480, 320);
            // 获取图片base64链接
            vm.imageBase64 = canvas.toDataURL('image/png');
        },
        // 人脸检测
        faceChange: function () {
            let vm = this;
            // 恢复提示语
            vm.faceDetect = '请将正脸对准摄像头'
            if (navigator.mediaDevices.getUserMedia || navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia) {
                //调用用户媒体设备, 访问摄像头
                this.getUserMedia({video: {width: 480, height: 320}}, this.success, this.error);
            } else {
                alert('不支持访问用户媒体');
            }
        },
        //访问用户媒体设备的兼容方法
        getUserMedia: function (constraints, success, error) {
            if (navigator.mediaDevices.getUserMedia) {
                //最新的标准API
                navigator.mediaDevices.getUserMedia(constraints).then(success).catch(error);
            } else if (navigator.webkitGetUserMedia) {
                //webkit核心浏览器
                navigator.webkitGetUserMedia(constraints, success, error)
            } else if (navigator.mozGetUserMedia) {
                //firfox浏览器
                navigator.mozGetUserMedia(constraints, success, error);
            } else if (navigator.getUserMedia) {
                //旧版API
                navigator.getUserMedia(constraints, success, error);
            }
        },
        // 成功回调
        success: function (stream) {
            let vm = this;
            //兼容webkit核心浏览器
            let CompatibleURL = window.URL || window.webkitURL;
            //将视频流设置为video元素的源
            // console.log(stream);
            // stream = stream;
            this.newstream = stream;
            //video.src = CompatibleURL.createObjectURL(stream);
            let video = this.$refs.video;
            video.srcObject = stream;
            video.play();
            this.intTime = setInterval(() => {
                vm.getImg();
            }, 0)
            setTimeout(function () {
                vm.facePost();
            }, 0)
        },
        error: function (error) {
            console.log(error)
            console.log(`访问用户媒体设备失败${error.name}, ${error.message}`);
        },
        // 请求后台验证人脸
        facePost: function () {
            if(!this.$store.state.ukey.isIn) {
                this.faceDetect = '请先插入ukey';
                this.setTime = setTimeout(() => {
                    this.facePost();
                }, 500);
            }else {
                let vm = this;
                faceManager.faceVerify({fileData: vm.imageBase64}).then(res => {
                    let result = JSON.parse(res.data.result);
                    if (result.code == 1) {
                        vm.faceDetect = "匹配成功";
                        setTimeout(() => {
                            vm.onLogin();
                        }, 1000);
                    } else {
                        vm.faceDetect = result.msg;
                        if (vm.status == true) {
                            this.setTime = setTimeout(() => {
                                this.facePost();
                            }, 3000);
                        }
                    }
                }).catch(err => {
                    vm.faceDetect = '网络链接失败';
                    if (vm.status == true) {
                        this.setTime = setTimeout(() => {
                            this.facePost();
                        }, 3000);
                    }
                })
            }
        },
        // 登陆设置sessionStorage
        onLogin: function () {
            let vm = this;
            faceManager.getUserName().then(res => {
                let result = JSON.parse(res.data.result);
                if (result.code == 1) {
                    let loginUser = sessionStorage.getItem('username');
                    let loginId = sessionStorage.getItem('userId');
                    if(loginUser==result.data.UName && loginId == result.data.USnId) {
                        this.$emit('checkSuccess');
                    }else {
                        vm.faceDetect = '人脸和登录用户不匹配';
                        this.setTime = setTimeout(() => {
                            this.facePost();
                        }, 3000);
                    }
                }
            }).catch(err => {
                console.log(err);
            })
        },
        uKeyLogin(username, password) {
            // ukey登录
            uKeyLogin(username, password, this.$store.state.ukey.id).then(res=>{
                // 对结果进行处理
                this.handleLogin(res, username);
            }).catch(error => {
                // 关闭等待
                this.loading = false;
                console.log(error);
                this.faceDetect = "网络异常";
                this.facePost();
            });
        },
        handleLogin(res, username) {
            let rs = JSON.parse(res.data.result);
            if (rs.code == 1) {
                this.$message.success("登录成功");
                sessionStorage.setItem('username', username);
                sessionStorage.setItem('userId', rs.data);
                this.$router.push("/home");
                // 设置用户的权限
                this.$store.dispatch('user/getPermits');
            } else {
                this.faceDetect  = rs.msg;
                this.facePost();
            }
        },
    },
}
</script>
<style lang="less" scoped>
.face-check {
    background-color: #FFFFFF;
}
.text {
    text-align: center;
}
</style>
src/components/params/61850/DischargeParams.vue
@@ -90,10 +90,28 @@
        </div>
        <div class="form-footer">
            <!-- <three-btn>清除告警</three-btn> -->
            <three-btn :disabled="!startTestFlag" @click="confirmStartTest">启动测试</three-btn>
            <three-btn :disabled="!startTestFlag" @click="startTestCheck">启动测试</three-btn>
            <three-btn @click="getParams(true)">读取</three-btn>
            <three-btn :disabled="!setTestFlag" @click="submitFrom">设定</three-btn>
        </div>
        <el-dialog
            title="人脸校验" width="480px"
            :visible.sync="setFaceShow"
            :close-on-click-modal="false" top="0"
            :modal="false"
            class="dialog-center"
            :modal-append-to-body="false" :destroy-on-close="true">
            <check-face @check-success="setFaceSuccess"></check-face>
        </el-dialog>
        <el-dialog
            title="人脸校验" width="480px"
            :visible.sync="startFaceShow"
            :close-on-click-modal="false" top="0"
            :modal="false"
            class="dialog-center"
            :modal-append-to-body="false" :destroy-on-close="true">
            <check-face @check-success="startFaceSuccess"></check-face>
        </el-dialog>
    </el-form>
</template>
@@ -105,8 +123,12 @@
import {
    testVal
} from '../../../assets/js/tools'
import CheckFace from "@/components/checkFace";
import config from "@/assets/js/config";
export default {
    components: {CheckFace},
    props: {
        batt: {
            type: Object,
@@ -131,6 +153,8 @@
        rules.MonomerVol_Low.max = (batt.MonVolStd*1.2).toHold(1);
        rules.MonomerVol_Low.msg = "取值范围"+rules.MonomerVol_Low.min+"~"+rules.MonomerVol_Low.max+"(保留一位小数)";
        return {
            setFaceShow: false,
            startFaceShow: false,
            cmd: cmd,       // 操作命令
            testType: testType,    // 测试类型
            startTestFlag: false,       // 启动测试的状态
@@ -294,7 +318,7 @@
                    this.$layer.confirm("确认修改参数", {icon: 3, title: '系统提示'}, (index)=>{
                        // 关闭确认框
                        this.$layer.close(index);
                        this.setParams();
                        this.setParamsCheck();
                    });
                } else {
@@ -302,6 +326,13 @@
                    return false;
                }
            });
        },
        setParamsCheck() {
           if(config.dischargeByFace.value) {
               this.setFaceShow = true;
           }else {
               this.setParams(true);
           }
        },
        // 设置参数
        setParams() {
@@ -332,6 +363,13 @@
                // 提示信息
                this.$layer.msg('设置失败,设置请求异常!');
            });
        },
        startTestCheck() {
            if(config.dischargeByFace.value) {
                this.startFaceShow = true;
            }else {
                this.confirmStartTest();
            }
        },
        // 确认框
        confirmStartTest() {
@@ -384,10 +422,14 @@
                this.$layer.msg('启动测试失败,启动测试请求异常!');
            });
        },
        // 清除告警
        clearWarning() {
        }
        setFaceSuccess() {
            this.setFaceShow = false;
            this.setParams();
        },
        startFaceSuccess() {
            this.startFaceShow = false;
            this.startTest();
        },
    },
    computed: {
        otherParams() {
src/components/params/BTS/DischargeParams.vue
@@ -114,10 +114,28 @@
        </div>
        <div class="form-footer">
            <!-- <three-btn>清除告警</three-btn> -->
            <three-btn :disabled="!startTestFlag" @click="startTest">启动测试</three-btn>
            <three-btn :disabled="!startTestFlag" @click="startTestCheck">启动测试</three-btn>
            <three-btn @click="getParams(true)">读取</three-btn>
            <three-btn :disabled="!setTestFlag" @click="submitFrom">设定</three-btn>
        </div>
        <el-dialog
            title="人脸校验" width="480px"
            :visible.sync="setFaceShow"
            :close-on-click-modal="false" top="0"
            :modal="false"
            class="dialog-center"
            :modal-append-to-body="false" :destroy-on-close="true">
            <check-face @check-success="setFaceSuccess"></check-face>
        </el-dialog>
        <el-dialog
            title="人脸校验" width="480px"
            :visible.sync="startFaceShow"
            :close-on-click-modal="false" top="0"
            :modal="false"
            class="dialog-center"
            :modal-append-to-body="false" :destroy-on-close="true">
            <check-face @check-success="startFaceSuccess"></check-face>
        </el-dialog>
    </el-form>
</template>
@@ -128,8 +146,13 @@
import {
    const_9100
} from "@/assets/js/const"
import config from "@/assets/js/config";
import checkFace from "@/components/checkFace";
export default {
    name: "BtsDischargeParams",
    components: {
        checkFace
    },
    props: {
        batt: {
            type: Object,
@@ -155,6 +178,8 @@
        rules.MonomerVol_Low.msg = "取值范围"+rules.MonomerVol_Low.min+"~"+rules.MonomerVol_Low.max+"(保留一位小数)";
        return {
            setFaceShow: false,
            startFaceShow: false,
            cmd: cmd,               // 操作命令
            startTestFlag: false,   // 启动测试的状态
            setTestFlag: false,     // 设置参数的状态
@@ -306,12 +331,19 @@
                // 校验通过
                if (valid) {
                    // 设置参数
                    this.setParams();
                    this.setParamsCheck();
                } else {
                    this.$layer.msg('存在校验未通过的数据!');
                    return false;
                }
            });
        },
        setParamsCheck() {
            if(config.dischargeByFace.value) {
                this.setFaceShow = true;
            }else {
                this.setParams(true);
            }
        },
        // 设置参数
        setParams() {
@@ -342,6 +374,35 @@
                // 提示信息
                this.$layer.msg('设置失败,设置请求异常!');
            });
        },
        startTestCheck() {
            if(config.dischargeByFace.value) {
                this.startFaceShow = true;
            }else {
                this.confirmStartTest();
            }
        },
        // 确认框
        confirmStartTest() {
            this.$layer.prompt({title: '输入启动口令,并确认', formType: 2, area: ['300px', '180px']}, (pass, index) => {
                // 请求后台校验密码
                this.$apis.login.checkUserPwd(pass).then(res=>{
                    let rs = JSON.parse(res.data.result);
                    if(rs.code == 1) {
                        // 关闭弹出框
                        this.$layer.close(index);
                        this.$layer.msg("密码检测通过,启动测试");
                        // 启动测试
                        this.startTest();
                    }else {
                        this.$layer.msg("启动口令错误!");
                    }
                }).catch(error=>{
                    console.log(error);
                    this.$layer.msg("网络请求异常");
                });
            });
        },
        // 启动
        startTest() {
@@ -381,7 +442,15 @@
                }
            }
            return false;
        }
        },
        setFaceSuccess() {
            this.setFaceShow = false;
            this.setParams();
        },
        startFaceSuccess() {
            this.startFaceShow = false;
            this.startTest();
        },
    },
    computed: {
        otherParams() {
src/pages/dataTest/movingRingSystem/powerBox.vue
@@ -9,6 +9,7 @@
                                <el-row :gutter="layout.gutter" class="full-height">
                                    <el-col :span="layout.span" class="full-height">
                                        <flex-box title="1路交流输入电压">
                                            <i class="flex-box-tools-icon el-icon-s-tools" slot="tools"></i>
                                            <e-chart-wrapper ref="acOneInputVol"></e-chart-wrapper>
                                        </flex-box>
                                    </el-col>
@@ -870,4 +871,11 @@
    padding-top: 8px;
    padding-bottom: 8px;
}
.flex-box-tools-icon {
    font-size: 20px;
    cursor: pointer;
}
.flex-box-tools-icon:active {
    color: #FF0000;
}
</style>