Pārlūkot izejas kodu

添加录像诊断

凉纪 1 gadu atpakaļ
vecāks
revīzija
a280616a1e

+ 6 - 2
src/assets/styles/index.scss

@@ -147,6 +147,12 @@ div:focus {
   }
 }
 
+ul,li{
+  padding:0;
+  margin: 0;
+  list-style:none;
+}
+
 aside {
   background: #eef1f6;
   padding: 8px 24px;
@@ -283,5 +289,3 @@ aside {
   background-color: #009240FF;
 }
 
-
-

+ 375 - 0
src/views/iot/videoIntegrity/ProgressBar.vue

@@ -0,0 +1,375 @@
+<template>
+    <div class="progress-box-bar" ref="progressbar">
+        <canvas draggable="false" id="procanvas" height="80" @contextmenu="contextMenuClick" @mousedown="mousedownFunc" @mouseup="mouseupFunc" @mousemove="mousemoveFunc" @mouseout="mouseoutFunc"></canvas>
+    </div>
+</template>
+
+<script>
+export default {
+    name:"ProgressBar",
+    props:["timeCell","startTime","videoData"],
+    data(){
+        return{
+            canvas:"",
+            ctx:"",
+            canvasW:"",
+            canvasH:"",
+            nowTime:"",
+            hours_per_ruler:24,    //时间轴显示12小时
+            half_time:5*60*60*1000,
+            graduation_step:20,     //刻度间最小宽度,单位px
+            start_timestamp:new Date().getTime()- 5*60*60*1000,    //开始时间、最左侧时间
+            minutes_per_step:[1, 2, 5, 10, 15, 20, 30, 60, 120, 180, 240, 360, 720, 1440],
+            distance_between_gtitle:80,
+            g_isMousedown:false,    //拖动mousedown标记
+            g_isMousemove:false,    //拖动mousemove标记
+            g_mousedownCursor:null,   //拖动mousedown的位置
+            returnTime: null,   //mouseup返回时间
+            downTime:[],    //下载时间
+            downLeft:0,
+            showDown:false,
+            tiaoTop:40,
+            tiaoHeight:20,
+
+        }
+    },
+    watch:{
+        timeCell(){
+            if(this.timeCell.length>0){
+                this.nowTime = this.changeTime(new Date(this.timeCell[0].beginTime).getTime());
+                this.start_timestamp = new Date(this.timeCell[0].beginTime).getTime()- this.half_time;
+                this.clearCanvas();
+                this.initCanvas();
+            }
+        },
+        startTime(){
+            if(!this.g_isMousedown){
+                this.nowTime = this.changeTime(this.startTime+this.half_time);
+                this.start_timestamp = this.startTime;
+                this.clearCanvas();
+                this.initCanvas();
+            }
+        }
+    },
+    mounted() {
+        this.canvas = document.getElementById("procanvas");
+        this.ctx = this.canvas.getContext('2d');
+        this.canvas.width = this.$refs.progressbar.offsetWidth;
+        this.canvasW = this.canvas.width;
+        this.canvasH = this.canvas.height;
+        this.nowTime = this.changeTime(new Date().getTime());
+        this.initCanvas();
+    },
+    methods:{
+        // 初始化canvas
+        initCanvas:function(){
+            this.drawCellBg();
+            this.add_cells(this.timeCell);
+            this.add_graduations(this.start_timestamp);
+            this.draw_down(this.downTime);
+            this.drawTimeTriangle();
+        },
+        // // 绘制三角 时间
+        drawTimeTriangle(){
+            // this.ctx.beginPath();
+            // let x = this.canvasW/2;
+            // let x1 = this.canvasW/2-7;
+            // let x2 = this.canvasW/2+7;
+            // this.ctx.moveTo(x1,25);
+            // this.ctx.lineTo(x2,25);
+            // this.ctx.lineTo(x,36);
+            // this.ctx.fillStyle = "#318ed4";
+            // this.ctx.closePath();
+            // this.ctx.fill();
+            // this.ctx.fillStyle = "#fff";
+            // this.ctx.font = "14px Arial";
+            // this.ctx.fillText(this.nowTime,x-60,20);
+        },
+        // 画背景色
+        drawCellBg:function(){
+            this.ctx.fillStyle = "#ccc";
+            this.ctx.fillRect(0, this.tiaoTop, this.canvasW, this.tiaoHeight);
+        },
+        // 添加刻度
+        add_graduations:function(start_timestamp){
+            var _this = this;
+            var px_per_min = _this.canvasW / (_this.hours_per_ruler * 60); // px/min
+            var px_per_ms = _this.canvasW / (_this.hours_per_ruler * 60 * 60 * 1000); // px/ms
+            var px_per_step = _this.graduation_step;  // px/格 默认最小值20px
+            var min_per_step = px_per_step / px_per_min; // min/格
+            for(var i = 0; i < _this.minutes_per_step.length;i++){
+                if(min_per_step <= _this.minutes_per_step[i]){ //让每格时间在minutes_per_step规定的范围内
+                    min_per_step = _this.minutes_per_step[i];
+                    px_per_step = px_per_min * min_per_step;
+                    break
+                }
+            }
+            var medium_step = 30;
+            for (var i = 0; i < _this.minutes_per_step.length; i++) {
+                if (_this.distance_between_gtitle / px_per_min <= _this.minutes_per_step[i]) {
+                    medium_step = _this.minutes_per_step[i];
+                    break;
+                }
+            }
+            var num_steps = _this.canvasW / px_per_step; //总格数
+            var graduation_left;
+            var graduation_time;
+            var ms_offset = _this.ms_to_next_step(start_timestamp,min_per_step*60*1000);//开始的偏移时间 ms
+            var px_offset = ms_offset * px_per_ms; //开始的偏移距离 px
+            var ms_per_step = px_per_step / px_per_ms; // ms/step
+            for(var i = 0; i < num_steps; i++){
+                graduation_left = px_offset + i * px_per_step; // 距离=开始的偏移距离+格数*px/格
+                graduation_time = start_timestamp + ms_offset + i * ms_per_step; //时间=左侧开始时间+偏移时间+格数*ms/格
+                var date = new Date(graduation_time);
+                if (graduation_time / (60 * 1000) % medium_step == 0) {
+                    var middle_date = _this.graduation_title(date);
+                    _this.ctx.fillStyle = "#318ed4";
+                    _this.ctx.font = "14px Arial";
+                    _this.ctx.fillText(middle_date,graduation_left-17,75);
+                    _this.drawLine(graduation_left,50,graduation_left,60,"#318ed4",1);
+                }else{
+                    _this.drawLine(graduation_left,55,graduation_left,60,"rgba(250,250,250,0.7)",1);
+                }
+            }
+        },
+
+        // 画刻度线
+        drawLine:function(beginX,beginY,endX,endY,color,width){
+            this.ctx.beginPath();
+            this.ctx.moveTo(beginX,beginY);
+            this.ctx.lineTo(endX,endY);
+            this.ctx.strokeStyle = color;
+            this.ctx.lineWidth = width;
+            this.ctx.stroke();
+        },
+        // 添加录像块
+        add_cells:function(cells){
+            var _this = this;
+            cells.forEach(cell => {
+                _this.draw_cell(cell)
+            });
+        },
+        // 绘制录像块
+        draw_cell:function(cell){
+            var _this = this;
+            var px_per_ms = _this.canvasW / (_this.hours_per_ruler * 60 * 60 * 1000); // px/ms
+            var beginX = (cell.beginTime - _this.start_timestamp) * px_per_ms;
+            var cell_width = ( cell.endTime - cell.beginTime) * px_per_ms;
+            _this.ctx.fillStyle = "#2d86cd";
+            _this.ctx.fillRect(beginX,this.tiaoTop,cell_width,this.tiaoHeight);
+        },
+        // 绘制下载录像块
+        draw_down:function(cell){
+            var _this = this;
+            var px_per_ms = _this.canvasW / (_this.hours_per_ruler * 60 * 60 * 1000); // px/ms
+            var beginX = cell[0]>cell[1]?(cell[1]- _this.start_timestamp)* px_per_ms:(cell[0]- _this.start_timestamp)* px_per_ms;
+            var cell_width = cell[0]>cell[1]?(cell[0]-cell[1])* px_per_ms:(cell[1]-cell[0])* px_per_ms;
+            _this.ctx.fillStyle = "#ff0000";
+            _this.ctx.fillRect(beginX,this.tiaoTop,cell_width,this.tiaoHeight);
+        },
+        // 返回时间轴上刻度时间
+        graduation_title:function(datetime){
+            return (datetime.getHours()<10?'0'+datetime.getHours():datetime.getHours()) + ':' + ('0' + datetime.getMinutes().toString()).substr(-2);
+        },
+        // 开始的便宜时间  px
+        ms_to_next_step:function(timestamp, step) {
+            var remainder = timestamp % step;
+            return remainder ? step - remainder : 0;
+        },
+        // 清除画布
+        clearCanvas:function(){
+            this.ctx.clearRect(0,0,this.canvasW,this.canvasH);
+        },
+        // 获取鼠标x位置
+        get_cursor_x_position:function(e){
+            var posx = 0;
+            if (! e) {
+                e = window.event;
+            }
+            if (e.pageX || e.pageY) {
+                posx = e.pageX;
+            }else if (e.clientX || e.clientY) {
+                posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
+            }
+            return posx-360;//调整鼠标误差值
+        },
+        // 返回时间日期格式
+        changeTime:function(time) {
+            var newTime = new Date(time);
+            var year = newTime.getFullYear();
+            var month = newTime.getMonth() + 1;
+            if(month < 10){
+                var month = "0" + month;
+            }
+            var date = newTime.getDate();
+            if (date < 10) {
+                var date = "0" + date;
+            }
+            var hour = newTime.getHours();
+            if (hour < 10) {
+                var hour = "0" + hour;
+            }
+            var minute = newTime.getMinutes();
+            if (minute < 10) {
+                var minute = "0" + minute;
+            }
+            var second = newTime.getSeconds();
+            if (second < 10) {
+                var second = "0" + second;
+            }
+            return year + "-" + month + "-" + date + " " + hour + ":" + minute + ":" + second;
+        },
+        // 鼠标按下事件
+        mousedownFunc:function(e){
+            if(e.button == 2){
+
+            }else{
+                this.g_isMousedown = true;
+            }
+            this.g_mousedownCursor = this.get_cursor_x_position(e);//记住mousedown的位置
+
+        },
+        // 鼠标移动事件
+        mousemoveFunc:function(e){
+            let _this = this;
+            let pos_x = _this.get_cursor_x_position(e);
+            let px_per_ms = _this.canvasW / (_this.hours_per_ruler * 60 * 60 * 1000); // px/ms
+            _this.clearCanvas();
+            if(_this.g_isMousedown){
+                var diff_x = pos_x - _this.g_mousedownCursor;
+                _this.start_timestamp = _this.start_timestamp - Math.round(diff_x / px_per_ms);
+                _this.initCanvas();
+                _this.g_isMousemove = true;
+                _this.g_mousedownCursor = pos_x;
+                this.nowTime = this.changeTime(_this.start_timestamp+this.half_time);
+            }else{
+                var time = _this.start_timestamp + pos_x/px_per_ms;
+                _this.initCanvas();
+                _this.drawLine(pos_x,30,pos_x,60,"rgb(49,142,212)",1);
+                _this.ctx.fillStyle = "rgb(194, 202, 215)";
+                _this.ctx.fillText(_this.changeTime(time),pos_x-65,35);
+            }
+        },
+        // 鼠标释放弹起事件
+        mouseupFunc:function(e){
+            if(e.button == 2){
+                if(this.downTime.length==2){
+                    this.downLeft = this.g_mousedownCursor;
+                    this.showDown = true;
+                }
+            }else{
+                this.g_isMousedown = false;
+                this.g_isMousemove = false;
+                let time = this.start_timestamp+this.half_time;
+                this.$emit("setDragPlayTime",time);
+            }
+
+        },
+        // 鼠标移除隐藏时间事件
+        mouseoutFunc:function(e){
+            this.clearCanvas();
+            this.initCanvas();
+        },
+        contextMenuClick:function(e){
+            e.preventDefault();
+            return;
+            var _this = this;
+            var pos_x = _this.get_cursor_x_position(e);
+            var px_per_ms = _this.canvasW / (_this.hours_per_ruler * 60 * 60 * 1000); // px/ms
+            var time = _this.start_timestamp + pos_x/px_per_ms;
+            var flag = false;
+            var index = 0;
+            for(let i = 0;i<_this.timeCell.length;i++){
+                if(time>=_this.timeCell[i].beginTime && time<=_this.timeCell[i].endTime){
+                    flag = true;
+                    index = i;
+                }
+            }
+            if(flag){
+                if(_this.downTime.length<2){
+                    _this.downTime.push(time);
+                    if(_this.downTime.length==2){
+                        _this.clearCanvas();
+                        _this.initCanvas();
+                    }
+                }else if(_this.downTime.length==2){
+                    // console.log(_this.downTime);
+                }
+            }
+
+        },
+        downCLickBack(){
+            if(this.downTime.length == 2){
+                this.downTime.sort(function(a,b){
+                    return a-b
+                })
+                var userData = this.$store.getters.replayDownVideo.length+1;
+                var startTime1 = this.downTime[0]<this.downTime[1]?this.downTime[0]:this.downTime[1];
+                var startTime = this.changeTime(startTime1);
+                var endTime1 = this.downTime[0]>=this.downTime[1]?this.downTime[0]:this.downTime[1];
+                var endTime = this.changeTime(endTime1);
+                var fileName = new Date().getTime()+".mp4";
+                var server = this.$store.getters.serverConfig;
+                var alltime = Math.ceil((endTime1-startTime1)/1000);
+                var obj = {
+                    fileName:fileName,startTime:startTime,endTime:endTime,allTime:alltime,progress:"0%",userDate:userData,downType:0
+                };
+                var s_index = 0,e_index = 0;
+                for(var i = 0;i<this.timeCell.length;i++){
+                    if(this.downTime[0]>=this.timeCell[i].beginTime&&this.downTime[0]<=this.timeCell[i].endTime){
+                        s_index = i;
+                    }
+                    if(this.downTime[1]>=this.timeCell[i].beginTime&&this.downTime[1]<=this.timeCell[i].endTime){
+                        e_index = i;
+                    }
+                }
+                var fileArr = new Array();
+                for(var j=s_index;j<=e_index;j++){
+                    fileArr.push(this.videoData.videoList[j]);
+                }
+                var filesJson = JSON.stringify(fileArr);
+                this.downTime.splice(0,this.downTime.length);
+
+                var ss = document.getElementById("videoOcx").StartDownloadVodFile(server.ServerIP,server.ServerPort,filesJson,fileName,startTime,endTime,userData);
+                this.$store.commit("addDownLoadVideo",obj);
+                this.showDown = false;
+            }
+
+        },
+        cancelDownClick(){
+            this.downTime.splice(0,this.downTime.length);
+            this.showDown = false;
+        }
+    }
+}
+</script>
+
+<style scoped>
+    .progress-box-bar{
+        position: relative;
+        width:100%;
+        height: 100%;
+    }
+    .progress-box-bar canvas{
+       width: 100%;
+       cursor: pointer;
+    }
+    .progress-box-bar .downVideo{
+        position: absolute;
+        z-index: 10;
+        top: 0;
+        left: 300px;
+
+    }
+    .progress-box-bar .downVideo ul{
+        background-color: #fff;
+    }
+    .progress-box-bar .downVideo ul li{
+        line-height: 20px;
+        font-size: 12px;
+        cursor: pointer;
+    }
+    .progress-box-bar .downVideo ul li:hover{
+        background-color: #318ed4;
+    }
+</style>

+ 409 - 0
src/views/iot/videoIntegrity/detail.vue

@@ -0,0 +1,409 @@
+<template>
+  <div class="videoDaysDetail">
+    <el-dialog title="录像详情" :visible.sync="isShow" width="1400px" :destroy-on-close="true">
+      <el-descriptions title="基础信息" :column="3">
+        <el-descriptions-item label="通道名称" >测试摄像头001</el-descriptions-item>
+        <el-descriptions-item label="监控主机" >讯美测试部服务主机01</el-descriptions-item>
+        <el-descriptions-item label="IP地址" >192.168.1.1</el-descriptions-item>
+<!--        <el-descriptions-item label="组织机构" >{{data.orgName}}</el-descriptions-item>-->
+<!--        <el-descriptions-item label="上报时间" >{{data.updateTime}}</el-descriptions-item>-->
+<!--        <el-descriptions-item label="监控主机" >{{data.equipmentName}}</el-descriptions-item>-->
+<!--        <el-descriptions-item label="摄像头" >{{data.channelName}}</el-descriptions-item>-->
+<!--        <el-descriptions-item label="通道号" >{{data.channelCode}}</el-descriptions-item>-->
+<!--        <el-descriptions-item label="计划存储天数" >{{data.planDays}}</el-descriptions-item>-->
+<!--        <el-descriptions-item label="实际存储天数" >{{data.realDays}}</el-descriptions-item>-->
+<!--        <el-descriptions-item label="计划录像开始时间" >{{data.planStartTime}}</el-descriptions-item>-->
+<!--        <el-descriptions-item label="计划录像结束时间" >{{data.planEndTime}}</el-descriptions-item>-->
+      </el-descriptions>
+
+      <el-descriptions title="录像质量" :column="3">
+        <el-descriptions-item label="检测结果" >异常</el-descriptions-item>
+        <el-descriptions-item label="原因" >被遮挡</el-descriptions-item>
+        <el-descriptions-item label="更新时间" >2024年1月26日 09:00</el-descriptions-item>
+      </el-descriptions>
+      <el-descriptions :column="1">
+        <el-descriptions-item label="诊断截图" >
+          <div>
+            <ul class="legend-box">
+              <li>
+                <el-tag size="small" type="warning">视频信号</el-tag>
+              </li>
+              <li>
+                <el-tag size="small" type="warning">遮挡</el-tag>
+              </li>
+              <li>
+                <el-tag size="small" type="warning">模糊</el-tag>
+              </li>
+              <li>
+                <el-tag size="small" type="warning">偏色</el-tag>
+              </li>
+              <li>
+                <el-tag size="small" type="warning">雪花</el-tag>
+              </li>
+              <li>
+                <el-tag size="small" type="warning">条纹</el-tag>
+              </li>
+              <li>
+                <el-tag size="small" type="warning">对比度</el-tag>
+              </li>
+              <li>
+                <el-tag size="small" type="warning">亮度</el-tag>
+              </li>
+            </ul>
+            <div style="display: block;width: 300px;max-height: 300px;margin-top: 20px;">
+              <el-image :src="src" :preview-src-list="[src]">
+                <div slot="error" class="image-slot">
+                  <i class="el-icon-picture-outline"></i>
+                </div>
+              </el-image>
+            </div>
+          </div>
+        </el-descriptions-item>
+      </el-descriptions>
+
+
+      <el-descriptions title="录像完整性" :column="3">
+        <el-descriptions-item label="录像日期" >2024年1月26日</el-descriptions-item>
+        <el-descriptions-item label="更新时间" >2024年1月26日 09:00</el-descriptions-item>
+        <el-descriptions-item label="原因" >被遮挡</el-descriptions-item>
+        <el-descriptions-item label="检测结果" >异常</el-descriptions-item>
+        <el-descriptions-item label="丢失时长" >8:46</el-descriptions-item>
+      </el-descriptions>
+      <el-descriptions :column="1">
+        <el-descriptions-item label="丢失时段" >
+          <!--          <time-line></time-line>-->
+          <ul class="legend-box">
+            <li>
+              <i class="legend" style="background-color: #00b2ff"></i>
+              <span>计划时长</span>
+            </li>
+            <li>
+              <i class="legend" style="background-color: green"></i>
+              <span>有录像</span>
+            </li>
+            <li>
+              <i class="legend" style="background-color: red"></i>
+              <span>无录像</span>
+            </li>
+            <li>
+              <i class="legend" style="background-color: #aaa"></i>
+              <span>未知</span>
+            </li>
+          </ul>
+        </el-descriptions-item>
+      </el-descriptions>
+
+      <div class="time-line-box">
+        <div style="width: 100%;height: 20px;background-color: red; "></div>
+        <progress-bar :timeCell="timeCells" :videoData="playVideoObj" :startTime="start_timestamp" ></progress-bar>
+      </div>
+      <div class="time-line">
+        <el-timeline :reverse="false">
+          <el-timeline-item
+            v-for="(activity, index) in data.loseDateList"
+            :key="index"
+            color="rgb(208 230 253)"
+            size="large"
+            type="primary">
+            <div class="time">
+              <div>
+                <span class="year">
+                  {{ activity.month }}
+                </span>
+              </div>
+              <!-- <div class="day">{{ activity.time.substring(0, 4) }}年</div> -->
+            </div>
+            <div class="ml10">
+              <el-tag v-for="(date, number) in activity.lostDates" :key="number">
+                <div>{{ date }}
+                  <div class="reTip">
+                  </div>
+                </div>
+              </el-tag>
+            </div>
+          </el-timeline-item>
+        </el-timeline>
+      </div>
+
+      <el-descriptions title="录像存储天数" :column="3">
+        <el-descriptions-item label="检查结果" >异常</el-descriptions-item>
+        <el-descriptions-item label="实际存储天数" >0</el-descriptions-item>
+        <el-descriptions-item label="计划要求存储天数" >30</el-descriptions-item>
+        <el-descriptions-item label="计划内最早录像日期" >2024年1月26日</el-descriptions-item>
+      </el-descriptions>
+      <el-descriptions :column="1">
+        <el-descriptions-item label="录像存储天数" >
+          <!--          <time-line></time-line>-->
+          <ul class="legend-box">
+            <li>
+              <i class="legend" style="background-color: green"></i>
+              <span>录像完整</span>
+            </li>
+            <li>
+              <i class="legend" style="background-color: orange"></i>
+              <span>部分丢失</span>
+            </li>
+            <li>
+              <i class="legend" style="background-color: red"></i>
+              <span>全部丢失</span>
+            </li>
+            <li>
+              <i class="legend" style="background-color: #aaa"></i>
+              <span>未知</span>
+            </li>
+          </ul>
+        </el-descriptions-item>
+      </el-descriptions>
+
+      <div class="calendar-box">
+        <div>
+          <el-calendar :value="'2024-01'">
+            <template
+              slot="dateCell"
+              slot-scope="{date, data}">
+              <div v-if="data.type === 'current-month'" style=" background-color: red;color:#fff;padding: 5px;display: flex;justify-content: center;align-items: center;">
+                {{dayjs(date).format('DD')}}
+              </div>
+              <div v-else style=" background-color: #ccc;color:#fff;padding: 5px;display: flex;justify-content: center;align-items: center;">
+                {{dayjs(date).format('DD')}}
+              </div>
+            </template>
+          </el-calendar>
+        </div>
+
+        <div>
+          <el-calendar :value="'2024-02'">
+            <template
+              slot="dateCell"
+              slot-scope="{date, data}">
+              <div v-if="data.type === 'current-month'" style=" background-color: red;color:#fff;padding: 5px;display: flex;justify-content: center;align-items: center;">
+                {{dayjs(date).format('DD')}}
+              </div>
+              <div v-else style=" background-color: #ccc;color:#fff;padding: 5px;display: flex;justify-content: center;align-items: center;">
+                {{dayjs(date).format('DD')}}
+              </div>
+            </template>
+          </el-calendar>
+        </div>
+
+        <div>
+          <el-calendar :value="'2024-03'">
+            <template
+              slot="dateCell"
+              slot-scope="{date, data}">
+
+              <div v-if="data.type === 'current-month'" style=" background-color: red;color:#fff;padding: 5px;display: flex;justify-content: center;align-items: center;">
+                {{dayjs(date).format('DD')}}
+              </div>
+              <div v-else style=" background-color: #ccc;color:#fff;padding: 5px;display: flex;justify-content: center;align-items: center;">
+                {{dayjs(date).format('DD')}}
+              </div>
+            </template>
+          </el-calendar>
+        </div>
+
+        <div>
+          <el-calendar :value="'2024-04'">
+            <template
+              slot="dateCell"
+              slot-scope="{date, data}">
+
+              <div v-if="data.type === 'current-month'" style=" background-color: red;color:#fff;padding: 5px;display: flex;justify-content: center;align-items: center;">
+                {{dayjs(date).format('DD')}}
+              </div>
+              <div v-else style=" background-color: #ccc;color:#fff;padding: 5px;display: flex;justify-content: center;align-items: center;">
+                {{dayjs(date).format('DD')}}
+              </div>
+            </template>
+          </el-calendar>
+        </div>
+
+        <div>
+          <el-calendar :value="'2024-05'">
+            <template
+              slot="dateCell"
+              slot-scope="{date, data}">
+              <div v-if="data.type === 'current-month'" style=" background-color: red;color:#fff;padding: 5px;display: flex;justify-content: center;align-items: center;">
+                {{dayjs(date).format('DD')}}
+              </div>
+              <div v-else style=" background-color: #ccc;color:#fff;padding: 5px;display: flex;justify-content: center;align-items: center;">
+                {{dayjs(date).format('DD')}}
+              </div>
+            </template>
+          </el-calendar>
+        </div>
+
+        <div>
+          <el-calendar :value="'2024-06'">
+            <template
+              slot="dateCell"
+              slot-scope="{date, data}">
+
+              <div v-if="data.type === 'current-month'" style=" background-color: red;color:#fff;padding: 5px;display: flex;justify-content: center;align-items: center;">
+                {{dayjs(date).format('DD')}}
+              </div>
+              <div v-else style=" background-color: #ccc;color:#fff;padding: 5px;display: flex;justify-content: center;align-items: center;">
+                {{dayjs(date).format('DD')}}
+              </div>
+            </template>
+          </el-calendar>
+        </div>
+
+      </div>
+
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="onHide">关闭</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+<script>
+
+import TimeLine from "./timeLine.vue";
+import ProgressBar from './ProgressBar'
+import dayjs from 'dayjs'
+export default {
+  components: {TimeLine,ProgressBar},
+  data() {
+    return {
+      src:'https://cube.elemecdn.com/6/94/4d3ea53c084bad6931a56d5158a48jpeg.jpeg',
+      isShow: false,
+      data: {},
+      id: null,
+      playVideoObj:{},   //选中的正在播放的录像
+      timeCells:[],    //录像时间块
+      start_timestamp:new Date().getTime() - 5*60*60*1000,    //刻度轴开始时间
+    };
+  },
+  methods: {
+    dayjs,
+    async show(id) {
+      this.id = id;
+      //this.data = await this.$api.videoDaysCheck.one(id);
+      this.isShow = true;
+    },
+    onHide() {
+      this.isShow = false;
+    },
+  },
+};
+</script>
+
+<style lang="scss">
+.videoDaysDetail {
+  .block {
+    display: block;
+  }
+
+  .time-line {
+    margin-top: 10px;
+    margin-left: 80px;
+  }
+
+  .list-title {
+    font-size: 16px;
+    font-family: PingFangSC-Medium, PingFang SC;
+    font-weight: 500;
+    color: #181b1e;
+  }
+
+  .list-company {
+    font-size: 14px;
+    font-family: PingFangSC-Regular, PingFang SC;
+    font-weight: 400;
+    color: #2991ff;
+    margin-top: 15px;
+    margin-bottom: 15px;
+  }
+
+  .list-desc {
+    font-size: 14px;
+    font-family: PingFangSC-Regular, PingFang SC;
+    font-weight: 400;
+    color: #596878;
+  }
+
+  .el-tag--small {
+    margin-bottom: 10px;
+  }
+
+  .reTip {
+    display: block;
+    background: #f00;
+    border-radius: 50%;
+    width: 4px;
+    height: 4px;
+    top: -21px;
+    right: -26px;
+    position: relative;
+    z-index: 4;
+  }
+
+  //左侧时间
+  .time {
+    color: rgb(181 215 251);
+    position: absolute;
+    left: -35px;
+    top: -1px;
+
+    .year {
+      font-size: 14px;
+      font-family: PingFangSC-Regular, PingFang SC;
+      font-weight: 400;
+      color: #20354a;
+    }
+
+    .day {
+      font-size: 14px;
+      font-family: PingFangSC-Regular, PingFang SC;
+      font-weight: 400;
+      color: #596878;
+      text-align: center;
+      margin-top: 10px;
+    }
+  }
+
+  .legend-box{
+    display: flex;
+    flex-direction: row;
+    justify-content: flex-start;
+    align-items: center;
+    >li{
+      display: flex;
+      flex-direction: row;
+      justify-content: flex-start;
+      align-items: center;
+      margin-right: 20px;
+      i{
+        margin-right: 5px;
+      }
+    }
+  }
+  .time-line-box{
+    width: 100%;
+    padding: 0 80px 50px 80px;
+  }
+  .calendar-box{
+    width: 100%;
+    display: flex;
+    flex-wrap: wrap;
+    justify-content: space-between;
+    >div{
+      width: 30%;
+    }
+  }
+  .el-calendar-table .el-calendar-day{
+    padding:5px;
+    height: auto;
+  }
+  .el-calendar__button-group{
+    display: none;
+  }
+  .legend {
+    display: block;
+    width: 14px;
+    height: 10px;
+    margin-right: 5px;
+  }
+}
+</style>

+ 31 - 38
src/views/iot/videoIntegrity/index.vue

@@ -31,18 +31,8 @@
               />
             </el-select>
           </el-form-item>
-          <el-form-item label="计划存储天数" prop="approveStatus">
-            <el-select v-model="queryParams.approveStatus" clearable placeholder="请选择审批状态">
-              <el-option
-                v-for="dict in dict.type.out_in_approve_status"
-                :key="dict.value"
-                :label="dict.label"
-                :value="dict.value"
-              />
-            </el-select>
-          </el-form-item>
           <el-form-item label="状态" prop="approveStatus">
-            <el-select v-model="queryParams.approveStatus" clearable placeholder="请选择审批状态">
+            <el-select v-model="queryParams.approveStatus" clearable placeholder="请选择状态">
               <el-option
                 v-for="dict in dict.type.out_in_approve_status"
                 :key="dict.value"
@@ -51,19 +41,6 @@
               />
             </el-select>
           </el-form-item>
-          <el-form-item label="检查日期">
-            <DataRangePicker
-              style="width: 240px"
-              v-model="queryParams.dateRange"
-              key="daterange"
-              type="daterange"
-              :editable="false"
-              :clearable="false"
-              range-separator="-"
-              start-placeholder="开始日期"
-              end-placeholder="结束日期"
-            />
-          </el-form-item>
         </el-form>
 
         <el-row :gutter="10">
@@ -89,23 +66,32 @@
       <el-table v-loading="loading" :data="dataList" border height="646" size="small">
         <el-table-column label="序号" type="index" align="center" width="70"></el-table-column>
         <el-table-column :show-overflow-tooltip="true" align="center" label="组织机构" prop="type" width="200"></el-table-column>
-        <el-table-column :show-overflow-tooltip="true" align="center" label="监控主机" prop="reasons"/>
-        <el-table-column align="center" label="摄像头" prop="letterNo" ></el-table-column>
+<!--        <el-table-column :show-overflow-tooltip="true" align="center" label="设备名称" prop="reasons"/>-->
+        <el-table-column :show-overflow-tooltip="true" align="center" label="通道名称" prop="letterNo" ></el-table-column>
         <el-table-column align="center" label="IP地址" prop="letterNo" ></el-table-column>
-        <el-table-column align="center" label="计划存储天数" prop="letterNo" ></el-table-column>
-        <el-table-column align="center" label="检查日期" width="150">
-          <template slot-scope="scope">
-            <span>{{ scope.row.startTime }}</span>
-          </template>
-        </el-table-column>
-        <el-table-column label="录像详情" ref="tabs" width="730px">
-          <template slot="header">
-            <img src="../../../assets/images/header.png" alt="" width="700px" />
-          </template>
+        <el-table-column align="center" label="录像丢失时长" prop="letterNo" ></el-table-column>
+        <el-table-column align="center" label="实际/计划存储(天)" prop="letterNo" ></el-table-column>
+        <el-table-column align="center" label="无视频信号" prop="letterNo" ></el-table-column>
+        <el-table-column align="center" label="视频遮挡" prop="letterNo" ></el-table-column>
+        <el-table-column align="center" label="视频质量" prop="letterNo" ></el-table-column>
+<!--        <el-table-column align="center" label="更新日期" width="150">-->
+<!--          <template slot-scope="scope">-->
+<!--            <span>{{ scope.row.startTime }}</span>-->
+<!--          </template>-->
+<!--        </el-table-column>-->
+        <el-table-column label="操作" align="center"  width="120" >
           <template slot-scope="r">
-<!--            <TimeLine :data="r.row" :rems="700" />-->
+            <el-button type="text" @click="openDetail(r.row.id)">详情</el-button>
           </template>
         </el-table-column>
+<!--        <el-table-column label="录像详情" ref="tabs" width="730px">-->
+<!--          <template slot="header">-->
+<!--            <img src="../../../assets/images/header.png" alt="" width="700px" />-->
+<!--          </template>-->
+<!--          <template slot-scope="r">-->
+<!--            <TimeLine :data="r.row" :rems="700" />-->
+<!--          </template>-->
+<!--        </el-table-column>-->
       </el-table>
 
       <pagination
@@ -117,6 +103,9 @@
       />
 
     </div>
+    <!--详情页面-->
+    <detail ref="DialogDetail" @success="refresh(true)"></detail>
+
   </div>
 </template>
 
@@ -126,8 +115,9 @@ import DataRangePicker from "@/components/dateTime/daterange.picker.vue";
 import TimeLine from "./timeLine.vue";
 import {getLetterApproveList} from "@/api/core/letter";
 import dayjs from 'dayjs';
+import detail from "./detail.vue";
 export default {
-  components: {DataRangePicker, OrgTree,TimeLine },
+  components: {detail, DataRangePicker, OrgTree,TimeLine },
   dicts: ['letter_status', 'out_in_type', 'out_in_approve_status'],
   data() {
     return {
@@ -153,6 +143,9 @@ export default {
   },
   methods: {
     dayjs,
+    openDetail(id){
+      this.$refs.DialogDetail.show(id);
+    },
     getDefaultKey(key) {
       this.queryParams.orgId = key;
       this.getList();

+ 2 - 1
src/views/iot/videoQuality/index.vue

@@ -108,7 +108,7 @@
       />
 
     </div>
-
+<!--  请  -->
     <dialog-alarm-history ref="alarmHistoryDialog"></dialog-alarm-history>
 
   </div>
@@ -147,6 +147,7 @@ export default {
   },
   methods: {
     dayjs,
+
     openAlarmHistoryDialog(row) {
       this.$refs.alarmHistoryDialog.show(row);
     },