<template>
<!-- 回放 -->
<div class='playback' ref="playback">
<div class="video-wrapper">
<video-player
class="video-player vjs-custom-skin"
ref="videoPlayer"
:playsinline="true"
crossOrigin="anonymous"
style="height: 100%;"
autoplay
:options="playerOptions"
@timeupdate="onPlayerTimeupdate($event)"
@ended="onPlayerEnded($event)"
@ready="playerReadied"
@pause="onPlayerPause($event)"
@playing="onPlayerPlaying($event)"
>
<span>1</span>
</video-player>
<div class="bottom-controls">
<!-- 进度条 -->
<div class="ruler-wrapper hide" ref="rulerWrapper">
<div class="ruler-wrap">
<div class="left" @click="swiperLeft"><i class="el-icon-arrow-left"></i></div>
<div class="ruler-content-wrap">
<div class="ruler-content-box">
<div class="ruler-content" ref="content">
<div class="ruler-item" ref="item">
<div class="ruler-lists" v-for="(item, index) in 288" :key="index">
<span v-if="index%6===0">{{ _formatSeconds(index/6*30) }}</span>
</div>
</div>
<div class="drop1" v-for="(item, index) in drops" :key="'k1'+index" :style="[{width: item.width+'px'}, {left: item.position+'px'}]"></div>
<div class="drop" ref="drops" v-for="(item, index) in drops" :key="'k2'+index" :class="{'red': item.status}" :style="[{width: item.width+'px'}, {left: item.position+'px'}]" @click="videoClick($event, index)"></div>
</div>
</div>
<div class="currTime" ref="currTime"></div>
</div>
<div class="right" @click="swiperRight"><i class="el-icon-arrow-right"></i></div>
</div>
</div>
<!-- 底部控制菜单 -->
<div class="control-wrapper">
<!-- 左边 -->
<div class="pic" @click="dianj">
<el-image
:url="dialogImageUrl.url"
:src="dialogImageUrl.url"
fit="cover"
></el-image>
</div>
<!-- 右边 -->
<div class="bottomRight">
<!-- 音量 -->
<span class="urlRight">
<el-image
:url="songS.url"
@click="yingliang"
:src="songS.url"
fit="cover"
></el-image>
<el-slider
class="pr"
:show-tooltip="false"
v-model="songsss"
vertical
height="100px"
v-show="yl"
@input="volumeChange"
>
</el-slider>
</span>
<!-- 截屏 -->
<span download id="downLoadImg" class="urlRight">
<el-image
@click="getVideoPic"
:url="jieP.url"
:src="jieP.url"
fit="cover"
></el-image>
</span>
<!-- 全屏 -->
<span @click="fullScreenHandle" class="urlRight">
<el-image
:url="qScreen.url"
:src="qScreen.url"
fit="cover"
></el-image>
</span>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { videoPlayer } from "vue-video-player";
import "video.js/dist/video-js.css";
export default {
components: {
videoPlayer,
},
props: {
domLength: { // 视频个数
type: Number,
default: 1
},
// devIds: { // 设备id
//   type: String,
//   default: "1"
// },
// dayDate: { //日期
//   type: String,
//   default: "2021-03-19"
// },
address: {
type: Array
}
},
data() {
return {
jieP: {
url: require("@/assets/playback/jp.png"),
flg: 1,
},
songS: {
url: require("@/assets/playback/song.png"),
flg: 1,
},
songS2: {
url: require("@/assets/playback/song.png"),
flg: 1,
},
songS1: {
url: require("@/assets/playback/songN.png"),
flg: 2,
},
qScreen: {
url: require("@/assets/playback/qScreen.png"),
flg: 1,
},
dialogImageUrl: {
//播放按钮
url: require("@/assets/playback/bf.png"),
flg: 1,
},
dialogImageUrl1: {
url: require("@/assets/playback/bf.png"),
flg: 2,
},
dialogImageUrl2: {
url: require("@/assets/playback/zd.png"),
flg: 2,
},
songsss: 1,
yl: false,
currentVideo: 0,
playerOptions: {
controls: false, // 是否显示控制栏
playbackRates: [0.5, 1.0, 1.5, 2.0], //播放速度
autoplay: false, //如果true,浏览器准备好时开始回放。
muted: false, // 默认情况下将会消除任何音频。
loop: false, // 导致视频一结束就重新开始。
preload: "auto", // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持)
language: "zh-CN",
aspectRatio: "16:10", // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")
fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。
sources: [
{
// type: "video/mp4",
// src: "https://cdn.theguardian.tv/webM/2015/07/20/150716YesMen_synd_768k_vp8.webm", // url地址
type: "application/x-mpegURL", // 这里的种类支持很多种:基本视频格式、直播、流媒体等,具体可以参看git网址项目
// src: "http://live.chci.cn/20210324/ANScHyUN3LcvGDPDuFbjiB/ANScHyUN3LcvGDPDuFbjiB.m3u8", //你的m3u8地址(必填)
}
],
// poster: "poster.jpg", //你的封面地址
notSupportedMessage: "此视频暂无法播放,请稍后再试", //允许覆盖Video.js无法播放媒体源时显示的默认信息。
controlBar: {
timeDivider: true, //当前时间和持续时间的分隔符
durationDisplay: true, //显示持续时间
remainingTimeDisplay: true, //是否显示剩余时间功能
fullscreenToggle: true, //全屏按钮
}
},
videos: [
// {
//   id: 1,
//   startDateStr: "00:05:00",
//   endDateStr: "00:15:53",
//   historyUrl: "https://cdn.theguardian.tv/webM/2015/07/20/150716YesMen_synd_768k_vp8.webm",
//   status: 0
// },
],
drops: []
}
},
created() {
this.videos = this.address
this.videoSwitch(true)
this.resetControlStyle(this.domLength)
},
mounted() {
this.domOnLoad()
// const _this = this
// window.onresize = function() {
//   console.log(_this.$refs.videoPlayer.player.isFullscreen())
// }
},
watch: {
domLength(val) {
this.resetControlStyle(val)
},
address(val) {
this.videos = val
this.videoSwitch(true)
},
},
methods: {
getVideoRecorders() {
let params = {
SSOID: this.$store.state.cookie,
dayDate: this.dayDate,
devIds: this.devIds
}
this.$axios
.get("/apis/monitorcenter/device/getRecorders",  {
params,
}
)
.then((res) => {
res.data.result[0].deviceRecorderList.map(res=>{
console.log(
res.historyUrl
);
})
console.log(res);
})
.catch(() => {
this.$message({
type: "info",
message: "视频加载失败 请重试!",
});
});
},
resetControlStyle(domLength) {
let root = document.querySelector(":root")
switch (domLength) {
case 1:
root.style.setProperty("--ruler-height", "100px")
root.style.setProperty("--ruler-pad-top", "29px")
root.style.setProperty("--ruler-big-line", "50px")
root.style.setProperty("--ruler-small-line", "18px")
root.style.setProperty("--ruler-font-size", "24px")
root.style.setProperty("--ruler-font-top", "29px")
root.style.setProperty("--ruler-swiper-size", "30px")
root.style.setProperty("--ruler-currTime-top", "-49px")
root.style.setProperty("--ruler-currTime-width", "40px")
root.style.setProperty("--ruler-currTime-height", "163px")
root.style.setProperty("--control-height", "90px")
root.style.setProperty("--control-play-size", "50px")
root.style.setProperty("--control-icon-size", "28px")
break;
case 4:
root.style.setProperty("--ruler-height", "46px")
root.style.setProperty("--ruler-pad-top", "13px")
root.style.setProperty("--ruler-big-line", "24px")
root.style.setProperty("--ruler-small-line", "8px")
root.style.setProperty("--ruler-font-size", "12px")
root.style.setProperty("--ruler-font-top", "13px")
root.style.setProperty("--ruler-swiper-size", "16px")
root.style.setProperty("--ruler-currTime-top", "-21px")
root.style.setProperty("--ruler-currTime-width", "18px")
root.style.setProperty("--ruler-currTime-height", "74px")
root.style.setProperty("--control-height", "40px")
root.style.setProperty("--control-play-size", "24px")
root.style.setProperty("--control-icon-size", "12px")
break;
case 9:
root.style.setProperty("--ruler-height", "30px")
root.style.setProperty("--ruler-pad-top", "10px")
root.style.setProperty("--ruler-big-line", "15px")
root.style.setProperty("--ruler-small-line", "5px")
root.style.setProperty("--ruler-font-size", "7px")
root.style.setProperty("--ruler-font-top", "8px")
root.style.setProperty("--ruler-swiper-size", "12px")
root.style.setProperty("--ruler-currTime-top", "-14px")
root.style.setProperty("--ruler-currTime-width", "12px")
root.style.setProperty("--ruler-currTime-height", "49px")
root.style.setProperty("--control-height", "26px")
root.style.setProperty("--control-play-size", "16px")
root.style.setProperty("--control-icon-size", "10px")
break;
case 16:
root.style.setProperty("--ruler-height", "22px")
root.style.setProperty("--ruler-pad-top", "7px")
root.style.setProperty("--ruler-big-line", "12px")
root.style.setProperty("--ruler-small-line", "4px")
root.style.setProperty("--ruler-font-size", "4px")
root.style.setProperty("--ruler-font-top", "6px")
root.style.setProperty("--ruler-swiper-size", "10px")
root.style.setProperty("--ruler-currTime-top", "-11px")
root.style.setProperty("--ruler-currTime-width", "8px")
root.style.setProperty("--ruler-currTime-height", "37px")
root.style.setProperty("--control-height", "20px")
root.style.setProperty("--control-play-size", "12px")
root.style.setProperty("--control-icon-size", "8px")
break
}
},
// 截屏
DPR() {
// 获取设备dpi
if (window.devicePixelRatio && window.devicePixelRatio > 1) {
return window.devicePixelRatio;
}
return 1;
},
getVideoPic() {
let video = document.getElementsByClassName("vjs-tech")[0];
const scaleBy = this.DPR();
let canvas = document.createElement("canvas");
let w = window.innerWidth;
let h = (window.innerWidth / 16) * 9;
canvas.width = w * scaleBy;
canvas.height = h * scaleBy;
const ctx = canvas.getContext("2d");
ctx.drawImage(video, 0, 0, w, h);
ctx.drawImage(video, 0, 0, w, h);
ctx.scale(scaleBy, scaleBy);
let previewImg = canvas.toDataURL("image/png");
//  console.log('1');
this.down(previewImg);
},
async down(image) {
//   下载图片
let a = document.createElement("a"); // 创建一个a节点插入的document
var event = new MouseEvent("click"); // 模拟鼠标click点击事件
a.download = "downLoadImg"; // 设置a节点的download属性值
a.href = image; // 将图片的src赋值给a节点的href
a.dispatchEvent(event); // 触发鼠标点击事件
},
// 截屏结束
// 点击
dianj() {
if (this.dialogImageUrl.flg == 2) {
this.dialogImageUrl = this.dialogImageUrl1;
this.dialogImageUrl.flg = 1;
this.$refs.videoPlayer.player.pause();
} else {
this.dialogImageUrl = this.dialogImageUrl2;
this.dialogImageUrl.flg = 2;
this.$refs.videoPlayer.player.play();
}
},
// 音量
yingliang() {
this.yl = !this.yl;
},
// 关闭声音
volumeChange(val) {
// console.log(va);
this.$refs.videoPlayer.player.volume(val/100);
// if (this.songsss == 0) {
//   this.songS = this.songS1;
// } else {
//   this.songS = this.songS2;
// }
// console.log(this.songsss, "ddd");
},
swiperLeft() {
this.$refs.content.scrollLeft -= Math.max(this.$refs.content.clientWidth, 0)
},
swiperRight() {
this.$refs.content.scrollLeft += this.$refs.content.clientWidth
// let left = parseInt(this.$refs.currTime.style.left)
// let scrollLeft = this.$refs.content.scrollLeft
// console.log(left)
// this.$refs.currTime.style.left = left - scrollLeft + "px"
},
// 初始化多个视频位置
domOnLoad() {
let dateSecond = 24*60*60
for(var i = 0;i < this.videos.length;i++) {
let startTime = this._timeToSeconds(this.videos[i].startDateStr) // 开始
let endTime = this._timeToSeconds(this.videos[i].endDateStr) // 结束
let startPosi = startTime / dateSecond * this.$refs.item.clientWidth // 起始位置
let videoWidth = (endTime - startTime) / dateSecond * this.$refs.item.clientWidth //视频宽度
this.drops.push({
position: startPosi,
width: videoWidth,
duration: endTime - startTime,
status: this.videos[i].status
})
if(i===0) {
this.$refs.content.scrollLeft = startPosi
}
}
},
videoClick(e, index) {
let isSwitch = index !== this.currentVideo
this.currentVideo = index
let offsetX = e.offsetX
let second = offsetX / this.drops[this.currentVideo].width * this.drops[this.currentVideo].duration
this.videoSwitch(isSwitch, second)
let contentWidth = this.$refs.content.getBoundingClientRect().left
let scrollLeft = this.$refs.content.scrollLeft
let currTimeLeft = e.pageX - contentWidth + scrollLeft
// setTimeout(()=>{
//   this.$refs.currTime.style.left = currTimeLeft+'px'
// }, 200)
},
// 视频切换
videoSwitch(switchVideo, time=0) {
if(switchVideo) {
this.playerOptions['sources'][0]['src'] = this.videos[this.currentVideo].historyUrl
console.log(this.videos[this.currentVideo].historyUrl)
}
setTimeout(()=>{
this.$refs.videoPlayer.player.currentTime(time)
this.$refs.videoPlayer.player.play()
}, 200)
},
// 视频播完回调
onPlayerEnded($event) {
this.dialogImageUrl = this.dialogImageUrl2;
this.currentVideo += 1
this.videoSwitch(true)
},
// 已开始播放回调
onPlayerPlaying($event) {
this.dialogImageUrl = this.dialogImageUrl2;
console.log("开始前的回调", $event);
},
// 暂停回调
onPlayerPause(player) {
this.dialogImageUrl = this.dialogImageUrl1;
console.log("暂停!", player);
},
// 当前播放位置发生变化时触发。
onPlayerTimeupdate(player) {
let currTime = player.cache_.currentTime
let allTime = player.cache_.duration
// let offsetX = currTime / allTime * this.drops[this.currentVideo].width // 指针偏移量
let offsetX = currTime / allTime * this.drops[this.currentVideo].width // 指针偏移量
let parentOffsetX = this.$refs.drops[this.currentVideo].offsetLeft // 盒子偏移量
let scrollLeft = this.$refs.content.scrollLeft
let allX = parentOffsetX + offsetX - scrollLeft
this.$refs.currTime.style.left = allX + 'px'
if(allX > this.$refs.content.clientWidth || (allX < 0 ? -allX > -this.$refs.content.clientWidth : false)) {
// this.swiperRight()
this.$refs.currTime.style.display = "none"
}else {
this.$refs.currTime.style.display = "block"
}
},
//将侦听器绑定到组件的就绪状态。与事件监听器的不同之处在于,如果ready事件已经发生,它将立即触发该函数。。
playerReadied(player, playtimes) {
// console.log(playtimes);
player.currentTime(playtimes)///开始的位置 可以通过这个值来修改
},
fullScreenHandle() {
// console.log("全屏");
let rulerWrapper = this.$refs.rulerWrapper
let fullScreenBox = this.$refs.videoPlayer.player.el_
let player = this.$refs.videoPlayer.player
//   fullScreenBox.appendChild(rulerWrapper)
if (!player.isFullscreen()) {
player.requestFullscreen();
player.isFullscreen(true);
} else {
player.exitFullscreen();
player.isFullscreen(false);
}
},
_formatSeconds(value) {
let second = value % 60
let minute = Math.floor(value/60) % 60
return ('00'+minute).slice(minute.toString().length)+':'+('00'+second).slice(second.toString().length)
},
_timeToSeconds(value) {
var s = '';
var hour = value.split(':')[0];
var min = value.split(':')[1];
var sec = value.split(':')[2];
s = Number(hour*3600) + Number(min*60) + Number(sec);
return s;
}
}
}
</script>
<style scoped>
.playback, .video-wrapper {
width: 100%;
height: 100%;
}
.hide {
opacity: 0;
}
.video-wrapper {
position: relative;
}
.video-wrapper:hover .hide {
opacity: 1;
}
.video-wrapper .bottom-controls {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
overflow-y: hidden;
overflow-x: hidden;
padding-top: 20px;
}
.video-wrapper .ruler-wrapper {
width: 100%;
background-color: rgba(0,0,0,0.6);
}
.ruler-wrap {
width: 100%;
height: 100px;
font-size: 0;
border: 1px solid #393b46;
border-width: 1px 0;
}
.video-wrapper .left, .video-wrapper .right {
display: inline-block;
vertical-align: top;
width: 5%;
height: 100px;
line-height: 100px;
cursor: pointer;
font-size: 27px;
font-weight: bold;
color: #ffffff;
text-align: center;
}
.ruler-content-wrap {
position: relative;
display: inline-block;
width: 90%;
}
.ruler-content-box {
position: relative;
height: 100px;
overflow: hidden;
}
.ruler-content {
position: relative;
display: inline-block;
width: 100%;
height: 120px;
overflow: hidden;
overflow-x: scroll;
}
.ruler-item {
font-size: 0;
height: 100px;
white-space: nowrap;
position: absolute;
z-index: 5;
}
.ruler-lists {
display: inline-block;
width: 35px;
height: 100px;
position: relative;
vertical-align: top;
}
.ruler-lists::before, .ruler-lists:first-child::after {
content: "";
display: inline-block;
width: 1px;
height: 18px;
background-color: #393b46;
opacity: 0.5;
position: absolute;
right: 0;
top: 0;
}
.ruler-lists:nth-child(6n)::before {
height:  50px;
}
.ruler-lists:first-child::before {
right: auto;
left: 0;
height: 50px;
}
.ruler-lists span {
line-height: 31px;
font-size: 24px;
color: #eeeeee;
vertical-align: top;
position: absolute;
left: 15px;
top: 30px;
z-index: 5;
}
.drop, .drop1 {
height: 100px;
position: absolute;
top: 0;
}
.drop {
z-index: 6;
}
.drop1 {
background-color: #2e71b2;
}
.drop1.red {
background-color: rgba(255,8,27,0.8);
}
.currTime {
display: inline-block;
width: 1px;
height: 100px;
position: absolute;
top: 0;
left: 0;
transition: left .3s;
z-index: 6;
}
.currTime::after {
content: "";
display: inline-block;
width: 40px;
height: 163px;
background: url(../../../assets/playback/currTime@2x.png);
background-size: cover;
transform: translateX(-50%);
}
/* -------- */
.control-wrapper {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 0;
color: #fff;
background-color: rgba(0,0,0,0.6);
}
.pic {
padding: 5px;
width: 30px;
height: 30px;
cursor: pointer;
}
.bottomRight {
width: 15%;
display: flex;
justify-content: space-around;
}
.urlRight {
z-index: 100;
display: inline-block;
width: 23px;
height: 23px;
}
.urlRight .el-image {
width: 100%;
height: 100%;
cursor: pointer;
vertical-align: top;
}
.pr {
position: absolute !important;
top: -115px;
left: 50%;
transform: translateX(-50%);
}
</style>
<style lang="scss">
:root {
--ruler-height: 100px;
--ruler-pad-top: 29px;
--ruler-big-line: 50px;
--ruler-small-line: 18px;
--ruler-font-size: 24px;
--ruler-font-top: 29px;
--ruler-swiper-size: 30px;
--ruler-currTime-top: -49px;
--ruler-currTime-width: 40px;
--ruler-currTime-height: 163px;
--control-height: 90px;
--control-play-size: 50px;
--control-icon-size: 28px;
}
/* 刻度尺样式兼容 */
.video-wrapper {
.ruler-wrapper {
bottom: var(--control-height);
padding-top: var(--ruler-pad-top);
.ruler-wrap, .ruler-content-box {
height: var(--ruler-height);
}
.ruler-lists {
height: var(--ruler-height);
&::before {
height: var(--ruler-small-line);
}
&:nth-child(6n)::before, &:first-child::before {
height: var(--ruler-big-line);
}
span {
top: var(--ruler-font-top);
font-size: var(--ruler-font-size);
}
}
.left, .right {
height: var(--ruler-height);
line-height: var(--ruler-height);
font-size: var(--ruler-swiper-size);
}
.currTime {
top: var(--ruler-currTime-top);
&::after {
width: var(--ruler-currTime-width);
height: var(--ruler-currTime-height);
}
}
}
.control-wrapper {
height: var(--control-height);
line-height: var(--control-height);
.pic {
width: var(--control-play-size);
height: var(--control-play-size);
margin-left: 2.4%;
}
.urlRight {
position: relative;
width: var(--control-icon-size);
height: var(--control-icon-size);
}
}
}
</style>

回放video 加 自定义tabBar 进度条相关推荐

  1. 直接修改html代码视频进度,HTML5实现video标签的自定义播放进度条

    现在随着html5的渐热,越来越多的web开发者都开始选择使用html5写出一些比较好的web应用. html代码: HTML5-Video-Player .videoPlayer{ border: ...

  2. 自定义扇形进度条、异步加载网络图片、Activity疯狂旋转动画

    效果预览: 正文 1.自定义扇形进度条. 思考: (1)如何绘制扇形. (2)重写onDraw(Canvas canvas) 或 draw(Canvas canvas). (3)是否保留背景设置. ( ...

  3. html加载swf 进度条,Flash加载外部文件创建进度条3种方法

    Flash加载外部文件创建进度条3种方法 互联网   发布时间:2008-10-07 09:36:14   作者:佚名   我要评论 加载外部文件的进度条(看帮助文档整理),只适合那些不愿看帮助文档的 ...

  4. android自定义带进度条的圆形图片

    前言:在项目听新闻的改版中需要实现环绕圆形新闻图片的进度条功能,作为技术预备工作我就去看了一些网上的相关的原理,做了一个自定义带进度条的圆形图片的demo,并将这个实现写成文章发布出来,谁需要了可以进 ...

  5. Android自定义半圆进度条 半圆渐变色进度条带指示 半圆开口大小可自由修改

    Android自定义半圆进度条 半圆渐变色进度条带指示 半圆开口大小可自由修改 首先我们来看下效果图 不同的开口大小只需要修改一个参数即可 半圆1: 半圆2: 半圆3: 如果是你想要的效果,就直接滑动 ...

  6. android自定义圆形进度条,实现动态画圆效果

    自定义圆形进度条效果图如下:应用场景如动态显示分数等. view的自定义属性如下attr.xml <?xml version="1.0" encoding="UTF ...

  7. 自定义环形进度条RoundProgressBar

    一.效果图: Canvas画圆环说明: 圆环宽度不必在意,只是画笔宽度设置后达到的效果. 二.实现步骤 1.自定义View-RoundProgressBar 2.设置属性resources(decle ...

  8. Java渐变进度条_Android ProgressBar自定义图片进度,自定义渐变色进度条

    java.lang.Object ↳android.view.View ↳android.widget.ProgressBar 直接子类 AbsSeekBar 间接子类 RatingBar, Seek ...

  9. Android自定义圆形进度条

    Android自定义圆形进度条 github地址:https://github.com/opq1289/CircleProgressView 效果图: 无动画: 有动画: 整圆: 切割圆: 具体步骤: ...

最新文章

  1. 利用bigpipe机制实现页面模块的异步渲染 chunked技术
  2. [APIO2018]铁人两项——圆方树+树形DP
  3. 启动服务错误5拒绝访问_【Go API 开发实战 5】基础1:启动一个最简单的 RESTful API 服务器...
  4. 智能安防 回家开门进入“看脸”时代
  5. 开源硬件_扩展对开源硬件的访问
  6. bat脚本更新本地Git仓库
  7. 数据恢复工程师视角看腾讯云静默损坏事件
  8. php文章发布时间修改,Dedecms编辑文章更新当前时间的修改方法
  9. 用AB对Webservice做压力测试
  10. python爬虫常用模块介绍(1)_python爬虫常用模块介绍(1)
  11. 发那科机器人点位编辑_【发那科】发那科机器人指令编辑大全
  12. 《学会呼吸》书中的精髓:如何通过训练自己的呼吸,逐步改善健康问题?
  13. ANN之乘积量化PQ
  14. STM32与中显串口屏的通信
  15. 论文阅读 Learning Motion in Feature Space: Locally-Consistent Deformable Convolution Networks
  16. 西交《物理化学》在线作业
  17. excel表格末尾添加一行_教你使用Python批量读写excel文件
  18. 计算机科学概论读后感
  19. 使用商用WiFi路由器有哪些优势?
  20. 软件测试技术之【自动化测试】

热门文章

  1. 【视频】网易学院 http://tech.163.com/school
  2. Word List 02
  3. 常用测量仪器和SCPI协议通信相关的那些事
  4. 资产会计(FI-AA) APC业务及其业务实践
  5. 酒店专用APP开发流程
  6. Apache IoTDB源码解析(0.11.2版本):Session的源码解析
  7. 2、Mysql添加数据(insert into t_student values();)
  8. elastic8 9200无法访问
  9. 2020年全国天梯赛赛前个人专题强化赛---C(最短路)
  10. CodeForces 663A Rebus