Commit 4c1b5376 authored by 朱松文's avatar 朱松文

智能检索模块

parent 188150e5
<template>
<video id="najiu-player" class="video-js" muted preload="auto">
<source ref="videoSource" :src="videoUrl" type="video/mp4" />
<source ref="videoSource" src="//vjs.zencdn.net/(…)oceans324.mp4" type="video/mp4" />
<p class="vjs-no-js">当前浏览器不支持视频播放</p>
</video>
</template>
......@@ -23,13 +23,12 @@ require("../../../node_modules/video.js/dist/lang/zh-CN");
export default class MyVideo extends Vue {
@Prop() private src!: string;
@Prop() private width!: number;
@Prop() private showCloseButton!: boolean;
player = null;
videoUrl = "";
dogTrack = null;
mounted() {
this.videoUrl = this.src;
const _this = this;
this.$nextTick(() => {
this.player = videojs(
......@@ -58,12 +57,21 @@ export default class MyVideo extends Vue {
{ name: "subsCapsButton" },
{ name: "audioTrackButton" },
{ name: "fullscreenToggle" },
{ name: "BigPlayButton" },
],
},
},
function onPlayerReady() {
// const myContainer = this.addChild("MyContainer");
this.addChild("DogTrack");
console.log("showCloseButton", _this.showCloseButton);
if (_this.showCloseButton) {
this.addChild("CloseButton");
this.getChild("CloseButton").on("close", function () {
_this.$emit("closeVideo", this);
});
}
_this.dogTrack = this.getChild("DogTrack");
this.play();
}
......@@ -74,6 +82,7 @@ export default class MyVideo extends Vue {
}
onSrcChange(videoSrc: string) {
console.log("videosrc", videoSrc);
this.player.src(videoSrc);
this.player.play();
}
......
<template>
<div class="my-dialog">
<el-dialog title="提示信息" :visible.sync="isShow" width="450px">
<slot></slot>
<span slot="footer" class="dialog-footer">
<el-button class="btn" type="info" @click="isShow = false">取 消</el-button>
<el-button class="btn" type="primary" @click="handleConfirm">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script lang='ts'>
import { Vue, Component, Prop } from "vue-property-decorator";
@Component
export default class MyDialog extends Vue {
isShow = false;
show() {
this.isShow = true;
}
hide() {
this.isShow = false;
}
handleConfirm() {
this.$emit("onConfirm");
}
}
</script>
<style lang="scss" scoped>
.my-dialog {
::v-deep {
.el-dialog__body {
padding: 20px 70px;
}
.el-dialog__header {
background-color: #333e5d;
}
.el-dialog__title {
color: #d7d7d7;
}
.el-dialog__close {
font-size: 20px;
color: #d7d7d7;
}
.el-dialog__body,
.el-dialog__footer {
background-color: $item-background-color;
}
.el-input__inner {
color: #d7d7d7;
background-color: $item-background-color;
}
.el-form-item__content {
text-align: right;
}
.el-pagination__total {
color: #d7d7d7;
}
}
}
</style>
\ No newline at end of file
......@@ -3,7 +3,7 @@ import App from "./App.vue";
import router from "./router";
import store from "./store";
import "@/utils/rem";
import { Message, Table, TableColumn, Button, Dialog, Form, FormItem, Input, InputNumber, Pagination, Loading, DatePicker, Empty, Tooltip } from 'element-ui';
import { Message, Table, TableColumn, Button, Dialog, Form, FormItem, Input, InputNumber, Pagination, Loading, DatePicker, Empty, Tooltip, Select, Option, OptionGroup } from 'element-ui';
Vue.config.productionTip = false;
......@@ -13,13 +13,16 @@ Vue.use(Button)
Vue.use(Dialog)
Vue.use(Form)
Vue.use(FormItem)
Vue.use(Input);
Vue.use(InputNumber);
Vue.use(Pagination);
Vue.use(Input)
Vue.use(InputNumber)
Vue.use(Pagination)
Vue.use(DatePicker)
Vue.use(Loading);
Vue.use(Loading)
Vue.use(Empty)
Vue.use(Tooltip)
Vue.use(Select)
Vue.use(Option)
Vue.use(OptionGroup)
Vue.prototype.$loading = Loading.service;
Vue.prototype.$message = Message;
......
......@@ -80,3 +80,17 @@ export function convertLabelInfo(data: TrackData[]) {
console.log(`标识文件大小:${data.length}行,处理耗时:${new Date().getTime() - now}毫秒`)
return [dogIds, trackData]
}
export async function addTrackData(dog, player) {
try {
const track = await getLabelInfo(dog.labelFileName);
const [dogIds, trackData] = convertLabelInfo(track);
player.onTrackDataChange(dogIds, trackData, dog.id);
} catch (err) {
this.$message.error("下载标识文件失败");
console.log(
`%c-下载标识文件失败:${err}`,
"color: red; background: yellow;"
);
}
}
\ No newline at end of file
......@@ -7,47 +7,70 @@
<div class="row">
<div class="col-label">时间起:</div>
<div>
<el-input v-model="queryData.beginDate"></el-input>
<el-date-picker v-model="queryData.beginTime" type="date" placeholder="时间起"></el-date-picker>
</div>
</div>
<div class="row">
<div class="col-label">时间止:</div>
<div>
<el-input v-model="queryData.endDate"></el-input>
<el-date-picker v-model="queryData.endTime" type="date" placeholder="时间止"></el-date-picker>
</div>
</div>
<div class="row">
<div class="col-label">犬只品种:</div>
<div>
<el-input v-model="queryData.endDate"></el-input>
<el-input v-model="queryData.dogBreeds"></el-input>
</div>
</div>
<div class="row">
<div class="col-label">犬只毛色:</div>
<div>
<el-input v-model="queryData.endDate"></el-input>
<el-input v-model="queryData.dogColor"></el-input>
</div>
</div>
<div class="row">
<div class="col-label">犬只体型:</div>
<div>
<el-input v-model="queryData.endDate"></el-input>
<el-select v-model="queryData.dogSize" clearable placeholder="请选择">
<el-option
v-for="item in dogSizeList"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</div>
</div>
<div class="row">
<div class="col-label">是否牵狗绳:</div>
<div>
<el-input v-model="queryData.endDate"></el-input>
<el-select v-model="queryData.withRope" clearable placeholder="请选择">
<el-option
v-for="item in [{label:'是',value:true},{label:'否',value:false}]"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</div>
</div>
<div class="row">
<div class="col-label">摄像头:</div>
<div>
<el-input v-model="queryData.endDate"></el-input>
<el-select v-model="queryData.cameraList" filterable multiple placeholder="请选择">
<el-option-group v-for="group in cameraGroup" :key="group.label" :label="group.label">
<el-option
v-for="item in group.options"
:key="item.cameraId"
:label="item.cameraName"
:value="item.cameraId"
></el-option>
</el-option-group>
</el-select>
</div>
</div>
<div class="btn-container">
<el-button class="btn" type="primary">查询</el-button>
<el-button @click="handleQuery" class="btn" type="primary" :disabled="disbaled">查询</el-button>
</div>
</div>
</div>
......@@ -66,15 +89,17 @@
<img :src="scope.row.dogImageFileName" alt />
</template>
</el-table-column>
<el-table-column prop="name" label="摄像头名称" width="140"></el-table-column>
<el-table-column prop="cameraName" label="摄像头名称" width="300"></el-table-column>
<el-table-column prop="startTimeInDay" label="源视频起始时间" width="180"></el-table-column>
<el-table-column prop="videoLen" label="识别时长" :formatter="formatterVideoLen" width="120"></el-table-column>
<el-table-column prop="dogBreeds" label="品种" width="120"></el-table-column>
<el-table-column label="体型" width="120"></el-table-column>
<el-table-column prop="dogSize" label="体型" width="120"></el-table-column>
<el-table-column prop="dogColor" label="毛色" width="120"></el-table-column>
<el-table-column prop="withRopeRatio" :formatter="isRope" label="是否牵狗绳" width="120"></el-table-column>
<el-table-column label="操作">
<el-button type="text" @click="handleEdit(item)">播放</el-button>
<template slot-scope="scope">
<el-button type="text" @click="handleEdit(scope.row)">播放</el-button>
</template>
</el-table-column>
</el-table>
</div>
......@@ -88,36 +113,122 @@
></el-pagination>
</div>
</div>
<MyDialog ref="myDialog">
<div>
<div class="dialog-content">
<Icon name="jinggao" iconClass />
<span>开始日期不能大于结束日期</span>
</div>
</div>
</MyDialog>
<div class="player-container" v-show="showVideo">
<div class="video-box">
<MyVideo ref="my-video" :showCloseButton="true" @closeVideo="handleCloseVideo" />
</div>
</div>
</div>
</template>
<script lang="ts">
import BaseVue from "@/types/baseVue";
import { Component } from "vue-property-decorator";
import { pageDogInfo } from "@/service/CameraService";
import { Component, Watch } from "vue-property-decorator";
import {
pageDogInfo,
getCameraDogFormate,
addTrackData,
} from "@/service/CameraService";
import { convertMilliSecondToTime, isRope } from "@/utils/timeHelper";
import MyDialog from "@/components/myDialog/index.vue";
import Icon from "@/components/Icon/index.vue";
import MyVideo from "@/components/MyVideo/index.vue";
@Component({})
@Component({ components: { MyDialog, Icon, MyVideo } })
export default class AiSearch extends BaseVue {
queryData = {
beginTime: "",
endTime: "",
cameraList: [],
dogBreeds: "",
dogColor: "",
dogSize: "",
withRope: "",
current: 1,
beginDate: "",
endDate: "",
size: 10,
};
dogs = [];
total = 0;
dogSizeList = [
{ label: "大型犬", value: "大型犬" },
{ label: "中型犬", value: "中型犬" },
{ label: "小型犬", value: "小型犬" },
];
myDialog: any;
cameraGroup: any[] = [];
disbaled = true;
showVideo = false;
myVideo: any;
@Watch("queryData", { deep: true })
queryDataChange(newVal: any) {
const keys = Object.keys(newVal);
let flag = true;
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
const val = newVal[key];
const typeStr = typeof val;
console.log("aaa", key, val, typeStr);
if (
key === "current" ||
key === "size" ||
(key === "cameraList" && val.length === 0)
) {
continue;
}
if (val) {
flag = false;
break;
}
}
this.disbaled = flag;
}
async created() {
this.query();
const data = await getCameraDogFormate({});
if (data) {
Object.keys(data).forEach((key) => {
this.cameraGroup.push({ label: key, options: [...data[key]] });
});
}
}
mounted() {
this.$nextTick(() => {
this.myDialog = this.$refs["myDialog"];
this.myVideo = this.$refs["my-video"];
});
}
async query() {
const rp = await pageDogInfo({
...this.queryData,
});
this.dogs = rp.data.records;
console.log("dogs", this.dogs);
this.total = rp.data.total;
}
handleCurrentChange() {
console.log("handleCurrentChange");
handleQuery() {
console.log("query", this.queryData);
if (this.queryData.beginTime && this.queryData.endTime) {
if (this.queryData.beginTime > this.queryData.endTime) {
this.myDialog.show();
return;
}
}
this.queryData.current = 1;
this.query();
}
handleCurrentChange(val) {
this.queryData.current = val;
this.query();
}
getTableRowClass({ rowIndex }) {
return rowIndex % 2 === 0 ? "even-row" : "odd-row";
......@@ -128,6 +239,16 @@ export default class AiSearch extends BaseVue {
isRope(row) {
return isRope(row.withRopeRatio);
}
async handleEdit(data) {
this.myVideo.onSrcChange(data.fileName);
//添加标识文件
await addTrackData(data, this.myVideo);
this.showVideo = true;
}
handleCloseVideo() {
this.showVideo = false;
this.myVideo.player.pause();
}
}
</script>
......@@ -136,16 +257,44 @@ export default class AiSearch extends BaseVue {
display: grid;
grid-template-columns: 335px minmax(500px, 1fr);
color: #fff;
gap: 10px;
gap: 5px;
.row {
.col-label {
padding: 5px 0;
padding: 15px 0 8px 0;
}
}
.player-container {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
overflow: auto;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
z-index: 100;
background: rgba($color: #000000, $alpha: 0.5);
.video-box {
width: 1064px;
height: 598px;
}
}
.dialog-content {
font-size: 16px;
font-weight: 700;
.icon-jinggao {
font-size: 20px;
padding-right: 5px;
color: red;
}
}
.search-container {
border: $border-color;
margin-top: 10px;
margin-top: 5px;
background-color: $item-background-color;
padding-bottom: 20px;
.search-title {
......@@ -159,7 +308,7 @@ export default class AiSearch extends BaseVue {
p {
font-size: 13px;
color: $theme-blue;
padding: 15px 0;
padding: 15px 0 0 0;
}
}
.btn-container {
......@@ -170,8 +319,9 @@ export default class AiSearch extends BaseVue {
}
}
.data-container {
margin-top: 10px;
margin-top: 5px;
background-color: $item-background-color;
border: $border-color;
.result-title {
font-size: 15px;
padding: 5px 5px 5px 30px;
......@@ -225,6 +375,14 @@ export default class AiSearch extends BaseVue {
background-color: $theme-blue;
border-color: $theme-blue;
}
.el-button--primary.is-disabled,
.el-button--primary.is-disabled:active,
.el-button--primary.is-disabled:focus,
.el-button--primary.is-disabled:hover {
color: #fff;
background-color: #a0cfff;
border-color: #a0cfff;
}
.el-table .cell,
.el-table--border .el-table__cell:first-child .cell {
display: flex;
......@@ -271,5 +429,12 @@ export default class AiSearch extends BaseVue {
border: $border-color;
}
}
.el-date-editor.el-input,
.el-date-editor.el-input__inner {
width: 100%;
}
.el-select {
width: 100%;
}
}
</style>
......@@ -23,7 +23,7 @@
</div>
</div>
<div id="player-container" class="player" ref="player-container">
<MyVideo ref="my-video" v-if="width > 0 " :src="videoUrl" :width="width" />
<MyVideo ref="my-video" v-if="width > 0 " :width="width" />
</div>
<div class="video-list">
<div class="title">犬只记录</div>
......@@ -69,6 +69,7 @@ import {
pageDogInfo,
getLabelInfo,
convertLabelInfo,
addTrackData,
} from "@/service/CameraService";
// import dogTrackData from "@/mock/trackData";
......@@ -78,7 +79,6 @@ export default class Dashboard extends BaseVue {
dogData: DogData[] = [];
width = 0;
height = 0;
videoUrl = "";
queryCameryParam = {
beginTime: "",
cameraName: "",
......@@ -123,27 +123,15 @@ export default class Dashboard extends BaseVue {
if (!dog) return;
console.log("dogInfo", dog);
this.currentDogId = dog.id;
this.videoUrl = dog.fileName; //dog.videoUrl;
const this_ = this;
//用异步是为了防止my-vidoe控件还没有挂载好
setTimeout(async () => {
//play video
const myVideo = this_.$refs["my-video"];
//@ts-ignore
myVideo.onSrcChange(this_.videoUrl);
try {
const track = await getLabelInfo(dog.labelFileName);
const [dogIds, trackData] = convertLabelInfo(track);
// const [dogIds, trackData] = convertLabelInfo(dogTrackData);
//@ts-ignore
myVideo.onTrackDataChange(dogIds, trackData, dog.id);
} catch (err) {
this.$message.error("下载标识文件失败");
console.log(
`%c-下载标识文件失败:${err}`,
"color: red; background: yellow;"
);
}
myVideo.onSrcChange(dog.fileName);
//添加标识文件
await addTrackData(dog, myVideo);
}, 100);
}
......
......@@ -95,8 +95,7 @@
</el-form-item>
</el-form>
</el-dialog>
<div class="delDialog">
<el-dialog title="提示信息" :visible.sync="dialogDelVisible" width="450px">
<MyDialog ref="delDialog" @onConfirm="handleConfirmDel">
<div>
<div class="confirm-del">
<Icon name="jinggao" iconClass />
......@@ -104,12 +103,7 @@
</div>
<div>确认后此接口将被彻底删除。</div>
</div>
<span slot="footer" class="dialog-footer">
<el-button class="btn" type="info" @click="dialogDelVisible = false">取 消</el-button>
<el-button class="btn" type="primary" @click="handleConfirmDel">确 定</el-button>
</span>
</el-dialog>
</div>
</MyDialog>
</div>
</template>
......@@ -125,17 +119,17 @@ import BaseVue from "@/types/baseVue";
import { CameraData } from "./data";
import Icon from "@/components/Icon/index.vue";
import Search from "./components/search.vue";
import MyDialog from "@/components/myDialog/index.vue";
@Component({ components: { Icon, Search } })
@Component({ components: { Icon, Search, MyDialog } })
export default class SysSetting extends BaseVue {
cameraData = [];
dialogVisible = false;
isDisabled = false;
dialogDelVisible = false;
currentId = "";
total = 0;
form: CameraData = {};
aaaa = "";
delDialog: any;
formRules = {
cameraName: [
......@@ -194,6 +188,12 @@ export default class SysSetting extends BaseVue {
this.queryCamera();
}
mounted() {
this.$nextTick(() => {
this.delDialog = this.$refs["delDialog"];
});
}
async submitForm(formName) {
this.isDisabled = true;
//@ts-ignore
......@@ -252,7 +252,7 @@ export default class SysSetting extends BaseVue {
async handleDel(id: string): Promise<void> {
this.currentId = id;
this.dialogDelVisible = true;
this.delDialog.show();
}
handleClean(): void {
this.queryData.groupName = "";
......@@ -266,7 +266,7 @@ export default class SysSetting extends BaseVue {
this.$message("删除数据失败");
return;
}
this.dialogDelVisible = false;
this.delDialog.hide();
this.queryCamera();
}
......@@ -305,7 +305,7 @@ export default class SysSetting extends BaseVue {
margin: 0 auto;
max-width: 1905px;
min-width: 1650px;
padding: 10px;
padding: 5px;
.add {
height: 50px;
......@@ -355,8 +355,15 @@ export default class SysSetting extends BaseVue {
}
}
::v-deep {
.el-dialog__header {
background-color: #333e5d;
.el-input__inner {
color: #d7d7d7;
background-color: $item-background-color;
}
.el-form-item__content {
text-align: right;
}
.el-pagination__total {
color: #d7d7d7;
}
.el-dialog__title {
color: #d7d7d7;
......@@ -369,18 +376,8 @@ export default class SysSetting extends BaseVue {
.el-dialog__footer {
background-color: $item-background-color;
}
.el-input__inner {
color: #d7d7d7;
background-color: $item-background-color;
}
.el-dialog__body {
padding-right: 70px;
}
.el-form-item__content {
text-align: right;
}
.el-pagination__total {
color: #d7d7d7;
.el-dialog__header {
background-color: #333e5d;
}
}
.confirm-del {
......@@ -392,12 +389,5 @@ export default class SysSetting extends BaseVue {
color: red;
}
}
.delDialog {
::v-deep {
.el-dialog__body {
padding: 20px 70px;
}
}
}
}
</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