Commit b406d4b3 authored by wangxiaoming's avatar wangxiaoming

直播初版

parent 42544e6b
This diff is collapsed.
......@@ -19,6 +19,7 @@
"vue": "^2.6.11",
"vue-baidu-map": "^0.21.22",
"vue-router": "^3.3.4",
"videojs-flash": "^2.1.2",
"vue-video-player": "^5.0.2",
"vuex": "^3.5.1",
"xlsx": "^0.16.5"
......
......@@ -6,15 +6,21 @@ import BaiduMap from 'vue-baidu-map';
import 'element-ui/lib/theme-chalk/index.css';
import _ from 'lodash';
import moment from 'moment';
import VideoPlayer from 'vue-video-player';
import VueVideoPlayer from 'vue-video-player';
import App from './App.vue';
import router from './router';
import store from './store';
require('video.js/dist/video-js.css');
require('vue-video-player/src/custom-theme.css');
Vue.use(VideoPlayer);
// require videojs style
import 'video.js/dist/video-js.css';
// import 'vue-video-player/src/custom-theme.css'
Vue.use(VueVideoPlayer);
Vue.use(ElementUI);
Vue.use(BaiduMap, {
ak: 'AZzMTSKLP4lVHphRauTBdINZUFnpWTcu',
......
......@@ -6,6 +6,8 @@ import Detail from './views/Detail.vue';
import Task from './views/Task.vue';
import Result from './views/Result.vue';
import ResultDetail from './views/ResultDetail.vue';
import Video from './views/Video.vue';
import Live from './views/Live.vue';
Vue.use(Router);
......@@ -45,6 +47,16 @@ export default new Router({
name: 'resultDetail',
component: ResultDetail,
},
{
path: '/video',
name: 'video',
component: Video,
},
{
path: '/live',
name: 'live',
component: Live,
},
],
},
// 注册页面
......
......@@ -49,23 +49,23 @@
</el-menu-item>
</el-submenu>
<!--<el-submenu index="4">
<el-submenu index="4">
<span slot="title" class="submenu_parent">视频查看入口</span>
<el-menu-item
index="4-1"
@click="goTo('/result')"
@click="goTo('/live')"
style="background:#252639 !important"
>
<span slot="title" style="font-size: 16px">实时视频查看</span>
</el-menu-item>
<el-menu-item
index="4-2"
@click="goTo('/resultDetail')"
@click="goTo('/video')"
style="background:#252639 !important"
>
<span slot="title" style="font-size: 16px">停车视频查看</span>
</el-menu-item>
</el-submenu>-->
</el-submenu>
</el-menu>
</el-aside>
<el-container>
......
<template>
<div class="detail">
<div class="box">
<!-- 查询区 -->
<el-col :span="24" class="warp-breadcrum">
<!--搜索栏-->
<el-col :span="24" class="toolbar">
<el-form :inline="true" :model="filters">
<el-form-item>
<el-select
v-model="filters.equipment"
multiple
collapse-tags
filterable
placeholder="车牌号"
>
<el-option
v-for="item in plateNoOptions"
:key="item.code"
:label="item.plateNo"
:value="item.code"
></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" v-loading="searchLoading" @click="getParkVideos">搜索</el-button>
</el-form-item>
</el-form>
</el-col>
</el-col>
<!-- 停车视频表 -->
<div class="detail-table">
<el-table
:data="tableData"
style="width: calc(100vw - 240px);overflow:hidden;"
border
fit
highlight-current-row
>
<el-table-column width="200" type="index" label="序号" align="center"></el-table-column>
<el-table-column width="400" label="车牌号" prop="plateNo" align="center"></el-table-column>
<el-table-column fixed="right" min-width="100" label="视频列表" align="center">
<template slot-scope="scope">
<el-button size="mini" @click="playVideos(scope.row)">播放</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 修改 -->
<el-pagination
:current-page="pageOption.pageIndex"
:page-sizes="[5, 10, 20, 40]"
:page-size="pageOption.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="pageOption.totalCount"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</div>
<el-dialog :visible.sync="isShowVideo" >
<video-player
@play="onPlayerPlay($event)"
@pause="onPlayerPause($event)"
@ended="onPlayerEnded($event)"
@loadeddata="onPlayerLoadeddata($event)"
@waiting="onPlayerWaiting($event)"
@playing="onPlayerPlaying($event)"
@timeupdate="onPlayerTimeupdate($event)"
@canplay="onPlayerCanplay($event)"
@canplaythrough="onPlayerCanplaythrough($event)"
@ready="playerReadied"
@statechanged="playerStateChanged($event)"
ref="videoPlayer"
:options="playerOptions"
class="vjs-custom-skin videoPlayer"
:playsinline="true"
/>
</el-dialog>
<el-dialog :visible.sync="isShowTip" width="250px">
<span>设备未启动</span>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="isShowTip = false">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<style lang="less" scope>
</style>
<script>
import axios from 'axios';
import { Message } from 'element-ui';
import { address } from '../config';
import 'video.js/dist/video-js.css';
import 'vue-video-player/src/custom-theme.css';
import 'videojs-flash';
export default {
name: 'video',
data() {
return {
isShowTip: false,
plateNoOptions: [],
searchData: [],
tableData: [],
startTime: null,
endTime: null,
pageOption: {
pageIndex: 1,
pageSize: 10,
totalCount: 0,
},
filters: {
equipment: [],
},
loading: false,
pickerOptions: {
shortcuts: [
{
text: '最近一周',
onClick(picker) {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
picker.$emit('pick', [start, end]);
},
},
{
text: '最近一个月',
onClick(picker) {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
picker.$emit('pick', [start, end]);
},
},
{
text: '最近三个月',
onClick(picker) {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
picker.$emit('pick', [start, end]);
},
},
],
},
searchLoading: false,
isShowVideo: false,
playerOptions: {
height: '360',
autoplay: true,
sources: [{
type: 'rtmp/flv',
src: 'rtmp://58.200.131.2:1935/livetv/hunantv',
}],
techOrder: ['flash'],
notSupportedMessage: '设备已停止',
controls: true,
poster: '',
},
};
},
mounted() {},
created() {
this.queryAllEquipment();
const searchVal = sessionStorage.getItem('videoSearchVal');
const that = this;
if (this.$route.params.startTime) {
that.startTime = this.$route.params.startTime;
}
if (this.$route.params.endTime) {
that.endTime = this.$route.params.endTime;
}
if (this.$route.params.plateNo) {
that.filters.plateNo = this.$route.params.plateNo;
}
if (that.startTime && that.endTime) {
this.filters.dateTime = [
this.$route.params.startTime,
this.$route.params.endTime,
];
} else if (searchVal) {
this.filters = JSON.parse(searchVal);
}
this.getParkVideos();
},
methods: {
// listen event
onPlayerPlay(player) {
console.log('player play!', player);
},
onPlayerPause(player) {
console.log('player pause!', player);
},
onPlayerEnded(player) {
console.log('player ended!', player);
},
onPlayerLoadeddata(player) {
console.log('player Loadeddata!', player);
},
onPlayerWaiting(player) {
console.log('player Waiting!', player);
},
onPlayerPlaying(player) {
console.log('player Playing!', player);
},
// 时间跳动
onPlayerTimeupdate(player) {
// console.log('player Timeupdate!', player.currentTime());
},
onPlayerCanplay(player) {
console.log('player Canplay!', player);
},
onPlayerCanplaythrough(player) {
console.log('player Canplaythrough!', player);
},
// or listen state event
playerStateChanged(playerCurrentState) {
console.log('player current update state', playerCurrentState);
},
// player is ready
playerReadied(player) {
// seek to 10s
console.log('example player 1 readied', player);
player.currentTime(10);
console.log('example 01: the player is readied', player);
},
// 播放
playVideos(item) {
axios
.post(`${address}getIfParkStart`, { vehicleId: 1 })
.then((response) => {
if (response.data.code === 200) {
if (response.data.data && response.data.data.length > 0) {
this.isShowVideo = true;
} else {
this.isShowTip = true;
}
}
})
.catch((error) => {
console.log(error);
});
},
handleSizeChange(size) {
this.pageOption.pageSize = size;
this.getParkVideos();
},
handleCurrentChange(currentPage) {
this.pageOption.pageIndex = currentPage;
this.getParkVideos();
},
queryAllEquipment() {
axios
.post(`${address}queryAllEquipment`, {})
.then((response) => {
if (response.data.code === 200) {
if (response.data.data) {
this.plateNoOptions = [];
response.data.data.forEach((item) => {
this.plateNoOptions.push(item);
});
}
} else {
Message({
message: response.data.message,
// type: 'error',
// duration: '800',
});
}
})
.catch((error) => {
console.log(error);
});
},
getParkVideos() {
this.searchLoading = true;
const that = this;
axios
.post(`${address}getParkLives`, {
equipment: that.filters.equipment,
pageIndex: this.pageOption.pageIndex,
pageSize: this.pageOption.pageSize,
})
.then((response) => {
that.searchLoading = false;
if (response.data.code === 200) {
if (response.data.data) {
this.pageOption.totalCount = response.data.data.total;
that.tableData = response.data.data.list;
that.tableData.forEach((e) => {
e.startTime = this.$moment(
e.startTime,
).format('YYYY-MM-DD HH:mm:ss');
e.endTime = e.endTime ? this.$moment(
e.endTime,
).format('YYYY-MM-DD HH:mm:ss') : '';
});
} else {
that.tableData = [];
}
} else {
that.tableData = [];
}
})
.catch((error) => {
console.log(error);
});
},
},
};
</script>
......@@ -101,8 +101,19 @@
@ready="handler"
>
<bm-navigation anchor="BMAP_ANCHOR_TOP_RIGHT"></bm-navigation>
<!-- 这个是视频点-->
<div v-for="(item,index) in videoPoints" :key="index">
<bm-marker
:zIndex="5"
:position="{lng: item?item.lng:'', lat: item?item.lat:''}"
:title="item.title"
:icon="{url: item.url, size: {width: 36, height: 36}}"
:offset="{width: 0, height: -16}"
@click="playVideos(item)"
>
</bm-marker>
</div>
<div v-for="(item,index) in carPoints" :key="index">
<!--红线-->
<bm-polyline
......@@ -154,6 +165,13 @@
</div>
</div>
</el-dialog>
<el-dialog :visible.sync="isShowVideo" >
<video-player class="video-player vjs-custom-skin"
ref="videoPlayer"
:playsinline="false"
:options="playerOptions"
></video-player>
</el-dialog>
</div>
</template>
......@@ -164,12 +182,14 @@ import gcoord from 'gcoord';
import moment from 'moment';
import { Message } from 'element-ui';
import { export_json_to_excel } from '@/excel/Export2Excel';
import { address } from '../config';
import { address, videoAddress } from '../config';
export default {
name: 'task',
data() {
return {
videoUrl: '',
allVideoPoints: [],
screenLoading: false,
showPoints: false,
fullHeight: document.documentElement.clientHeight / 1.5,
......@@ -258,12 +278,33 @@ export default {
showRedBox: false,
trajectoryWithLinkId: [],
allPicPoints: [],
videoPoints: [],
isShowVideo: false,
playerOptions: {
playbackRates: [0.7, 1.0, 1.5, 2.0], // 播放速度
autoplay: false, // 如果true,浏览器准备好时开始回放。
controls: true, // 控制条
preload: 'auto', // 视频预加载
muted: false, // 默认情况下将会消除任何音频。
loop: false, // 导致视频一结束就重新开始。
language: 'zh-CN',
aspectRatio: '16:9', // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")
fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。
sources: [{
type: 'video/mp4',
src: this.videoUrl, // 你所放置的视频的地址,最好是放在服务器上
}],
poster: '', // 你的封面地址(覆盖在视频上面的图片)
width: document.documentElement.clientWidth,
notSupportedMessage: '此视频暂无法播放,请稍后再试', // 允许覆盖Video.js无法播放媒体源时显示的默认信息。
},
};
},
mounted() {
this.queryAllEquipment();
this.queryTravel();
this.queryImagesTravel();
this.queryVideosTravel();
},
created() {
const that = this;
......@@ -293,7 +334,11 @@ export default {
}
},
methods: {
playVideos(item) {
const videoUrl = videoAddress + item.filePath;
this.playerOptions.sources[0].src = videoUrl;
this.isShowVideo = true;
},
// 加载大图
loadBigImg() {
const newRedArray = [];
......@@ -598,7 +643,7 @@ export default {
);
const point = { lng: result[0], lat: result[1], linkId: e.linkId };
const dateTime = moment(e.imageTime).format(
'YYYY-MM-DD hh:mm:ss',
'YYYY-MM-DD HH:mm:ss',
);
// 这个感觉是 鼠标移动过来之后 事件遍历用的
this.infos.push({
......@@ -689,7 +734,7 @@ export default {
);
const dateTime = moment(item.timestamp).format(
'YYYY-MM-DD hh:mm:ss',
'YYYY-MM-DD HH:mm:ss',
);
// 这个感觉是 鼠标移动过来之后 事件遍历用的
this.infos.push({
......@@ -832,8 +877,79 @@ export default {
},
queryImagesAndTravel() {
this.queryImagesTravel();
this.queryVideosTravel();
this.queryTravel();
},
// 获取图片信息
queryVideosTravel() {
// eslint-disable-next-line eqeqeq
if (this.filters.dateTime.length == 0) {
this.filters.dateTime[0] = `${moment(
new Date().setTime(new Date().getTime() - 3600 * 1000 * 24),
).format('YYYY-MM-DD')} 00:00:00`;
this.filters.dateTime[1] = `${moment(
new Date().setTime(new Date().getTime() - 3600 * 1000 * 24),
).format('YYYY-MM-DD')} 23:59:59`;
}
let equipmentCode = '';
if (this.filters.plateNo && this.filters.plateNo.length > 0) {
this.filters.plateNo.forEach((item) => {
// eslint-disable-next-line eqeqeq
if (equipmentCode == '') {
equipmentCode += item;
} else {
equipmentCode += `,${item}`;
}
});
}
const that = this;
axios
.post(`${address}getVideosTravel`, {
startTime: this.filters.dateTime[0],
endTime: this.filters.dateTime[1],
equipment: equipmentCode,
})
.then((res) => {
this.allVideoPoints = [];
this.videoPoints = [];
if (res.data.data.length > 0) {
const points = [];
const videosPoints = res.data.data;
videosPoints.forEach((e) => {
const result = gcoord.transform(
[e.longitude, e.latitude],
gcoord.WGS84,
gcoord.BD09,
);
const point = {
lng: result[0],
lat: result[1],
linkId: e.linkId,
equipment: e.equipment,
time: that.$moment(e.imageTime).format('YYYY-MM-DD HH:mm:ss'),
position: e.position,
url: require('../assets/img/video.png'),
filePath: e.filePath,
};
const dateTime = moment(e.imageTime).format(
'YYYY-MM-DD hh:mm:ss',
);
points.push(point);
});
points.forEach((e) => {
e.title = `车辆:${e.equipment}\n时间:${e.time}\n位置:${e.position}`;
});
that.allVideoPoints = points;
that.videoPoints = points;
}
});
},
// 获取轨迹点 TODO 重点优化
queryTravel() {
// eslint-disable-next-line eqeqeq
......
This diff is collapsed.
module.exports = {
chainWebpack: (config) => {
config.module
.rule('swf')
.test(/\.swf$/)
.use('url-loader')
.loader('url-loader')
.options({
limit: 10000,
});
},
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment