qiushang hace 6 meses
padre
commit
d42a4f45b8

BIN
bin/gif/gif.exe


BIN
bin/icon.png


+ 0 - 0
bin/ffmpeg.exe → bin/video/ffmpeg.exe


+ 0 - 0
bin/ffplay.exe → bin/video/ffplay.exe


+ 0 - 0
bin/ffprobe.exe → bin/video/ffprobe.exe


+ 2 - 0
package.json

@@ -37,11 +37,13 @@
 	"dependencies": {
 		"axios": "^0.18.0",
 		"element-ui": "^2.15.14",
+		"image-size": "1.0.0",
 		"regedit": "^5.0.0",
 		"request": "^2.88.2",
 		"vue": "^2.5.2",
 		"vue-electron": "^1.0.6",
 		"vue-router": "^3.0.1",
+		"vuedraggable": "^2.24.3",
 		"vuex": "^3.0.1",
 		"vuex-electron": "^1.0.0",
 		"vxe-table": "^3.7.9",

BIN
src/renderer/assets/image/1.png


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 588 - 437
src/renderer/components/home.vue


+ 764 - 0
src/renderer/components/vueVideoClip.vue

@@ -0,0 +1,764 @@
+<template>
+	<div class="custom-video" v-if="videoShow">
+		<div class="custom-video_container" ref="custom-video_container">
+			<div class="custom-video_video">
+				<video ref="custom-video" controls :src="url">
+					<p>设备不支持</p>
+				</video>
+			</div>
+		</div>
+		<!-- 缩略图,裁剪区域 -->
+		<div class="video-controls" @mousedown="handleClick">
+			<div class="thumbs" ref="thumbs">
+				<div class="inner" v-if="thumbCount" ref="thumbs-inner">
+					<div class="inner-item" :style="`width:${videoUnitWidth}px;`" v-for="(item, index) in thumbArr"
+						:key="index">
+						<video width="100%" preload="metadata" :src="item.url" @canplay="item.loading = false;"></video>
+						<div class="inner-loading" v-if="item.loading">
+							<div class="loading">
+								<div class="loading-con"></div>
+							</div>
+						</div>
+					</div>
+				</div>
+			</div>
+			<div class="control-bars" ref="control-bars">
+				<div class="control-bars-mask left" data-direction="left" :style="`width:${leftMovePercentage}%;`">
+				</div>
+				<div class="control-bars-mask right" data-direction="right" :style="`width:${rightMovePercentage}%;`">
+				</div>
+				<div class="control-bars-progress" :style="`left:${videoEdit.currentPosition}%;`"
+					:class="{ animate: videoEdit.play }">
+					<svg width="54px" height="24px" viewBox="0 0 54 24" version="1.1" xmlns="http://www.w3.org/2000/svg"
+						xmlns:xlink="http://www.w3.org/1999/xlink">
+						<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+							<path
+								d="M27,23 L27,24 L26,24 L26,23 C26,20.2385763 23.7614237,18 21,18 L9,18 C4.02943725,18 0,13.9705627 0,9 C0,4.02943725 4.02943725,0 9,0 L45,0 C49.9705627,0 54,4.02943725 54,9 C54,13.9705627 49.9705627,18 45,18 L32,18 L32,18 C29.2385763,18 27,20.2385763 27,23 Z"
+								id="time_bg" fill="#FFFFFF"></path>
+						</g>
+					</svg>
+					<span class="text">{{ timeTranslate(currentTime) }}</span>
+				</div>
+				<div class="control-bars-wrapper" :style="`left:${leftMovePercentage}%;right:${rightMovePercentage}%;`">
+					<div ref="move-left-icon" class="control-bars-move left"
+						@mousedown="handleMoveDown($event, 'left')"></div>
+					<div ref="move-right-icon" class="control-bars-move right"
+						@mousedown="handleMoveDown($event, 'right')"></div>
+				</div>
+			</div>
+		</div>
+		<!-- 按钮文字 -->
+		<div class="video-btn">
+			<div class="crop-range" style="font-size: 12px; margin-bottom: 4px; text-align: center;">
+				<div style="width: 150px;">输入开始时间</div>
+				<span></span>
+				<div style="width: 150px;">输入截止时间</div>
+			</div>
+		</div>
+		<!-- 按钮区域 -->
+		<div class="video-btn">
+			<!-- <div class="toggle" @click="togglePlayStatus">
+				<div class="toggle-icon" :class="{ playing: videoEdit.play }"></div>
+			</div> -->
+			<div class="crop-range">
+				<div class="crop-input crop-start">
+					<input class="text-right" type="text" placeholder="00" maxlength="3" id="range-0"
+						v-model.number="inputStartLeftTime" @blur="onBlur('inputStartLeftTime')" />
+					<span>:</span>
+					<input class="text-left" type="text" placeholder="00" maxlength="2" id="range-1"
+						v-model.number="inputStartRightTime" @blur="onBlur('inputStartRightTime')" />
+				</div>
+				<span style="color:#fff;margin:0 10px;"></span>
+				<div class="crop-input crop-end">
+					<input class="text-right" type="text" placeholder="00" maxlength="3" id="range-2" v-model.number="inputEndLeftTime" @blur="onBlur('inputEndLeftTime')" />
+					<span>:</span>
+					<input class="text-left" type="text" placeholder="00" maxlength="2" id="range-3" v-model.number="inputEndRightTime" @blur="onBlur('inputEndRightTime')" />
+				</div>
+			</div>
+		</div>
+	</div>
+</template>
+<script>
+	export default {
+		name: 'vueVideoClip',
+		props: {
+			url: {
+				type: String,
+				required: true
+			}
+		},
+		data() {
+			return {
+				blobURL: '',
+				videoState: {
+					play: false, // 播放状态
+					currentPosition: 0 // 当前播放点距离左边的百分比
+				},
+				videoEdit: {
+					start: 0,
+					end: 0,
+					duration: 0,
+					play: false, // 播放状态
+					currentPosition: 0 // 当前播放点距离左边的百分比
+				},
+				videoDom: null, // video
+				duration: 0, // 视频总时长
+				currentTime: 0, // 视频当前播放时长 = this.videoDom.currentTime
+				objectURL: '',
+				videoUnit: 0,
+				videoUnitWidth: 0,
+				videoRatio: 0,
+				isPortraitVideo: false,
+				thumbCount: 0,
+				thumbArr: [], // 缩略图数组
+				leftMovePercentage: 0,
+				leftMoveInit: 0,
+				rightMovePercentage: 0,
+				rightMoveInit: 0,
+				videoShow: true,
+				
+				loadingTap: '',
+			}
+		},
+		mounted() {
+			this.loadingTap = this.$loading({
+				text: '加载中',
+				spinner: 'el-icon-loading',
+			});
+			this.init();
+			window.onresize = () => {
+				this.throttle(this.init(), 300)
+				this.handleClick(null, this.handleMoveDirection);
+			}
+		},
+		computed: {
+			inputStartLeftTime: {
+				set(val) {
+					val = val * 60 + this.toInt(document.getElementById('range-1').value)
+					// if (val >= this.videoEdit.end || val < 0) {
+					// 	val = 0
+					// }
+					this.videoEdit.start = val
+				},
+				get() {
+					return this.timeTranslate(this.videoEdit.start).split(':')[0]
+				}
+			},
+			inputStartRightTime: {
+				set(val) {
+					val = this.toInt(document.getElementById('range-0').value) * 60 + val
+					// if (val >= this.videoEdit.end || val < 0) {
+					// 	val = 0
+					// }
+					this.videoEdit.start = val
+				},
+				get() {
+					return this.timeTranslate(this.videoEdit.start).split(':')[1]
+				}
+			},
+			inputEndLeftTime: {
+				set(val) {
+					val = val * 60 + this.toInt(document.getElementById('range-3').value)
+					// if (val <= this.videoEdit.start || val > this.videoEdit.duration) {
+					// 	val = this.videoEdit.duration
+					// }
+					this.videoEdit.end = val
+				},
+				get() {
+					return this.timeTranslate(this.videoEdit.end).split(':')[0]
+				}
+			},
+			inputEndRightTime: {
+				set(val) {
+					val = this.toInt(document.getElementById('range-2').value) * 60 + val
+					// if (val <= this.videoEdit.start || val > this.videoEdit.duration) {
+					// 	val = this.videoEdit.duration
+					// }
+					this.videoEdit.end = val
+				},
+				get() {
+					return this.timeTranslate(this.videoEdit.end).split(':')[1]
+				}
+			}
+		},
+		watch: {
+			'videoEdit.start': {
+				handler(val) {
+					this.currentTime = val
+					this.videoEdit.currentPosition =
+						(this.currentTime / this.videoEdit.duration) * 100
+					this.leftMovePercentage = this.videoEdit.currentPosition
+					this.$emit('getTime', {
+						start: val,
+						end: this.videoEdit.end
+					})
+				},
+				deep: true
+			},
+			'videoEdit.end': {
+				handler(val) {
+					this.currentTime = val
+					this.videoEdit.currentPosition =
+						(this.currentTime / this.videoEdit.duration) * 100
+					this.rightMovePercentage = 100 - this.videoEdit.currentPosition
+					this.$emit('getTime', {
+						start: this.videoEdit.start,
+						end: val
+					})
+				},
+				deep: true
+			}
+		},
+		methods: {
+			onBlur(str){
+				let val = Number(this[str]);
+				switch(str){
+					case 'inputStartLeftTime':
+						val = val * 60 + this.toInt(document.getElementById('range-1').value)
+						if (val >= this.videoEdit.end || val < 0) {
+							val = 0
+						}
+						this.videoEdit.start = val
+						break;
+						
+					case 'inputStartRightTime':
+						val = this.toInt(document.getElementById('range-0').value) * 60 + val
+						if (val >= this.videoEdit.end || val < 0) {
+							val = 0
+						}
+						this.videoEdit.start = val
+						break;
+						
+					case 'inputEndLeftTime':
+						val = val * 60 + this.toInt(document.getElementById('range-3').value)
+						if (val <= this.videoEdit.start || val > this.videoEdit.duration) {
+							val = this.videoEdit.duration
+						}
+						this.videoEdit.end = val
+						break;
+						
+					case 'inputEndRightTime':
+						val = this.toInt(document.getElementById('range-2').value) * 60 + val
+						if (val <= this.videoEdit.start || val > this.videoEdit.duration) {
+							val = this.videoEdit.duration
+						}
+						this.videoEdit.end = val
+						break;
+				}
+				
+				// console.log(this.videoEdit.end, this.videoEdit.start);
+			},
+			throttle(fn, threshold, scope) {
+				let timer
+				return function() {
+					const context = scope || this
+					const args = arguments
+					if (!timer) {
+						timer = setTimeout(function() {
+							fn.apply(context, args)
+							timer = null
+						}, threshold)
+					}
+				}
+			},
+			init() {
+				// 初始化相关元数据
+				this.videoDom = this.$refs['custom-video']
+				this.leftIconDom = this.$refs['move-left-icon']
+				this.rightIconDom = this.$refs['move-right-icon']
+				this.thumbsWidth = this.$refs.thumbs.clientWidth
+				this.leftMoveInit = this.getOffset(this.leftIconDom).left + 5
+				this.rightMoveInit = this.getOffset(this.rightIconDom).left + 5
+				this.minWidthPercentage = ((10 / this.thumbsWidth) * 100).toFixed(4) // 最小裁剪区域所占百分比
+				this.thumbArr = [];
+				this.initMedaData()
+				
+				// this.transformBlob()
+				document.addEventListener('mouseup', ev => {
+					this.handleMoveStatus = false
+				})
+				document.addEventListener('mousemove', ev => {
+					if (!this.handleMoveStatus) return
+					if (this.handleMoveDirection === 'left') {
+						const distanceMoveXLeft = ev.clientX - this.leftMoveInit
+
+						this.leftMovePercentage =
+							distanceMoveXLeft > 0 ?
+							((distanceMoveXLeft / (this.thumbsWidth - 20)) * 100).toFixed(4) :
+							0
+
+						// 控制裁剪百分比最小值
+						if (
+							this.leftMovePercentage >
+							100 - this.rightMovePercentage - this.minWidthPercentage
+						) {
+							this.leftMovePercentage =
+								100 - this.rightMovePercentage - this.minWidthPercentage
+						}
+
+						this.videoEdit.start = (
+							(this.videoEdit.duration * this.leftMovePercentage) /
+							100
+						).toFixed(4)
+					}
+					if (this.handleMoveDirection === 'right') {
+						const distanceMoveXRight = this.rightMoveInit - ev.clientX
+
+						this.rightMovePercentage =
+							distanceMoveXRight > 0 ?
+							((distanceMoveXRight / (this.thumbsWidth - 20)) * 100).toFixed(
+								4
+							) :
+							0
+
+						// 控制裁剪百分比最小值
+						if (
+							this.rightMovePercentage >
+							100 - this.leftMovePercentage - this.minWidthPercentage
+						) {
+							this.rightMovePercentage =
+								100 - this.leftMovePercentage - this.minWidthPercentage
+						}
+
+						this.videoEdit.end = (
+							this.videoEdit.duration *
+							(1 - this.rightMovePercentage / 100)
+						).toFixed(4)
+					}
+					this.handleClick(ev, this.handleMoveDirection)
+				})
+			},
+			toInt(val) {
+				return parseInt(val) || 0
+			},
+			togglePlayStatus() {
+				// 播放暂停按钮事件
+				this.videoEdit.play ? this.toggleVideoPause() : this.toggleVideoPlay()
+			},
+			toggleVideoPlay() {
+				// 处理当前位置在末尾的时候先初始化开始播放时间
+				if (this.videoEdit.end - this.currentTime < 0.01) {
+					this.videoDom.currentTime = this.videoEdit.start
+				}
+				// 为了取消当前点平滑移动到开始点的过渡
+				setTimeout(() => {
+					this.videoDom.play()
+					this.videoEdit.play = true
+				}, 50)
+			},
+			toggleVideoPause() {
+				this.videoDom.pause()
+				this.videoEdit.play = false
+			},
+			playEnd() {
+				this.videoDom.currentTime = this.videoEdit.start
+				this.videoDom.pause()
+				this.videoEdit.play = false
+			},
+			transformBlob() {
+				const self = this
+				const xhr = new XMLHttpRequest()
+				xhr.open('GET', this.url, true)
+				xhr.responseType = 'blob'
+				xhr.onload = function(e) {
+					if (this.status === 200) {
+						// 获取blob对象
+						const myBlob = this.response
+						self.blobURL = URL.createObjectURL(myBlob)
+					} else {
+						this.$Notice.error({
+							title: '读取失败',
+							desc: '参数有误,读取视频失败!',
+							duration: 5
+						})
+					}
+				}
+				xhr.send()
+			},
+			initMedaData() {
+				// 初始化video相关事件
+				this.videoDom.addEventListener('loadedmetadata', () => {
+					// 获取视频总时长
+					this.videoEdit.duration = this.videoDom.duration // 视频总时长
+					this.videoEdit.end = this.videoEdit.duration
+				})
+				const self = this
+				this.videoDom.addEventListener('canplay', () => {
+					// 监听视频可播放时的状态
+					self.videoRatio = this.videoHeight / this.videoWidth
+					self.isPortraitVideo = self.videoRatio > 1.5 // 是否是竖向视频
+					self.videoUnitWidth = self.isPortraitVideo ? 28 : 88 // 单个缩略图宽度
+					self.thumbCount = Math.ceil(self.thumbsWidth / self.videoUnitWidth) // 缩略图个数
+					self.videoUnit = self.videoEdit.duration / self.thumbCount
+					// 缩略图
+					if (self.thumbArr.length !== self.thumbCount) {
+						self.thumbArr = []
+						for (let i = 0; i < self.thumbCount; i++) {
+							self.thumbArr.push({
+								url: `${self.url}#t=${self.videoUnit * i}`,
+								loading: true
+							})
+						}
+					}
+					const innerMoveLeft = Math.round(
+						(self.thumbCount * self.videoUnitWidth - self.thumbsWidth) / 2
+					)
+					self.$nextTick(() => {
+						self.$refs['thumbs-inner'].style.marginLeft = `${-innerMoveLeft}px`
+					})
+					
+				})
+
+				this.videoDom.addEventListener('timeupdate', () => {
+					// 监听视频播放过程中的时间
+					this.videoEdit.currentPosition =
+						(this.videoDom.currentTime / this.videoEdit.duration) * 100
+					this.currentTime = this.videoDom.currentTime
+					if (
+						this.videoEdit.end - this.currentTime < 0.01 &&
+						this.videoEdit.play
+					) {
+						this.playEnd()
+					}
+				})
+				
+				this.loadingTap.close();
+			},
+			handleMoveDown(ev, direction) {
+				this.handleMoveStatus = true
+				this.handleMoveDirection = direction
+				this.toggleVideoPause()
+				this.handleClick(ev, direction)
+			},
+			handleClick(ev, direction) {
+				// 区分各种情况是为了获取各种情况的当前播放点更准确
+				if (direction === 'left') {
+					this.videoEdit.currentPosition = this.leftMovePercentage
+				} else if (direction === 'right') {
+					this.videoEdit.currentPosition = 100 - this.rightMovePercentage
+				} else {
+					if(ev){
+						// 点击中间剪辑区域
+						this.videoEdit.currentPosition =
+							((ev.clientX - this.leftMoveInit) / this.thumbsWidth) * 100
+					}else{
+						this.videoEdit.currentPosition = 0;
+					}
+				}
+				this.currentTime = (
+					(this.videoEdit.currentPosition * this.videoEdit.duration) /
+					100
+				).toFixed(4)
+				
+				this.videoDom.currentTime = this.currentTime
+				// 处理两边 mask 点击而非滑动时,拖拽区域的处理
+				if(ev){
+					if (ev.target.dataset.direction === 'left' && !this.handleMoveStatus) {
+						this.leftMovePercentage = this.videoEdit.currentPosition
+						this.videoEdit.start = this.currentTime
+					}
+					if (ev.target.dataset.direction === 'right' && !this.handleMoveStatus) {
+						this.rightMovePercentage = 100 - this.videoEdit.currentPosition
+						this.videoEdit.end = this.currentTime
+					}
+				}
+				// 百分比取最大值:100 最小值:0
+				this.videoEdit.currentPosition =
+					this.videoEdit.currentPosition > 100 ?
+					100 :
+					this.videoEdit.currentPosition
+				this.videoEdit.currentPosition =
+					this.videoEdit.currentPosition < 0 ? 0 : this.videoEdit.currentPosition
+				
+			},
+			getOffset(node, offset) {
+				// 获取当前屏幕下进度条的左偏移量和又偏移量
+				if (!offset) {
+					offset = {}
+					offset.left = 0
+					offset.top = 0
+				}
+				if (node === document.body || node === null) {
+					return offset
+				}
+				offset.top += node.offsetTop
+				offset.left += node.offsetLeft
+				return this.getOffset(node.offsetParent, offset)
+			},
+			timeTranslate(t) {
+				// 时间转化
+				let m = Math.floor(t / 60)
+				m < 10 && (m = '0' + m)
+				return m + ':' + ((t % 60) / 100).toFixed(2).slice(-2)
+			}
+		}
+	}
+</script>
+<style scoped lang="scss">
+	.custom-video {
+		user-select: none;
+		margin: 0 auto;
+		// min-height: 100%;
+		padding: 20px;
+		border-radius: 20px;
+		min-width: 500px;
+		
+		.custom-video_video{
+			text-align: center;
+		}
+
+		&_container {
+			height: 290px;
+			margin: 0 auto;
+			position: relative;
+			overflow: hidden;
+		}
+
+		&_video {
+			height: 100%;
+			
+			video {
+				height: 100%;
+			}
+		}
+	}
+
+	.thumbs {
+		white-space: nowrap;
+		overflow: hidden;
+		height: 50px;
+		background: #ffc7d1;
+
+		.inner {
+			height: 50px;
+			display: flex;
+
+			&-item {
+				position: relative;
+			}
+
+			&-loading {
+				position: absolute;
+				top: 0;
+				left: 0;
+				height: 100%;
+				width: 100%;
+			}
+		}
+
+		video {
+			object-fit: cover;
+		}
+	}
+
+	.video-controls {
+		position: relative;
+		margin: 50px 0 15px;
+		overflow: hidden;
+	}
+
+	.control-bars {
+		position: absolute;
+		right: 0;
+		bottom: 0;
+		top: 0;
+		left: 0;
+
+		&-wrapper {
+			position: absolute;
+			right: 0;
+			bottom: 0;
+			top: 0;
+			left: 0;
+			border: 1px solid #04f0fb;
+			z-index: 10;
+			min-width: 10px;
+		}
+
+		&-mask {
+			position: absolute;
+			top: 0;
+			bottom: 0;
+			background-color: rgba(25, 30, 64, 0.8);
+
+			&.left {
+				left: 0;
+			}
+
+			&.right {
+				right: 0;
+			}
+		}
+
+		&-progress {
+			position: absolute;
+			height: 80px;
+			top: -15px;
+			width: 1px;
+			background: #ffffff;
+			border-radius: 100px;
+
+			&.animate {
+				transition: all 0.3s;
+			}
+
+			svg {
+				position: absolute;
+				top: -10px;
+				left: -26px;
+			}
+
+			.text {
+				position: absolute;
+				width: 54px;
+				height: 18px;
+				top: -10px;
+				left: -26px;
+				font-size: 12px;
+				line-height: 18px;
+			}
+		}
+
+		&-move {
+			position: absolute;
+			width: 10px;
+			height: 10px;
+			background: #04f0fb;
+			top: 50%;
+			transform: translateY(-50%);
+			border-radius: 50%;
+			cursor: ew-resize;
+			z-index: 2;
+
+			&:active {
+				background: #fff;
+			}
+
+			&.left {
+				left: -5px;
+			}
+
+			&.right {
+				right: -5px;
+			}
+		}
+	}
+
+	.video-btn {
+		display: flex;
+		align-items: center;
+		justify-content: space-between;
+
+		.toggle {
+			width: 70px;
+			height: 30px;
+			line-height: 30px;
+			border-radius: 30px;
+			background-color: rgba(0, 0, 0, 0.3);
+			position: relative;
+			transition: background-color 0.2s;
+			cursor: pointer;
+
+			&-icon {
+				position: absolute;
+				display: inline-block;
+				top: 50%;
+				left: 50%;
+				transform: translate(-50%, -50%);
+				width: 0;
+				height: 0;
+				border-top: 8px solid transparent;
+				border-bottom: 8px solid transparent;
+				border-left: 12px solid #fff;
+				opacity: 1;
+				transition: all 0.2s;
+
+				&.playing {
+					width: 12px;
+					height: 15px;
+					border-left: solid 4px #fff;
+					border-right: solid 4px #fff;
+					border-top: solid 0 transparent;
+					border-bottom: solid 0 transparent;
+					box-sizing: border-box;
+				}
+			}
+		}
+
+		.crop {
+			&-range {
+				display: flex;
+				align-items: center;
+				font-size: 14px;
+			}
+
+			&-input {
+				height: 30px;
+				border-radius: 15px;
+				overflow: hidden;
+				padding: 0 14px;
+				display: flex;
+				align-items: center;
+
+				input {
+					float: left;
+					width: 50px;
+					border: 1px solid #ddd;
+					font-size: 14px;
+					border-radius: 20px;
+					text-align: center;
+				}
+
+				span {
+					width: 8px;
+					line-height: 28px;
+					height: 28px;
+					float: left;
+					margin: 0;
+					padding: 0;
+				}
+			}
+		}
+	}
+
+	.loading {
+		width: 100%;
+		height: 100%;
+		position: relative;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+
+		&-con {
+			position: absolute;
+			animation: loading 1s linear infinite;
+			width: 25px;
+			height: 25px;
+			border-radius: 50%;
+			box-shadow: 0 2px 0 0 #fff; // ffc7d1
+			transform-origin: 50% 50%;
+		}
+	}
+
+	@keyframes loading {
+		0% {
+			transform: rotate(0deg);
+		}
+
+		50% {
+			transform: rotate(180deg);
+		}
+
+		100% {
+			transform: rotate(360deg);
+		}
+	}
+	
+	.text-right{
+		text-align: right;
+	}
+	
+	.text-left{
+		text-align: left;
+	}
+</style>

+ 32 - 6
yarn.lock

@@ -3689,9 +3689,9 @@ electron-store@^2.0.0:
     conf "^2.0.0"
 
 electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.47:
-  version "1.5.83"
-  resolved "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.5.83.tgz#3f74078f0c83e24bf7e692eaa855a998d1bec34f"
-  integrity sha512-LcUDPqSt+V0QmI47XLzZrz5OqILSMGsPFkDYus22rIbgorSvBYEFqq854ltTmUdHkY92FSdAAvsh4jWEULMdfQ==
+  version "1.5.84"
+  resolved "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.5.84.tgz#8e334ca206bb293a20b16418bf454783365b0a95"
+  integrity sha512-I+DQ8xgafao9Ha6y0qjHHvpZ9OfyA1qKlkHkjywxzniORU2awxyz7f/iVJcULmrF2yrM3nHQf+iDjJtbbexd/g==
 
 electron@6.0.0:
   version "6.0.0"
@@ -5157,6 +5157,13 @@ ignore@^3.3.5:
   resolved "https://registry.npmmirror.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043"
   integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==
 
+image-size@1.0.0:
+  version "1.0.0"
+  resolved "https://registry.npmmirror.com/image-size/-/image-size-1.0.0.tgz#58b31fe4743b1cec0a0ac26f5c914d3c5b2f0750"
+  integrity sha512-JLJ6OwBfO1KcA+TvJT+v8gbE6iWbj24LyDNFgFEN0lzegn6cC6a/p3NIDaepMsJjQjlUWqIC7wJv8lBFxPNjcw==
+  dependencies:
+    queue "6.0.2"
+
 import-lazy@^2.1.0:
   version "2.1.0"
   resolved "https://registry.npmmirror.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43"
@@ -7808,6 +7815,13 @@ querystringify@^2.1.1:
   resolved "https://registry.npmmirror.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6"
   integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==
 
+queue@6.0.2:
+  version "6.0.2"
+  resolved "https://registry.npmmirror.com/queue/-/queue-6.0.2.tgz#b91525283e2315c7553d2efa18d83e76432fed65"
+  integrity sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==
+  dependencies:
+    inherits "~2.0.3"
+
 randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0:
   version "2.1.0"
   resolved "https://registry.npmmirror.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
@@ -8709,6 +8723,11 @@ sort-keys@^1.0.0:
   dependencies:
     is-plain-obj "^1.0.0"
 
+sortablejs@1.10.2:
+  version "1.10.2"
+  resolved "https://registry.npmmirror.com/sortablejs/-/sortablejs-1.10.2.tgz#6e40364d913f98b85a14f6678f92b5c1221f5290"
+  integrity sha512-YkPGufevysvfwn5rfdlGyrGjt7/CRHwvRPogD/lC+TnvcN29jDpCifKP+rBqf+LRldfXSTh+0CGLcSg0VIxq3A==
+
 source-list-map@^2.0.0:
   version "2.0.1"
   resolved "https://registry.npmmirror.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34"
@@ -9801,6 +9820,13 @@ vue@^2.5.2:
     "@vue/compiler-sfc" "2.7.16"
     csstype "^3.1.0"
 
+vuedraggable@^2.24.3:
+  version "2.24.3"
+  resolved "https://registry.npmmirror.com/vuedraggable/-/vuedraggable-2.24.3.tgz#43c93849b746a24ce503e123d5b259c701ba0d19"
+  integrity sha512-6/HDXi92GzB+Hcs9fC6PAAozK1RLt1ewPTLjK0anTYguXLAeySDmcnqE8IC0xa7shvSzRjQXq3/+dsZ7ETGF3g==
+  dependencies:
+    sortablejs "1.10.2"
+
 vuex-electron@^1.0.0:
   version "1.0.3"
   resolved "https://registry.npmmirror.com/vuex-electron/-/vuex-electron-1.0.3.tgz#c8ce0fd06ed9d3beb8881bce39bf76c9fcdc5611"
@@ -9815,9 +9841,9 @@ vuex@^3.0.1:
   integrity sha512-ETW44IqCgBpVomy520DT5jf8n0zoCac+sxWnn+hMe/CzaSejb/eVw2YToiXYX+Ex/AuHHia28vWTq4goAexFbw==
 
 vxe-pc-ui@^3.3.73:
-  version "3.3.80"
-  resolved "https://registry.npmmirror.com/vxe-pc-ui/-/vxe-pc-ui-3.3.80.tgz#e0ca89032e0d32122543938e7063284e497c3755"
-  integrity sha512-4s2fhaDuuB7VN8d20tGauIRAvJA69HSSANqwU2yweKJ5XVNjvQzX4hxzfIBHxVcSzd7WqaAvxi5m9JEVBFTbyQ==
+  version "3.3.83"
+  resolved "https://registry.npmmirror.com/vxe-pc-ui/-/vxe-pc-ui-3.3.83.tgz#59f46d0dc09b1fa69d35e8edeefc711e03e76d24"
+  integrity sha512-K8SFv4D0tm8RsCefw92nTO5L/SVZ6uX3GQ7O0CwonoANqpo446N7bewrE3mHeuFm7lJsjXUp2UcOCokix1DoAg==
   dependencies:
     "@vxe-ui/core" "^3.0.26"
 

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio