凉纪 1 жил өмнө
parent
commit
34d124b7fc

+ 1 - 0
package.json

@@ -57,6 +57,7 @@
     "quill": "1.3.7",
     "screenfull": "5.0.2",
     "sortablejs": "1.10.2",
+    "v-calendar": "^2.4.1",
     "vue": "2.6.12",
     "vue-count-to": "1.0.13",
     "vue-cropper": "0.5.5",

+ 7 - 0
src/main.js

@@ -56,6 +56,8 @@ import layoutCom from "@/components/layoutContainer/index.vue";
 import "@/utils/dialogdrag.js";
 // 水印组件
 import watercom from '@/components/waterCom.vue'
+//日历组件
+import VCalendar from 'v-calendar';
 // 全局方法挂载
 Vue.prototype.getDicts = getDicts;
 //根据参数键名查询参数值
@@ -94,6 +96,7 @@ Vue.component("layoutCom", layoutCom);
 Vue.use(directive);
 Vue.use(plugins);
 Vue.use(VueMeta);
+
 DictData.install();
 
 /**
@@ -109,6 +112,10 @@ Vue.use(Element, {
   size: sessionStorage.getItem("size") || "medium", // set element-ui default size
 });
 
+Vue.use(VCalendar, {
+  componentPrefix: 'v',  // Use <vc-calendar /> instead of <v-calendar />
+});
+
 Vue.config.productionTip = false;
 
 new Vue({

+ 152 - 0
src/views/iot/videoIntegrity/Calendar.vue

@@ -0,0 +1,152 @@
+<template>
+  <v-calendar
+    ref="calendar"
+    :columns="layout.columns"
+    :rows="layout.rows"
+    :is-expanded="layout.isExpanded"
+    :attributes="attrs"
+    :min-date='new Date()'
+    :max-date='new Date(2024, 3, 28)'
+  />
+</template>
+<script>
+export default {
+  name: "Calendar",
+  data() {
+    return {
+      layout: {
+        columns: 3,
+        rows: 2,
+        isExpanded: true
+      },
+      attrs: [
+        {
+          highlight: {
+            start: {
+              fillMode: 'outline'
+            },
+            base: {
+              color: 'gray',
+              fillMode: 'light'
+            },
+            end: {
+              fillMode: 'outline'
+            },
+          },
+          dates: { start: new Date(), end: new Date(2024, 3, 28) },
+        },
+        {
+          dot:{
+            color:'green',
+            contentClass:'italic',
+          },
+          dates:[ '2024-01-29','2024-01-31','2024-02-02','2024-02-03','2024-02-04','2024-02-05','2024-02-06','2024-02-07','2024-02-08','2024-02-09','2024-02-10','2024-02-11',],
+        },
+        {
+          dot:{
+            color:'red',
+            contentClass:'italic',
+          },
+          dates: '2024-01-30',
+        },
+        {
+          dot:{
+            color:'yellow',
+            style:{
+              backgroundColor:'orange'
+            },
+            contentClass:'italic',
+          },
+          dates: '2024-02-01',
+        },
+      ],
+    };
+  },
+  mounted(){
+     this.init();
+  },
+  methods:{
+    init(){
+      this.setLayout();
+      const calendar = this.$refs.calendar;
+      // setTimeout(() => {
+      //   calendar.move({ month: 1, year: 1983 });
+      // }, 3000);
+      //calendar.move({ month: 1, year: 1983 });
+      //this.setOps();
+    },
+    setLayout() {
+      this.layout = {
+        columns: 3,
+        rows: 1,
+        isExpanded: true
+      };
+    },
+    setOps(){
+      this.attrs = [
+        {
+          highlight: {
+            color: 'green',
+            fillMode: 'solid',
+            contentClass: 'italic',
+          },
+          dates: new Date(),
+        },
+        {
+          // highlight: {
+          //   color: 'green',
+          //   fillMode: 'solid',
+          //   contentClass: 'italic',
+          // },
+          dot:'yellow',
+          dates: '2024-01-30',
+        },
+        {
+          highlight: {
+            color: 'yellow',
+            fillMode: 'solid',
+            contentClass: 'italic',
+          },
+          dates: '2024-01-31',
+        },
+        {
+          highlight: {
+            color: 'red',
+            fillMode: 'solid',
+            contentClass: 'italic',
+          },
+          dates: '2024-02-01',
+        },
+        {
+          highlight: {
+            color: 'yellow',
+            fillMode: 'solid',
+            contentClass: 'italic',
+          },
+          dates: '2024-02-02',
+        },
+        {
+          highlight: {
+            color: 'green',
+            fillMode: 'solid',
+            contentClass: 'italic',
+          },
+          dates: '2024-02-03',
+        },
+        {
+          highlight: {
+            color: 'green',
+            fillMode: 'solid',
+            contentClass: 'italic',
+          },
+          dates: '2024-02-04',
+        },
+      ];
+
+    },
+  }
+}
+</script>
+<style scoped lang="scss">
+
+</style>

+ 74 - 36
src/views/iot/videoIntegrity/ProgressBar.vue

@@ -1,6 +1,11 @@
 <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>
+        <canvas draggable="false" id="procanvas" height="60" @contextmenu="contextMenuClick" @mousedown="mousedownFunc" @mouseup="mouseupFunc" @mousemove="mousemoveFunc" @mouseout="mouseoutFunc"></canvas>
+        <div class="bar-container">
+          <div class="bar1"></div>
+          <div class="bar2"></div>
+          <div class="bar3"></div>
+        </div>
     </div>
 </template>
 
@@ -64,10 +69,10 @@ export default {
         // 初始化canvas
         initCanvas:function(){
             this.drawCellBg();
-            this.add_cells(this.timeCell);
+            //this.add_cells(this.timeCell);
             this.add_graduations(this.start_timestamp);
-            this.draw_down(this.downTime);
-            this.drawTimeTriangle();
+            //this.draw_down(this.downTime);
+            //this.drawTimeTriangle();
         },
         // // 绘制三角 时间
         drawTimeTriangle(){
@@ -87,7 +92,7 @@ export default {
         },
         // 画背景色
         drawCellBg:function(){
-            this.ctx.fillStyle = "#ccc";
+            this.ctx.fillStyle = "#eaeaea";
             this.ctx.fillRect(0, this.tiaoTop, this.canvasW, this.tiaoHeight);
         },
         // 添加刻度
@@ -97,7 +102,7 @@ export default {
             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++){
+            for(let 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;
@@ -105,7 +110,7 @@ export default {
                 }
             }
             var medium_step = 30;
-            for (var i = 0; i < _this.minutes_per_step.length; i++) {
+            for (let 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;
@@ -125,10 +130,10 @@ export default {
                     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.ctx.fillText(middle_date,graduation_left-17,35);
                     _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);
+                    _this.drawLine(graduation_left,55,graduation_left,60,"rgba(49,142,212,0.7)",1);
                 }
             }
         },
@@ -143,35 +148,35 @@ export default {
             this.ctx.stroke();
         },
         // 添加录像块
-        add_cells:function(cells){
-            var _this = this;
-            cells.forEach(cell => {
-                _this.draw_cell(cell)
-            });
-        },
+        // 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_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);
-        },
+        // 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
+        // 开始时间  px
         ms_to_next_step:function(timestamp, step) {
             var remainder = timestamp % step;
             return remainder ? step - remainder : 0;
@@ -191,7 +196,7 @@ export default {
             }else if (e.clientX || e.clientY) {
                 posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
             }
-            return posx-360;//调整鼠标误差值
+            return posx-455;//调整鼠标误差值
         },
         // 返回时间日期格式
         changeTime:function(time) {
@@ -250,7 +255,7 @@ export default {
                 _this.ctx.fillText(_this.changeTime(time),pos_x-65,35);
             }
         },
-        // 鼠标释放弹起事件
+        //鼠标释放弹起事件
         mouseupFunc:function(e){
             if(e.button == 2){
                 if(this.downTime.length==2){
@@ -265,7 +270,7 @@ export default {
             }
 
         },
-        // 鼠标移除隐藏时间事件
+        //鼠标移除隐藏时间事件
         mouseoutFunc:function(e){
             this.clearCanvas();
             this.initCanvas();
@@ -344,7 +349,7 @@ export default {
 }
 </script>
 
-<style scoped>
+<style lang="scss" scoped>
     .progress-box-bar{
         position: relative;
         width:100%;
@@ -372,4 +377,37 @@ export default {
     .progress-box-bar .downVideo ul li:hover{
         background-color: #318ed4;
     }
+    .bar-container{
+      width: 100%;
+      height: 20px;
+      background-color: #eaeaea;
+      position: relative;
+      .bar1{
+        width: 80%;
+        height: 100%;
+        position: absolute;
+        top:0;
+        left: 0;
+        background: green;
+        z-index:2;
+      }
+      .bar2{
+        width: 93%;
+        height: 100%;
+        position: absolute;
+        top:0;
+        left: 0;
+        background: rgb(0, 178, 255);
+        z-index:1;
+      }
+      .bar3{
+        width: 10%;
+        height: 100%;
+        position: absolute;
+        top:0;
+        left: 30%;
+        background: red;
+        z-index:3;
+      }
+    }
 </style>

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

@@ -0,0 +1,375 @@
+<template>
+    <div class="progress-box-bar" ref="progressbar">
+        <canvas draggable="false" id="procanvas" height="60" @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-355;//调整鼠标误差值
+        },
+        // 返回时间日期格式
+        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>

+ 114 - 146
src/views/iot/videoIntegrity/detail.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="videoDaysDetail">
-    <el-dialog title="录像详情" :visible.sync="isShow" width="1400px" :destroy-on-close="true">
+    <el-dialog title="录像详情" :visible.sync="isShow" width="1200px" :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>
@@ -17,57 +17,57 @@
       </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-item label="检测结果" >常</el-descriptions-item>
+<!--        <el-descriptions-item label="原因" >被遮挡</el-descriptions-item>-->
+        <el-descriptions-item label="更新时间" >2024年1月29日 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>
+<!--            <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="录像日期" >2024年1月29日</el-descriptions-item>
         <el-descriptions-item label="检测结果" >异常</el-descriptions-item>
-        <el-descriptions-item label="丢失时长" >8:46</el-descriptions-item>
+        <el-descriptions-item label="原因" >被遮挡</el-descriptions-item>
+        <el-descriptions-item label="丢失时长" >126分钟</el-descriptions-item>
+        <el-descriptions-item label="更新时间" >2024年1月29日 09:00</el-descriptions-item>
       </el-descriptions>
       <el-descriptions :column="1">
         <el-descriptions-item label="丢失时段" >
@@ -126,13 +126,12 @@
       </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-item label="计划存储天数" >90</el-descriptions-item>
+        <el-descriptions-item label="实际存储天数" >12</el-descriptions-item>
+        <el-descriptions-item label="最早录像日期" >2024年1月29日</el-descriptions-item>
       </el-descriptions>
       <el-descriptions :column="1">
-        <el-descriptions-item label="录像存储天数" >
+        <el-descriptions-item label="存储状态" >
           <!--          <time-line></time-line>-->
           <ul class="legend-box">
             <li>
@@ -148,108 +147,56 @@
               <span>全部丢失</span>
             </li>
             <li>
-              <i class="legend" style="background-color: #aaa"></i>
-              <span>未知</span>
+              <i class="legend" style="background-color: #cbd5e0"></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  class="calendar-box">
+        <Calendar></Calendar>
+      </div>
 
-        <div>
-          <el-calendar :value="'2024-06'">
-            <template
-              slot="dateCell"
-              slot-scope="{date, data}">
+<!--      <el-carousel :autoplay="false" indicator-position="outside" trigger="click" >-->
+<!--        <el-carousel-item  key="1">-->
+<!--          <div class="calendar-box">-->
+<!--            <div v-for="(item,i ) in calendarList" :key="item.date">-->
+<!--              <el-calendar v-if="i <= 2" :value="item.date">-->
+<!--                <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-carousel-item>-->
+<!--        <el-carousel-item v-if="calendarList.length > 3" key="2">-->
+<!--          <div class="calendar-box">-->
+<!--            <div v-for="(item,i ) in calendarList" :key="item.date">-->
+<!--              <el-calendar v-if="i >= 3" :value="item.date">-->
+<!--                <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-carousel-item>-->
+<!--      </el-carousel>-->
 
-              <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>
@@ -260,10 +207,11 @@
 <script>
 
 import TimeLine from "./timeLine.vue";
-import ProgressBar from './ProgressBar'
+import ProgressBar from './ProgressBar';
+import Calendar from "./Calendar.vue";
 import dayjs from 'dayjs'
 export default {
-  components: {TimeLine,ProgressBar},
+  components: {TimeLine,ProgressBar,Calendar},
   data() {
     return {
       src:'https://cube.elemecdn.com/6/94/4d3ea53c084bad6931a56d5158a48jpeg.jpeg',
@@ -273,6 +221,26 @@ export default {
       playVideoObj:{},   //选中的正在播放的录像
       timeCells:[],    //录像时间块
       start_timestamp:new Date().getTime() - 5*60*60*1000,    //刻度轴开始时间
+      calendarList:[
+        {
+          date:'2024-02'
+        },
+        {
+          date:'2024-03'
+        },
+        {
+          date:'2024-04'
+        },
+        {
+          date:'2024-05'
+        },
+        {
+          date:'2024-06'
+        },
+        {
+          date:'2024-07'
+        }
+      ],
     };
   },
   methods: {
@@ -388,9 +356,9 @@ export default {
     display: flex;
     flex-wrap: wrap;
     justify-content: space-between;
-    >div{
-      width: 30%;
-    }
+    //>div{
+    //  width: 30%;
+    //}
   }
   .el-calendar-table .el-calendar-day{
     padding:5px;