提交 07e72614 作者: 翁进城

feat: 无人机

1. 指点飞行
2. 内场控制
3. 视图库
上级 a0346bba
......@@ -38,12 +38,6 @@ export default {
type: Object,
default: () => ({})
},
wsShow: {
type: Boolean,
default: () => {
false;
}
}
},
components: { Info, battery, obstacle, throttleGauge },
mounted(){
......
import request from '../request';
import request_uav from '../request_uav';
import request from "../request";
import request_uav from "../request_uav";
class Control_API {
/**
......@@ -9,12 +9,12 @@ class Control_API {
*/
static login(data) {
return request({
url: '/crm/account/loginInfo',
method: 'post',
url: "/crm/account/loginInfo",
method: "post",
data,
headers: {
token: window.localStorage.getItem('tmj_token')
}
token: window.localStorage.getItem("tmj_token"),
},
});
}
/**
......@@ -26,34 +26,34 @@ class Control_API {
static updateTakeOver(id) {
return request({
url: `/dms/uav/updateTakeOver/${id}`,
method: 'put'
method: "put",
});
}
// 获取无人机树结构列表
static getUavTree(params) {
return request({
url: '/dms/uav/tree',
url: "/dms/uav/tree",
// url: '/crm/personalCenter/list?id=4',
method: 'get',
params
method: "get",
params,
});
}
// 获取无人机列表
static getUavDataList(params) {
return request({
url: '/dms/uav/page',
method: 'get',
params
url: "/dms/uav/page",
method: "get",
params,
});
}
// 获取航线列表
static getUavRouteList(params) {
return request({
url: '/dms/route/page',
method: 'get',
params
url: "/dms/route/page",
method: "get",
params,
});
}
......@@ -61,7 +61,7 @@ class Control_API {
static getFlightSortic({ taskId, deviceHardId }) {
return request({
url: `/tss/task/getFlightSortic/${taskId}/${deviceHardId}`,
method: 'get'
method: "get",
});
}
......@@ -69,7 +69,7 @@ class Control_API {
static uavDetail(params) {
return request({
url: `/dms/uav/detail/${params.id}`,
method: 'get'
method: "get",
});
}
......@@ -77,8 +77,8 @@ class Control_API {
static getFlightLog(data) {
return request({
url: `/dms/sortie/flightLog`,
method: 'post',
data
method: "post",
data,
});
}
......@@ -86,8 +86,8 @@ class Control_API {
static addPhoto(data) {
return request({
url: `/dms/sortie-image/add`,
method: 'post',
data
method: "post",
data,
});
}
// 保存AI图片
......@@ -102,70 +102,107 @@ class Control_API {
static getAllOrg() {
return request({
url: `/crm/organization/tree`,
method: 'get'
method: "get",
});
}
// 获取所有无人机操作日志
static getUavAllLog(params) {
return request_uav({
url: `/api/log/selectUavCmdLikeList`,
method: 'get',
params
method: "get",
params,
});
}
// 获取1小时短时天气预报
static getUavShortForEcast(params) {
return request_uav({
url: `/whapi/json/aliweather/shortforecast`,
method: 'post',
params
method: "post",
params,
});
}
// 获取24小时短时天气预报(详细)包含风向等等...
static getUavShortForEcast24(params) {
return request_uav({
url: `/whapi/json/aliweather/forecast24hours`,
method: 'post',
params
method: "post",
params,
});
}
// 获取树结构-鹰巢
static getUavNestList(params) {
return request({
url: `/dms/nest/getNestList`,
method: 'get',
params
method: "get",
params,
});
}
// 获取任务库列表
static getTaskList(data) {
return request({
url: `/tss/task/list`,
method: 'post',
data
method: "post",
data,
});
}
// 获取任务库内的任务详情
static getTaskDetails(params) {
return request({
url: `/tss/task/${params.id}`,
method: 'get'
method: "get",
});
}
// 鹰巢-定时,周期自启动
static startUavNest = (data) =>
request({
url: '/tss/task/start',
method: 'POST',
data
url: "/tss/task/start",
method: "POST",
data,
});
// 鹰巢-运行日志
static getUavNestLog = (params) =>
request_uav({
url: `api/log/selectProcessLikeList`,
method: 'get',
params
method: "get",
params,
});
// 获取架次列表
static getSortie(params) {
return request({
url: "/dms/sortie/page",
method: "get",
params,
});
}
// 获取架次图片列表
static getSortieImage(params) {
return request({
url: "/dms/sortie-image/page",
method: "get",
params,
});
}
// 获取架次视频列表
static getSortieVideo(params) {
return request({
url: "/dms/sortie/history-video",
method: "get",
params,
});
}
// 导出成果
static getExportToWordForSortie(params) {
return request({
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
responseType: "blob",
url: `/dms/sortie/export-word`,
method: "GET",
params,
});
}
}
export default Control_API;
<?xml version="1.0" encoding="UTF-8"?>
<svg width="22px" height="22px" viewBox="0 0 22 22" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组 58</title>
<g id="鹰视子页面" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="无人机应用3" transform="translate(-437.000000, -91.000000)">
<g id="编组-44" transform="translate(424.000000, 84.000000)">
<g id="编组-58" transform="translate(13.000000, 7.000000)">
<rect id="矩形" x="0" y="0" width="22" height="22"></rect>
<g id="编组-24" transform="translate(1.000000, 0.000000)">
<g id="编组">
<path d="M3.88923078,2.41768162 L3.88923078,2.90699556 C3.89135237,3.71997902 4.54351573,4.37741013 5.34615385,4.37568669 L14.6538461,4.37568669 C15.0394305,4.37672127 15.409628,4.22256551 15.6829986,3.9471322 C15.9563693,3.67169889 16.1105197,3.2975503 16.1115385,2.90699556 L16.1115385,2.41768162 L18.0561538,2.41768162 C18.5702664,2.41624304 19.0638901,2.62171794 19.4284324,2.98891369 C19.7929747,3.35610944 19.9985739,3.85494697 20,4.37568669 L20,20.0419851 C19.9985741,20.5628602 19.7928693,21.0618161 19.4281605,21.4290343 C19.0634517,21.7962524 18.5696302,22.0016358 18.0553846,21.9999902 L1.94461539,21.9999902 C1.42923078,21.9999902 0.933846162,21.7942856 0.569230765,21.4265284 C0.205080492,21.0601733 0.000204616439,20.5618526 0,20.0419851 L0,4.37568669 C0.00142586731,3.85481157 0.207130678,3.35585567 0.57183949,2.98863751 C0.936548301,2.62141936 1.43036975,2.41603597 1.94461539,2.41768162 L3.88923078,2.41768162 Z M8.03089086,7.05007484 C7.25556571,7.05007484 6.50823684,7.43670355 5.98144997,8.10900158 C5.48894424,8.73770348 5.21812322,9.5643088 5.21812322,10.4345102 L5.21812322,13.5757252 L5.23069297,13.8051785 C5.22326539,14.8021528 6.753347,14.6570236 6.75220429,13.7460942 L6.7413486,13.5349973 L6.7413486,10.4345102 C6.7413486,9.42893139 7.33212692,8.57938074 8.03089086,8.57938074 C8.73022614,8.57938074 9.32100448,9.42835775 9.32100448,10.4345102 L9.32100448,15.6161382 C9.32100448,16.4863397 9.59182549,17.3117977 10.0849026,17.9404996 C10.6122608,18.6133713 11.358447,19 12.1337721,19 C12.9096686,19 13.6564261,18.6133713 14.1837844,17.9404996 C14.6762901,17.3117977 14.9476825,16.4863397 14.9476825,15.6161382 L14.9476825,13.7460942 C14.9476825,13.3237881 14.6066968,12.9814413 14.1860698,12.9814413 C13.7654427,12.9814413 13.4244571,13.3237881 13.4244571,13.7460942 L13.4244571,15.6161382 C13.4244571,16.6217171 12.8331074,17.4706941 12.1337721,17.4706941 C11.4344368,17.4706941 10.8442299,16.6217171 10.8442299,15.6161382 L10.8442299,10.4345102 C10.8442299,9.56373516 10.5728375,8.73885074 10.0803318,8.10900158 C9.55297353,7.43670356 8.80621601,7.05007484 8.03089086,7.05007484 Z M5.97516509,14.9455611 C4.88461082,14.9468261 4.00094457,15.8342765 4,16.9291844 C4.0018887,18.0248844 4.8855348,18.9115448 5.97573645,18.9128078 C7.06664416,18.9118582 7.95058664,18.0238736 7.95090153,16.9286108 C7.94995603,15.8335722 7.06585007,14.9461937 5.97516509,14.9455611 Z M5.97573645,15.8639477 C6.56202684,15.8639477 7.03730912,16.3411273 7.03730912,16.9297581 C7.03730912,17.5183889 6.56202684,17.9955684 5.97573645,17.9955684 C5.38944605,17.9955684 4.91416377,17.5183889 4.91416377,16.9297581 C4.91416377,16.3411273 5.38944605,15.8639477 5.97573645,15.8639477 Z M14.1032237,7 C13.9820029,7 13.8657981,7.04858666 13.7804096,7.13497254 L12.3286033,8.5925743 C12.2429834,8.6785294 12.1948821,8.79511348 12.1948821,8.91667701 C12.1948821,9.03824054 12.2429834,9.15482463 12.3286033,9.24077972 C12.4141875,9.32723452 12.5305812,9.37584903 12.6519887,9.37584903 C12.7733962,9.37584903 12.8897899,9.32723452 12.9753741,9.24077972 L13.3421824,8.87308089 L13.3421824,11.1498307 C13.3421824,11.5721369 13.683168,11.9144837 14.103795,11.9144837 C14.5244221,11.9144837 14.8654077,11.5721369 14.8654077,11.1498307 L14.8654077,8.87250726 L15.2327873,9.24077972 C15.4131049,9.40799186 15.692774,9.40235843 15.8662663,9.22801943 C16.0397585,9.05368044 16.0451222,8.77289011 15.8784155,8.59200067 L14.4260378,7.13497254 C14.3406493,7.04858666 14.2244445,7 14.1032237,7 Z M10,0 C10.8817357,0.000861025619 11.6408671,0.63065615 11.8153846,1.50609017 L14.44,1.50609017 C15.0560099,1.50609017 15.5553846,2.01190203 15.5553846,2.63585258 C15.5553846,3.25980313 15.0560099,3.76561499 14.44,3.76561499 L5.56000001,3.76561499 C4.9439901,3.76561499 4.4446154,3.25980313 4.4446154,2.63585258 C4.4446154,2.01190203 4.9439901,1.50609017 5.56000001,1.50609017 L8.18461538,1.50609017 C8.35913286,0.63065615 9.11826429,0.000861025619 10,0 Z" id="形状结合" fill="#FFFFFF" fill-rule="nonzero"></path>
<g id="编组-5" transform="translate(12.194882, 7.000000)"></g>
</g>
<path d="M8.18461538,1.50609017 C8.35913286,0.63065615 9.11826429,0.000861025619 10,3.40838469e-13 C10.8817357,0.000861025619 11.6408671,0.63065615 11.8153846,1.50609017 L14.44,1.50609017 C15.0560099,1.50609017 15.5553846,2.01190203 15.5553846,2.63585258 C15.5553846,3.25980313 15.0560099,3.76561499 14.44,3.76561499 L5.56000001,3.76561499 C4.9439901,3.76561499 4.4446154,3.25980313 4.4446154,2.63585258 C4.4446154,2.01190203 4.9439901,1.50609017 5.56000001,1.50609017 L8.18538463,1.50609017 L8.18461538,1.50609017 Z" id="路径" fill="#FFBD36"></path>
</g>
<path d="M8.03730912,16.9297581 C8.03730912,16.3411273 7.56202684,15.8639477 6.97573645,15.8639477 C6.38944605,15.8639477 5.91416377,16.3411273 5.91416377,16.9297581 C5.91416377,17.5183889 6.38944605,17.9955684 6.97573645,17.9955684 C7.56202684,17.9955684 8.03730912,17.5183889 8.03730912,16.9297581 Z" id="路径" fill="#FFBD36"></path>
</g>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<template>
<div class="car dialog1027">
<div class="dialog-header" v-interact>
<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">
<div class="dialog-header" v-interact>
<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">
<div class="dialog-header" v-interact>
<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/observe/faceAI_border1.png');
background-size: 100% 100%;
padding: 7px;
display: flex;
align-items: center;
&.rate-img--contrary {
background-image: url('~@/assets/images/observe/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="taskListBox w380" :class="{ yidong: taskstyle == false }">
<div class="header wih100 h32">
<div class="title ml10">
<img src="~@/assets/images/mount/mount_head.png" />
<div class="font">任务库</div>
</div>
</div>
<div v-show="taskType == 'itemA'" class="pt38 jianju pr">
<div class="flexs">
<span class="cf">任 务 库</span>
<!-- <el-select size="mini" class="w300 mt10 ml10" v-model="flyTypeId" placeholder="请选择任务">
<el-option v-for="item in TaskList" :key="item.id" :label="item.taskTitle" :value="item.id">
</el-option>
</el-select>-->
<el-tooltip :content="clew" placement="top">
<el-cascader
filterable
popper-class="cpt-observe-mspace-dashboard-airway"
size="mini"
class="w276 ml10 cpt-observe-mspace-dashboard-airway"
v-model="flyTypeId"
:options="airway_list"
clearable
:show-all-levels="false"
placeholder="请选择任务"
:props="{
children: 'children',
label: 'taskTitle',
value: 'id',
emitPath: false,
}"
@change="v_value"
:disabled="taskCate == 3 ? true : 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-tooltip>
<div class="cf mt20 tc" style="display: flex">
<span class="line_height">
<i style="opacity: 0"></i> 线
</span>
<el-tooltip content="航线名称" placement="top">
<el-input
v-if="flightFlag"
disabled
v-model="flight[0].flightName"
placeholder="请选择航线"
class="ml10 w276 mrg_left6"
size="mini"
></el-input>
<el-button v-else @click="lineshow = true" class="kbt_button"
>选择航线</el-button
>
<!-- <el-select
v-else
size="mini"
class="w276 ml10 mt10"
v-model="flightId"
placeholder="请选择航线"
>
<el-option
v-for="item in flightList"
:key="item.id"
:label="item.title"
:value="item.id"
>
</el-option>
</el-select>-->
</el-tooltip>
</div>
<div>
<div></div>
<div class="btn cf ml18 cp mt40" @click="handClickTask">一键任务</div>
<div class>
<span
v-if="!flightFlag"
style="color: #43deff; bottom: -18px"
class="lh30 dib cp f8 right16 pa"
@click="craeteRoute"
>
<span class="f8"></span> 创建航线
</span>
</div>
</div>
</div>
</div>
<LineList
v-if="lineshow"
@changeLine="changeLine"
@close="lineshow = false"
></LineList>
</div>
</template>
<script>
import API from "@/api";
import LineList from "../lineList";
import methods from "./methods";
import { mapGetters } from "vuex";
// 引用bus
import Bus from "@/assets/ligature.js";
export default {
name: "taskList",
components: { LineList },
data() {
return {
taskType: "itemA",
rwList: [],
TaskList: [],
// 任务id
flyTypeId: "",
flight: [
{
flightName: "",
},
],
// 航线数据
flightList: [],
// 航线id
flightId: "",
flightIdv2: "",
// 航线是否可选
flightFlag: true,
// 航线数据
flightLinefkData: "",
airway_list: [],
lineshow: false,
clew: "任务库", // 飞控任务库提示语
// taskstyle: false,
flightSortic: null,
taskCate: 1,
username: null,
distanceLine: 0,
};
},
props: {
wsShow: {
type: Boolean,
default: false,
},
device: {
type: Object,
default: () => ({}),
},
taskstyle: {
type: Boolean,
default: false,
},
},
inject: ["uav_This"],
async created() {
this.username = this.user_info.username;
await this.list_airway();
await this.initTask();
// 飞控选择其他模块时,关闭航线
// 关键字:关闭预设航线
Bus.$on("uav_Route", () => {
this.close_the_router();
});
// 等待航线上传成功在执行
Bus.$on("take_off", () => {
this.upload_complete();
});
// 修改飞控 无人机 左边'任务库'的位置
// Bus.$on("ydh", (status) => {
// if (status == false) {
// this.taskstyle = false;
// } else {
// this.taskstyle = true;
// }
// });
},
methods: {
...methods,
craeteRoute() {
this.close_the_router();
this.$emit("craeteRoute");
},
v_value(e) {
if (e == null) {
this.clew = "任务库";
sessionStorage.removeItem("waypointList");
}
},
changeLine(id) {
this.flightId = id;
},
async checkUseOperateFn(device) {
// 查看是否有控制权限
let res = await API.FCKERNEL.checkUseOperate({ deviceHardId: device });
if (res.code == 201) {
this.$message.warning(res.msg);
return false;
} else {
return true;
}
},
async initTask() {
let res = await API.FCKERNEL.getTaskAndUserRelation({
sourceType: 0,
deviceHardId: this.device.deviceHardId,
});
if (res.code == 200 && res.list) {
this.list = res.list;
// taskCateId 2 1警情 3临时
this.airway_list[this.list.taskCateId]?.children.push({
id: res.list.taskId,
flightName: res.list.flightName,
flightLineId: res.list.flightId,
flightCourseJson: res.list.flightCourseJson,
userId: res.list.userId,
taskStatus: res.list.taskStatus,
taskTitle: res.list.taskTitle,
taskCateId: res.list.taskCateId,
});
this.showRoute(res.list);
this.flyTypeId = res.list.taskId;
this.taskCate = res.list.taskStatus;
this.flightIdv2 = res.list.flightId;
this.saveFlightLineId(res.list.flightId);
} else {
sessionStorage.removeItem("waypointList");
this.taskCate = 1;
this.flight[0].flightName = null;
this.clew = "任务库";
this.flyTypeId = null;
}
},
async handClickTask() {
let flag = await this.checkUseOperateFn(this.device.deviceHardId);
if (!flag) return;
if (this.flightFlag && this.flyTypeId) {
if (this.uav_This.uav.control.device.stationType == 1) {
this.$emit("getSelf");
} else {
this.handClickTask2();
}
} else {
this.$message.error("请选择任务");
}
},
async handClickTask2() {
// this.$emit("uav-location");
// let flag = await this.checkUseOperateFn(this.device.deviceHardId);
// if (!flag) return;
// 航线
// if (this.flightFlag && this.flyTypeId) {
// 局部预警
let checkBeforeTakeOff = await API.DEVICE.checkBeforeTakeOff({
taskId: this.flyTypeId,
});
if (!checkBeforeTakeOff.code) {
this.$emit("Lsdom", checkBeforeTakeOff);
return;
}
// this.$confirm("请确认是否进行一键任务操作?", "安全确认", {
// cancelButtonText: "取消",
// confirmButtonText: "确定",
// customClass: "uav_controlPane",
// showClose: false,
// })
// .then(async () => {
this.getTrue();
// })
// .catch(() => {
// this.$message({
// type: "info",
// message: "已取消操作",
// });
// });
// } else {
// this.$message.error("请选择任务");
// }
},
async getTrue() {
// console.log(this.flightLinefkData,"this.flightLinefkData.labelName");
// this.$emit("changeLableName",this.flightLinefkData.labelName)
// this.$emit("uav-location", 1);
// return
// // 生成架次號
let getFlightSortic = await API.DEVICE.getFlightSortic({
taskId: this.flyTypeId,
deviceHardId: this.uav_This.uav.control.device.deviceHardId,
});
this.flightSortic = getFlightSortic;
if (this.uav_This.uav.control.device.stationType == 1) {
//飞控中心链路
// 上传航线指令
this.$emit("fn", {
type: 521,
data: {
...this.flightLinefkData,
taskId: this.flyTypeId,
flightSortiesID: getFlightSortic,
},
});
// 等待航线上传成功在执行
// 判断是否以一键任务
Bus.$emit("off_take");
} else {
//地面站链路
this.$emit("fun", {
type: 200,
systemCode: "mmc",
state: 1,
username: this.username,
data: {
cmdFunction: 2113,
cmdValue: this.flightId || this.flightIdv2, //航线id
taskId: this.flyTypeId + "",
flightSortieName: getFlightSortic,
},
deviceHardId: this.uav_This.uav.control.device.deviceHardId,
});
// this.upload_complete()
}
},
// 航线上传成功再执行
async upload_complete() {
if (this.uav_This.uav.control.device.stationType == 1) {
// 生成架次號
// let getFlightSortic = await API.DEVICE.getFlightSortic({
// taskId: this.flyTypeId,
// deviceHardId: this.uav_This.uav.control.device.deviceHardId,
// });
// 告诉飞控开始任务,并且把架次号和 任务id传过去
this.startFlight({
taskId: this.flyTypeId,
flightSortiesID: this.flightSortic,
});
// }
// 更改任务状态 status 任务执行状态 默认-1待派发 0表示待执行;3执行中;1执行完成
this.task_update(3);
// if(this.uav_This.uav.control.device.stationType == 1){
// 记录任务
await API.FCKERNEL.addTaskAndUserRelation({
taskId: this.flyTypeId,
sourceType: 0, //机库为1 无人机0
deviceHardId: this.device.deviceHardId,
});
let _this = this;
setTimeout(() => {
_this.$emit("fn", {
data: 0,
type: 522,
});
}, 3000);
} else {
console.log(
this.uav_This.uav.control.device.deviceHardId,
this.flyTypeId,
"4741852963"
);
//地面站链路
//解锁无人机
this.$emit("fun", {
type: 200,
systemCode: "mmc",
state: 1,
username: this.username,
data: {
cmdFunction: 2110,
},
deviceHardId: this.uav_This.uav.control.device.deviceHardId,
});
//预览航线
// this.$emit("fun", {
// type: 200,
// systemCode: "mmc",
// state: 1,
// username: this.username,
// data: {
// cmdControlType: 900,
// cmdFunction: 9001
// },
// deviceHardId: this.uav_This.uav.control.device.deviceHardId,
// });
//一键起飞
this.$emit("fun", {
type: 200,
systemCode: "mmc",
state: 1,
username: this.username,
data: {
cmdFunction: 2111,
cmdValue: 50, //高度
taskId: this.flightId || this.flightIdv2,
},
deviceHardId: this.uav_This.uav.control.device.deviceHardId,
});
// status 任务执行状态 默认-1待派发 0表示待执行;3执行中;1执行完成
let task = await API.DEVICE.task_update({
id: this.flyTypeId,
status: 3,
deviceHardId: this.uav_This.uav.control.device.deviceHardId,
});
// 记录任务
await API.FCKERNEL.addTaskAndUserRelation({
taskId: this.flyTypeId,
sourceType: 0, //机库为1 无人机0
deviceHardId: this.uav_This.uav.control.device.deviceHardId,
});
// 一键起飞任务监听
let res = await API.TASK.flytaskLisener({
taskId: this.flyTypeId,
deviceHardId: this.uav_This.uav.control.device.deviceHardId,
});
//航线模式
this.$emit("fun", {
type: 200,
systemCode: "mmc",
state: 1,
username: this.username,
data: {
cmdFunction: 2115,
},
deviceHardId: this.uav_This.uav.control.device.deviceHardId,
});
}
this.taskCate = 3;
this.$message.success("操作成功");
this.$emit("iconShow");
},
async saveFlightLineId(flightLineId) {
console.log("暂无航线_a", flightLineId);
if (flightLineId) {
// this.$emit("changeLableName","河道巡检")
let res = await API.AIRWAY.GetAirwayInfo(flightLineId);
this.flightLinefkData = res.data;
// console.log(res.data,"res.data");
// delete this.flightLinefkData.flightJson
// console.log(JSON.parse(res.data.flightJson));
let lineData = null;
// console.log(JSON.parse(res.data.flightJson),"JSON.parse(res.data.flightJson)");
if (JSON.parse(res.data.flightJson).points[0].ailist) {
this.flightLinefkData.headingMode = "USING_WAYPOINT_HEADING";
}
if (JSON.parse(res.data.flightJson).waypoints) {
lineData = JSON.parse(res.data.flightJson).waypoints;
this.flightLinefkData.waypointList = lineData;
} else {
lineData = JSON.parse(res.data.flightJson).points;
this.flightLinefkData.waypointList.forEach((val, i) => {
lineData.forEach((val2, j) => {
if (i == j) {
val.waypointActions = val2.actions;
}
});
});
}
delete this.flightLinefkData.flightJson;
console.log(this.flightLinefkData, "flightLinefkData");
if (this.flightLinefkData) {
this.$emit("changeLableName", "");
console.log("zheli");
try {
sessionStorage.setItem(
"waypointList",
JSON.stringify({
uavDeviceId: this.uav_This.uav.control.device.deviceHardId,
wayLineObj: this.flightLinefkData,
flyTypeId: this.flyTypeId,
})
);
} catch (error) {
sessionStorage.removeItem("waypointList");
}
}
}
},
async getFlightLine(id) {
let flightLineData = await API.USER.routesListqq(id);
this.flight[0] = flightLineData;
// 预览航线
this.showRoute(flightLineData);
// 自动生成任务
let task = await API.AIRWAY.addNestAutoTask({
lineId: id,
type: 1,
});
// 重新请求航线
await this.list_airway();
this.flyTypeId = task.id;
console.log(10);
return;
let flightLinefkData = await API.AIRWAY.GetAirwayInfo(id);
this.flightLinefkData = flightLinefkData.data;
},
},
computed: {
...mapGetters(["user_info"]),
task_end_data() {
return this.$store.state.fckernel.task_end_data;
},
},
watch: {
task_end_data: function (val) {
if (this.device.deviceHardId == val.data) {
this.flyTypeId = "";
this.flight = [
{
flightName: "",
},
];
this.taskCate = 1;
this.$message.success("任务已结束!");
}
},
device: function (value) {
this.initTask();
},
flyTypeId: function (value) {
if (window.location.hash.includes("accident")) {
this.$store.commit("fckernel/SET_TASK_ID_YJ", value);
} else {
this.$store.commit("fckernel/SET_TASK_ID", value);
}
if (value) {
if (value == "z1322" || value == "") {
this.flightFlag = false;
this.flightId = "";
this.clew = "任务库";
} else {
this.flightFlag = true;
let arr = [];
if (this.airway_list[1]?.children) {
arr.push(...this.airway_list[1].children);
}
if (this.airway_list[2]?.children) {
arr.push(...this.airway_list[2].children);
}
if (this.airway_list[3]?.children) {
arr.push(...this.airway_list[3].children);
}
if (arr.length > 0) {
let item = arr.find((item) => item.id === value);
// 提示语的信息
this.clew = item.taskTitle;
this.flight = [item];
if (item.flightLineId) {
this.flightIdv2 = item.flightLineId;
this.saveFlightLineId(item.flightLineId);
this.showRoute(item);
}
}
}
}
},
flightId: function (value) {
if (value) {
// this.saveFlightLineId(value)
this.getFlightLine(value);
}
// this.handleAirLinePreview(this.flight[0], true);
},
"uavData.gps.fixType": function (value) {
if (value == "LOCK_3D_RTK_GPS_LOCK_FIXED") {
this.$message.success("RTK已就绪");
this.fixType = true;
} else {
this.fixType = false;
}
},
},
};
</script>
<style>
.el-cascader-menu__list {
background: rgba(9, 32, 87, 1) !important;
max-height: 300px;
max-width: 327px;
}
.el-cascader-node {
background: rgba(9, 32, 87, 1) !important;
}
</style>
<style lang="scss" scoped>
.yidong {
left: 544px !important;
}
.taskListBox {
position: absolute;
left: 80px;
top: 85px;
min-height: 254px;
background: rgba(9, 32, 87, 0.7);
// border: 1px solid #70daf9;
border-radius: 10px;
transition: 0.3s;
.header {
display: flex;
justify-content: space-between;
height: 32px;
background: linear-gradient(
180deg,
#9198ff 0%,
rgba(45, 81, 153, 0.45) 40%,
#05091a 100%
);
box-shadow: inset 0px 0px 10px 2px #3f9dff;
border-radius: 10px 10px 0px 0px;
border: 1px solid #427dff;
.title {
display: flex;
align-items: center;
.font {
font-size: 20px;
font-family: YouSheBiaoTiHei;
color: #14faff;
line-height: 26px;
text-shadow: 0px 1px 1px rgba(2, 32, 56, 0.2);
background: linear-gradient(
135deg,
#e3aa77 0%,
#f5cda9 38%,
#f9ecd3 58%,
#fcdbb1 79%,
#edb07a 100%
);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
}
.active {
background-image: linear-gradient(
180deg,
#9198ff 0%,
rgba(45, 81, 153, 0.22) 40%,
#05091a 100%
);
border: 1px solid #70daf9;
box-shadow: inset 0 0 10px 2px #3f9dff;
font-family: MicrosoftYaHei-Bold;
font-size: 14px;
color: #70daf9;
letter-spacing: 0;
font-weight: 700;
}
.default {
background-image: linear-gradient(
180deg,
#9198ff 0%,
rgba(45, 81, 153, 0.22) 40%,
#05091a 100%
);
border: 1px solid #70daf9;
font-family: MicrosoftYaHei-Bold;
font-size: 14px;
color: rgba(112, 218, 249, 0.5);
letter-spacing: 0;
font-weight: 700;
}
}
.jianju {
// background: rgba(9, 32, 87, 0.7);
border-radius: 10px 0 0 10px;
display: flex;
justify-content: center;
}
.taskList {
overflow-y: auto;
.rwtitle {
font-family: MicrosoftYaHei-Bold;
font-size: 14px;
color: #b5e5ff;
padding: 5px 0;
letter-spacing: 0;
font-weight: 700;
background: rgba(87, 96, 138, 0.2);
border: 1px solid rgba(207, 234, 255, 0.33);
}
.rwinfo {
color: #ffffff;
background: url("~@/assets/images/observe/fckernel/nest/listBg.png");
background-repeat: no-repeat;
background-size: 100% 100%;
height: 33px;
line-height: 33px;
padding-left: 4px;
}
}
.btn {
width: 122px;
height: 32px;
text-align: center;
line-height: 32px;
margin: 0 auto;
margin-bottom: 10px;
// background-image: linear-gradient(
// 180deg,
// #9198ff 0%,
// rgba(45, 81, 153, 0.22) 40%,
// #05091a 100%
// );
// border: 1px solid #70daf9;
// box-shadow: inset 0 0 10px 2px #3f9dff;
background: url("~@/assets/yingkong1027/btn_lan.png") no-repeat;
background-size: 100% 100%;
}
.Titlehideen {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.el-cascader-menu {
width: 200px;
}
.mrg_left6 {
margin-left: 10px;
}
.kbt_button {
margin-left: 10px;
width: 80%;
height: 30px;
padding: 0;
}
.line_height {
line-height: 28px;
}
</style>
import API from "@/api";
import { Utils } from "@/lib/cesium";
let airline_entitys = [];
let air_line_preview = [];
export default {
createFn() {
this.$emit("createTaskClick");
},
// 航线数据
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 = [
{
taskTitle: "选择航线自动生成任务",
id: 'z1322'
},
{
id: "警情任务",
taskTitle: "警情任务",
children: jqList,
},
{
id: "常态任务",
taskTitle: "常态任务",
children: ctList,
},
{
id: "临时任务",
taskTitle: "临时紧急任务",
children: lsList,
},
];
this.airway_list = airway_list;
}
let FlightLineList = await API.AIRWAY.Drd({sourceType:1});
this.flightList = FlightLineList
},
// // 获取任务列表
// async init() {
// let res = await API.AIRWAY.getNestApprovedTask();
// this.TaskList = [{
// taskTitle: "选择航线自动生成任务",
// id: 'z1322'
// }, ...res];
// },
// 预览航线
showRoute(item) {
this.distanceLine = 0
this.handleAirLinePreview(item, true)
},
changeBtn(item) {
this.taskType = item;
this.$emit('taskType',item)
if (this.taskType == "itemA") {
this.list_airway()
}
},
close() {
this.$nextTick(async () => {
let viewer = window.viewer;
if (airline_entitys?.length) {
airline_entitys.forEach((item) => {
viewer.entities.remove(item);
});
}
let res = {};
air_line_preview.forEach((item) => {
viewer.entities.remove(item);
});
await this.list_airway();
await this.initTask();
this.flightId = "";
this.flyTypeId = "";
this.flight = [
{
flightName: "",
},
];
this.taskCate = 1
});
},
task_update(status) {
API.DEVICE.task_update({
id: this.flyTypeId,
status,
deviceHardId: this.uav_This.uav.control.device.deviceHardId,
});
},
startFlight(data) {
// 开始任务
this.$emit(
"fn",
{
data,
type: 769,
},
"wrj"
);
},
end(item) {
// 结束任务
this.task_update(4)
this.$emit("fn", this.data[item].data, "wrj");
// 飞控结束任务
this.startFlight(null)
this.flyTypeId = null
this.list_airway()
this.flight = [
{
flightName: "",
},
],
sessionStorage.removeItem("waypointList");
this.$message.success("操作成功");
},
unlock() {
if (this.unlockValue) {
this.ws = new WebSocket("ws://127.0.0.1:8802");
this.ws.onmessage = (e) => {
let reader = new FileReader();
console.log(e.data, 'e.data');
reader.onload = (event) => {
let data = event.currentTarget.result;
data = JSON.parse(data).data;
this.$emit(
"fn",
{
type: 519,
data
}
);
}
reader.readAsText(e.data);
}
// 更改为定点模式
// this.$emit('fn', {
// type: 513,
// data: "POSITION",
// }, "wrj")
this.$message.success("操作成功");
}
},
plan() {
if (this.airwayUploadData.totalWaypointCount) {
return parseInt(
(this.airwayUploadData.uploadedWaypointIndex /
this.airwayUploadData.totalWaypointCount) *
100
);
} else {
return "";
}
},
handle_airway_change() {
if (!this.flyTypeId) return this.$message.warning("请选择任务");
this.$emit("airway-view", this.flight[0]);
},
upload__airway() {
if (!this.flyTypeId) return this.$message.warning("请选择任务");
this.$emit("fn", { type: 521, data: this.flightLineData.data }, "wrj")
this.$message.success("操作成功");
},
// 飞控选择其他模块时,关闭航线
// 关键字:关闭预设航线
async close_the_router(item, state){
try {
let viewer = window.viewer;
if (airline_entitys?.length) {
airline_entitys.forEach((item) => {
viewer.entities.remove(item);
});
}
let res = {};
air_line_preview.forEach((item) => {
viewer.entities.remove(item);
});
if (state) {
res.flightCourseJson = item.flightCourseJson;
}
if (res?.flightCourseJson) {
let positions = [];
let center = [];
let polyline = JSON.parse(res.flightCourseJson);
let label_arr = [];
let _this = this;
polyline.points.forEach((item, index) => {
positions.push(item.lon, item.lat, item.alt);
label_arr.push(
Cesium.Cartesian3.fromDegrees(item.lon, item.lat, item.alt)
);
let point_entity = viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(
item.lon,
item.lat,
item.alt
),
name: "show_airline_point",
point: {
pixelSize: 10,
color: Cesium.Color.fromCssColorString("#00A9A9"),
},
label: {
text: String(item.alt) + "m",
scale: 0.6,
font: "bold 28px Microsoft YaHei",
// fillColor: Cesium.Color.BLUE,
fillColor: Cesium.Color.fromCssColorString("#FF7F09"),
horizontalOrigin: Cesium.VerticalOrigin.CENTER,
verticalOrigin: Cesium.VerticalOrigin.CENTER,
disableDepthTestDistance: Number.POSITIVE_INFINITY,
showBackground: false,
outlineWidth: 0,
pixelOffset: new Cesium.Cartesian2(25, -10),
},
});
airline_entitys.push(point_entity);
if (label_arr.length > 1) {
let before = label_arr[label_arr.length - 2];
let after = label_arr[label_arr.length - 1];
_this.create_label(before, after);
}
});
positions = Cesium.Cartesian3.fromDegreesArrayHeights(positions);
let redLine = viewer.entities.add({
name: "Red line on terrain",
polyline: {
positions,
width: 4,
// material: Cesium.Color.RED,
material: Cesium.Color.fromCssColorString("#00A9A9"),
// clampToGround: true,
},
});
viewer.flyTo(redLine);
airline_entitys.push(redLine);
}
} catch (error) {
}
},
async handleAirLinePreview(item, state) {
try {
let viewer = window.viewer;
if (airline_entitys?.length) {
airline_entitys.forEach((item) => {
viewer.entities.remove(item);
});
}
let res = {};
air_line_preview.forEach((item) => {
viewer.entities.remove(item);
});
if (state) {
res.flightCourseJson = item.flightCourseJson;
} else {
// res = await API.TASK.JingQingTrack({
// taskId: item.flightLineId,
// });
}
// 有航点高度和距离的代码
if (res?.flightCourseJson) {
let positions = [];
let center = [];
let polyline = JSON.parse(res.flightCourseJson);
let baseSpeed = polyline.line.baseSpeed;
let label_arr = [];
let _this = this;
polyline.points.forEach((item, index) => {
positions.push(item.lon, item.lat, item.alt);
label_arr.push(
Cesium.Cartesian3.fromDegrees(item.lon, item.lat, item.alt)
);
let point_entity = viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(
item.lon,
item.lat,
item.alt
),
name: "show_airline_point",
point: {
pixelSize: 10,
color: Cesium.Color.fromCssColorString("#00A9A9"),
},
label: {
text: String(item.alt) + "m",
scale: 0.6,
font: "bold 28px Microsoft YaHei",
// fillColor: Cesium.Color.BLUE,
fillColor: Cesium.Color.fromCssColorString("#FF7F09"),
horizontalOrigin: Cesium.VerticalOrigin.CENTER,
verticalOrigin: Cesium.VerticalOrigin.CENTER,
disableDepthTestDistance: Number.POSITIVE_INFINITY,
showBackground: false,
outlineWidth: 0,
pixelOffset: new Cesium.Cartesian2(25, -10),
},
});
let point_entity_num = viewer.entities.add({
name: "airline_point",
// id: uuid,
position: Cesium.Cartesian3.fromDegrees(
item.lon,
item.lat,
item.alt
),
point: {
pixelSize: 20,
color: Cesium.Color.red,
color: Cesium.Color.fromCssColorString("red"),
// fillColor: Cesium.Color.red,
// heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND, // supermap版本会导致拖动显示错误
},
label: {
text: new Cesium.CallbackProperty(() => {
return String(index + 1);
}, false),
// text:index + 1,
font: "bold 14px Microsoft YaHei",
// fillColor: Cesium.Color.BLUE,
fillColor: Cesium.Color.fromCssColorString("white"),
horizontalOrigin: Cesium.VerticalOrigin.CENTER,
verticalOrigin: Cesium.VerticalOrigin.CENTER,
disableDepthTestDistance: Number.POSITIVE_INFINITY,
showBackground: false,
outlineWidth: 0,
pixelOffset: new Cesium.Cartesian2(0, 0),
},
});
airline_entitys.push(point_entity);
airline_entitys.push(point_entity_num);
if (label_arr.length > 1) {
let before = label_arr[label_arr.length - 2];
let after = label_arr[label_arr.length - 1];
_this.create_label(before, after, baseSpeed);
}
});
console.log(polyline,"航线数据")
_this.$store.commit('fckernel/SET_TASK_INFO', polyline);
positions = Cesium.Cartesian3.fromDegreesArrayHeights(positions);
let redLine = viewer.entities.add({
name: "Red line on terrain",
polyline: {
positions,
width: 4,
// material: Cesium.Color.RED,
material: Cesium.Color.fromCssColorString("#00A9A9"),
// clampToGround: true,
},
});
viewer.flyTo(redLine);
airline_entitys.push(redLine);
} else {
this.$el_message("暂无航线", () => { }, "error");
}
} catch (error) {
this.$el_message("暂无航线", () => { }, "error");
}
},
// 显示距离
create_label(before, after, baseSpeed) {
let viewer = window.viewer;
let before_wgs84 = Utils.transformCartesian2WGS84(before);
let after_wgs84 = Utils.transformCartesian2WGS84(after);
let center_lng = (before_wgs84.lng + after_wgs84.lng) / 2;
let cetner_lat = (before_wgs84.lat + after_wgs84.lat) / 2;
let alt = (after_wgs84.alt + before_wgs84.alt) / 2;
let position = Utils.transformWGS842Cartesian({
lng: center_lng,
lat: cetner_lat,
alt: alt + 10,
});
let text = `${Cesium.Cartesian3.distance(before, after).toFixed(2)} m | ${baseSpeed}m/s`;
let time = Cesium.Cartesian3.distance(before, after).toFixed(2)/baseSpeed
this.distanceLine += time
this.$emit("getDistanceLine",this.distanceLine)
let label_entity = viewer.entities.add({
id: `label_${before}`,
position: position,
label: {
text: text,
scale: 0.5,
font: "bold 30px Microsoft YaHei",
fillColor: Cesium.Color.fromCssColorString("#fff"),
horizontalOrigin: Cesium.VerticalOrigin.CENTER,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
disableDepthTestDistance: Number.POSITIVE_INFINITY,
showBackground: true,
backgroundPadding: new Cesium.Cartesian2(10, 10),
},
});
airline_entitys.push(label_entity);
},
}
\ No newline at end of file
<template>
<div class="traffic dialog1027">
<div class="dialog-header" v-interact>
<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="left-bar" :class="{ collapse: listCollapse }">
<div class="left-bar-item item" @click="closeAI()">
<img class="left-bar-item__icon" src="./assets/images/task.svg" />
<div class="left-bar-item__text">任务</div>
</div>
<div
class="left-bar-item item"
@click="
openAIList = !openAIList;
$emit('changeTask', false);
"
>
<img class="left-bar-item__icon" src="./assets/images/ai.png" />
<div class="left-bar-item__text">智能识别</div>
</div>
<div class="ai-list" :class="{ active: openAIList }" @click.stop>
<div class="left-bar-item item" @click="switchAI(0)">
<img class="left-bar-item__icon" src="./assets/images/faceAI2.png" />
<div class="left-bar-item__text">人脸识别</div>
</div>
<Face v-if="openFace" class="ai-dialog" :uavId="uav.hardId" @close="openFace = false" />
<div class="left-bar-item item" @click="switchAI(1)">
<img class="left-bar-item__icon" src="./assets/images/carAI2.png" />
<div class="left-bar-item__text">车辆识别</div>
</div>
<Car v-if="openPlate" class="ai-dialog" :uavId="uav.hardId" @close="openPlate = false" />
<div class="left-bar-item item" @click="switchAI(2)">
<img class="left-bar-item__icon" src="./assets/images/traffic.png" />
<div class="left-bar-item__text">交通指引</div>
</div>
<div class="left-bar-item item" @click="switchAI(3)">
<img class="left-bar-item__icon" src="./assets/images/ksjm.png" />
<div class="left-bar-item__text">快速建模</div>
</div>
<Jm v-if="jmflag" :device="device" class="jm-dialog" @close="jmflag = false"></Jm>
<Traffic v-if="openTraffic" class="ai-dialog" :uavId="uav.hardId" @close="openTraffic = false" />
</div>
</div>
</template>
<script>
import { mapState } from "vuex";
export default {
name: "ControlLeft",
data() {
return {
openAIList: false, //打开AI列表
openTraffic: false, //打开交通指引
openFace: false, //打开人脸识别
openPlate: false, //车牌识别
};
},
computed: {
...mapState("MMCFlightControlCenter/uavApplications", [
"uav",
]),
// 收起列表按钮
listCollapse: {
get() {
return this.$store.state.MMCFlightControlCenter.listCollapse;
},
set(val) {
this.$store.commit("MMCFlightControlCenter/setState", {
key: "listCollapse",
value: val,
});
},
},
},
methods: {
/**
* 切换AI功能
*/
switchAI(type) {
this.openFace = false;
this.openPlate = false;
this.openTraffic = 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.jmflag = !this.jmflag;
break;
}
},
/**
* 关闭所有ai
*/
closeAI() {
this.openAIList = false;
this.openFace = false;
this.openPlate = false;
this.openTraffic = false;
},
},
};
</script>
<style scoped lang="scss">
.left-bar {
position: absolute;
left: 470px;
top: 13%;
transition: 0.3s;
&.collapse {
left: 10px;
}
.left-bar-item {
cursor: pointer;
position: relative;
width: 48px;
height: 48px;
background: rgba(9, 32, 87, 0.7);
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
margin-bottom: 2px;
.left-bar-item__icon {
width: 20px;
height: 20px;
margin-bottom: 2px;
}
.left-bar-item__text {
font-size: 16px;
transform: scale(0.6);
white-space: nowrap;
color: #fff;
}
}
.ai-list {
width: 0;
position: absolute;
left: 65px;
top: 62px;
display: none;
&.active {
display: flex;
}
.left-bar-item {
margin-right: 4px;
}
}
}
</style>
\ No newline at end of file
......@@ -33,11 +33,11 @@
<SymbolIcon icon="yunhangrizhi2" />
<span class="txt">运行日志</span>
</div>
<div class="item" @click="zdfx">
<div class="item" @click="guideFlight" v-if="uav.network === 1">
<SymbolIcon icon="tiaozhuandaozuobiao" />
<span class="txt">指点飞行</span>
</div>
<div class="item" @click="isRcConnectingDialog">
<div class="item" @click="onInfieldControl" v-if="uav.network === 1">
<img class="dib mt3" src="./assets/images/1.svg" alt />
<span class="txt">内场控制</span>
</div>
......@@ -64,30 +64,30 @@
<!-- 强制切换外场权限 -->
<el-dialog
title
:visible.sync="isRcConnectingType"
:visible.sync="showInfieldControlDialog"
width="30%"
:append-to-body="true"
style="margin-top: 20vh"
>
<div class="endrenwu">
<div class="tishiyu">温馨提示</div>
<div class="queding" v-if="isChange == 1">
<div class="queding" v-if="!isAcceleratorMedian">
当前油门值为
<span style="color:red">{{ygValue.toFixed(2)||0}}</span>,请调到中位(470-530)
<span style="color:red">{{uavRealTimeData.rcChannelState.toFixed(2)||0}}</span>,请调到中位(470-530)
</div>
<div class="queding" v-if="isChange == 2">摇杆已处于中位,即将切换内场权限</div>
<div class="queding" v-if="isAcceleratorMedian">摇杆已处于中位,即将切换内场权限</div>
</div>
</el-dialog>
<el-dialog
title
:visible.sync="zdydShow"
:visible.sync="guideFlightShow"
width="30%"
:append-to-body="true"
:show-close="false"
:close-on-click-modal="false"
style="margin-top: 20vh"
>
<div class="endrenwu zdfx">
<div class="endrenwu guideFlight">
<div class="tishiyu">引导飞行确认</div>
<div class="queding">位置获取成功,请确认是否进行指点模式飞行</div>
<div class="fleSpeed">
......@@ -97,9 +97,9 @@
</div>
<div class="red" v-if="maxSpeed">指点飞行最大速度为8米/秒</div>
<div class="btn_kuang">
<div class="btn btn_lan" @click="zdydClose">取消</div>
<div class="btn btn_lan" @click="onGuideFlightCancel">取消</div>
<div style="width: 20px"></div>
<div class="btn btn_lv" @click="zdydThen">确定</div>
<div class="btn btn_lv" @click="onGuideFlightConfirm">确定</div>
</div>
</div>
</el-dialog>
......@@ -108,11 +108,11 @@
</template>
<script>
let Point = null;
// import API from "@/api";
import { Control_API } from "../../../../../../../../api";
import SymbolIcon from "../../../../../../../../../symbol-icon";
let handler = null;
import { mapGetters, mapState, mapActions } from "vuex";
import Logger from './components/logger';
import Logger from "./components/logger";
// 引用bus
import Vue from "vue";
......@@ -128,41 +128,74 @@ export default {
default: () => "",
},
},
watch: {
},
data() {
return {
ygValue: 0,
isChange: 0,
isSend: false,
zdfcFlag: true,
isAcceleratorMedian: false, //油门是否在中位
YGPermissionsSend: false, //摇杆权限更改中
safetyNotice: false, //安全降落弹框
unlockType: true,
chargerPower: true,
isRcConnectingType: false, //强制切换状态为内场权限 提示框
showInfieldControlDialog: false, //强制切换状态为内场权限 提示框
flySpeed: 6, //指点飞行设置
zdlat: "",
zdlng: "",
zdydShow: false,
maxSpeed: false,
showLogger: false, //显示日志
showLogger: false, //显示日志
guideFlightShow: false, //指示指点飞行的窗口
guideFlightDone: true, //指点飞行是否已完成
guideFlightLat: "", //指点飞行选择的纬度
guideFlightLng: "", //指点飞行选择的经度.
};
},
computed: {
...mapState("MMCFlightControlCenter/uavApplications", [
"uav",
"airlineEntity",
"cesiumViewer",
"userInfo",
"uavRealTimeData",
]),
...mapState("MMCFlightControlCenter", ["userInfo"]),
},
watch: {
"uavRealTimeData.rcChannelState"(val) {
// 判断是否为外场权限
if (this.uavRealTimeData.rcState == 0) {
// 判断油门是否处于中位
if (val >= 470 && val <= 530) {
this.isAcceleratorMedian = true;
if (!this.YGPermissionsSend) {
this.YGPermissionsSend = true;
// 发送抢权限指令
this.$store.dispatch("uavApplications/changeYGPermissions", {
callback: () => {},
});
setTimeout(() => {
if (this.uavRealTimeData.rcState == 1) {
this.$message.success("已切换内场权限,请使用摇杆控制!");
this.showInfieldControlDialog = false;
} else {
// this.$message.error("摇杆权限切换失败");
console.log("摇杆权限切换失败");
}
this.YGPermissionsSend = false;
}, 2000);
}
} else {
this.isAcceleratorMedian = false;
}
}
},
},
beforeDestroy() {
if (Point) {
window.viewer.entities.remove(Point);
}
},
computed: {
...mapState("MMCFlightControlCenter/uavApplications", ["airlineEntity"]),
...mapGetters(["user_info"]),
},
methods: {
...mapActions("MMCFlightControlCenter/uavApplications", [
"continueFly",
"pauseFly",
"land",
"routeControl",
"isTakeOver",
]),
/**
* 显示隐藏航线
......@@ -175,138 +208,50 @@ export default {
/**
* 暂停飞行
*/
onPauseFly(){
onPauseFly() {
this.pauseFly({
callback: () => {
this.$message.success('暂停飞行指令已发出');
}
})
this.$message.success("暂停飞行指令已发出");
},
});
},
/**
* 继续飞行
*/
onContinueFly(){
onContinueFly() {
this.continueFly({
callback: () => {
this.$message.success('继续飞行指令已发出');
}
})
this.$message.success("继续飞行指令已发出");
},
});
},
/**
* 紧急迫降
*/
onLand(){
onLand() {
this.safetyNotice = false;
this.land();
},
// 强制切换状态为内场权限
async isRcConnectingChange() {
this.isSend = false;
let obj = {
type: 534,
data: {
cmd: 31021,
param1: 1,
param2: 0,
param3: 0,
param4: 0,
param5: 0,
param6: 0,
param7: 0,
},
};
this.$emit("fn", obj);
// 刷新飞行任务-警情任务列表
// // 记录操作
let { user_info } = this;
let { deviceHardId } = this.uav;
const date = time;
let errorData =
"登录用户:" +
user_info.name +
",无人机id:" +
deviceHardId +
",操作时间" +
date;
let errorType = "抢占无人机外场权限:";
/* let res = await API.FCKERNEL.inserWebLogs({
errorType,
errorData,
});
this.isSend = false;
if (this.uavData.rcState == 1) {
this.$message.success("已切换内场权限,请使用摇杆控制!");
} else {
this.$message.error("摇杆权限切换失败");
} */
},
async isRcConnectingDialog() {
if (this.ModeStatus == "离线")
/**
* 内场控制
*/
async onInfieldControl() {
if (this.online === 0)
return this.$message.warning("处于离线状态,不可操作!");
let flag = await this.checkUseOperateFn(this.uav.deviceHardId);
if (!flag) return false;
if (await this.isTakeOver()) {
return this.$message.warning("请先接管!");
}
// 自动切换摇杆权限
let time = Date.now();
this.$store.commit("uav/SET_IS_RC_C0NNECTING_TYPE", time);
if (this.uavData.rcState == 1) {
this.isSend = false;
if (this.uavRealTimeData.rcState == 1) {
this.$message.success("当前处于内场模式,请使用摇杆控制!");
} else {
this.isSend = true;
this.showInfieldControlDialog = true;
}
},
async handclick() {
// 权限判断
if (this.ModeStatus == "离线")
return this.$message.warning("处于离线状态,不可操作!");
let flag = await this.checkUseOperateFn(this.uav.deviceHardId);
if (!flag) return;
this.safetyNotice = true;
},
async wrjfn(item) {
if (this.ModeStatus == "离线")
return this.$message.warning("处于离线状态,不可操作!");
let flag = await this.checkUseOperateFn(this.uav.deviceHardId);
if (!flag) return false;
if (item == 0) {
if (!this.wsShow) {
this.$emit("fn", { type: 524 });
} else {
//航线模式
this.$emit("fun", {
type: 200,
systemCode: "mmc",
state: 1,
username: this.username,
data: {
cmdFunction: 2118,
},
deviceHardId: this.uav.deviceHardId,
});
}
} else if (item == 1) {
if (!this.wsShow) {
this.$emit("fn", { type: 523 });
} else {
//暂停飞行
this.$emit("fun", {
type: 200,
systemCode: "mmc",
state: 1,
username: this.username,
data: {
cmdFunction: 2117,
},
deviceHardId: this.uav.deviceHardId,
});
}
}
this.$message.success("操作成功");
},
addModeelPoint(viewer, position, name) {
/**
* cesium添加目标点
*/
addTargetPoint(viewer, position, name) {
return viewer.entities.add({
position,
point: {
......@@ -328,17 +273,23 @@ export default {
},
});
},
async zdfx() {
if (this.ModeStatus == "离线")
/**
* 指点飞行
*/
async guideFlight() {
if (this.uav.online === 0)
return this.$message.warning("处于离线状态,不可操作!");
let flag = await this.checkUseOperateFn(this.uav.deviceHardId);
if (!flag) return false;
if (!this.zdfcFlag) {
return false;
if (!this.guideFlightDone) {
return this.$message.warning("指点飞行操作中!");
}
let viewer = window.viewer;
if (await this.isTakeOver()) {
return this.$message.warning("请先接管!");
}
let viewer = this.cesiumViewer;
// 指点飞行 wgs84
this.zdfcFlag = false;
this.guideFlightDone = false;
let position = null;
this.$message("请点击地图获取目标位置");
handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
......@@ -354,27 +305,27 @@ export default {
);
let lng = Cesium.Math.toDegrees(cartographic.longitude);
let lat = Cesium.Math.toDegrees(cartographic.latitude);
this.zdlat = lat;
this.zdlng = lng;
this.guideFlightLat = lat;
this.guideFlightLng = lng;
if (Point) {
window.viewer.entities.remove(Point);
viewer.entities.remove(Point);
}
console.log(movement.position, "movement.position");
// let position = window.viewer.scene.camera.pickEllipsoid(
// movement.position
// );
(position = Cesium.Cartesian3.fromDegrees(lng, lat, 20)),
(Point = this.addModeelPoint(window.viewer, position, "目标点"));
(Point = this.addTargetPoint(viewer, position, "目标点"));
// 指点飞行
this.zdydShow = true;
this.guideFlightShow = true;
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
},
zdydThen() {
/**
* 指点飞行确定事件
*/
onGuideFlightConfirm() {
console.log(
{
data: {
latitude: this.zdlat,
longitude: this.zdlng,
latitude: this.guideFlightLat,
longitude: this.guideFlightLng,
speed: Number(this.flySpeed),
},
type: 518,
......@@ -388,43 +339,21 @@ export default {
} else {
// console.log(123);
this.maxSpeed = false;
this.zdfcFlag = true;
this.zdydShow = false;
if (!this.wsShow) {
this.$emit(
"fn",
{
data: {
latitude: this.zdlat,
longitude: this.zdlng,
speed: Number(this.flySpeed),
},
type: 518,
},
"wrj"
);
} else {
this.$emit("fun", {
type: 200,
systemCode: "mmc",
state: 1,
username: this.username,
data: {
cmdFunction: 2219,
latitude: this.zdlat,
longitude: this.zdlng,
},
deviceHardId: this.uav.deviceHardId,
});
}
this.guideFlightShow = false;
this.routeControl({
latitude: this.guideFlightLat,
longitude: this.guideFlightLng,
});
this.flySpeed = 6;
handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
}
},
zdydClose() {
/**
* 指点飞行取消事件
*/
onGuideFlightCancel() {
this.maxSpeed = false;
this.zdydShow = false;
this.zdfcFlag = true;
this.guideFlightShow = false;
this.flySpeed = 6;
if (Point) {
window.viewer.entities.remove(Point);
......@@ -435,46 +364,6 @@ export default {
message: "已取消操作",
});
},
changeType() {
this.unlockType = true;
this.ws = null;
},
// unlock() {
// this.unlockType = false
// this.ws = new WebSocket("ws://127.0.0.1:8802");
// this.ws.onmessage = (e) => {
// let reader = new FileReader();
// reader.onload = (event) => {
// let data = event.currentTarget.result;
// data = JSON.parse(data).data;
// this.$emit(
// "fn",
// {
// type: 519,
// data
// },
// "wrj"
// );
// }
// reader.readAsText(e.data);
// }
// this.$message.success("操作成功");
// },
async checkUseOperateFn(uav) {
// 查看是否有控制权限
/* let res = await API.FCKERNEL.checkUseOperate({ deviceHardId: uav });
if (res.code == 201) {
this.$message.warning(res.msg);
return false;
} else {
return true;
} */
},
handClick(item) {
this.$emit("fn", this.list[item].data, "yc");
this.$message.success("操作成功");
},
},
};
</script>
......@@ -600,7 +489,7 @@ export default {
border: 1px solid #70daf9;
background: rgba(9, 32, 87, 0.7);
}
.zdfx::v-deep {
.guideFlight::v-deep {
height: 240px;
display: flex;
flex-direction: column;
......
<template>
<div class="stk">
<div class="stk_head">
<div :class="viewLibTab == 1 ? 'ac' : ''" @click="onChangeViewLibTab(1)">视图</div>
<div :class="viewLibTab == 2 ? 'bc' : ''" @click="onChangeViewLibTab(2)">机载</div>
</div>
<div class="content">
<!-- 先注释,下次更新要用 -->
<div class="head">
<div class="aitype mr60" v-if="viewLibTab == 1 && !moreShow">
<el-select popper-class="mmc" v-model="aiType" placeholder="全部" @change="onChangeAiType">
<el-option
v-for="item in aiTypeList"
:key="item.id"
:label="item.value"
:value="item.id"
></el-option>
</el-select>
</div>
<div class="select" v-if="viewLibTab == 2">
<div class="btns" :class="fileType == 0 ? 'bg' : ''" @click="onChangeFileType(0)">图片</div>
<div class="btns" :class="fileType == 1 ? 'bg' : ''" @click="onChangeFileType(1)">视频</div>
<span class="iconfont icon-gengxin" @click="init"></span>
</div>
<div class="select" v-if="viewLibTab == 1 && !moreShow">
<div class="btns" :class="fileType2 == 1 ? 'bg' : ''" @click="onChangeFileType2(1)">图片</div>
<div class="btns" :class="fileType2 == 2 ? 'bg' : ''" @click="onChangeFileType2(2)">视频</div>
<span class="iconfont icon-gengxin" @click="init"></span>
</div>
<div class="select" v-if="viewLibTab == 1 && moreShow">
<div class="btns bg">返回</div>
</div>
</div>
<p v-if="viewLibTab == 2 && fileType == 1">
如遇视频无法播放,请
<a href="http://32.128.6.52:4500/11.11平台部署/ChromeStandaloneSetup64.exe">下载最新谷歌</a>
</p>
<div class="lists">
<!-- <div style="text-align: left">asfnjkfassfausfasn</div> -->
<div class="boxs" :style="!moreShow ? 'height: 100%;' : ''" v-if="viewLibTab == 1">
<div class="boxst" :style="!moreShow ? 'height: 100%;' : ''" v-if="!moreShow">
<div class="images">
<div
class="box"
v-for="(item2, index2) in photoList"
:key="index2"
:class="viewLibTab == 1 && fileType2 == 2 ? 'boxv2' : ''"
>
<img
v-if="viewLibTab == 1 && fileType2 == 1"
:src="item2.image"
crossorigin="anonymous"
/>
<video controls v-if="viewLibTab == 1 && fileType2 == 2" :src="item2.image"></video>
<div
class="down"
v-if="viewLibTab == 1 && fileType2 == 1"
@click="onDownload(item2.image)"
>下载</div>
</div>
</div>
</div>
<div v-else>
<el-checkbox-group v-model="checkList">
<div
class="box"
:class="viewLibTab == 1 && fileType2 == 2 ? 'boxv2' : ''"
v-for="(item, index) in morelist"
:key="index"
>
<el-checkbox :label="item">
<video
controls
v-if="viewLibTab == 1 && fileType2 == 2"
:src="imgApi + '/uploads' + item.fileKey"
></video>
<img v-else :src="imgApi + '/uploads' + item.fileKey" crossorigin="anonymous" />
<div class="down" v-if="viewLibTab == 1 && fileType2 == 1">下载</div>
<!-- <el-image
v-else
:src="imgApi + '/uploads' + item.fileKey"
fit="cover"
:preview-src-list="[imgApi + '/uploads' + item.fileKey]"
></el-image>-->
</el-checkbox>
</div>
</el-checkbox-group>
</div>
</div>
<div class="boxs jz" v-else>
<el-checkbox-group v-model="checkList">
<div
class="box"
v-for="(item, index) in photoList"
:key="index"
:class="viewLibTab == 2 && fileType == 1 ? 'boxv2' : ''"
>
<el-checkbox :label="item.name">
<el-image
v-if="viewLibTab == 2 && fileType == 0"
:src="item.image"
fit="cover"
:preview-src-list="[item.image]"
></el-image>
<video controls v-if="viewLibTab == 2 && fileType == 1" :src="item.image"></video>
<div
class="down"
v-if="viewLibTab == 2 && fileType == 0"
@click="onDownload(item.image)"
>下载</div>
</el-checkbox>
</div>
</el-checkbox-group>
</div>
</div>
<div class="foot" v-if="moreShow || viewLibTab == 2 || fileType2 == 2">
<div class="btns blue" v-if="selectAll">全选</div>
<div class="btns blue" v-else>取消全选</div>
<div class="btns" v-if="viewLibTab == 2">转存</div>
<div class="btns red" style>删除</div>
</div>
</div>
</div>
</template>
<script>
import { flightTaskAPI, Control_API } from "../../../../../../../../api";
export default {
name: "ViewLib",
data() {
return {
checkList: [], // 多选结果
selectAll: false, //全选
viewLibTab: 1, // 视图库tab索引, 1: 视图, 2: 机载
aiType: 1, // 图片类型
aiTypeList: [
// 普通图片或ai图片选项
{
id: 1,
value: "图片",
},
{
id: 2,
value: "AI图片",
},
// {
// id: 0,
// value: "全部",
// },
// {
// id: 1,
// value: "人脸识别",
// },
// {
// id: 2,
// value: "车辆识别",
// },
// {
// id: 9,
// value: "人流识别",
// },
// {
// id: 4,
// value: "游泳识别",
// },
// {
// id: 5,
// value: "跌倒检测",
// },
// {
// id: 6,
// value: "异物检测",
// },
// {
// id: 7,
// value: "火焰烟雾",
// },
// {
// id: 8,
// value: "车辆朝向",
// },
// {
// id: 9,
// value: "车辆类型检测",
// },
// {
// id: 10,
// value: "车道分割线",
// },
// {
// id: 11,
// value: "绿化带分割",
// },
// {
// id: 10,
// value: "车牌识别",
// },
], //视图库类型
fileType: 1, //视图文件类型
fileType2: 1, //机载文件类型
photoList: [], //资源列表
moreShow: false, //显示更多
};
},
mounted() {
this.init();
},
methods: {
async init() {
let res = await Control_API.getSortieImage({
imageType: this.aiType,
page: 1,
pageSize: 999,
});
this.photoList = res.data.records;
},
/**
* 视图库tab更改
*/
async onChangeViewLibTab(index) {
this.viewLibTab = index;
},
/**
* 图片ai类型切换
*/
onChangeAiType() {
this.init();
},
/**
* 更改视图中文件类型
*/
onChangeFileType(i) {
this.fileType = i;
this.init();
},
/**
* 更改机载中文件类型
*/
onChangeFileType2(i) {
this.fileType2 = i;
this.init();
},
onDownload(url) {
window.open(url, "_self");
},
},
};
</script>
<style lang="scss" scoped>
.stk::v-deep {
position: absolute;
right: 70px;
top: 190px;
width: 470px;
height: 450px;
background: rgba(12, 34, 73, 0.7);
border-radius: 10px;
border: 1px solid rgba(26, 92, 246, 0.5);
backdrop-filter: blur(1px);
.stk_head {
display: flex;
cursor: pointer;
div {
padding: 0 8px;
// width: 243px;
width: 100%;
text-align: center;
line-height: 32px;
font-size: 16px;
font-family: YouSheBiaoTiHei;
color: #ffffff;
line-height: 21px;
text-shadow: 0px 1px 1px rgba(2, 32, 56, 0.2);
}
.ac {
background: linear-gradient(
180deg,
#9198ff 0%,
rgba(45, 81, 153, 0.45) 40%,
#05091a 100%
);
box-shadow: inset 0px 0px 10px 2px #3f9dff;
border-radius: 10px 0px 0px 0px;
border: 1px solid #427dff;
font-size: 20px;
font-family: YouSheBiaoTiHei;
color: #14faff;
line-height: 26px;
text-shadow: 0px 1px 1px rgba(2, 32, 56, 0.2);
background: linear-gradient(
135deg,
#e3aa77 0%,
#f5cda9 38%,
#f9ecd3 58%,
#fcdbb1 79%,
#edb07a 100%
);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.bc {
background: linear-gradient(
180deg,
#9198ff 0%,
rgba(45, 81, 153, 0.45) 40%,
#05091a 100%
);
box-shadow: inset 0px 0px 10px 2px #3f9dff;
border-radius: 0px 10px 0px 0px;
border: 1px solid #427dff;
font-size: 20px;
font-family: YouSheBiaoTiHei;
color: #14faff;
line-height: 26px;
text-shadow: 0px 1px 1px rgba(2, 32, 56, 0.2);
background: linear-gradient(
135deg,
#e3aa77 0%,
#f5cda9 38%,
#f9ecd3 58%,
#fcdbb1 79%,
#edb07a 100%
);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
}
.content {
margin-top: 10px;
padding: 0 15px;
display: flex;
flex-direction: column;
height: 405px;
> p {
font-size: 14px;
color: #fff;
cursor: default;
a {
cursor: pointer;
color: #00ffff;
}
}
.foot {
flex-shrink: 0;
margin-top: 12px;
display: flex;
// justify-content: space-between;
align-items: center;
gap: 12px;
.btns {
width: 64px;
height: 32px;
text-align: center;
line-height: 32px;
font-size: 14px;
font-family: MicrosoftYaHei;
color: #ffffff;
background: url("../../assets/images/zc.png") no-repeat;
background-size: 100% 100%;
cursor: pointer;
}
.blue {
background: url("../../assets/images/qx.png") no-repeat;
background-size: 100% 100%;
}
.red {
background: url("../../assets/images/red.png") no-repeat;
background-size: 100% 100%;
}
}
.head {
display: flex;
justify-content: space-between;
align-items: center;
flex-shrink: 0;
.btns {
width: 64px;
height: 32px;
text-align: center;
line-height: 32px;
font-size: 14px;
font-family: MicrosoftYaHei;
color: #ffffff;
background: url("../../assets/images/zc.png") no-repeat;
background-size: 100% 100%;
cursor: pointer;
}
.bg {
background: url("../../assets/images/qx.png") no-repeat;
background-size: 100% 100%;
}
.blue {
background: url("../../assets/images/qx.png") no-repeat;
background-size: 100% 100%;
}
.select {
display: flex;
align-items: center;
.iconfont {
color: #fff;
}
.btns {
margin-right: 16px;
width: 64px;
height: 32px;
text-align: center;
line-height: 32px;
font-size: 14px;
font-family: MicrosoftYaHei;
color: #ffffff;
background: url("../../assets/images/zc.png") no-repeat;
background-size: 100% 100%;
// &:hover {
// background: url("../../assets/images/qx.png") no-repeat;
// background-size: 100% 100%;
// }
}
.bg {
background: url("../../assets/images/qx.png") no-repeat;
background-size: 100% 100%;
}
.el-select {
width: 80px;
height: 32px;
.el-input--suffix {
width: 100%;
height: 100%;
.el-input__inner {
width: 100%;
height: 100%;
}
}
.el-input__suffix {
display: flex;
align-items: center;
}
}
}
}
.lists {
flex: 1;
display: flex;
flex-direction: column;
justify-content: flex-start;
overflow-y: auto;
overflow-x: hidden;
margin-top: 10px;
}
.boxs {
display: flex;
flex-wrap: wrap;
align-content: flex-start;
height: 100%;
}
.boxst {
width: 100%;
display: flex;
flex-direction: column;
height: 100%;
.name {
margin: 0 8px;
display: flex;
justify-content: space-between;
color: #fff;
}
.images {
display: flex;
flex-wrap: wrap;
align-content: flex-start;
.box {
position: relative;
width: 135px;
height: 88px;
background: #ffffff;
border-radius: 2px;
margin-left: 8px;
margin-bottom: 14px;
.el-image {
width: 138px;
height: 88px;
background: #ffffff;
border-radius: 2px;
}
img {
width: 135px;
height: 88px;
}
.down {
position: absolute;
bottom: 0;
right: -3px;
width: 30px;
height: 20px;
text-align: center;
line-height: 20px;
background: rgba($color: #000000, $alpha: 0.6);
color: #fff;
font-size: 12px;
display: none;
}
&:hover {
.down {
display: block;
}
}
}
.boxv2 {
width: 430px;
height: 120px;
margin-left: 0;
video {
width: 430px;
height: 120px;
}
}
}
}
}
.down {
cursor: pointer;
}
.icon-gengxin {
cursor: pointer;
}
}
</style>
\ No newline at end of file
......@@ -82,133 +82,7 @@
<img src="../../assets/images/stk.png" alt />
<span class="dib f8">视图库</span>
</div>
<div class="stk" v-if="showViewLib">
<div class="stk_head">
<div :class="isfk == 1 ? 'ac' : ''">视图</div>
<div :class="isfk == 2 ? 'bc' : ''">机载</div>
</div>
<div class="content">
<!-- 先注释,下次更新要用 -->
<div class="head" style="justify-content: flex-end">
<div class="aitype mr60" v-if="isfk == 1 && !moreshow">
<el-select v-model="aiType" placeholder="全部" @change="changeAiType">
<el-option
v-for="item in aitypeList"
:key="item.id"
:label="item.value"
:value="item.id"
></el-option>
</el-select>
</div>
<div class="select" v-if="isfk == 2">
<div class="btns" :class="filetype == 0 ? 'bg' : ''">图片</div>
<div class="btns" :class="filetype == 1 ? 'bg' : ''">视频</div>
<span class="iconfont icon-gengxin"></span>
</div>
<div class="select" v-if="isfk == 1 && !moreshow">
<div class="btns" :class="filetypev2 == 1 ? 'bg' : ''">图片</div>
<div class="btns" :class="filetypev2 == 2 ? 'bg' : ''">视频</div>
<span class="iconfont icon-gengxin"></span>
</div>
<div class="select" v-if="isfk == 1 && moreshow">
<div class="btns bg">返回</div>
</div>
</div>
<p v-if="isfk == 2 && filetype == 1">
如遇视频无法播放,请
<a href="http://32.128.6.52:4500/11.11平台部署/ChromeStandaloneSetup64.exe">下载最新谷歌</a>
</p>
<div class="lists">
<!-- <div style="text-align: left">asfnjkfassfausfasn</div> -->
<div class="boxs" :style="!moreshow ? 'height: 300px;' : ''" v-if="isfk == 1">
<div class="boxst" :style="!moreshow ? 'height: 280px;' : ''" v-if="!moreshow">
<div class="task" v-for="(item, index) in photoList" :key="index">
<div class="name">
{{ item.taskName }}
<div v-if="isfk == 1">更多</div>
</div>
<div class="images">
<div
class="box"
v-for="(item2, index2) in photoList[index].list"
:key="index2"
:class="isfk == 1 && filetypev2 == 2 ? 'boxv2' : ''"
>
<!-- <el-image v-if="isfk == 1 && filetypev2 == 1" :src="imgApi + '/uploads' + item2.fileKey"
fit="cover" :preview-src-list="[imgApi + '/uploads' + item2.fileKey]"></el-image>-->
<img
v-if="isfk == 1 && filetypev2 == 1"
:src="imgApi + '/uploads' + item2.fileKey"
/>
<video
controls
v-if="isfk == 1 && filetypev2 == 2"
:src="imgApi + '/uploads' + item2.fileKey"
></video>
<div class="down" v-if="isfk == 1 && filetypev2 == 1">下载</div>
</div>
</div>
</div>
</div>
<div v-else>
<el-checkbox-group v-model="checkList">
<div
class="box"
:class="isfk == 1 && filetypev2 == 2 ? 'boxv2' : ''"
v-for="(item, index) in morelist"
:key="index"
>
<el-checkbox :label="item">
<video
controls
v-if="isfk == 1 && filetypev2 == 2"
:src="imgApi + '/uploads' + item.fileKey"
></video>
<img v-else :src="imgApi + '/uploads' + item.fileKey" />
<div class="down" v-if="isfk == 1 && filetypev2 == 1">下载</div>
<!-- <el-image
v-else
:src="imgApi + '/uploads' + item.fileKey"
fit="cover"
:preview-src-list="[imgApi + '/uploads' + item.fileKey]"
></el-image>-->
</el-checkbox>
</div>
</el-checkbox-group>
</div>
</div>
<div class="boxs jz" v-else>
<el-checkbox-group v-model="checkList">
<div
class="box"
v-for="(item, index) in photoList"
:key="index"
:class="isfk == 2 && filetype == 1 ? 'boxv2' : ''"
>
<el-checkbox :label="item">
<el-image
v-if="isfk == 2 && filetype == 0"
:src="item.jsonFilePath"
fit="cover"
:preview-src-list="[item.jsonFilePath]"
></el-image>
<video controls v-if="isfk == 2 && filetype == 1" :src="item.jsonFilePath"></video>
<div class="down" v-if="isfk == 2 && filetype == 0">下载</div>
</el-checkbox>
</div>
</el-checkbox-group>
</div>
</div>
<div class="foot" v-if="moreshow || isfk == 2 || filetypev2 == 2">
<div class="btns blue" v-if="allshow">全选</div>
<div class="btns blue" v-else>取消全选</div>
<div class="btns ml12" v-if="isfk == 2">转存</div>
<div class="btns red ml12">删除</div>
</div>
</div>
</div>
<ViewLib v-if="showViewLib"></ViewLib>
</div>
<!-- 警灯控制 -->
<div v-if="showAlarmLamp == true">
......@@ -265,9 +139,7 @@
v-if="showControlList"
></ControlList>
<Health v-if="showHealth" @exit="showHealth = false"></Health>
<Mount
v-if="showMount"
></Mount>
<Mount v-if="showMount"></Mount>
<!-- 喊话器 -->
<MMCGimbalP1
class="PagerP1"
......@@ -291,6 +163,7 @@ import ControlList from "./components/controlList";
import MountController from "./components/mountController";
import Mount from "./components/mount";
import MMCGimbalP1 from "./components/PagerP1";
import ViewLib from './components/viewLib';
export default {
name: "ControlRight",
......@@ -300,6 +173,7 @@ export default {
MountController,
Mount,
MMCGimbalP1,
ViewLib
},
data() {
return {
......@@ -333,6 +207,7 @@ export default {
this.hideAll();
this[key] = !this[key];
},
},
};
</script>
......
......@@ -3,7 +3,6 @@
<MMCDataTransferPanel
class="data-panel"
:device="device"
:wsShow="wsShow"
:throttleValue="throttleValue"
:uav-battery="battery"
:uav-data="uavData"
......@@ -12,6 +11,8 @@
<ControlBottom></ControlBottom>
<!-- 健康管理-挂载-警灯-无人机 -->
<ControlRight></ControlRight>
<!-- 任务 智能识别 -->
<ControlLeft></ControlLeft>
</div>
</template>
......@@ -20,19 +21,20 @@ import { mapState } from "vuex";
import Moment from "moment";
import ControlBottom from './components/controlBottom';
import ControlRight from './components/controlRight';
import ControlLeft from './components/controlLeft';
export default {
name: 'ControlPanel',
components: {
ControlBottom,
ControlRight
ControlRight,
ControlLeft
},
data() {
return {
device: {
cateName: "px4",
},
wsShow: false,
throttleValue: 500,
battery: {
voltage: 0,
......
<template>
<div class="uav-list" :class="{ collapse: collapseFlag }">
<div class="uav-list" :class="{ collapse: listCollapse }">
<img
@click="collapseFlagfn"
v-if="collapseFlag"
v-if="listCollapse"
style="transform: rotate(180deg)"
src="./assets/images/hs.png"
class="icon-collapse uav-list_btn"
......@@ -59,10 +59,23 @@ export default {
data() {
return {
uavList: [], // 无人机列表
collapseFlag: false, // 收起列表按钮
uavSearchContent: "", // 无人机搜索内容
};
},
computed: {
// 收起列表按钮
listCollapse: {
get(){
return this.$store.state.MMCFlightControlCenter.listCollapse;
},
set(val){
this.$store.commit('MMCFlightControlCenter/setState', {
key: 'listCollapse',
value: val
})
}
}
},
mounted() {
// this.uavList = data.data;
this.initList();
......@@ -73,7 +86,7 @@ export default {
this.uavList = res.data;
},
collapseFlagfn() {
this.collapseFlag = !this.collapseFlag;
this.listCollapse = !this.listCollapse;
},
/**
* 无人机搜索
......
......@@ -32,11 +32,11 @@ export default {
default: null,
},
},
beforeCreate(){
if(!window.mmc){
window.mmc = {};
beforeCreate() {
if (!window.$mmc) {
window.$mmc = {};
}
window.mmc.store = this.$store;
window.$mmc.store = this.$store;
},
created() {
if (!window.$mmc) {
......@@ -71,7 +71,13 @@ export default {
</style>
<style lang="scss">
.mmc-dialog {
.mmc-filght-control-center {
.el-input__inner {
background-color: #02173d;
color: #00aacb;
border: 1px solid #2b56b7;
}
.el-dialog__body {
button:nth-child(2) {
box-shadow: inset 0 0 5px #00ffff;
......@@ -79,5 +85,91 @@ export default {
opacity: 0.8;
}
}
* {
/* 滚动条整体样式 */
&::-webkit-scrollbar {
width: 10px; /* 滚动条宽度 */
}
/* 滚动条滑块样式 */
&::-webkit-scrollbar-thumb {
background-color: #02173d; /* 滑块颜色 */
}
/* 滚动条滑块悬停样式 */
&::-webkit-scrollbar-thumb:hover {
background-color: #112d5b; /* 悬停时滑块颜色 */
}
&::-webkit-scrollbar-track-piece {
/* background-color: #182F5C; */
}
&::-webkit-scrollbar-track {
background-color: #182f5c;
}
}
}
.mmc {
// 所有下拉选择框样式
&.el-select-dropdown {
border: none !important;
//item选项的hover样式
.el-select-dropdown__item.hover,
.el-select-dropdown__item:hover {
background: #34466e !important;
}
.option.hover,
.option:hover {
background-image: linear-gradient(
90deg,
rgba(44, 135, 176, 0.7) 0%,
rgba(26, 100, 139, 0.37) 51%,
rgba(7, 61, 98, 0.7) 100%
);
font-family: MicrosoftYaHei;
font-size: 12px;
color: #00f5ff;
letter-spacing: 0 !important;
font-weight: 400 !important;
}
.el-select-dropdown__item {
color: #00aeff !important;
.selected {
background-color: #606266 !important;
}
}
.option {
font-family: MicrosoftYaHei;
font-size: 12px !important;
color: rgba(146, 217, 255, 0.7) !important;
letter-spacing: 0;
font-weight: 400 !important;
}
.popper__arrow::after {
border-bottom-color: #161d2d !important;
}
.el-scrollbar {
overflow: hidden;
position: relative;
background: #0d224f !important;
border: 1px solid #178890;
}
&.is-multiple {
.el-select-dropdown__item.selected {
background-color: #34466e !important;
}
}
}
}
</style>
\ No newline at end of file
......@@ -31,14 +31,14 @@ export default function main(elementOrSelector, options = {}){
if(!options.hasMMCSTLVue2){
Vue.use(MMCSTL);
}
if(!window.mmc){
window.mmc = {};
if(!window.$mmc){
window.$mmc = {};
}
window.mmc.store = new Vuex.Store(store);
window.$mmc.store = new Vuex.Store(store);
return new Vue({
render: (h) => h(App),
router,
store: window.mmc.store,
store: window.$mmc.store,
}).$mount(elementOrSelector);
}
......
......@@ -26,6 +26,7 @@ export default {
},
},
cesium3DModels: [], //cesium的3D模型
listCollapse: false, //无人机或盈巢列表是否折叠
},
mutations: {
/**
......
import Vue from 'vue';
import Vue from "vue";
import { Control_API } from "../api";
import mount from "../components/mount";
if(!window.mmc){
window.mmc = {};
if (!window.$mmc) {
window.$mmc = {};
}
window.mmc.vue =Vue;
window.$mmc.vue = Vue;
let positions = []; // 飞机走过的点
const defaultPos = {
......@@ -14,7 +13,6 @@ const defaultPos = {
longitude: 113.75, // 经度
};
const uavRealTimeData = {
attitude: {
roll: 0, // 飞机的俯仰值:向前为正,向后为负。单位为度。
......@@ -38,7 +36,7 @@ const uavRealTimeData = {
levelDivisor: 0, // 水平因子
verticalDivisor: 0, // 垂直因子
type: 15, // 19 RTK,15 GPS,0 默认(固件未更新)
isMainSensor: false // true主传感器,false备用传感器
isMainSensor: false, // true主传感器,false备用传感器
},
rtk: {
absoluteAlt: 0, // 绝对高度,以米为单位
......@@ -48,7 +46,7 @@ const uavRealTimeData = {
levelDivisor: 0, // 水平因子
verticalDivisor: 0, // 垂直因子
type: 19, // 19 RTK,15 GPS,0 默认(固件未更新)
isMainSensor: false // true主传感器,false备用传感器
isMainSensor: false, // true主传感器,false备用传感器
},
flyDistance: 0, // 当前飞行里程
distanceToHome: 0, // 距离home的位置
......@@ -57,7 +55,8 @@ const uavRealTimeData = {
velocityZ: 0, // 使用NED(北-东-下)坐标系,飞机在z方向上的当前速度,以米/秒为单位, 爬升率
voltage: 0, // 返回当前电池电压(V)
chargeRemaining: 0, // 电池中的剩余能量百分比
obstacle: null/* {
rcChannelState: 0, // 0摇杆处于中位,-99摇杆未连接,-98为外场摇杆权限,1与-1俯仰,2与-2横滚,3与-3油门,4与-4偏航(大于0表示该通道处于高位,小于0表示该通道处于低位)
obstacle: null /* {
// 避障信息(#272)
minDistance: 100, // 壁障最小距离单位(cm)
maxDistance: 2000, // 壁障最大距离单位(cm)
......@@ -150,7 +149,7 @@ const state = {
uavModelEntity: null, // 飞机模型实例
smuTime: false, // 模拟上报定时器
airlineData: null, // 当前选择的航线数据
airlineId: '', // 当前选择的航线id(任务中带的航线)
airlineId: "", // 当前选择的航线id(任务中带的航线)
flyMode: "auto", // 飞行模式, auto: 自动, manual: 手动,
showVideo: false, // 显示视频
mountList: [
......@@ -209,7 +208,7 @@ const actions = {
commit("setState", { key: "showAIVideo", value: false });
commit("setState", { key: "showMenu", value: false });
commit("setState", { key: "uavRealTimeData", value: uavRealTimeData });
positions = [];
},
/**
......@@ -279,16 +278,16 @@ const actions = {
type258.gps = type258.rtk;
}
// 257返回单次电池信息, 实际飞机可能有多个电池, 但是每次只返回其中一个信息, 通过id判断来组成电池列表
let batteryList = state.uavRealTimeData?.batteryList || [];
if(type257){
let findIndex = -1;
let batteryList = state.uavRealTimeData?.batteryList || [];
if (type257) {
let findIndex = -1;
batteryList.find((item, i) => {
if(item.id === type257.id){
if (item.id === type257.id) {
findIndex = i;
return true;
}
});
if(findIndex !== -1){
if (findIndex !== -1) {
batteryList[findIndex] = type257;
} else {
batteryList.push(type257);
......@@ -304,7 +303,7 @@ const actions = {
...type2017,
obstacle: type272,
healthData: type275,
batteryList
batteryList,
},
});
......@@ -406,22 +405,25 @@ const actions = {
},
/**
* 订阅无人机数据
* @param {*} param0
* @param {object} data
* @param {*} param0
* @param {object} data
*/
subscribe({ state, dispatch }){
if(state.uav.network === 1){
window.mmc.store.dispatch("MMCMQTT/subscribe", {
topic: 'PX4/RECEIVE/' + state.uav.hardId,
callback(ok){
ok && console.log('mqtt订阅主题', 'PX4/RECEIVE/' + state.uav.hardId)
subscribe({ state, dispatch }) {
if (state.uav.network === 1) {
window.$mmc.store.dispatch("MMCMQTT/subscribe", {
topic: "PX4/RECEIVE/" + state.uav.hardId,
callback(ok) {
ok && console.log("mqtt订阅主题", "PX4/RECEIVE/" + state.uav.hardId);
dispatch("createUavModel");
dispatch("createAirline");
dispatch("flyToUavModel");
}
},
});
} else {
window.mmc.store.dispatch("MMCGroundStation/subscribe", state.uav.hardId);
window.$mmc.store.dispatch(
"MMCGroundStation/subscribe",
state.uav.hardId
);
// 由于地面站连接没响应数据,1秒后再创建飞机对象
setTimeout(() => {
dispatch("createUavModel");
......@@ -432,16 +434,19 @@ const actions = {
},
/**
* 取消订阅
* @param {} param0
* @param {} param0
*/
unsubscribe({ state, dispatch }){
if(state.uav.network === 1){
window.mmc.store.dispatch("MMCMQTT/unsubscribe", state.uav.hardId);
unsubscribe({ state, dispatch }) {
if (state.uav.network === 1) {
window.$mmc.store.dispatch("MMCMQTT/unsubscribe", state.uav.hardId);
} else {
window.mmc.store.dispatch("MMCGroundStation/unsubscribe", state.uav.hardId);
window.$mmc.store.dispatch(
"MMCGroundStation/unsubscribe",
state.uav.hardId
);
}
dispatch('destroy');
dispatch("destroy");
},
/**
* 创建飞机模型
......@@ -545,10 +550,10 @@ const actions = {
});
// 上传航线指令
const waypointList = JSON.parse(state.airlineData?.content);
window.mmc.store.dispatch("MMCMQTT/publish", {
window.$mmc.store.dispatch("MMCMQTT/publish", {
topic: "PX4/OBTAIN/" + state.uav.hardId,
data: {
type: window.mmc.store.state.MMCMQTT.orders.航线上传,
type: window.$mmc.store.state.MMCMQTT.orders.航线上传,
data: {
taskId: state.airlineData.id,
flightSortiesID: getFlightSortic.data,
......@@ -564,10 +569,10 @@ const actions = {
});
// 告诉飞控开始任务,并且把架次号和 任务id传过去
window.mmc.store.dispatch("MMCMQTT/publish", {
window.$mmc.store.dispatch("MMCMQTT/publish", {
topic: "PX4/OBTAIN/" + state.uav.hardId,
data: {
type: window.mmc.store.state.MMCMQTT.orders.绑定任务id,
type: window.$mmc.store.state.MMCMQTT.orders.绑定任务id,
data: {
taskId: state.airlineData.id,
flightSortiesID: getFlightSortic.data,
......@@ -580,10 +585,10 @@ const actions = {
// 起飞指令
setTimeout(() => {
window.mmc.store.dispatch("MMCMQTT/publish", {
window.$mmc.store.dispatch("MMCMQTT/publish", {
topic: "PX4/OBTAIN/" + state.uav.hardId,
data: {
type: window.mmc.store.state.MMCMQTT.orders.航线一键起飞,
type: window.$mmc.store.state.MMCMQTT.orders.航线一键起飞,
data: {
taskId: state.airlineData.id,
seq: 0,
......@@ -600,7 +605,7 @@ const actions = {
}
} else {
// 地面站链路
window.mmc.store.dispatch("MMCGroundStation/order", {
window.$mmc.store.dispatch("MMCGroundStation/order", {
order: "航线上传",
data: {
cmdValue: state.airlineData?.id,
......@@ -610,7 +615,7 @@ const actions = {
// 起飞指令
setTimeout(() => {
window.mmc.store.dispatch("MMCGroundStation/order", {
window.$mmc.store.dispatch("MMCGroundStation/order", {
order: "起飞",
data: {},
deviceHardId: state.uav.hardId,
......@@ -628,7 +633,7 @@ const actions = {
if (state.uav.network == 1) {
try {
// 结束航线指令
window.mmc.store.dispatch("MMCMQTT/publish", {
window.$mmc.store.dispatch("MMCMQTT/publish", {
topic: "PX4/OBTAIN/" + state.uav.hardId,
data: {
type: 525,
......@@ -645,7 +650,7 @@ const actions = {
} else {
try {
// //地面站链路
window.mmc.store.dispatch("MMCGroundStation/order", {
window.$mmc.store.dispatch("MMCGroundStation/order", {
order: "结束平台任务",
data: {
cmdFunction: 2280,
......@@ -660,7 +665,7 @@ const actions = {
// //起飞指令
// setTimeout(() => {
// window.mmc.store.dispatch("MMCGroundStation/order", {
// window.$mmc.store.dispatch("MMCGroundStation/order", {
// order: "起飞",
// data: {},
// deviceHardId: state.uav.hardId,
......@@ -676,10 +681,10 @@ const actions = {
*/
land({ state }, data) {
if (state.uav.network == 1) {
window.mmc.store.dispatch("MMCMQTT/publish", {
window.$mmc.store.dispatch("MMCMQTT/publish", {
topic: "PX4/OBTAIN/" + state.uav.hardId,
data: {
type: window.mmc.store.state.MMCMQTT.orders.原地降落,
type: window.$mmc.store.state.MMCMQTT.orders.原地降落,
},
callback() {
data?.callback && data.callback(true);
......@@ -687,7 +692,7 @@ const actions = {
});
} else {
// 地面站链路
window.mmc.store.dispatch("MMCGroundStation/order", {
window.$mmc.store.dispatch("MMCGroundStation/order", {
order: "降落",
data: {},
deviceHardId: state.uav.hardId,
......@@ -702,10 +707,10 @@ const actions = {
*/
pauseFly({ state }, data) {
if (state.uav.network == 1) {
window.mmc.store.dispatch("MMCMQTT/publish", {
window.$mmc.store.dispatch("MMCMQTT/publish", {
topic: "PX4/OBTAIN/" + state.uav.hardId,
data: {
type: window.mmc.store.state.MMCMQTT.orders.暂停航线任务,
type: window.$mmc.store.state.MMCMQTT.orders.暂停航线任务,
},
callback() {
data?.callback && data.callback(true);
......@@ -713,7 +718,7 @@ const actions = {
});
} else {
// 地面站链路
window.mmc.store.dispatch("MMCGroundStation/order", {
window.$mmc.store.dispatch("MMCGroundStation/order", {
order: "悬停",
data: {},
deviceHardId: state.uav.hardId,
......@@ -728,10 +733,10 @@ const actions = {
*/
continueFly({ state }, data) {
if (state.uav.network == 1) {
window.mmc.store.dispatch("MMCMQTT/publish", {
window.$mmc.store.dispatch("MMCMQTT/publish", {
topic: "PX4/OBTAIN/" + state.uav.hardId,
data: {
type: window.mmc.store.state.MMCMQTT.orders.继续航线任务,
type: window.$mmc.store.state.MMCMQTT.orders.继续航线任务,
},
callback() {
data?.callback && data.callback(true);
......@@ -739,7 +744,7 @@ const actions = {
});
} else {
// 地面站链路
window.mmc.store.dispatch("MMCGroundStation/order", {
window.$mmc.store.dispatch("MMCGroundStation/order", {
order: "航线模式",
data: {},
deviceHardId: state.uav.hardId,
......@@ -754,10 +759,10 @@ const actions = {
*/
returnFlight({ state }, data) {
if (state.uav.network == 1) {
window.mmc.store.dispatch("MMCMQTT/publish", {
window.$mmc.store.dispatch("MMCMQTT/publish", {
topic: "PX4/OBTAIN/" + state.uav.hardId,
data: {
type: window.mmc.store.state.MMCMQTT.orders.返航,
type: window.$mmc.store.state.MMCMQTT.orders.返航,
},
callback() {
data?.callback && data.callback(true);
......@@ -765,7 +770,7 @@ const actions = {
});
} else {
// 地面站链路
window.mmc.store.dispatch("MMCGroundStation/order", {
window.$mmc.store.dispatch("MMCGroundStation/order", {
order: "返航",
data: {},
deviceHardId: state.uav.hardId,
......@@ -780,10 +785,10 @@ const actions = {
*/
routeControl({ state }, data) {
if (state.uav.network == 1) {
window.mmc.store.dispatch("MMCMQTT/publish", {
window.$mmc.store.dispatch("MMCMQTT/publish", {
topic: "PX4/OBTAIN/" + state.uav.hardId,
data: {
type: window.mmc.store.state.MMCMQTT.orders.航线控制,
type: window.$mmc.store.state.MMCMQTT.orders.航线控制,
data: {
latitude: data.latitude,
longitude: data.longitude,
......@@ -806,10 +811,10 @@ const actions = {
*/
modeManual({ state }, data) {
if (state.uav.network == 1) {
window.mmc.store.dispatch("MMCMQTT/publish", {
window.$mmc.store.dispatch("MMCMQTT/publish", {
topic: "PX4/OBTAIN/" + state.uav.hardId,
data: {
type: window.mmc.store.state.MMCMQTT.orders.无人机模式切换,
type: window.$mmc.store.state.MMCMQTT.orders.无人机模式切换,
data: "POSITION",
},
callback() {
......@@ -826,10 +831,10 @@ const actions = {
*/
modeAuto({ state }, data) {
if (state.uav.network == 1) {
window.mmc.store.dispatch("MMCMQTT/publish", {
window.$mmc.store.dispatch("MMCMQTT/publish", {
topic: "PX4/OBTAIN/" + state.uav.hardId,
data: {
type: window.mmc.store.state.MMCMQTT.orders.无人机模式切换,
type: window.$mmc.store.state.MMCMQTT.orders.无人机模式切换,
data: "AUTO_MISSION",
},
callback() {
......@@ -853,7 +858,7 @@ const actions = {
"xxx"
);
if (state.uav.network == 1) {
window.mmc.store.dispatch("MMCMQTT/publish", {
window.$mmc.store.dispatch("MMCMQTT/publish", {
topic: "PX4/OBTAIN/" + state.uav.hardId,
data: {
type: 514,
......@@ -870,10 +875,10 @@ const actions = {
*/
modeLAND({ state }, data) {
if (state.uav.network == 1) {
window.mmc.store.dispatch("MMCMQTT/publish", {
window.$mmc.store.dispatch("MMCMQTT/publish", {
topic: "PX4/OBTAIN/" + state.uav.hardId,
data: {
type: window.mmc.store.state.MMCMQTT.orders.无人机模式切换,
type: window.$mmc.store.state.MMCMQTT.orders.无人机模式切换,
data: "LAND",
},
callback() {
......@@ -882,7 +887,7 @@ const actions = {
});
} else {
// 地面站链路
window.mmc.store.dispatch("MMCGroundStation/order", {
window.$mmc.store.dispatch("MMCGroundStation/order", {
order: "指点飞行",
data: {},
deviceHardId: state.uav.hardId,
......@@ -890,15 +895,20 @@ const actions = {
data?.callback && data.callback(true);
}
},
/**
* 发送指令申请内场摇杆控制权限,抢占无人机外场摇杆控制权限
* @param {*} param0
* @param {*} data
*/
changeYGPermissions({ state }, data) {
if (state.uav.network == 1) {
window.mmc.store.dispatch("MMCMQTT/publish", {
window.$mmc.store.dispatch("MMCMQTT/publish", {
topic: "PX4/OBTAIN/" + state.uav.hardId,
data: {
type: 534,
data: {
cmd: 31021,
param1: 1,
cmd: 31021, //内场请求摇杆控制权限
param1: 1, //数值等于1的时候,地面站请求抢占外场权限
param2: 0,
param3: 0,
param4: 0,
......@@ -919,10 +929,10 @@ const actions = {
*/
modeAUTO_RTL({ state }, data) {
if (state.uav.network == 1) {
window.mmc.store.dispatch("MMCMQTT/publish", {
window.$mmc.store.dispatch("MMCMQTT/publish", {
topic: "PX4/OBTAIN/" + state.uav.hardId,
data: {
type: window.mmc.store.state.MMCMQTT.orders.无人机模式切换,
type: window.$mmc.store.state.MMCMQTT.orders.无人机模式切换,
data: "AUTO_RTL",
},
callback() {
......@@ -931,7 +941,7 @@ const actions = {
});
} else {
// 地面站链路
window.mmc.store.dispatch("MMCGroundStation/order", {
window.$mmc.store.dispatch("MMCGroundStation/order", {
order: "指点飞行",
data: {},
deviceHardId: state.uav.hardId,
......@@ -944,10 +954,10 @@ const actions = {
*/
modeAUTO_MISSION({ state }, data) {
if (state.uav.network == 1) {
window.mmc.store.dispatch("MMCMQTT/publish", {
window.$mmc.store.dispatch("MMCMQTT/publish", {
topic: "PX4/OBTAIN/" + state.uav.hardId,
data: {
type: window.mmc.store.state.MMCMQTT.orders.无人机模式切换,
type: window.$mmc.store.state.MMCMQTT.orders.无人机模式切换,
data: "AUTO_MISSION",
},
callback() {
......@@ -956,7 +966,7 @@ const actions = {
});
} else {
// 地面站链路
window.mmc.store.dispatch("MMCGroundStation/order", {
window.$mmc.store.dispatch("MMCGroundStation/order", {
order: "指点飞行",
data: {},
deviceHardId: state.uav.hardId,
......@@ -970,10 +980,10 @@ const actions = {
*/
modePOSITION({ state }, data) {
if (state.uav.network == 1) {
window.mmc.store.dispatch("MMCMQTT/publish", {
window.$mmc.store.dispatch("MMCMQTT/publish", {
topic: "PX4/OBTAIN/" + state.uav.hardId,
data: {
type: window.mmc.store.state.MMCMQTT.orders.无人机模式切换,
type: window.$mmc.store.state.MMCMQTT.orders.无人机模式切换,
data: "POSITION",
},
callback() {
......@@ -982,7 +992,7 @@ const actions = {
});
} else {
// 地面站链路
window.mmc.store.dispatch("MMCGroundStation/order", {
window.$mmc.store.dispatch("MMCGroundStation/order", {
order: "指点飞行",
data: {},
deviceHardId: state.uav.hardId,
......@@ -1021,7 +1031,7 @@ const actions = {
streamData.data.messageID = 1006;
streamData.data.data.recordControl = data.recordControl;
}
window.mmc.store.dispatch("MMCMQTT/publish", {
window.$mmc.store.dispatch("MMCMQTT/publish", {
topic: "PX4/OBTAIN/" + state.uav.hardId,
data: streamData,
callback() {
......@@ -1048,7 +1058,7 @@ const actions = {
// streamData.data.messageID = 1006;
// streamData.data.data.recordControl = this.record;
// }
window.mmc.store.dispatch("MMCMQTT/publish", {
window.$mmc.store.dispatch("MMCMQTT/publish", {
topic: "PX4/OBTAIN/" + state.uav.hardId,
data: streamData,
callback() {
......@@ -1085,7 +1095,7 @@ const actions = {
} else {
streamData.data.messageID = 1007;
}
window.mmc.store.dispatch("MMCMQTT/publish", {
window.$mmc.store.dispatch("MMCMQTT/publish", {
topic: "PX4/OBTAIN/" + state.uav.hardId,
data: streamData,
callback() {
......@@ -1103,10 +1113,10 @@ const actions = {
*/
mountDirective({ state }, data) {
if (state.uav.network == 1) {
window.mmc.store.dispatch("MMCMQTT/publish", {
window.$mmc.store.dispatch("MMCMQTT/publish", {
topic: "PX4/OBTAIN/" + state.uav.hardId,
data: {
type: window.mmc.store.state.MMCMQTT.orders.云台控制指令can包透传,
type: window.$mmc.store.state.MMCMQTT.orders.云台控制指令can包透传,
data: {
mountId: data.mountId,
payload: data.buffer,
......@@ -1119,7 +1129,7 @@ const actions = {
} else {
// 地面站链路
const buff = data.buffer.join(",");
window.mmc.store.dispatch("MMCGroundStation/publish", {
window.$mmc.store.dispatch("MMCGroundStation/publish", {
type: 200,
cmdFunction: null,
data: {
......@@ -1150,9 +1160,9 @@ const actions = {
key: "uav",
value: {
...state.uav,
showPlayer: false
}
})
showPlayer: false,
},
});
} else {
// 获取该无人机视频流信息
let res = await Control_API.uavDetail({
......@@ -1171,9 +1181,9 @@ const actions = {
key: "uav",
value: {
...state.uav,
showPlayer: false
}
})
showPlayer: false,
},
});
}
},
/**
......@@ -1192,10 +1202,10 @@ const actions = {
key: "uav",
value: {
...state.uav,
showPanel: false
}
})
dispatch('unsubscribe');
showPanel: false,
},
});
dispatch("unsubscribe");
} else {
commit("setState", {
key: "showPanel",
......@@ -1205,12 +1215,26 @@ const actions = {
key: "uav",
value: {
...data,
showPanel: true
}
})
dispatch('showPlayer', data);
dispatch('subscribe');
showPanel: true,
},
});
dispatch("showPlayer", data);
dispatch("subscribe");
}
},
/**
* 判断是否已接管
* @param { Number } data.id 无人机id
*/
async isTakeOver({ state }, data) {
let res = await Control_API.uavDetail({ id: data?.id || state.uav.id });
if (
res.data.currentOperator !==
window.$mmc.store.state.MMCFlightControlCenter.userInfo.id
) {
return false;
}
return true;
},
};
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论