|
|
@@ -1,14 +1,15 @@ |
|
|
|
|
|
|
|
<template> |
|
|
|
<div class="fire-alarm"> |
|
|
|
<div v-if="warningShow" class="fire-alarm"> |
|
|
|
<span class="close-content" @click="closeWarning">x</span> |
|
|
|
<div class="fire-details"> |
|
|
|
<p class="alarm-title">火灾详情</p> |
|
|
|
<div style="width: 100%; height: 210px"> |
|
|
|
视频位置 |
|
|
|
<div class="pic-content"> |
|
|
|
<img :src="warningPic" class="warning-pic"> |
|
|
|
</div> |
|
|
|
<p class="alarm-detail"> |
|
|
|
<span>火灾位置:</span> |
|
|
|
<span>{{ fireDetail.location }}</span> |
|
|
|
<span style="overflow: hidden;white-space: nowrap;text-overflow: ellipsis;">{{ fireDetail.location }}</span> |
|
|
|
</p> |
|
|
|
<p class="alarm-detail"> |
|
|
|
<span>发现方式:</span> |
|
|
@@ -24,68 +25,77 @@ |
|
|
|
<p class="alarm-title">机场调度</p> |
|
|
|
<p class="dispatch-detail"> |
|
|
|
<span>选择机场:</span> |
|
|
|
<!-- <n-select v-model:value="value" :options="airpotOptions" /> --> |
|
|
|
<a>可用机场列表</a> |
|
|
|
<n-select v-model:value="airValue" placeholder="请选择机场" :options="airpotOptions" /> |
|
|
|
<a @click="checkAirport">可用机场列表</a> |
|
|
|
</p> |
|
|
|
<p class="dispatch-detail"> |
|
|
|
<span>飞行高度:</span> |
|
|
|
<!-- <n-slider v-model:value="value" :default-value="100" :format-tooltip="formatHeight" :max="600" :show-tooltip="true" placement="bottom" /> --> |
|
|
|
<n-slider v-model:value="flyHeight" :default-value="100" :format-tooltip="formatHeight" :max="600" :show-tooltip="true" /> |
|
|
|
</p> |
|
|
|
<p class="execute-btn" @click="handleExecute">立即执行</p> |
|
|
|
<p class="task-log"> |
|
|
|
<span>任务记录</span> |
|
|
|
<p class="execute-btn" @click="test">立即执行</p> |
|
|
|
<p class="alarm-title">任务记录</p> |
|
|
|
<div class="task-log"> |
|
|
|
<ul> |
|
|
|
<li> 2023-01-23 10:00:00 XXXXX机场执行任务 执行中</li> |
|
|
|
<li> 2023-01-23 10:00:00 XXXXX机场执行任务 已完成</li> |
|
|
|
<li> 2023-01-23 10:00:00 XXXXX机场执行任务 已完成</li> |
|
|
|
<li v-for="(item, index) in recoedList" :key="index"> |
|
|
|
<span class="task-time">{{ item.time }}</span> |
|
|
|
<span class="task-name">{{ item.name }}</span> |
|
|
|
<span v-if="item.statusNum === 1" class="task-status on-fly">{{ item.status }}</span> |
|
|
|
<span v-else class="task-status">{{ item.status }}</span> |
|
|
|
</li> |
|
|
|
</ul> |
|
|
|
</p> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<p class="dividing-line" /> |
|
|
|
<div class="fire-verify"> |
|
|
|
<p class="alarm-title">火灾核实</p> |
|
|
|
<!-- <n-input |
|
|
|
v-model:value="value" |
|
|
|
<n-input |
|
|
|
v-model:value="warningDesc" |
|
|
|
type="textarea" |
|
|
|
placeholder="请输入火灾核实描述" |
|
|
|
/> --> |
|
|
|
<p class="verify-btns"> |
|
|
|
<span>忽略</span> |
|
|
|
<span>已处理</span> |
|
|
|
<span @click="ignore">忽略</span> |
|
|
|
<span @click="confirm">已处理</span> |
|
|
|
</p> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
<div class="available-airports"> |
|
|
|
<p class="alarm-title">可用机场列表</p> |
|
|
|
<div class="airport-params"> |
|
|
|
<p> |
|
|
|
<span class="airport-name">机场1</span> |
|
|
|
<span class="airport-find">发现隐患的机场</span> |
|
|
|
</p> |
|
|
|
<p class="uav-params"> |
|
|
|
<img src="@/assets/gis/images/range.png"> |
|
|
|
<span>6km</span> |
|
|
|
<span>续航里程</span> |
|
|
|
</p> |
|
|
|
<p class="uav-params"> |
|
|
|
<img src="@/assets/gis/images/power.png"> |
|
|
|
<span>60%</span> |
|
|
|
<span>无人机电量</span> |
|
|
|
</p> |
|
|
|
<p class="uav-params" style="width: 252px"> |
|
|
|
<img src="@/assets/gis/images/measure.png"> |
|
|
|
<span style="width: 130px">3km</span> |
|
|
|
<span style="width: 130px">机场距离火灾隐患点</span> |
|
|
|
</p> |
|
|
|
<div v-show="airportShow" class="available-airports"> |
|
|
|
<span class="close-content" @click="closeAirport">x</span> |
|
|
|
<p class="alarm-title">可用机场列表 |
|
|
|
</p> |
|
|
|
<div class="airport-list"> |
|
|
|
<div v-for="(item, index) in usableAirport" :key="index" class="airport-params"> |
|
|
|
<p> |
|
|
|
<span class="airport-name">{{ item?.airName }}</span> |
|
|
|
<span v-show="item.find" class="airport-find">发现隐患的机场</span> |
|
|
|
</p> |
|
|
|
<p class="uav-params"> |
|
|
|
<img src="@/assets/gis/images/range.png"> |
|
|
|
<span>6km</span> |
|
|
|
<span>续航里程</span> |
|
|
|
</p> |
|
|
|
<p class="uav-params"> |
|
|
|
<img src="@/assets/gis/images/power.png"> |
|
|
|
<span>60%</span> |
|
|
|
<span>无人机电量</span> |
|
|
|
</p> |
|
|
|
<p class="uav-params" style="width: 252px"> |
|
|
|
<img src="@/assets/gis/images/measure.png"> |
|
|
|
<span style="width: 130px">{{ item.distance }}km</span> |
|
|
|
<span style="width: 130px">机场距离火灾隐患点</span> |
|
|
|
</p> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
<script> |
|
|
|
|
|
|
|
import { reactive, toRefs, watch } from 'vue' |
|
|
|
import { EARLY_SOURCE } from '@/utils/dictionary.js' |
|
|
|
import { getWarningRecord } from '@/api/dashboard/index.js' |
|
|
|
import { EARLY_SOURCE, TASK_STATUS } from '@/utils/dictionary.js' |
|
|
|
import { getWarningRecord, getWarningInfo, ignoreWarning, confirmWarning } from '@/api/dashboard/index.js' |
|
|
|
// turf 用于简单的空间计算 |
|
|
|
import * as turf from '@turf/turf' |
|
|
|
export default { |
|
|
|
name: 'FireAlarm', |
|
|
|
components: { }, |
|
|
@@ -93,28 +103,37 @@ export default { |
|
|
|
data: { |
|
|
|
type: Object, |
|
|
|
default: () => { } |
|
|
|
}, |
|
|
|
airport: { |
|
|
|
type: Object, |
|
|
|
default: () => { } |
|
|
|
} |
|
|
|
}, |
|
|
|
emits: ['start'], |
|
|
|
setup(props, { emit }) { |
|
|
|
const data = reactive({ |
|
|
|
airpotOptions: [ |
|
|
|
{ |
|
|
|
label: '机场1', |
|
|
|
value: 'airport1' |
|
|
|
}, |
|
|
|
{ |
|
|
|
label: '机场2', |
|
|
|
value: 'airport2' |
|
|
|
} |
|
|
|
], |
|
|
|
fireDetail: {} |
|
|
|
airpotOptions: [], |
|
|
|
airport: {}, |
|
|
|
fireDetail: {}, |
|
|
|
warningDesc: '', |
|
|
|
flyHeight: 100, |
|
|
|
usableAirport: [], |
|
|
|
airportShow: false, |
|
|
|
warningInfo: {}, |
|
|
|
airportSelect: '', |
|
|
|
airValue: 0, |
|
|
|
warningPic: null, |
|
|
|
recoedList: [], |
|
|
|
warningShow: false |
|
|
|
}) |
|
|
|
|
|
|
|
watch(() => props.data, (value) => { |
|
|
|
if (JSON.stringify(value) !== '{}') { |
|
|
|
data.warningList = props.data |
|
|
|
showDetail(data.warningList) |
|
|
|
data.warningInfo = props.data |
|
|
|
data.airport = props.airport |
|
|
|
showDetail(data.warningInfo) |
|
|
|
data.warningShow = true |
|
|
|
closeAirport() |
|
|
|
} |
|
|
|
}) |
|
|
|
|
|
|
@@ -126,12 +145,99 @@ export default { |
|
|
|
data.fireDetail.discoveryWay = item.label |
|
|
|
} |
|
|
|
}) |
|
|
|
data.fireDetail.time = value?.updateTime |
|
|
|
data.fireDetail.time = value?.createTime |
|
|
|
|
|
|
|
Promise.all([await getWarningInfo(value.id), await getWarningRecord({ warningId: value.id })]) |
|
|
|
.then(([info, record]) => { |
|
|
|
data.warningPic = info?.data?.fileMarkerUrl |
|
|
|
showUsableAirport(info) |
|
|
|
showWarningRecord(record) |
|
|
|
}) |
|
|
|
.catch(err => { |
|
|
|
console.log(err) |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
// 预警记录列表 |
|
|
|
const showWarningRecord = (record) => { |
|
|
|
data.recoedList.length = 0 |
|
|
|
var status = '' |
|
|
|
var statusNum = 0 |
|
|
|
record?.data?.map((item) => { |
|
|
|
TASK_STATUS?.forEach((val) => { |
|
|
|
if (val.value === item.status) { |
|
|
|
status = val.label |
|
|
|
statusNum = item.status |
|
|
|
} |
|
|
|
}) |
|
|
|
data.recoedList.push({ |
|
|
|
time: item.createTime, |
|
|
|
name: item.name, |
|
|
|
status: status, |
|
|
|
statusNum: statusNum |
|
|
|
}) |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
// 可用机场列表 |
|
|
|
const showUsableAirport = (info) => { |
|
|
|
data.usableAirport.length = 0 |
|
|
|
data.airpotOptions.length = 0 |
|
|
|
const warningLngLat = turf.point([parseFloat(info?.data?.lng), parseFloat(info?.data?.lat)]) |
|
|
|
data.airport?.map((item) => { |
|
|
|
var airportFind = false |
|
|
|
if (parseInt(info?.data?.airportId) === item.id) { |
|
|
|
airportFind = true |
|
|
|
} |
|
|
|
const airLngLat = turf.point([parseFloat(item.longitude), parseFloat(item.latitude)]) |
|
|
|
data.usableAirport.push({ |
|
|
|
id: item.id, |
|
|
|
airName: item.name, |
|
|
|
distance: turf.distance(warningLngLat, airLngLat).toFixed(2), |
|
|
|
find: airportFind |
|
|
|
}) |
|
|
|
data.airpotOptions.push({ |
|
|
|
value: item.id, |
|
|
|
label: item.name |
|
|
|
}) |
|
|
|
}) |
|
|
|
data.airValue = data.airpotOptions[0]?.value || null |
|
|
|
} |
|
|
|
|
|
|
|
const res = await getWarningRecord({ |
|
|
|
warningId: value.id |
|
|
|
const checkAirport = () => { |
|
|
|
data.airportShow = true |
|
|
|
} |
|
|
|
|
|
|
|
const closeAirport = () => { |
|
|
|
data.airportShow = false |
|
|
|
} |
|
|
|
|
|
|
|
const closeWarning = () => { |
|
|
|
closeAirport() |
|
|
|
data.warningShow = false |
|
|
|
} |
|
|
|
|
|
|
|
const test = () => { |
|
|
|
handleExecute() |
|
|
|
} |
|
|
|
|
|
|
|
// 忽略预警 |
|
|
|
const ignore = async() => { |
|
|
|
const res = await ignoreWarning(data.warningInfo.id) |
|
|
|
if (res.code === 0) { |
|
|
|
closeWarning() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 已处理 |
|
|
|
const confirm = async() => { |
|
|
|
const res = await confirmWarning({ |
|
|
|
id: data.warningInfo.id, |
|
|
|
checkResult: data.warningDesc |
|
|
|
}) |
|
|
|
console.log(res) |
|
|
|
if (res.code === 0) { |
|
|
|
closeWarning() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
const formatHeight = (value) => { |
|
|
@@ -145,6 +251,12 @@ export default { |
|
|
|
return { |
|
|
|
...toRefs(data), |
|
|
|
formatHeight, |
|
|
|
checkAirport, |
|
|
|
closeAirport, |
|
|
|
test, |
|
|
|
closeWarning, |
|
|
|
ignore, |
|
|
|
confirm, |
|
|
|
handleExecute |
|
|
|
} |
|
|
|
} |
|
|
@@ -154,7 +266,7 @@ export default { |
|
|
|
<style lang="scss" scoped> |
|
|
|
.fire-alarm { |
|
|
|
position: absolute; |
|
|
|
left: 1345px; |
|
|
|
right: 20px; |
|
|
|
top: 10px; |
|
|
|
width: 407px; |
|
|
|
height: 925px; |
|
|
@@ -163,6 +275,18 @@ export default { |
|
|
|
background: rgba(0, 0, 0, 1); |
|
|
|
} |
|
|
|
|
|
|
|
.close-content { |
|
|
|
width: 34px; |
|
|
|
height: 34px; |
|
|
|
position: relative; |
|
|
|
color: #fff; |
|
|
|
font-size: 20px; |
|
|
|
cursor: pointer; |
|
|
|
float: right; |
|
|
|
text-align: center; |
|
|
|
line-height: 34px; |
|
|
|
} |
|
|
|
|
|
|
|
.alarm-title { |
|
|
|
width: 200px; |
|
|
|
height: 30px; |
|
|
@@ -174,6 +298,18 @@ export default { |
|
|
|
display: inline-block; |
|
|
|
} |
|
|
|
|
|
|
|
.pic-content { |
|
|
|
width: 360px; |
|
|
|
height: 195px; |
|
|
|
position: relative; |
|
|
|
left: 24px; |
|
|
|
} |
|
|
|
|
|
|
|
.warning-pic { |
|
|
|
width: 360px; |
|
|
|
height: 195px; |
|
|
|
} |
|
|
|
|
|
|
|
.alarm-detail { |
|
|
|
width: 100%; |
|
|
|
height: 30px; |
|
|
@@ -181,7 +317,8 @@ export default { |
|
|
|
width: 85px; |
|
|
|
height: 30px; |
|
|
|
line-height: 30px; |
|
|
|
display: inline-block; |
|
|
|
// display: inline-block; |
|
|
|
float: left; |
|
|
|
color: rgba(139, 139, 139, 1); |
|
|
|
font-size: 14px; |
|
|
|
text-align: right; |
|
|
@@ -258,22 +395,50 @@ export default { |
|
|
|
text-align: center; |
|
|
|
margin-left: 30px; |
|
|
|
cursor: pointer; |
|
|
|
} |
|
|
|
|
|
|
|
.task-log { |
|
|
|
width: 100%; |
|
|
|
height: 90px; |
|
|
|
overflow: auto; |
|
|
|
scrollbar-width: none; |
|
|
|
-ms-overflow-style: none; |
|
|
|
&::-webkit-scrollbar { |
|
|
|
display: none; |
|
|
|
} |
|
|
|
.task-time { |
|
|
|
width: 150px; |
|
|
|
height: 30px; |
|
|
|
line-height: 30px; |
|
|
|
color: #fff; |
|
|
|
font-size: 12px; |
|
|
|
text-align: center; |
|
|
|
float: left; |
|
|
|
} |
|
|
|
.task-name { |
|
|
|
width: 200px; |
|
|
|
height: 30px; |
|
|
|
display: inline-block; |
|
|
|
line-height: 30px; |
|
|
|
color: #fff; |
|
|
|
font-size: 12px; |
|
|
|
text-align: left; |
|
|
|
} |
|
|
|
.task-status { |
|
|
|
width: 50px; |
|
|
|
height: 30px; |
|
|
|
display: inline-block; |
|
|
|
line-height: 30px; |
|
|
|
color: rgba(24, 144, 255, 1); |
|
|
|
font-size: 12px; |
|
|
|
text-align: left; |
|
|
|
cursor: pointer; |
|
|
|
|
|
|
|
.task-log { |
|
|
|
width: 100%; |
|
|
|
margin-top: 30px; |
|
|
|
span { |
|
|
|
width: 100%; |
|
|
|
height: 30px; |
|
|
|
display: inline-block; |
|
|
|
line-height: 30px; |
|
|
|
color: #fff; |
|
|
|
font-size: 14px; |
|
|
|
padding-left: 25px; |
|
|
|
&.on-fly { |
|
|
|
color: rgba(34, 211, 61, 1); |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
::v-deep(.fire-verify){ |
|
|
|
width: 100%; |
|
|
@@ -310,8 +475,8 @@ export default { |
|
|
|
|
|
|
|
.available-airports { |
|
|
|
position: absolute; |
|
|
|
left: 764px; |
|
|
|
top: 91px; |
|
|
|
right: 432px; |
|
|
|
top: 350px; |
|
|
|
width: 285px; |
|
|
|
height: 449px; |
|
|
|
opacity: 0.85; |
|
|
@@ -319,6 +484,15 @@ export default { |
|
|
|
background: rgba(0, 0, 0, 1); |
|
|
|
} |
|
|
|
|
|
|
|
::v-deep(.airport-list) { |
|
|
|
height: 410px; |
|
|
|
overflow: auto; |
|
|
|
scrollbar-width: none; |
|
|
|
-ms-overflow-style: none; |
|
|
|
&::-webkit-scrollbar { |
|
|
|
display: none; |
|
|
|
} |
|
|
|
} |
|
|
|
.airport-params { |
|
|
|
width: 278px; |
|
|
|
height: 191px; |
|
|
@@ -365,9 +539,14 @@ export default { |
|
|
|
height: 30px; |
|
|
|
line-height: 30px; |
|
|
|
text-align: center; |
|
|
|
color: #fff; |
|
|
|
font-size: 12px; |
|
|
|
} |
|
|
|
span:nth-child(2){ |
|
|
|
color: #fff; |
|
|
|
} |
|
|
|
span:nth-child(3){ |
|
|
|
color: rgba(171, 171, 171, 1); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
</style> |