Commit 1aa851d8 authored by 朱松文's avatar 朱松文

视频播放对接真实api

parent da57e1d8
...@@ -4924,6 +4924,11 @@ ...@@ -4924,6 +4924,11 @@
"assert-plus": "^1.0.0" "assert-plus": "^1.0.0"
} }
}, },
"dayjs": {
"version": "1.10.7",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.7.tgz",
"integrity": "sha512-P6twpd70BcPK34K26uJ1KT3wlhpuOAPoMwJzpsIWUxHZ7wpmbdZL/hQqBDfz7hGurYSa5PhzdhDHtt319hL3ig=="
},
"de-indent": { "de-indent": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npm.taobao.org/de-indent/download/de-indent-1.0.2.tgz", "resolved": "https://registry.npm.taobao.org/de-indent/download/de-indent-1.0.2.tgz",
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
"dependencies": { "dependencies": {
"@types/webpack-env": "^1.16.2", "@types/webpack-env": "^1.16.2",
"core-js": "^3.6.5", "core-js": "^3.6.5",
"dayjs": "^1.10.7",
"element-ui": "^2.15.6", "element-ui": "^2.15.6",
"postcss-px2rem": "^0.3.0", "postcss-px2rem": "^0.3.0",
"px2rem-loader": "^0.1.9", "px2rem-loader": "^0.1.9",
......
export interface CameraItem { export interface CameraItem {
provinceCode?: string; cameraId?: string;
provinceName?: string; cameraName?: string;
cityCode?: string; cameraLocation?: string;
cityName?: string; longitude?: number;
areaCode?: string; latitude?: string;
areaName: string; number: number;
list: Detail[];
} }
export interface Detail {
id: number;
name: string;
total: number;
}
...@@ -3,18 +3,25 @@ ...@@ -3,18 +3,25 @@
<div class="area"> <div class="area">
<a v-on:click="hideCameras"> <a v-on:click="hideCameras">
<Icon name="jiantou" :iconClass="`icon-jiantou-${showCarmera ? 'down' : 'left'}`" /> <Icon name="jiantou" :iconClass="`icon-jiantou-${showCarmera ? 'down' : 'left'}`" />
<span>{{ cameraItem.areaName }}</span> <span>{{ cameraLocation }}</span>
</a> </a>
</div> </div>
<div v-show="showCarmera" class="item" v-for="item in cameraItem.list" :key="item.id"> <a
<div class="item-name"> v-show="showCarmera"
<Icon name="camera" iconClass="icon-camera" /> v-for="(item,i) in detail"
<span>{{ item.name }}</span> :key="i"
@click="handleClickCamera(item.cameraId,i)"
>
<div :class="{item:true,active:activeId===`${item.cameraId}-${i}`}">
<div class="item-name">
<Icon name="camera" iconClass="icon-camera" />
<span>{{ item.cameraName }}</span>
</div>
<div class="item-total">
<span>{{ item.number }}</span>
</div>
</div> </div>
<div class="item-total"> </a>
<span>{{ item.total }}</span>
</div>
</div>
</div> </div>
</template> </template>
...@@ -26,13 +33,20 @@ import BaseVue from "@/types/baseVue"; ...@@ -26,13 +33,20 @@ import BaseVue from "@/types/baseVue";
@Component({ components: { Icon } }) @Component({ components: { Icon } })
export default class Camera extends BaseVue { export default class Camera extends BaseVue {
@Prop() private cameraItem!: CameraItem; @Prop() private detail!: CameraItem[];
@Prop() private cameraLocation!: string;
showCarmera = true; showCarmera = true;
activeId = "";
hideCameras(): void { hideCameras(): void {
this.showCarmera = !this.showCarmera; this.showCarmera = !this.showCarmera;
} }
handleClickCamera(cameraId: string, index: number): void {
this.activeId = `${cameraId}-${index}`;
this.$emit("clickCamera", { cameraId });
}
} }
</script> </script>
...@@ -40,15 +54,19 @@ export default class Camera extends BaseVue { ...@@ -40,15 +54,19 @@ export default class Camera extends BaseVue {
.area-camera { .area-camera {
margin-top: 15px; margin-top: 15px;
// border: 1px solid red; // border: 1px solid red;
a {
text-decoration: none;
cursor: pointer;
}
.active {
background-color: #333333;
}
.area { .area {
height: 35px; height: 35px;
line-height: 35px; line-height: 35px;
padding-left: 20px; padding-left: 20px;
border-bottom: $border-color; border-bottom: $border-color;
a {
text-decoration: none;
cursor: pointer;
}
.icon-jiantou-down { .icon-jiantou-down {
display: inline-block; display: inline-block;
transform: rotate(90deg); transform: rotate(90deg);
......
<template> <template>
<div class="search"> <div class="search">
<div class="left"> <div class="left">
<div class="search-date"></div> <div class="search-date">
<div class="search-name"></div> <el-date-picker
v-model="beginEndTime"
type="daterange"
range-separator="~"
start-placeholder="开始日期"
end-placeholder="结束日期"
@change="handleDateChange"
></el-date-picker>
</div>
<div class="search-name">
<el-input v-model="cameraName" placeholder="输入关键词进行过滤"></el-input>
</div>
</div> </div>
<div class="right"> <div class="right">
<a>搜索</a> <a @click="handleSearch">搜索</a>
</div> </div>
</div> </div>
</template> </template>
<style lang="scss"> <script lang="ts">
import { Component } from "vue-property-decorator";
import BaseVue from "@/types/baseVue";
import dayjs from "dayjs";
@Component({})
export default class Search extends BaseVue {
beginTime = "";
endTime = "";
beginEndTime = "";
cameraName = "";
handleSearch() {
this.dealDate();
this.$emit("search", {
beginTime: this.beginTime,
endTime: this.endTime,
cameraName: this.cameraName,
});
}
handleDateChange(e) {
this.beginEndTime = e;
this.dealDate();
this.$emit("dateChange", {
beginTime: this.beginTime,
endTime: this.endTime,
});
}
dealDate() {
if (this.beginEndTime && this.beginEndTime.length === 2) {
this.beginTime = dayjs(this.beginEndTime[0]).format("YYYY-MM-DD");
this.endTime = dayjs(this.beginEndTime[1]).format("YYYY-MM-DD");
} else {
this.beginTime = "";
this.endTime = "";
}
}
}
</script>
<style lang="scss" scoped>
.search { .search {
display: flex; display: flex;
.left { .left {
flex: 1; flex: 1;
margin-right: 10px; margin-right: 10px;
.search-date {
border: 1px solid #d7d7d7;
height: 30px;
}
.search-name { .search-name {
border: 1px solid #d7d7d7;
height: 30px;
margin-top: 5px; margin-top: 5px;
} }
} }
...@@ -38,6 +84,37 @@ ...@@ -38,6 +84,37 @@
font-weight: 700; font-weight: 700;
font-size: 16px; font-size: 16px;
line-height: 65px; line-height: 65px;
text-decoration: none;
}
}
::v-deep {
.el-input__inner {
color: white;
height: 29px;
background-color: $item-background-color;
}
.el-date-editor {
width: 100%;
height: 30px;
color: #d7d7d7;
background-color: $item-background-color;
}
.el-range__icon {
line-height: 22px;
}
.el-range-input {
height: 28px;
background-color: $item-background-color;
}
.el-range-separator {
color: #d7d7d7;
line-height: 22px;
}
.el-range-input {
color: #d7d7d7;
}
.el-range__close-icon {
line-height: 22px;
} }
} }
} }
......
import { DogTrackData } from "../MyVideo/data";
export interface DogData { export interface DogData {
id: number; id: string;
videoUrl: string; cameraId: string;
picture: string; startTimeInDay?: string;
beginTime: string; endTimeInDay?: string;
endTime: string; dogImageFileName?: string;
totalTime: string; labelFileName?: string;
isHand: boolean; videoLen?: number;
dogType: string; fileName?: string;
hairColor: string; dogBreeds?: string;
trackData?: DogTrackData[]; dogColor?: string;
tethering?: string;
startFrameIndex?: number;
endFrameIndex?: number;
frameCountWithRope?: number;
frameCountWithoutRope?: number;
withRopeRatio?: number;
} }
...@@ -5,14 +5,16 @@ ...@@ -5,14 +5,16 @@
<tr> <tr>
<td class="td-img" rowspan="6"> <td class="td-img" rowspan="6">
<div class="dog-img"> <div class="dog-img">
<img :src="dog.picture" alt /> <a @click="play">
<img :src="dog.dogImageFileName" alt />
</a>
</div> </div>
</td> </td>
<td> <td>
<div class="col-left">识别开始时间</div> <div class="col-left">识别开始时间</div>
</td> </td>
<td> <td>
<div>{{ dog.beginTime }}</div> <div>{{ dog.startTimeInDay }}</div>
</td> </td>
</tr> </tr>
<tr> <tr>
...@@ -20,7 +22,7 @@ ...@@ -20,7 +22,7 @@
<div class="col-left">识别结束时间</div> <div class="col-left">识别结束时间</div>
</td> </td>
<td> <td>
<div>{{ dog.endTime }}</div> <div>{{ dog.endTimeInDay }}</div>
</td> </td>
</tr> </tr>
<tr> <tr>
...@@ -28,7 +30,7 @@ ...@@ -28,7 +30,7 @@
<div class="col-left">识别时长</div> <div class="col-left">识别时长</div>
</td> </td>
<td> <td>
<div>{{ dog.totalTime }}</div> <div>{{ dog.videoLen }}</div>
</td> </td>
</tr> </tr>
<tr> <tr>
...@@ -36,7 +38,7 @@ ...@@ -36,7 +38,7 @@
<div class="col-left">是否牵狗绳</div> <div class="col-left">是否牵狗绳</div>
</td> </td>
<td> <td>
<div>{{ dog.isHand ? "" : "" }}</div> <div>{{ dog.withRopeRatio }}</div>
</td> </td>
</tr> </tr>
<tr> <tr>
...@@ -44,7 +46,7 @@ ...@@ -44,7 +46,7 @@
<div class="col-left">品种</div> <div class="col-left">品种</div>
</td> </td>
<td> <td>
<div>{{ dog.dogType }}</div> <div>{{ dog.dogBreeds }}</div>
</td> </td>
</tr> </tr>
<tr> <tr>
...@@ -52,7 +54,7 @@ ...@@ -52,7 +54,7 @@
<div class="col-left">毛色</div> <div class="col-left">毛色</div>
</td> </td>
<td> <td>
<div>{{ dog.hairColor }}</div> <div>{{ dog.dogColor }}</div>
</td> </td>
</tr> </tr>
<tr> <tr>
...@@ -90,6 +92,10 @@ export default class DogInfo extends BaseVue { ...@@ -90,6 +92,10 @@ export default class DogInfo extends BaseVue {
.#{$prefixCls}-dog { .#{$prefixCls}-dog {
font-size: 12px; font-size: 12px;
font-weight: 700; font-weight: 700;
a {
cursor: pointer;
text-decoration: none;
}
.td-img { .td-img {
width: 120px; width: 120px;
} }
...@@ -130,10 +136,6 @@ export default class DogInfo extends BaseVue { ...@@ -130,10 +136,6 @@ export default class DogInfo extends BaseVue {
line-height: 30px; line-height: 30px;
text-align: center; text-align: center;
color: #0079fe; color: #0079fe;
a {
cursor: pointer;
text-decoration: none;
}
.icon-player { .icon-player {
font-size: 12px; font-size: 12px;
padding-right: 5px; padding-right: 5px;
......
...@@ -61,7 +61,7 @@ class DogTrack extends Component { ...@@ -61,7 +61,7 @@ class DogTrack extends Component {
if (firstFrameIndex <= currentTime && currentTime <= d.FrameIndex * 40) { if (firstFrameIndex <= currentTime && currentTime <= d.FrameIndex * 40) {
// //
this.arrayIndex = i this.arrayIndex = i
console.log("arrayIndex", this.arrayIndex, d.FrameIndex) // console.log("arrayIndex", this.arrayIndex, d.FrameIndex)
if (!this.player_.isFullscreen()) { if (!this.player_.isFullscreen()) {
//跟踪框大小 //跟踪框大小
this.myel.style.width = `${(d.x2 - d.x1) * this.defaultWidth}px` this.myel.style.width = `${(d.x2 - d.x1) * this.defaultWidth}px`
......
const API = { const API = {
'development': { 'development': {
skyNet: 'http://skynet-test.inajiu.com:7011/sn-web/' skyNet: 'http://10.2.70.19:48021/'
}, },
'production': { 'production': {
skyNet: 'http://10.2.60.59:48021/' skyNet: 'http://10.2.60.59:48021/'
......
...@@ -3,7 +3,7 @@ import App from "./App.vue"; ...@@ -3,7 +3,7 @@ import App from "./App.vue";
import router from "./router"; import router from "./router";
import store from "./store"; import store from "./store";
import "@/utils/rem"; import "@/utils/rem";
import { Message, Table, TableColumn, Button, Dialog, Form, FormItem, Input, InputNumber, Pagination, Loading } from 'element-ui'; import { Message, Table, TableColumn, Button, Dialog, Form, FormItem, Input, InputNumber, Pagination, Loading, DatePicker, Empty } from 'element-ui';
Vue.config.productionTip = false; Vue.config.productionTip = false;
...@@ -16,7 +16,9 @@ Vue.use(FormItem) ...@@ -16,7 +16,9 @@ Vue.use(FormItem)
Vue.use(Input); Vue.use(Input);
Vue.use(InputNumber); Vue.use(InputNumber);
Vue.use(Pagination); Vue.use(Pagination);
Vue.use(DatePicker)
Vue.use(Loading); Vue.use(Loading);
Vue.use(Empty)
Vue.prototype.$loading = Loading.service; Vue.prototype.$loading = Loading.service;
Vue.prototype.$message = Message; Vue.prototype.$message = Message;
......
...@@ -15,4 +15,24 @@ export function addCamera(data: any) { ...@@ -15,4 +15,24 @@ export function addCamera(data: any) {
export function delCamera(id: string) { export function delCamera(id: string) {
return NetUtil.fetch_request('camera/delCamera/' + id, 'POST') return NetUtil.fetch_request('camera/delCamera/' + id, 'POST')
}
export async function getCameraDog(data: any) {
const rp = await NetUtil.fetch_request('video/cameraDog', 'POST', data)
if (rp.code !== 0) return {}
if (!rp.data || rp.data.length === 0) return undefined
//组装数据结构
const ar = {}
rp.data.forEach(d => {
if (!ar[d.cameraLocation]) {
ar[d.cameraLocation] = [d]
} else {
ar[d.cameraLocation].push(d)
}
})
return ar
}
export function pageDogInfo(data: any) {
return NetUtil.fetch_request('video/pageDogInfo/', 'POST', data)
} }
\ No newline at end of file
...@@ -34,9 +34,17 @@ class NetUtil { ...@@ -34,9 +34,17 @@ class NetUtil {
} else { } else {
promise = new Promise((resolve, reject) => { promise = new Promise((resolve, reject) => {
fetch(api.skyNet + url, { method: method, headers: header, body: JSON.stringify(params) }) fetch(api.skyNet + url, { method: method, headers: header, body: JSON.stringify(params) })
.then(response => response.json()) .then(response => {
if (response.status === 404) {
throw Error("网络404错误!")
}
return response.json()
})
.then(responseData => resolve(responseData)) .then(responseData => resolve(responseData))
.then(err => reject(err)) .then(err => reject(err))
.catch(err => {
reject(err)
})
}) })
} }
......
...@@ -5,7 +5,7 @@ const baseSize = 16; ...@@ -5,7 +5,7 @@ const baseSize = 16;
function setRem() { function setRem() {
// 当前页面宽度相对于 1920宽的缩放比例,可根据自己需要修改。 // 当前页面宽度相对于 1920宽的缩放比例,可根据自己需要修改。
const clientWidth = document.documentElement.clientWidth const clientWidth = document.documentElement.clientWidth
const minWidth = 1567 const minWidth = 1615
const scale = (clientWidth > minWidth ? clientWidth : minWidth) / 1920; const scale = (clientWidth > minWidth ? clientWidth : minWidth) / 1920;
// 设置页面根节点字体大小(“Math.min(scale, 2)” 指最高放大比例为2,可根据实际业务需求调整) // 设置页面根节点字体大小(“Math.min(scale, 2)” 指最高放大比例为2,可根据实际业务需求调整)
......
...@@ -2,6 +2,6 @@ import { CameraItem } from "@/components/Camera/data"; ...@@ -2,6 +2,6 @@ import { CameraItem } from "@/components/Camera/data";
import { DogData } from "@/components/DogInfo/data"; import { DogData } from "@/components/DogInfo/data";
export interface DashBoardData { export interface DashBoardData {
cameras: CameraItem[]; cameras?: CameraItem[];
dogData: DogData[]; dogData?: DogData[];
} }
...@@ -3,17 +3,28 @@ ...@@ -3,17 +3,28 @@
<div class="camera-list"> <div class="camera-list">
<div> <div>
<div class="title">摄像头选择</div> <div class="title">摄像头选择</div>
<Search /> <Search @search="queryCamera" @dateChange="handleDateChange" />
</div> </div>
<div class="cameras"> <div class="cameras">
<Camera v-for="(camera, i) in cameras" :key="i" :cameraItem="camera" /> <div v-show="cameras">
<Camera
v-for="(value,key,index) in cameras"
:key="index"
:cameraLocation="key"
:detail="value"
@clickCamera="queryDogInfo"
/>
</div>
<div v-show="!cameras" class="no-data">
<el-empty description="没有数据"></el-empty>
</div>
</div> </div>
</div> </div>
<div class="player" ref="player-container"> <div class="player" ref="player-container">
<MyVideo <MyVideo
ref="myVideo" ref="myVideo"
v-if="width > 0" v-if="width > 0 && videoUrl"
:src="videoUrl" :src="videoUrl"
:trackData="trackData" :trackData="trackData"
:width="width" :width="width"
...@@ -22,7 +33,21 @@ ...@@ -22,7 +33,21 @@
<div class="video-list"> <div class="video-list">
<div class="title">犬只记录</div> <div class="title">犬只记录</div>
<div class="detail"> <div class="detail">
<DogInfo @play="handlePlay" v-for="(dog, i) in dogData" :key="i" :dog="dog" /> <div v-show="dogData && dogData.length>0">
<DogInfo @play="handlePlay" v-for="(dog, i) in dogData" :key="i" :dog="dog" />
</div>
<div v-show="!dogData || dogData.length === 0" class="no-data">
<el-empty description="没有数据"></el-empty>
</div>
</div>
<div class="paging">
<el-pagination
background
layout="total,prev, pager, next,jumper"
:current-page.sync="queryCameryParam.current"
@current-change="handleCurrentChange"
:total="dogTotal"
></el-pagination>
</div> </div>
</div> </div>
</div> </div>
...@@ -31,48 +56,104 @@ ...@@ -31,48 +56,104 @@
<script lang="ts"> <script lang="ts">
import { Component } from "vue-property-decorator"; import { Component } from "vue-property-decorator";
import Camera from "@/components/Camera/index.vue"; import Camera from "@/components/Camera/index.vue";
import { DashBoardData } from "./data";
import DogInfo from "@/components/DogInfo/index.vue"; import DogInfo from "@/components/DogInfo/index.vue";
import Search from "@/components/Camera/search.vue"; import Search from "@/components/Camera/search.vue";
import BaseVue from "@/types/baseVue"; import BaseVue from "@/types/baseVue";
import MyVideo from "@/components/MyVideo/index.vue"; import MyVideo from "@/components/MyVideo/index.vue";
import CameraData from "@/mock/cameraData";
import { DogData } from "@/components/DogInfo/data"; import { DogData } from "@/components/DogInfo/data";
import { TrackData } from "@/components/MyVideo/data"; import { TrackData } from "@/components/MyVideo/data";
import dogTrackData from "@/mock/trackData"; import dogTrackData from "@/mock/trackData";
import { getCameraDog, pageDogInfo } from "@/service/CameraService";
@Component({ components: { Camera, DogInfo, Search, MyVideo } }) @Component({ components: { Camera, DogInfo, Search, MyVideo } })
export default class Dashboard extends BaseVue { export default class Dashboard extends BaseVue {
data(): DashBoardData { cameras: any = [];
return CameraData; dogData: DogData[] = [];
}
width = 0; width = 0;
height = 0; height = 0;
videoUrl = ""; videoUrl = "";
trackData: TrackData[]; trackData: TrackData[] = [];
queryCameryParam = {
beginTime: "",
cameraName: "",
endTime: "",
};
queryDogParam = {
beginTime: "",
cameraId: "",
current: 1,
endTime: "",
size: 10,
};
dogTotal = 0;
async created(): Promise<void> {
this.queryCamera(this.queryCameryParam);
}
mounted() { mounted() {
this.trackData = dogTrackData.filter(
(d) => d.DogId === "1440845582095753223"
);
this.$nextTick(() => { this.$nextTick(() => {
const p = this.$refs["player-container"]; const p = this.$refs["player-container"];
//@ts-ignore //@ts-ignore
this.width = p.offsetWidth; this.width = p.offsetWidth;
//@ts-ignore //@ts-ignore
this.height = p.offsetHeight; this.height = p.offsetHeight;
//todo:
this.videoUrl = CameraData.dogData[0].videoUrl;
}); });
} }
handlePlay(dog: DogData): void { handlePlay(dog: DogData): void {
this.videoUrl = dog.videoUrl; this.videoUrl = dog.fileName; //dog.videoUrl;
this.trackData = dogTrackData.filter( this.trackData = dogTrackData.filter((d) => d.DogId === dog.id);
(d) => d.DogId === "1440845582095753223"
);
//@ts-ignore //@ts-ignore
this.$refs["myVideo"].onSrcChange(this.videoUrl, this.trackData); this.$refs["myVideo"].onSrcChange(this.videoUrl, this.trackData);
} }
async queryDogInfo(query) {
const rp = await pageDogInfo({
...this.queryDogParam,
...this.queryCameryParam,
...query,
});
//@ts-ignore
this.dogData = rp.data.records;
this.dogTotal = rp.data.total;
//初始第一条视频
if (this.dogData && this.dogData.length > 0) {
this.videoUrl = this.dogData[0].fileName; //"1440845582095753223"
//todo:
this.trackData = dogTrackData.filter(
(d) => d.DogId === "1440845582095753223" //this.dogData[0].id
);
}
}
async queryCamera(query) {
//查询摄像头数据
const data = await getCameraDog({ ...query });
this.cameras = data;
if (!this.cameras) {
this.dogData = [];
this.dogTotal = 0;
return;
}
//默认查询第一个摄像头狗的数据
for (const item in this.cameras) {
if (this.cameras[item] && this.cameras[item].length > 0) {
await this.queryDogInfo({
...query,
cameraId: this.cameras[item][0].cameraId,
});
break;
}
}
}
handleDateChange(changeDate) {
this.queryCameryParam = { ...this.queryCameryParam, ...changeDate };
}
handleCurrentChange(val) {
this.queryDogParam.current = val;
this.queryDogInfo({});
}
} }
</script> </script>
...@@ -112,16 +193,28 @@ export default class Dashboard extends BaseVue { ...@@ -112,16 +193,28 @@ export default class Dashboard extends BaseVue {
} }
.video-list { .video-list {
width: 440px; width: 440px;
position: relative;
background-color: $item-background-color; background-color: $item-background-color;
border: $border-color; border: $border-color;
padding: 0 10px; padding: 0 10px;
padding-bottom: 15px; // padding-bottom: 15px;
.detail { .detail {
max-height: 758px; height: 706px;
min-height: 600px; // min-height: 600p x;
overflow: auto; overflow: auto;
} }
.paging {
display: flex;
justify-content: right;
padding: 10px 20px;
border-top: $border-color;
}
}
.no-data {
text-align: center;
padding-top: 20px;
} }
} }
</style> </style>
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