提交 8cd66e52 作者: 翁进城

Merge branch 'v4' into v4_master

...@@ -233,8 +233,6 @@ export default { ...@@ -233,8 +233,6 @@ export default {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.cesium_layerBox {
}
.cpt-cesium_layer::v-deep { .cpt-cesium_layer::v-deep {
width: 100%; width: 100%;
...@@ -254,6 +252,10 @@ export default { ...@@ -254,6 +252,10 @@ export default {
.cesium-viewer-navigationContainer { .cesium-viewer-navigationContainer {
display: none; display: none;
} }
.cesium-credit-logoContainer {
display: none;
}
} }
.videoWallMapStyle { .videoWallMapStyle {
......
<template>
<div class="car dialog1027" v-interact>
<div class="dialog-header">
<div class="dialog-header__icon" />
<div class="dialog-header__title">
快速建模
</div>
<div class="dialog-header_close" style="color:#fff" @click="() => $emit('close')">关闭</div>
</div>
<div class="dialog-content w267">
<el-cascader size="mini" filterable popper-class="cpt-observe-mspace-dashboard-airway_popper" v-model="taskCateId"
:options="airway_list" clearable :show-all-levels="false" placeholder="请选择任务" :props="{
children: 'children',
label: 'taskTitle',
value: 'id',
emitPath: false,
}">
<template slot-scope="{ data }">
<el-tooltip :disabled="data.taskTitle.length < 11" class="item" effect="dark" :content="data.taskTitle"
placement="top-start">
<span>{{ data.taskTitle }}</span>
</el-tooltip>
</template>
</el-cascader>
<el-select class="mt10" v-model="type" size="mini" placeholder="请选择类型">
<el-option label="图片" :value="0"></el-option>
<el-option label="视频" :value="1"></el-option>
</el-select>
<div class="jcsb w267 h30 mt30">
<div class="dec mt5">1</div><span class="dib cf ml10 lh30"> 快速建模</span>
<div class="btn fr cf h30 lh30 w80 cp" @click="jmFn(1)">启动</div>
</div>
<div class="jcsb mt18 w267 h30">
<div class="dec mt5">2</div><span class="dib cf lh30 ml10">数据处理</span>
<div class="btn fr cf h30 lh30 w80 cp" @click="jmFn(2)">启动</div>
</div>
</div>
</div>
</template>
<script>
// import API from '@/api';
export default {
props: {
device: {
type: Object,
default: () => ({})
},
},
data() {
return {
imgUrl: process.env.VUE_APP_IMG_URL,
list: [],
type: null,
taskCateId: null,
airway_list: []
}
},
created() {
this.list_airway();
},
methods: {
jmFn(num) {
let { deviceHardId } = this.device
if (num == 1) {
let a = document.createElement("a");
a.href = `MMCEagleEye:// `
a.click()
}
else {
if(!this.taskCateId) return this.$message.warning('请选择任务!')
if(this.type==null ) return this.$message.warning('请选择类型!')
let a = document.createElement("a");
a.href = `MMCPosTool://&deviceId=${deviceHardId}enddeviceId&taskId=${this.taskCateId}endtaskId&type=${this.type}endtype`
a.click()
}
},
async list_airway() {
/* let res = await API.AIRWAY.getApprovedTask();
if (res) {
let jqList = [],
ctList = [],
lsList = [];
for (let i = 0; i < res.length; i++) {
if (res[i].taskCateId == 1) {
jqList.push(res[i]);
}
if (res[i].taskCateId == 2) {
ctList.push(res[i]);
}
if (res[i].taskCateId == 3) {
lsList.push(res[i]);
}
}
let airway_list = [
{
id: "警情任务",
taskTitle: "警情任务",
children: jqList,
},
{
id: "常态任务",
taskTitle: "常态任务",
children: ctList,
},
{
id: "临时任务",
taskTitle: "临时任务",
children: lsList,
},
];
this.airway_list = airway_list;
} */
},
}
}
</script>
<style lang="scss" scoped>
.car {
width: 268px;
}
.dialog-content {
padding: 20px 14px 12px;
max-height: 461px;
overflow: auto;
.dec {
width: 20px;
height: 20px;
line-height: 20px;
text-align: center;
border-radius: 50%;
background: #06199b;
}
.btn {
text-align: center;
border: 1px #315ec7 solid;
border-radius: 3px;
background-color: #02173d;
font-size: 14px;
font-family: MicrosoftYaHei;
color: #D2D9FF;
cursor: pointer;
}
.btn:hover {
background: #06199b;
}
}
.car-img {
position: relative;
width: 100%;
height: 135px;
.car-img__img {
width: 100%;
height: 100%;
}
.car-img__label {
position: absolute;
bottom: 0;
width: 100%;
height: 28px;
display: flex;
justify-content: center;
align-items: center;
font-size: 14px;
color: #aee9ff;
font-family: MicrosoftYaHeiUI;
}
}
.car-form {
padding: 10px 0 0;
font-size: 14px;
font-family: MicrosoftYaHei;
color: #fff;
>div {
margin-bottom: 8px;
&:last-child {
margin-bottom: 0;
}
}
}
.car-item {
margin-bottom: 24px;
}
</style>
\ No newline at end of file
...@@ -264,10 +264,10 @@ export default { ...@@ -264,10 +264,10 @@ export default {
speed: point.speed, speed: point.speed,
pointActionSaveReqVOS: point.waypointActions.map((action) => { pointActionSaveReqVOS: point.waypointActions.map((action) => {
let actionValue = []; let actionValue = [];
actionValue.push(`param1:${action.param1 || ""}`); action.param1 && actionValue.push(`param1:${action.param1 || ""}`);
actionValue.push(`param2:${action.param2 || ""}`); action.param2 && actionValue.push(`param2:${action.param2 || ""}`);
actionValue.push(`param3:${action.param3 || ""}`); action.param3 && actionValue.push(`param3:${action.param3 || ""}`);
actionValue.push(`param4:${action.param4 || ""}`); action.param4 && actionValue.push(`param4:${action.param4 || ""}`);
return { return {
actionType: action.actionType, actionType: action.actionType,
actionValue: actionValue.join(";"), actionValue: actionValue.join(";"),
......
<template>
<div class="car dialog1027" v-interact>
<div class="dialog-header">
<div class="dialog-header__icon" />
<div class="dialog-header__title">
车辆识别
</div>
<div class="dialog-header_close" style="color:#fff" @click="()=>$emit('close')">关闭</div>
</div>
<div class="dialog-content" v-infinite-scroll="load">
<template v-if="list.length > 0" >
<div v-for="(item, i) in list" :key="i" class="car-item">
<div class="car-img">
<img class="car-img__img" :src="imgUrl + item.imageUrl" />
<div class="car-img__label">{{ item.plateNum || '暂无' }}</div>
</div>
<div class="car-form">
<div>地点:{{ item.addr || item.findAddress || '暂无' }}</div>
<div>时间:{{ item.findTime || '暂无' }}</div>
</div>
</div>
</template>
<template v-else>
<div style="text-align: center; width: 100%;">暂无数据</div>
</template>
</div>
</div>
</template>
<script>
// import API from '@/api';
export default {
props: {
uavId: {
type: String,
default: ''
}
},
data(){
return {
imgUrl: process.env.VUE_APP_IMG_URL,
list: [],
pageNo: 1,
pageSize: 3,
}
},
created(){
this.getCarList()
},
methods: {
async load(){
this.pageNo++
/* let res = await API.HOME.getflightvideoMsg({
uavId: this.uavId,
pageNo: this.pageNo,
pageSize: this.pageSize
})
for(let i = 0; i < res.length; i++){
let item = res[i];
if(item.lon){
let address = await API.MAP.AiRegeo({
location: `${item.lon},${item.lat}`
})
item.addr = address.province.value + address.city.value + address.dist.value + address.road.roadname + address.poi;
}
this.list.push(res[i])
}
console.log(this.list,"list"); */
},
async getCarList(){
if(!this.uavId){
this.$message.error('请选择无人机');
return;
}
let res = await API.HOME.getflightvideoMsg({
uavId: this.uavId,
pageNo: this.pageNo,
pageSize: this.pageSize
})
for(let i = 0; i < res.length; i++){
let item = res[i];
if(item.lon){
let address = await API.MAP.AiRegeo({
location: `${item.lon},${item.lat}`
})
item.addr = address.province.value + address.city.value + address.dist.value + address.road.roadname + address.poi;
}
this.list.push(res[i])
}
// this.list = res || [];
}
}
}
</script>
<style lang="scss" scoped>
.car{
width: 268px;
}
.dialog-content{
padding: 20px 14px 12px;
max-height: 461px;
overflow: auto;
}
.car-img{
position: relative;
width: 100%;
height: 135px;
.car-img__img {
width: 100%;
height: 100%;
}
.car-img__label {
position: absolute;
bottom: 0;
width: 100%;
height: 28px;
display: flex;
justify-content: center;
align-items: center;
font-size: 14px;
color: #aee9ff;
font-family: MicrosoftYaHeiUI;
}
}
.car-form{
padding: 10px 0 0;
font-size: 14px;
font-family: MicrosoftYaHei;
color: #fff;
>div {
margin-bottom: 8px;
&:last-child {
margin-bottom: 0;
}
}
}
.car-item{
margin-bottom: 24px;
}
</style>
\ No newline at end of file
<template>
<div class="face dialog1027" v-interact>
<div class="dialog-header">
<div class="dialog-header__icon" />
<div class="dialog-header__title">
人脸识别
</div>
<div class="dialog-header_close" style="color:#fff" @click="()=>$emit('close')">关闭</div>
</div>
<div class="dialog-content" v-infinite-scroll="load">
<template v-if="list.length > 0">
<div class="result" v-for="(item, i) in list" :key="i">
<div class="rate-box">
<div class="rate-img">
<img :src="imgUrl + item.recordImageUrl" />
</div>
<div class="rate-round">
<div class="rate-round__value">{{ Number(item.similarity).toFixed(2) }}%</div>
<div class="rate-routd__text" @click="onDetail(item)">详情</div>
</div>
<div class="rate-img rate-img--contrary">
<img :src="imgUrl + item.snapImageUrl" />
</div>
</div>
<div class="rate-form" v-if="item.show">
<div class="rate-form-item">
<div class="rate-form-item__label">
姓名:
</div>
<div class="rate=form-item__value">
{{ item.userName || '暂无' }}
</div>
</div>
<div class="rate-form-item">
<div class="rate-form-item__label">
出生年份:
</div>
<div class="rate=form-item__value">
{{ item.birthday || '暂无' }}
</div>
</div>
<div class="rate-form-item">
<div class="rate-form-item__label">
发现时间:
</div>
<div class="rate=form-item__value">
{{ item.occurTime || '暂无' }}
</div>
</div>
<div class="rate-form-item">
<div class="rate-form-item__label">
发现地点:
</div>
<div class="rate=form-item__value">
{{ item.addr || item.address || '暂无' }}
</div>
</div>
<div class="rate-form-item">
<div class="rate-form-item__label">
身份证号:
</div>
<div class="rate=form-item__value">
{{ item.idCard || '暂无' }}
</div>
</div>
<div class="rate-form-item">
<div class="rate-form-item__label">
AI识别:
</div>
<div class="rate=form-item__value">
<template v-if="item.labels && item.labels.length">
<div class="round-border" v-for="(label, j) in item.labels" :key="j" >
{{label}}
</div>
</template>
<template v-else>
暂无
</template>
</div>
</div>
</div>
</div>
</template>
<template v-else>
<div style="text-align: center; width: 100%;">暂无数据</div>
</template>
</div>
</div>
</template>
<script>
// import API from '@/api';
export default {
props: {
uavId: {
type: String,
default: ''
}
},
data(){
return {
imgUrl: process.env.VUE_APP_IMG_URL,
list: [
/* {
userName: '人热二',
birthday: '1888-02-11',
occurTime: '2022-02-30 08:22:14',
address: '深圳市南山区',
idCard: '112313123123',
labels: ['省内人员'],
similarity: '63',
img: '',
imgs: '',
show: true
} */
],
pageNo: 1,
pageSize: 4,
}
},
created(){
this.getFaceList();
},
methods: {
async load(){
this.pageNo++
/* let res = await API.HOME.getFaceuavvideoMsg({
uavId: this.uavId,
pageNo: this.pageNo,
pageSize: this.pageSize
})
for(let i = 0; i < res.length; i++){
let item = res[i];
if(item.longi){
let address = await API.MAP.AiRegeo({
location: `${item.longi},${item.lati}`
})
item.addr = address.province.value + address.city.value + address.dist.value + address.road.roadname + address.poi;
}
this.list.push(res[i])
}
console.log(this.list,"list"); */
},
async getFaceList(){
if(!this.uavId){
this.$message.error('请选择无人机');
return;
}
let res = await API.HOME.getFaceuavvideoMsg({
uavId: this.uavId,
pageNo: this.pageNo,
pageSize: this.pageSize
}) || [];
for(let i = 0; i < res.length; i++){
let item = res[i];
if(item.longi){
let address = await API.MAP.AiRegeo({
location: `${item.longi},${item.lati}`
})
item.addr = address.province.value + address.city.value + address.dist.value + address.road.roadname + address.poi;
}
this.list.push(res[i])
}
// this.list = res || [];
},
onDetail(item){
this.$set(item, 'show', !item.show);
}
}
}
</script>
<style lang="scss" scoped>
.face{
width: 268px;
}
.dialog-content{
padding: 14px;
cursor: initial;
max-height: 461px;
overflow-y: auto;
}
.result{
width: 100%;
margin-top: 27px;
&:first-child {
margin-top: 0;
}
}
.rate-box{
display: flex;
align-items: center;
position: relative;
width: 100%;
.rate-img{
flex: 1;
height: 75px;
background-image: url('../../assets/images/faceAI_border1.png');
background-size: 100% 100%;
padding: 7px;
display: flex;
align-items: center;
&.rate-img--contrary {
background-image: url('../../assets/images/faceAI_border2.png');
justify-content: right;
}
img {
width: 70px;
height: 70px;
border-radius: 7px;
overflow: hidden;
}
}
.rate-round{
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.rate-round__value{
color: #fb799d;
font-size: 14px;
font-family: MicrosoftYaHei;
}
.rate-routd__text{
cursor: pointer;
font-size: 12px;
color: #b9d7f0;
font-family: MicrosoftYaHei;
transform: scale(0.9);
margin-top: 3px;
}
}
}
.rate-form{
margin-top: 10px;
font-size: 14px;
font-family: MicrosoftYaHei;
color: #fff;
.rate-form-item {
margin-bottom: 12px;
display: flex;
&:last-child {
margin-bottom: 0;
}
.rate-form-item__label {
width: 70px;
text-align: right;
flex-shrink: 0;
}
.rate-form-item__value {
}
}
}
.round-border{
padding: 2px 8px;
border-radius: 11px;
border: 1px solid #ff4a4a;
color: #ff4a4a;
font-size: 14px;
font-family: MicrosoftYaHei;
}
</style>
\ No newline at end of file
...@@ -35,7 +35,7 @@ export default { ...@@ -35,7 +35,7 @@ export default {
// console.log('livenvr', value) // console.log('livenvr', value)
if (newVal ) { if (newVal ) {
this.$nextTick(() => { this.$nextTick(() => {
this.$refs["livePlayer"].play(); this.$refs["livePlayer"]?.play();
}); });
} }
}, },
......
...@@ -17,13 +17,12 @@ export default { ...@@ -17,13 +17,12 @@ export default {
computed: { computed: {
...mapState("MMCFlightControlCenter/hangar", ["hangar"]), ...mapState("MMCFlightControlCenter/hangar", ["hangar"]),
name() { name() {
return `${this.hangar?.name || ""}机库` return `${this.hangar?.name || ""}`;
// return `${this.hangar?.name || ""}机库无人机`;
}, },
url() { url() {
let find = this.hangar?.streamConfiguration let find = this.hangar?.streamConfiguration
?.find((v) => v.urlType === 1) ?.find((v) => v.urlType === 1)
return find?.originalUrl || ''; return find?.originalUrl || find?.lowLatencyUrl || find?.fluencyUrl || '';
}, },
}, },
}; };
......
...@@ -17,13 +17,12 @@ export default { ...@@ -17,13 +17,12 @@ export default {
computed: { computed: {
...mapState("MMCFlightControlCenter/hangar", ["hangar"]), ...mapState("MMCFlightControlCenter/hangar", ["hangar"]),
name() { name() {
return `${this.hangar?.name || ""}机库`; return `${this.hangar?.name || ""}`;
// return `${this.hangar?.name || ""}机库无人机`;
}, },
url() { url() {
let find = this.hangar?.streamConfiguration let find = this.hangar?.streamConfiguration
?.find((v) => v.urlType === 2) ?.find((v) => v.urlType === 2)
return find?.originalUrl || ''; return find?.originalUrl || find?.lowLatencyUrl || find?.fluencyUrl || '';
}, },
}, },
methods: {}, methods: {},
......
...@@ -41,8 +41,7 @@ export default { ...@@ -41,8 +41,7 @@ export default {
]), ]),
...mapState("MMCFlightControlCenter/uav", ["uav"]), ...mapState("MMCFlightControlCenter/uav", ["uav"]),
name() { name() {
return `${this.hangar?.name || ""}机库`; return `${this.uav?.name || ""}`;
// return `${this.hangar?.name || ""}机库无人机`;
}, },
label() { label() {
return this.hangar?.uav?.organizationName || ""; return this.hangar?.uav?.organizationName || "";
......
<template>
<div class="traffic dialog1027" v-interact>
<div class="dialog-header">
<div class="dialog-header__icon" />
<div class="dialog-header__title">交通指引</div>
<div class="dialog-header_close" style="color:#fff" @click="()=>$emit('close')">关闭</div>
</div>
<div class="dialog-content">
<div class="step active">
<div class="step-box">
<div class="step-icon">1</div>
<div class="step-desc">无人机飞往交通事故现场进行拍摄取证</div>
</div>
<div class="btn-box1027">
<div class="btn1027" @click="onTakePhoto">取证</div>
</div>
<div class="imgList mt8" v-if="xcimg">
<el-image
style="width: 110px;height: 88px"
:src="imgApi + xcimg"
fit="cover"
:preview-src-list="[imgApi + xcimg]"
></el-image>
</div>
</div>
<div class="step">
<div class="step-box">
<div class="step-icon">2</div>
<div class="step-desc">激活事故绘制软件并上传事故图</div>
</div>
<div class="btn-box1027">
<div class="btn1027" @click="onActiveApp">激活软件</div>
<el-upload
class="dib"
accept=".png, .jpg, .image, .jpeg"
:action="upLoadApi + '/upload/v2_uploads'"
:on-success="onSuccess"
multiple
name="uploadFiles"
:show-file-list="false"
>
<div class="btn1027" style="margin-right: 0">上传事故图</div>
</el-upload>
</div>
<div class="imgList mt8" v-if="image">
<el-image
style="width: 110px;height: 88px"
:src="imgApi + image"
fit="cover"
:preview-src-list="[imgApi + image]"
></el-image>
</div>
</div>
<div class="step">
<div class="step-box">
<div class="step-icon">3</div>
<div class="step-desc">生成交通事故报告</div>
</div>
<div class="btn-box1027">
<div class="btn1027" @click="onExportReport">导出报告</div>
</div>
</div>
</div>
</div>
</template>
<script>
// import Bus from "@/assets/ligature.js";
import { saveAs } from "file-saver";
import Moment from "moment";
// import API from "@/api";
export default {
props: {
uavId: {
type: String,
default: ""
}
},
data() {
return {
upLoadApi: process.env.VUE_APP_UPLOADS_URL,
imgApi: process.env.VUE_APP_IMG_URL,
imageUrl: [],
imageName: [],
baseList: [],
image: null,
xcimg: null
};
},
computed: {
taskId() {
return this.$store.state.fckernel.taskId;
},
user_info() {
return this.$store.state.user.user_info;
}
},
methods: {
//拍照
async onTakePhoto() {
console.log("uav_take_photo emit");
Bus.$emit("uav_take_photo", {
callback: async blob => {
console.log("uav_take_photo callback");
const moment = new Moment();
const dateTime = moment.format("yyyyMMddhhmmss");
saveAs(blob, `${dateTime}.jpg`);
let fd2 = new FormData();
fd2.append("uploadFile", blob, `拍照.png`);
fd2.append("taskId", this.taskId);
fd2.append("deviceHardId", this.uavId);
let res2 = await API.FCKERNEL.Upload(fd2);
console.log(res2,"urlrel");
this.xcimg = '/uploads'+ res2.fileKey;
this.$message.success("取证成功!");
this.imageUrl.push(this.xcimg);
this.imageName.push('拍照.png');
let res1 = await API.ACCIDENT.createTaskWord({
imageUrl: this.imageUrl,
imageName: this.imageName,
taskId: this.taskId,
baseList: null
});
this.imageName = [];
this.imageUrl = [];
}
});
},
//激活程序
onActiveApp() {
window.open(`TrafficAccident://`, "_blank");
},
//导出报告
onExportReport() {
let url = `${process.env.VUE_APP_BASE_URL}/hawksystemserver/task/exportTaskWord?id=${this.taskId}&FLYINGSESSIONID=${this.user_info.FLYINGSESSIONID}&mmc-identity=${this.user_info["mmc-identity"]}`;
const fileName = url;
window.open(fileName);
},
//图片上传成功
async onSuccess(res, file, fileList) {
console.log("onSuccess", res);
if (res.status == 1) {
this.imageUrl.push(res.data[0].url);
this.imageName.push(res.data[0].name);
this.baseList.push(res.data[0].encode);
this.image = res.data[0].url;
let res1 = await API.ACCIDENT.createTaskWord({
imageUrl: this.imageUrl,
imageName: this.imageName,
taskId: this.taskId,
baseList: this.baseList
});
this.imageName = [];
this.imageUrl = [];
this.baseList = [];
this.$message.success("上传成功");
} else {
this.$message.error(res.msg || "上传失败");
}
}
}
};
</script>
<style lang="scss" scoped>
.traffic {
width: 268px;
}
.dialog-content {
padding: 16px !important;
height: initial !important;
}
.step {
font-size: 14px;
font-family: SourceHanSansCN-Medium, SourceHanSansCN;
font-weight: 500;
color: #fff;
width: 100%;
margin-bottom: 24px;
&:last-child {
margin-bottom: 0;
}
&.active {
.step-icon {
background: #1439ff;
}
}
.step-box {
display: flex;
// justify-content: space-between;
align-items: baseline;
}
.step-icon {
width: 18px;
height: 18px;
background: #515050;
display: flex;
justify-content: center;
align-items: center;
border-radius: 50%;
margin-right: 8px;
flex-shrink: 0;
}
.step-desc {
height: 40px;
line-height: 20px;
}
}
.btn-box1027 {
padding: 0 !important;
justify-content: right;
}
.btn1027 {
padding: 3px 8px;
min-width: 64px;
}
</style>
\ No newline at end of file
<template>
<div class="vm-switch" @mousemove="onMousemove" @mouseleave="onMouseleave">
<div class="vm-switch-btn"></div>
<div class="vm-switch-list" v-show="showMenu">
<div
class="vm-switch-item uav"
:class="{ active: activeIndex === 0 }"
@click="onClickItem(0)"
></div>
<div class="vm-switch-item" :class="{ active: activeIndex === 1 }" @click="onClickItem(1)">舱内</div>
<div class="vm-switch-item" :class="{ active: activeIndex === 2 }" @click="onClickItem(2)">舱外</div>
</div>
</div>
</template>
<script>
export default {
name: "VideoMapSwitch",
data() {
return {
showMenu: false,
activeIndex: -1, // 激活项
};
},
beforeDestroy(){
console.log('hangar videoMapSwitch beforeDestroy');
this.reset();
},
methods: {
onMousemove() {
this.showMenu = true;
clearTimeout(this.handler);
},
onMouseleave() {
this.handler = setTimeout(() => {
this.showMenu = false;
}, 300);
},
onClickItem(i) {
this.reset();
if (this.activeIndex === i) {
this.activeIndex = -1;
} else {
this.activeIndex = i;
let cesiumParentEl = document.querySelector("#layer-container");
let cesiumEl = document.querySelector(".cesium-viewer");
cesiumParentEl.removeChild(cesiumEl);
let parentEl;
let el;
switch (i) {
case 0:
parentEl = document.querySelector("#playerUavParent");
el = document.querySelector("#playerUav");
break;
case 1:
parentEl = document.querySelector("#playInnerParent");
el = document.querySelector("#playInner");
break;
case 2:
parentEl = document.querySelector("#playOutParent");
el = document.querySelector("#playerOuter");
break;
}
parentEl.removeChild(el);
parentEl.appendChild(cesiumEl);
cesiumParentEl.appendChild(el);
}
},
reset() {
let cesiumEl = document.querySelector(".cesium-viewer");
// 判断cesium的父元素是否是layer-container来确定当前是否已经切换, 未切换就退出
if(cesiumEl.parentElement.id === 'layer-container'){
return;
}
let cesiumParentEl = document.querySelector("#layer-container");
let uavParentEl = document.querySelector("#playerUavParent");
let uavEl = document.querySelector("#playerUav");
let innerParentEl = document.querySelector("#playInnerParent");
let innerEl = document.querySelector("#playInner");
let outParentEl = document.querySelector("#playOutParent");
let outEl = document.querySelector("#playerOuter");
cesiumParentEl.innerHTML = "";
uavParentEl.innerHTML = "";
innerParentEl.innerHTML = "";
outParentEl.innerHTML = "";
cesiumParentEl.append(cesiumEl);
uavParentEl.append(uavEl);
innerParentEl.append(innerEl);
outParentEl.append(outEl);
},
},
};
</script>
<style lang="scss" scoped>
.vm-switch {
position: fixed;
left: 73px;
bottom: 30px;
display: flex;
align-items: center;
.vm-switch-btn {
box-sizing: border-box;
width: 48px;
height: 48px;
background-color: #000;
border-radius: 50%;
border: 2px solid #fff;
background-image: url("./assets/images/btn.png");
background-size: 26px 26px;
background-repeat: no-repeat;
background-position: center;
cursor: pointer;
&:hover {
background-image: url("./assets/images/btn-active.png");
}
}
.vm-switch-list {
background: #ffffff;
border-radius: 4px;
gap: 10px;
padding: 7px 9px;
position: relative;
margin-left: 6px;
height: fit-content;
display: flex;
&::before {
content: "";
position: absolute;
left: -6px;
top: 50%;
transform: translate(0, -50%) rotate(-90deg);
background-color: transparent;
width: 0;
height: 0;
border-left: 3px solid transparent;
border-right: 3px solid transparent;
border-bottom: 6px solid #fff;
}
.vm-switch-item {
width: 34px;
height: 34px;
background-color: #000;
font-size: 10px;
display: flex;
justify-content: center;
align-items: center;
color: #fff;
background-repeat: no-repeat;
background-position: center;
border-radius: 2px;
cursor: pointer;
&.active {
color: #3388ff;
}
&.uav {
background-image: url("./assets/images/uav.png");
background-size: 24px 24px;
&.active {
background-image: url("./assets/images/uav-active.png");
}
}
}
}
}
</style>
\ No newline at end of file
...@@ -5,30 +5,6 @@ ...@@ -5,30 +5,6 @@
<div class="left-bar-item__text">任务</div> <div class="left-bar-item__text">任务</div>
</div> </div>
<AirwayList class="task-list" v-if="openTask"></AirwayList> <AirwayList class="task-list" v-if="openTask"></AirwayList>
<!-- <div class="left-bar-item item" @click="onClickAI">
<img class="left-bar-item__icon" src="./assets/images/ai.svg" />
<div class="left-bar-item__text">智能识别</div>
</div>
<div class="ai-list" :class="{ active: openAIList }">
<div class="left-bar-item item" @click.stop="switchAI(0)">
<img class="left-bar-item__icon" src="./assets/images/face.svg" />
<div class="left-bar-item__text">人脸识别</div>
</div>
<div class="left-bar-item item" @click.stop="switchAI(1)">
<img class="left-bar-item__icon" src="./assets/images/car.svg" />
<div class="left-bar-item__text">车辆识别</div>
</div>
<Face v-if="openFace" class="ai-dialog" :uavId="uav.deviceId" @close="openFace = false" />
<Car v-if="openPlate" class="ai-dialog" :uavId="uav.deviceId" @close="openPlate = false" />
<Traffic
v-if="openTraffic"
class="ai-dialog"
:uavId="uav.deviceId"
@close="openTraffic = false"
/>
<Jm v-if="openModeling" :device="device" class="jm-dialog" @close="openModeling = false"></Jm>
</div> -->
<!-- 展示视频 --> <!-- 展示视频 -->
<div class="left-video" :class="{collapse: playerCollapse}" v-if="hangar && showPanel && listCollapse"> <div class="left-video" :class="{collapse: playerCollapse}" v-if="hangar && showPanel && listCollapse">
<div class="collapse-btn" @click="playerCollapse = !playerCollapse"> <div class="collapse-btn" @click="playerCollapse = !playerCollapse">
...@@ -36,58 +12,48 @@ ...@@ -36,58 +12,48 @@
</div> </div>
<div class="left-video-header"> <div class="left-video-header">
<div class="left-video-header__title" @click="listCollapse = false">机库列表</div> <div class="left-video-header__title" @click="openList">机库列表</div>
<div class="nest-name"> <div class="nest-name">
<span class="nest-name__text">{{ hangar.name }}</span> <span class="nest-name__text">{{ hangar.name }}</span>
<span class="nest-name__text">{{ hangar.name }}</span> <span class="nest-name__text">{{ hangar.name }}</span>
</div> </div>
</div> </div>
<div class="left-video-nest"> <div class="left-video-nest">
<div class="player1"> <div id="playInnerParent" class="player1">
<PlayerInner /> <PlayerInner id="playInner" />
</div> </div>
<div class="player2"> <div id="playOutParent" class="player2">
<PlayerOuter /> <PlayerOuter id="playerOuter" />
</div> </div>
<div class="player3"> <div id="playerUavParent" class="player3">
<PlayerUav /> <PlayerUav id="playerUav" />
</div> </div>
</div> </div>
</div> </div>
<VideoMapSwitch ref="videoMapSwitch"></VideoMapSwitch>
</div> </div>
</template> </template>
<script> <script>
import { mapState } from "vuex"; import { mapState } from "vuex";
import Car from "./components/car";
import Face from "./components/face";
import Jm from "./components/Jm";
import AirwayList from "./components/airwayList"; import AirwayList from "./components/airwayList";
import Traffic from "./components/traffic";
import PlayerInner from "./components/player/inner"; import PlayerInner from "./components/player/inner";
import PlayerOuter from "./components/player/outer"; import PlayerOuter from "./components/player/outer";
import PlayerUav from "./components/player/uav"; import PlayerUav from "./components/player/uav";
import VideoMapSwitch from './components/videoMapSwitch';
export default { export default {
name: "ControlLeft", name: "ControlLeft",
components: { components: {
Car,
Jm,
AirwayList, AirwayList,
Traffic,
Face,
PlayerInner, PlayerInner,
PlayerOuter, PlayerOuter,
PlayerUav, PlayerUav,
VideoMapSwitch
}, },
data() { data() {
return { return {
openTask: true, //打开任务 openTask: true, //打开任务
openAIList: false, //打开AI列表
openTraffic: false, //打开交通指引
openFace: false, //打开人脸识别
openPlate: false, //车牌识别
openModeling: false, //打开建模
playerCollapse: false, //收起播放器 playerCollapse: false, //收起播放器
}; };
}, },
...@@ -110,7 +76,6 @@ export default { ...@@ -110,7 +76,6 @@ export default {
watch: { watch: {
hangar(){ hangar(){
this.openTask = false; this.openTask = false;
this.openAIList = false;
this.$nextTick(() => { this.$nextTick(() => {
this.openTask = true; this.openTask = true;
}) })
...@@ -122,52 +87,11 @@ export default { ...@@ -122,52 +87,11 @@ export default {
methods: { methods: {
onClickTask() { onClickTask() {
this.openTask = !this.openTask; this.openTask = !this.openTask;
this.openAIList = false;
this.closeAI();
},
onClickAI() {
this.openTask = false;
this.openAIList = !this.openAIList;
this.closeAI();
},
/**
* 切换AI功能
*/
switchAI(type) {
this.openFace = false;
this.openPlate = false;
this.openTraffic = false;
this.openModeling = false;
switch (type) {
case 0:
this.openFace = !this.openFace;
break;
case 1:
this.openPlate = !this.openPlate;
break;
case 2:
if (this.taskId == null) {
return this.$message.error("暂无绑定任务!");
}
this.openTraffic = !this.openTraffic;
break;
case 3:
this.openModeling = !this.openModeling;
break;
}
},
/**
* 关闭所有ai
*/
closeAI() {
this.openFace = false;
this.openPlate = false;
this.openTraffic = false;
this.openModeling = false;
}, },
openList(){
this.listCollapse = false;
this.$refs.videoMapSwitch.reset();
}
}, },
}; };
</script> </script>
...@@ -176,14 +100,14 @@ export default { ...@@ -176,14 +100,14 @@ export default {
.task-list { .task-list {
position: absolute; position: absolute;
left: 60px; left: 60px;
top: -30px; top: 0px;
cursor: initial; cursor: initial;
} }
.control-left { .control-left {
position: absolute; position: absolute;
z-index: 2; z-index: 2;
left: 430px; left: 430px;
top: 13%; top: 28px;
transition: 0.3s; transition: 0.3s;
&.collapse { &.collapse {
...@@ -369,7 +293,7 @@ export default { ...@@ -369,7 +293,7 @@ export default {
} }
.player3 { .player3 {
width: 100%; width: 100%;
height: 240; height: 235px;
} }
} }
} }
......
<!-- 飞控地图选择 --> <!-- 飞控地图选择 -->
<template> <template>
<div class="map-switch"> <div class="map-switch" @mousemove="onMousemove" @mouseleave="onMouseleave">
<div class="map-switch-wrap cp" @click="change" @mouseout="likai"> <div class="map-switch-btn">
<div class="map-item map-item-satellite"></div> <div class="map-item" :class="selectIconClass"></div>
</div> </div>
<div class="changeMapBox pa cp"> <div class="map-list" v-show="showMenu">
<div class="dise" @mouseout="likai"> <div class="map-item">
<div <div
class="bai" class="dim"
:class="{ active: !is_3d }" :class="{ active: !is_3d }"
v-show="!is_3d" v-show="!is_3d"
@click="handle_change_3d(true)" @click="handle_change_3d(true)"
>2D</div> >2D</div>
<div <div
class="bai" class="dim"
:class="{ active: is_3d }" :class="{ active: is_3d }"
v-show="is_3d" v-show="is_3d"
@click="handle_change_3d(false)" @click="handle_change_3d(false)"
>3D</div> >3D</div>
</div> </div>
<div v-for="item in tabs" :key="item.id" class="dise" @mousemove="jinru(item.id)"> <div v-for="item in tabs" :key="item.id" class="map-item" @click="onSelect(item.class_name)">
<div <el-tooltip effect="dark" :content="item.name" placement="top-start">
:class="{ <div
'map-item': 1, class="map-item"
[item.class_name]: 1, :class="item.class_name"
}" @click="handle_change(item.id)"
@click="handle_change(item.id)" style="position: relative; overflow: hidden"
style="position: relative; overflow: hidden" ></div>
> </el-tooltip>
<div class="zimu" :class="{ sh: numId == item.id + 1 }">{{ item.name }}</div>
</div>
</div> </div>
</div> </div>
</div> </div>
...@@ -42,8 +40,8 @@ export default { ...@@ -42,8 +40,8 @@ export default {
components: {}, components: {},
data() { data() {
return { return {
numId: null, //鼠标悬浮效果 selectIconClass: "map-item-satellite",
active: false, showMenu: false,
is_3d: true, is_3d: true,
current: 1, current: 1,
tabs: [ tabs: [
...@@ -68,6 +66,7 @@ export default { ...@@ -68,6 +66,7 @@ export default {
class_name: "map-item-night-blue", class_name: "map-item-night-blue",
}, },
], ],
handler: null,
}; };
}, },
computed: { computed: {
...@@ -85,12 +84,18 @@ export default { ...@@ -85,12 +84,18 @@ export default {
}, },
watch: {}, watch: {},
methods: { methods: {
// 鼠标悬浮效果 onMousemove() {
jinru(id) { this.showMenu = true;
this.numId = id + 1; clearTimeout(this.handler);
},
onMouseleave() {
this.handler = setTimeout(() => {
this.showMenu = false;
}, 300);
}, },
likai() { // 选中的图标
this.numId = null; onSelect(className) {
this.selectIconClass = className;
}, },
handle_change_3d(bool) { handle_change_3d(bool) {
this.is_3d = bool; this.is_3d = bool;
...@@ -118,16 +123,6 @@ export default { ...@@ -118,16 +123,6 @@ export default {
} }
console.log("this.cesiumImagesLayers", this.cesiumImagesLayers, id); console.log("this.cesiumImagesLayers", this.cesiumImagesLayers, id);
}, },
change() {
this.active = !this.active;
// global_leyers.forEach(promise => {
// promise.then((layer) =>{
// layer.visible = this.active;
// });
// })
// base_layer.BASIC && (base_layer.BASIC.show = !this.active)
// base_layer.SATELLITE && (base_layer.SATELLITE.show = this.active)
},
}, },
}; };
</script> </script>
...@@ -136,89 +131,40 @@ export default { ...@@ -136,89 +131,40 @@ export default {
.map-switch { .map-switch {
z-index: 1; z-index: 1;
bottom: 30px; bottom: 30px;
.changeMapBox {
position: absolute;
width: 201px;
height: 48px;
background: rgba(9, 32, 87, 0.7);
border: 1px solid #43deff;
left: -159px;
margin-top: 3px;
display: none;
justify-content: space-around;
align-items: center;
// display: flex;
.map-item {
width: 30px;
height: 30px;
color: #04d5da;
text-align: right;
line-height: 49px;
// margin-top: 5px;
border-radius: 4px;
font-size: 9px;
border: 1px solid #eee;
cursor: pointer;
}
.map-item-satellite {
background: url(./assets/images/3d.png) center no-repeat;
}
.map-item-street {
background: url(./assets/images/2d.png) center no-repeat;
}
.map-item-night-blue {
background: url(./assets/images/night-blue.png) center no-repeat;
}
.map-item-3d {
background: url(./assets/images/3d.png) center no-repeat;
}
.map-item-2d {
background: url(./assets/images/2d.png) center no-repeat;
}
}
position: absolute; position: absolute;
right: 14px; right: 14px;
width: 48px;
width: 104px; height: 48px;
height: 78px;
transition: 0.2s; transition: 0.2s;
transform: translateX(0); transform: translateX(0);
.map-switch-wrap { .map-switch-btn {
cursor: pointer;
position: absolute; position: absolute;
right: 0; right: 0;
min-width: 52px; width: 100%;
height: 52px; height: 100%;
border-radius: 2px; border-radius: 2px;
overflow: hidden; overflow: hidden;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
transition: width 0.25s;
&.active { &.active {
width: 166px; width: 166px;
} }
.map-item { .map-item {
width: 52px;
height: 52px;
box-sizing: border-box; box-sizing: border-box;
border-radius: 50%; border-radius: 50%;
border: 3px solid #fff; border: 3px solid #fff;
position: relative; position: relative;
width: 100%;
height: 100%;
&.map-item-satellite { &.map-item-satellite {
// background: url(./assets/images/3d.png) center no-repeat; background: url(./assets/images/3d.png) center no-repeat;
background: url("./assets/images/ditu_icon.png") center no-repeat; // background: url("./assets/images/ditu_icon.png") center no-repeat;
background-size: 112% 112%; background-size: 112% 112%;
} }
...@@ -259,103 +205,56 @@ export default { ...@@ -259,103 +205,56 @@ export default {
} }
} }
.waterbox { .map-list {
height: 48px;
width: 48px;
position: absolute; position: absolute;
top: 130px; background: #fff;
right: 0px; right: 60px;
border: 1px solid #04d5da;
background: rgba(22, 29, 45, 0.7);
color: #43deff;
font-size: 20px;
line-height: 48px;
}
.water_quality {
width: 459px;
height: 418px;
background: rgba(0, 23, 79, 0.7);
box-shadow: 0 2px 4px 0 rgba(1, 162, 255, 0.35),
inset 0 0 40px 0 rgba(0, 184, 255, 0.5);
border-radius: 13px;
}
}
.map-switch:hover {
.changeMapBox {
display: flex; display: flex;
} justify-content: space-around;
} align-items: center;
padding: 6px;
gap: 6px;
.dise { // display: flex;
width: 34px; .map-item {
height: 34px; width: 42px;
border-radius: 4px; height: 36px;
display: flex; cursor: pointer;
align-items: center;
justify-content: center;
background: #fff;
}
.bai { .dim {
text-align: center; width: 100%;
line-height: 30px; height: 100%;
font-size: 14px; font-size: 14px;
color: #ffffff !important; color: #ffffff;
font-weight: 700; font-weight: 700;
width: 30px; border-radius: 4px;
height: 30px; background: #000000;
// border: 2px solid #fff; cursor: pointer;
border-radius: 4px; display: flex;
// margin: 5px 0 0 0; justify-content: center;
background: #000000; align-items: center;
cursor: pointer; }
} }
.zimu { .map-item-satellite {
position: absolute; background: url(./assets/images/3d.png) center no-repeat;
left: 0; }
bottom: 0;
height: 18px;
opacity: 0.64;
background: #fff;
border-radius: 0 0 4px 4px;
width: 100%;
text-align: center;
font-size: 12px;
font-family: MicrosoftYaHei;
color: #000;
line-height: 16px;
font-weight: 400;
display: none;
pointer-events: auto;
}
@keyframes fr { .map-item-street {
from { background: url(./assets/images/2d.png) center no-repeat;
bottom: -60%; }
}
to { .map-item-night-blue {
bottom: 0%; background: url(./assets/images/night-blue.png) center no-repeat;
} }
}
.sh { .map-item-3d {
display: block; background: url(./assets/images/3d.png) center no-repeat;
animation: fr 1s linear; }
animation-fill-mode: forwards;
pointer-events: auto;
}
.anniu { .map-item-2d {
width: 48px; background: url(./assets/images/2d.png) center no-repeat;
height: 48px; }
background: #fff; }
border-radius: 50%;
display: flex;
justify-content: center;
align-content: center;
} }
</style> </style>
\ No newline at end of file
<template>
<div class="car dialog1027" v-interact>
<div class="dialog-header">
<div class="dialog-header__icon" />
<div class="dialog-header__title">
快速建模
</div>
<div class="dialog-header_close" style="color:#fff" @click="() => $emit('close')">关闭</div>
</div>
<div class="dialog-content w267">
<el-cascader size="mini" filterable popper-class="cpt-observe-mspace-dashboard-airway_popper" v-model="taskCateId"
:options="airway_list" clearable :show-all-levels="false" placeholder="请选择任务" :props="{
children: 'children',
label: 'taskTitle',
value: 'id',
emitPath: false,
}">
<template slot-scope="{ data }">
<el-tooltip :disabled="data.taskTitle.length < 11" class="item" effect="dark" :content="data.taskTitle"
placement="top-start">
<span>{{ data.taskTitle }}</span>
</el-tooltip>
</template>
</el-cascader>
<el-select class="mt10" v-model="type" size="mini" placeholder="请选择类型">
<el-option label="图片" :value="0"></el-option>
<el-option label="视频" :value="1"></el-option>
</el-select>
<div class="jcsb w267 h30 mt30">
<div class="dec mt5">1</div><span class="dib cf ml10 lh30"> 快速建模</span>
<div class="btn fr cf h30 lh30 w80 cp" @click="jmFn(1)">启动</div>
</div>
<div class="jcsb mt18 w267 h30">
<div class="dec mt5">2</div><span class="dib cf lh30 ml10">数据处理</span>
<div class="btn fr cf h30 lh30 w80 cp" @click="jmFn(2)">启动</div>
</div>
</div>
</div>
</template>
<script>
// import API from '@/api';
export default {
props: {
device: {
type: Object,
default: () => ({})
},
},
data() {
return {
imgUrl: process.env.VUE_APP_IMG_URL,
list: [],
type: null,
taskCateId: null,
airway_list: []
}
},
created() {
this.list_airway();
},
methods: {
jmFn(num) {
let { deviceHardId } = this.device
if (num == 1) {
let a = document.createElement("a");
a.href = `MMCEagleEye:// `
a.click()
}
else {
if(!this.taskCateId) return this.$message.warning('请选择任务!')
if(this.type==null ) return this.$message.warning('请选择类型!')
let a = document.createElement("a");
a.href = `MMCPosTool://&deviceId=${deviceHardId}enddeviceId&taskId=${this.taskCateId}endtaskId&type=${this.type}endtype`
a.click()
}
},
async list_airway() {
/* let res = await API.AIRWAY.getApprovedTask();
if (res) {
let jqList = [],
ctList = [],
lsList = [];
for (let i = 0; i < res.length; i++) {
if (res[i].taskCateId == 1) {
jqList.push(res[i]);
}
if (res[i].taskCateId == 2) {
ctList.push(res[i]);
}
if (res[i].taskCateId == 3) {
lsList.push(res[i]);
}
}
let airway_list = [
{
id: "警情任务",
taskTitle: "警情任务",
children: jqList,
},
{
id: "常态任务",
taskTitle: "常态任务",
children: ctList,
},
{
id: "临时任务",
taskTitle: "临时任务",
children: lsList,
},
];
this.airway_list = airway_list;
} */
},
}
}
</script>
<style lang="scss" scoped>
.car {
width: 268px;
}
.dialog-content {
padding: 20px 14px 12px;
max-height: 461px;
overflow: auto;
.dec {
width: 20px;
height: 20px;
line-height: 20px;
text-align: center;
border-radius: 50%;
background: #06199b;
}
.btn {
text-align: center;
border: 1px #315ec7 solid;
border-radius: 3px;
background-color: #02173d;
font-size: 14px;
font-family: MicrosoftYaHei;
color: #D2D9FF;
cursor: pointer;
}
.btn:hover {
background: #06199b;
}
}
.car-img {
position: relative;
width: 100%;
height: 135px;
.car-img__img {
width: 100%;
height: 100%;
}
.car-img__label {
position: absolute;
bottom: 0;
width: 100%;
height: 28px;
display: flex;
justify-content: center;
align-items: center;
font-size: 14px;
color: #aee9ff;
font-family: MicrosoftYaHeiUI;
}
}
.car-form {
padding: 10px 0 0;
font-size: 14px;
font-family: MicrosoftYaHei;
color: #fff;
>div {
margin-bottom: 8px;
&:last-child {
margin-bottom: 0;
}
}
}
.car-item {
margin-bottom: 24px;
}
</style>
\ No newline at end of file
<template>
<div class="car dialog1027" v-interact>
<div class="dialog-header">
<div class="dialog-header__icon" />
<div class="dialog-header__title">
车辆识别
</div>
<div class="dialog-header_close" style="color:#fff" @click="()=>$emit('close')">关闭</div>
</div>
<div class="dialog-content" v-infinite-scroll="load">
<template v-if="list.length > 0" >
<div v-for="(item, i) in list" :key="i" class="car-item">
<div class="car-img">
<img class="car-img__img" :src="imgUrl + item.imageUrl" />
<div class="car-img__label">{{ item.plateNum || '暂无' }}</div>
</div>
<div class="car-form">
<div>地点:{{ item.addr || item.findAddress || '暂无' }}</div>
<div>时间:{{ item.findTime || '暂无' }}</div>
</div>
</div>
</template>
<template v-else>
<div style="text-align: center; width: 100%;">暂无数据</div>
</template>
</div>
</div>
</template>
<script>
// import API from '@/api';
export default {
props: {
uavId: {
type: String,
default: ''
}
},
data(){
return {
imgUrl: process.env.VUE_APP_IMG_URL,
list: [],
pageNo: 1,
pageSize: 3,
}
},
created(){
this.getCarList()
},
methods: {
async load(){
this.pageNo++
/* let res = await API.HOME.getflightvideoMsg({
uavId: this.uavId,
pageNo: this.pageNo,
pageSize: this.pageSize
})
for(let i = 0; i < res.length; i++){
let item = res[i];
if(item.lon){
let address = await API.MAP.AiRegeo({
location: `${item.lon},${item.lat}`
})
item.addr = address.province.value + address.city.value + address.dist.value + address.road.roadname + address.poi;
}
this.list.push(res[i])
}
console.log(this.list,"list"); */
},
async getCarList(){
if(!this.uavId){
this.$message.error('请选择无人机');
return;
}
let res = await API.HOME.getflightvideoMsg({
uavId: this.uavId,
pageNo: this.pageNo,
pageSize: this.pageSize
})
for(let i = 0; i < res.length; i++){
let item = res[i];
if(item.lon){
let address = await API.MAP.AiRegeo({
location: `${item.lon},${item.lat}`
})
item.addr = address.province.value + address.city.value + address.dist.value + address.road.roadname + address.poi;
}
this.list.push(res[i])
}
// this.list = res || [];
}
}
}
</script>
<style lang="scss" scoped>
.car{
width: 268px;
}
.dialog-content{
padding: 20px 14px 12px;
max-height: 461px;
overflow: auto;
}
.car-img{
position: relative;
width: 100%;
height: 135px;
.car-img__img {
width: 100%;
height: 100%;
}
.car-img__label {
position: absolute;
bottom: 0;
width: 100%;
height: 28px;
display: flex;
justify-content: center;
align-items: center;
font-size: 14px;
color: #aee9ff;
font-family: MicrosoftYaHeiUI;
}
}
.car-form{
padding: 10px 0 0;
font-size: 14px;
font-family: MicrosoftYaHei;
color: #fff;
>div {
margin-bottom: 8px;
&:last-child {
margin-bottom: 0;
}
}
}
.car-item{
margin-bottom: 24px;
}
</style>
\ No newline at end of file
<template>
<div class="face dialog1027" v-interact>
<div class="dialog-header">
<div class="dialog-header__icon" />
<div class="dialog-header__title">
人脸识别
</div>
<div class="dialog-header_close" style="color:#fff" @click="()=>$emit('close')">关闭</div>
</div>
<div class="dialog-content" v-infinite-scroll="load">
<template v-if="list.length > 0">
<div class="result" v-for="(item, i) in list" :key="i">
<div class="rate-box">
<div class="rate-img">
<img :src="imgUrl + item.recordImageUrl" />
</div>
<div class="rate-round">
<div class="rate-round__value">{{ Number(item.similarity).toFixed(2) }}%</div>
<div class="rate-routd__text" @click="onDetail(item)">详情</div>
</div>
<div class="rate-img rate-img--contrary">
<img :src="imgUrl + item.snapImageUrl" />
</div>
</div>
<div class="rate-form" v-if="item.show">
<div class="rate-form-item">
<div class="rate-form-item__label">
姓名:
</div>
<div class="rate=form-item__value">
{{ item.userName || '暂无' }}
</div>
</div>
<div class="rate-form-item">
<div class="rate-form-item__label">
出生年份:
</div>
<div class="rate=form-item__value">
{{ item.birthday || '暂无' }}
</div>
</div>
<div class="rate-form-item">
<div class="rate-form-item__label">
发现时间:
</div>
<div class="rate=form-item__value">
{{ item.occurTime || '暂无' }}
</div>
</div>
<div class="rate-form-item">
<div class="rate-form-item__label">
发现地点:
</div>
<div class="rate=form-item__value">
{{ item.addr || item.address || '暂无' }}
</div>
</div>
<div class="rate-form-item">
<div class="rate-form-item__label">
身份证号:
</div>
<div class="rate=form-item__value">
{{ item.idCard || '暂无' }}
</div>
</div>
<div class="rate-form-item">
<div class="rate-form-item__label">
AI识别:
</div>
<div class="rate=form-item__value">
<template v-if="item.labels && item.labels.length">
<div class="round-border" v-for="(label, j) in item.labels" :key="j" >
{{label}}
</div>
</template>
<template v-else>
暂无
</template>
</div>
</div>
</div>
</div>
</template>
<template v-else>
<div style="text-align: center; width: 100%;">暂无数据</div>
</template>
</div>
</div>
</template>
<script>
// import API from '@/api';
export default {
props: {
uavId: {
type: String,
default: ''
}
},
data(){
return {
imgUrl: process.env.VUE_APP_IMG_URL,
list: [
/* {
userName: '人热二',
birthday: '1888-02-11',
occurTime: '2022-02-30 08:22:14',
address: '深圳市南山区',
idCard: '112313123123',
labels: ['省内人员'],
similarity: '63',
img: '',
imgs: '',
show: true
} */
],
pageNo: 1,
pageSize: 4,
}
},
created(){
this.getFaceList();
},
methods: {
async load(){
this.pageNo++
/* let res = await API.HOME.getFaceuavvideoMsg({
uavId: this.uavId,
pageNo: this.pageNo,
pageSize: this.pageSize
})
for(let i = 0; i < res.length; i++){
let item = res[i];
if(item.longi){
let address = await API.MAP.AiRegeo({
location: `${item.longi},${item.lati}`
})
item.addr = address.province.value + address.city.value + address.dist.value + address.road.roadname + address.poi;
}
this.list.push(res[i])
}
console.log(this.list,"list"); */
},
async getFaceList(){
if(!this.uavId){
this.$message.error('请选择无人机');
return;
}
let res = await API.HOME.getFaceuavvideoMsg({
uavId: this.uavId,
pageNo: this.pageNo,
pageSize: this.pageSize
}) || [];
for(let i = 0; i < res.length; i++){
let item = res[i];
if(item.longi){
let address = await API.MAP.AiRegeo({
location: `${item.longi},${item.lati}`
})
item.addr = address.province.value + address.city.value + address.dist.value + address.road.roadname + address.poi;
}
this.list.push(res[i])
}
// this.list = res || [];
},
onDetail(item){
this.$set(item, 'show', !item.show);
}
}
}
</script>
<style lang="scss" scoped>
.face{
width: 268px;
}
.dialog-content{
padding: 14px;
cursor: initial;
max-height: 461px;
overflow-y: auto;
}
.result{
width: 100%;
margin-top: 27px;
&:first-child {
margin-top: 0;
}
}
.rate-box{
display: flex;
align-items: center;
position: relative;
width: 100%;
.rate-img{
flex: 1;
height: 75px;
background-image: url('../../assets/images/faceAI_border1.png');
background-size: 100% 100%;
padding: 7px;
display: flex;
align-items: center;
&.rate-img--contrary {
background-image: url('../../assets/images/faceAI_border2.png');
justify-content: right;
}
img {
width: 70px;
height: 70px;
border-radius: 7px;
overflow: hidden;
}
}
.rate-round{
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.rate-round__value{
color: #fb799d;
font-size: 14px;
font-family: MicrosoftYaHei;
}
.rate-routd__text{
cursor: pointer;
font-size: 12px;
color: #b9d7f0;
font-family: MicrosoftYaHei;
transform: scale(0.9);
margin-top: 3px;
}
}
}
.rate-form{
margin-top: 10px;
font-size: 14px;
font-family: MicrosoftYaHei;
color: #fff;
.rate-form-item {
margin-bottom: 12px;
display: flex;
&:last-child {
margin-bottom: 0;
}
.rate-form-item__label {
width: 70px;
text-align: right;
flex-shrink: 0;
}
.rate-form-item__value {
}
}
}
.round-border{
padding: 2px 8px;
border-radius: 11px;
border: 1px solid #ff4a4a;
color: #ff4a4a;
font-size: 14px;
font-family: MicrosoftYaHei;
}
</style>
\ No newline at end of file
<template>
<div class="traffic dialog1027" v-interact>
<div class="dialog-header">
<div class="dialog-header__icon" />
<div class="dialog-header__title">交通指引</div>
<div class="dialog-header_close" style="color:#fff" @click="()=>$emit('close')">关闭</div>
</div>
<div class="dialog-content">
<div class="step active">
<div class="step-box">
<div class="step-icon">1</div>
<div class="step-desc">无人机飞往交通事故现场进行拍摄取证</div>
</div>
<div class="btn-box1027">
<div class="btn1027" @click="onTakePhoto">取证</div>
</div>
<div class="imgList mt8" v-if="xcimg">
<el-image
style="width: 110px;height: 88px"
:src="imgApi + xcimg"
fit="cover"
:preview-src-list="[imgApi + xcimg]"
></el-image>
</div>
</div>
<div class="step">
<div class="step-box">
<div class="step-icon">2</div>
<div class="step-desc">激活事故绘制软件并上传事故图</div>
</div>
<div class="btn-box1027">
<div class="btn1027" @click="onActiveApp">激活软件</div>
<el-upload
class="dib"
accept=".png, .jpg, .image, .jpeg"
:action="upLoadApi + '/upload/v2_uploads'"
:on-success="onSuccess"
multiple
name="uploadFiles"
:show-file-list="false"
>
<div class="btn1027" style="margin-right: 0">上传事故图</div>
</el-upload>
</div>
<div class="imgList mt8" v-if="image">
<el-image
style="width: 110px;height: 88px"
:src="imgApi + image"
fit="cover"
:preview-src-list="[imgApi + image]"
></el-image>
</div>
</div>
<div class="step">
<div class="step-box">
<div class="step-icon">3</div>
<div class="step-desc">生成交通事故报告</div>
</div>
<div class="btn-box1027">
<div class="btn1027" @click="onExportReport">导出报告</div>
</div>
</div>
</div>
</div>
</template>
<script>
// import Bus from "@/assets/ligature.js";
import { saveAs } from "file-saver";
import Moment from "moment";
// import API from "@/api";
export default {
props: {
uavId: {
type: String,
default: ""
}
},
data() {
return {
upLoadApi: process.env.VUE_APP_UPLOADS_URL,
imgApi: process.env.VUE_APP_IMG_URL,
imageUrl: [],
imageName: [],
baseList: [],
image: null,
xcimg: null
};
},
computed: {
taskId() {
return this.$store.state.fckernel.taskId;
},
user_info() {
return this.$store.state.user.user_info;
}
},
methods: {
//拍照
async onTakePhoto() {
console.log("uav_take_photo emit");
Bus.$emit("uav_take_photo", {
callback: async blob => {
console.log("uav_take_photo callback");
const moment = new Moment();
const dateTime = moment.format("yyyyMMddhhmmss");
saveAs(blob, `${dateTime}.jpg`);
let fd2 = new FormData();
fd2.append("uploadFile", blob, `拍照.png`);
fd2.append("taskId", this.taskId);
fd2.append("deviceHardId", this.uavId);
let res2 = await API.FCKERNEL.Upload(fd2);
console.log(res2,"urlrel");
this.xcimg = '/uploads'+ res2.fileKey;
this.$message.success("取证成功!");
this.imageUrl.push(this.xcimg);
this.imageName.push('拍照.png');
let res1 = await API.ACCIDENT.createTaskWord({
imageUrl: this.imageUrl,
imageName: this.imageName,
taskId: this.taskId,
baseList: null
});
this.imageName = [];
this.imageUrl = [];
}
});
},
//激活程序
onActiveApp() {
window.open(`TrafficAccident://`, "_blank");
},
//导出报告
onExportReport() {
let url = `${process.env.VUE_APP_BASE_URL}/hawksystemserver/task/exportTaskWord?id=${this.taskId}&FLYINGSESSIONID=${this.user_info.FLYINGSESSIONID}&mmc-identity=${this.user_info["mmc-identity"]}`;
const fileName = url;
window.open(fileName);
},
//图片上传成功
async onSuccess(res, file, fileList) {
console.log("onSuccess", res);
if (res.status == 1) {
this.imageUrl.push(res.data[0].url);
this.imageName.push(res.data[0].name);
this.baseList.push(res.data[0].encode);
this.image = res.data[0].url;
let res1 = await API.ACCIDENT.createTaskWord({
imageUrl: this.imageUrl,
imageName: this.imageName,
taskId: this.taskId,
baseList: this.baseList
});
this.imageName = [];
this.imageUrl = [];
this.baseList = [];
this.$message.success("上传成功");
} else {
this.$message.error(res.msg || "上传失败");
}
}
}
};
</script>
<style lang="scss" scoped>
.traffic {
width: 268px;
}
.dialog-content {
padding: 16px !important;
height: initial !important;
}
.step {
font-size: 14px;
font-family: SourceHanSansCN-Medium, SourceHanSansCN;
font-weight: 500;
color: #fff;
width: 100%;
margin-bottom: 24px;
&:last-child {
margin-bottom: 0;
}
&.active {
.step-icon {
background: #1439ff;
}
}
.step-box {
display: flex;
// justify-content: space-between;
align-items: baseline;
}
.step-icon {
width: 18px;
height: 18px;
background: #515050;
display: flex;
justify-content: center;
align-items: center;
border-radius: 50%;
margin-right: 8px;
flex-shrink: 0;
}
.step-desc {
height: 40px;
line-height: 20px;
}
}
.btn-box1027 {
padding: 0 !important;
justify-content: right;
}
.btn1027 {
padding: 3px 8px;
min-width: 64px;
}
</style>
\ No newline at end of file
<template>
<div class="vm-switch" @mousemove="onMousemove" @mouseleave="onMouseleave">
<div class="vm-switch-btn"></div>
<div class="vm-switch-list" v-show="showMenu">
<div
class="vm-switch-item uav"
:class="{ active: activeIndex === 0 }"
@click="onClickItem(0)"
></div>
</div>
<div id="uavPlayerParent" v-show="activeIndex === 0" class="uav-video"></div>
</div>
</template>
<script>
export default {
name: "VideoMapSwitch",
data() {
return {
showMenu: false,
activeIndex: -1,
};
},
beforeDestroy(){
console.log('uav videoMapSwitch beforeDestroy');
this.reset();
},
methods: {
onMousemove() {
this.showMenu = true;
clearTimeout(this.handler);
},
onMouseleave() {
this.handler = setTimeout(() => {
this.showMenu = false;
}, 300);
},
onClickItem(i) {
this.reset();
if (this.activeIndex === i) {
this.activeIndex = -1;
} else {
this.activeIndex = i;
let cesiumParentEl = document.querySelector("#layer-container");
let cesiumEl = document.querySelector(".cesium-viewer");
cesiumParentEl.removeChild(cesiumEl);
let parentEl;
let el;
switch (i) {
case 0:
parentEl = document.querySelector("#uavPlayerParent");
el = document.querySelector("#uavPlayer");
uavPlayerWrap.style.display = 'none';
break;
}
parentEl.appendChild(cesiumEl);
cesiumParentEl.appendChild(el);
}
},
reset() {
let cesiumEl = document.querySelector(".cesium-viewer");
// 判断cesium的父元素是否是layer-container来确定当前是否已经切换, 未切换就退出
if(cesiumEl.parentElement.id === 'layer-container'){
return;
}
let cesiumParentEl = document.querySelector("#layer-container");
let uavParentEl = document.querySelector("#uavPlayerParent");
let uavEl = document.querySelector("#uavPlayer");
let uavPlayerWrap = document.querySelector('#uavPlayerWrap');
let uavPlayerParent = uavPlayerWrap?.querySelector('.cpt_video');
cesiumParentEl.innerHTML = "";
uavParentEl.innerHTML = "";
cesiumParentEl.append(cesiumEl);
uavPlayerParent.append(uavEl);
uavPlayerWrap.style.display = '';
},
},
};
</script>
<style lang="scss" scoped>
.vm-switch {
position: fixed;
left: 73px;
bottom: 30px;
display: flex;
align-items: center;
.vm-switch-btn {
box-sizing: border-box;
width: 48px;
height: 48px;
background-color: #000;
border-radius: 50%;
border: 2px solid #fff;
background-image: url("./assets/images/btn.png");
background-size: 26px 26px;
background-repeat: no-repeat;
background-position: center;
cursor: pointer;
&:hover {
background-image: url("./assets/images/btn-active.png");
}
}
.vm-switch-list {
background: #ffffff;
border-radius: 4px;
gap: 10px;
padding: 7px 9px;
position: relative;
margin-left: 6px;
height: fit-content;
display: flex;
&::before {
content: "";
position: absolute;
left: -6px;
top: 50%;
transform: translate(0, -50%) rotate(-90deg);
background-color: transparent;
width: 0;
height: 0;
border-left: 3px solid transparent;
border-right: 3px solid transparent;
border-bottom: 6px solid #fff;
}
.vm-switch-item {
width: 34px;
height: 34px;
background-color: #000;
font-size: 10px;
display: flex;
justify-content: center;
align-items: center;
color: #fff;
background-repeat: no-repeat;
background-position: center;
border-radius: 2px;
cursor: pointer;
&.active {
color: #3388ff;
}
&.uav {
background-image: url("./assets/images/uav.png");
background-size: 24px 24px;
&.active {
background-image: url("./assets/images/uav-active.png");
}
}
}
}
.uav-video {
position: absolute;
bottom: 100px;
left: 0px;
width: 388px;
height: 220px;
}
}
</style>
\ No newline at end of file
...@@ -6,50 +6,22 @@ ...@@ -6,50 +6,22 @@
</div> </div>
<TaskList class="task-list" v-if="!useAirway && openTask"></TaskList> <TaskList class="task-list" v-if="!useAirway && openTask"></TaskList>
<AirwayList class="task-list" v-if="useAirway && openTask"></AirwayList> <AirwayList class="task-list" v-if="useAirway && openTask"></AirwayList>
<!-- <div class="left-bar-item item" @click="onClickAI"> <VideoMapSwitch ref="videoMapSwitch"></VideoMapSwitch>
<img class="left-bar-item__icon" src="./assets/images/ai.svg" />
<div class="left-bar-item__text">智能识别</div>
</div>
<div class="ai-list" :class="{ active: openAIList }">
<div class="left-bar-item item" @click.stop="switchAI(0)">
<img class="left-bar-item__icon" src="./assets/images/face.svg" />
<div class="left-bar-item__text">人脸识别</div>
</div>
<div class="left-bar-item item" @click.stop="switchAI(1)">
<img class="left-bar-item__icon" src="./assets/images/car.svg" />
<div class="left-bar-item__text">车辆识别</div>
</div>
<Face v-if="openFace" class="ai-dialog" :uavId="uav.deviceId" @close="openFace = false" />
<Car v-if="openPlate" class="ai-dialog" :uavId="uav.deviceId" @close="openPlate = false" />
<Traffic
v-if="openTraffic"
class="ai-dialog"
:uavId="uav.deviceId"
@close="openTraffic = false"
/>
<Jm v-if="openModeling" :device="device" class="jm-dialog" @close="openModeling = false"></Jm>
</div> -->
</div> </div>
</template> </template>
<script> <script>
import { mapState } from "vuex"; import { mapState } from "vuex";
import Car from "./components/car";
import Face from "./components/face";
import Jm from "./components/Jm";
import TaskList from "./components/taskList"; import TaskList from "./components/taskList";
import AirwayList from "./components/airwayList"; import AirwayList from "./components/airwayList";
import Traffic from "./components/traffic"; import VideoMapSwitch from './components/videoMapSwitch';
export default { export default {
name: "ControlLeft", name: "ControlLeft",
components: { components: {
Car,
Jm,
TaskList, TaskList,
AirwayList, AirwayList,
Traffic, VideoMapSwitch
Face,
}, },
data() { data() {
return { return {
...@@ -85,6 +57,9 @@ export default { ...@@ -85,6 +57,9 @@ export default {
this.openTask = true; this.openTask = true;
}); });
}, },
listCollapse(){
this.$refs.videoMapSwitch.reset();
}
}, },
methods: { methods: {
onClickTask() { onClickTask() {
......
...@@ -86,10 +86,10 @@ export default { ...@@ -86,10 +86,10 @@ export default {
if (value.vUrl == oldVal?.vUrl) { if (value.vUrl == oldVal?.vUrl) {
return; return;
} }
// console.log('livenvr', value) console.log('livenvr', value, oldVal)
if (value && value.vUrl) { if (value && value.vUrl) {
this.$nextTick(() => { this.$nextTick(() => {
this.$refs["livePlayer"].play(); this.$refs["livePlayer"]?.play();
}); });
} }
}, },
......
<template> <template>
<!-- 清流融合 --> <!-- 清流融合 -->
<div class="player" :class="big" v-interact> <div id="uavPlayerWrap" class="player" :class="big" v-interact>
<div ref="video" class="video-wrap" @dblclick="screen"> <div ref="video" class="video-wrap" @dblclick="screen">
<div class="cpt_video" @click="lensControl" v-if="showPlayer"> <div class="cpt_video" @click="lensControl" v-if="showPlayer">
<Obstacle v-if="!isStatus"></Obstacle> <Obstacle v-if="!isStatus"></Obstacle>
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
></videoModelChange>--> ></videoModelChange>-->
<components <components
id="uavPlayer"
:is="playerCom" :is="playerCom"
:smallFPV="smallFPV" :smallFPV="smallFPV"
:isStatus="isStatus" :isStatus="isStatus"
......
import axios from 'axios';
// import API from "../../../../../api";
export default {
interfaceAI(url) {
let blob = this.screenShot();
let data = {
image: null
}
blobToBase64(blob, async (base64DataUrl) => {
data.image = base64DataUrl
let res = await axios.post("http://32.128.6.151:9090/api/inflet/v1/tasks/3b2c435f-0652-418c-82d0-37efed27e9c1/predict", data)
// console.log(res);
console.log(res.data.data,"swiming");
// if(this.indexswim == 10){
if (res.data.data.targets && res.data.data.targets.length > 0) {
clearInterval(this.AISetInterval)
this.AISetInterval = null
// this.$emit("fn", {data: "POSITION",type: 513});
// if (this.lineLableName.includes("河道")) {
this.$emit("AIDialog", true, "当前区域发现疑似游泳人员")
// }
let fd = new FormData();
fd.append("uploadFiles", blob, `下载.jpeg`);
let res2 = await API.MAPMANAGE.fileUpload(fd);
let data2 = {
imageUrl: res2[0].storage,
deviceHardId: this.device.deviceHardId,
jsonData: JSON.stringify(res.data.data)
}
let swimres = await API.FCKERNEL.insertSwimmingMonitor(data2)
// process.env.VUE_APP_IMG_URL +
let imgshowurl = process.env.VUE_APP_IMG_URL + res2[0].url;
this.$emit("imgUrl", imgshowurl,4,JSON.stringify(res.data.data));
}
});
function blobToBase64(blob, callback) {
let reader = new FileReader()
reader.onload = () => {
callback(reader.result)
}
reader.readAsDataURL(blob)
}
},
//人流识别
async setIntervalFrame() {
let blob = this.screenShot();
let fd = new FormData();
fd.append("uploadFiles", blob, `下载.jpeg`);
let res = await API.MAPMANAGE.fileUpload(fd);
let data = {
// imageUrl:"http://32.128.6.52:9000/uploads/2023/05/26/2f183488-ad62-41c2-bb89-736ade5d8f36.png",
imageUrl: res[0].storage,
deviceHardId: this.device.deviceHardId,
};
let res2 = await API.FCKERNEL.crowdDensity(data);
if (res2.total && res2.total > 20) {
clearInterval(this.AISetInterval)
this.AISetInterval = null
this.$emit("fn", {
data: "POSITION",
type: 513
});
this.$emit("AIDialog", true, "当前区域人流聚集")
}
},
}
\ No newline at end of file
...@@ -638,5 +638,21 @@ export default { ...@@ -638,5 +638,21 @@ export default {
background: transparent !important; background: transparent !important;
} }
} }
.cesium-viewer-bottom {
display: none;
}
.cesium-viewer-zoomIndicatorContainer {
display: none;
}
.cesium-viewer-navigationContainer {
display: none;
}
.cesium-credit-logoContainer {
display: none;
}
} }
</style> </style>
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论