RESCUEWeb/src/views/TaskDemand.vue

356 lines
8.8 KiB
Vue
Raw Normal View History

2025-09-08 10:02:48 +08:00
<template>
<div class="container">
<div class="left" v-show="isShow">
<img class="fold" v-show="isShow" src="@/assets/icons/折叠.png" @click="handleFold">
<div class="search">
<div class="input-bar">
<el-input
v-model="rescueCode"
style="width: 120px"
size="large"
placeholder="任务编号"
/>
<el-select
v-model="rescueType"
placeholder="任务类型"
size="large"
style="width: 120px"
>
<el-option label="应急搜捞" value="SAR" />
<el-option label="专项调查" value="SI" />
</el-select>
<el-select
v-model="rescueResponseLevel"
placeholder="响应等级"
size="large"
style="width: 120px"
>
<el-option label="一级" value="一级" />
<el-option label="二级" value="二级" />
<el-option label="三级" value="三级" />
</el-select>
</div>
</div>
<div class="btn-bar">
<el-button :icon="RefreshRight" @click="onReset">重置</el-button>
<el-button type="primary" :icon="Search" @click="onSearch">搜索</el-button>
</div>
<div class="line" />
<div class="list">
<div class="item" v-for="item in dataList" :key="item.id">
<div class="name">{{ item.rescue_code }}</div>
<div class="time">{{ item.fill_time }}</div>
<div class="row">
<div class="col">航次<span>{{ item.voyage_name }}</span></div>
<div class="col">任务状态<span>{{ item.rescue_status }}</span></div>
</div>
<div class="row">
<div class="col">快速响应等级<span>{{ item.rescue_response_level }}</span></div>
<div class="col">目标名称<span>{{ item.rescue_target_name }}</span></div>
</div>
<div class="row">
<div class="col">任务类型<span>{{ item.rescue_type === 'SAR' ? '应急搜捞' : '专项调查' }}</span></div>
</div>
</div>
</div>
<div class="pagination">
<el-pagination
v-model:current-page="currentPage"
v-model:page-size="pageSize"
layout="total, prev, pager, next"
:total="total"
@current-change="handleCurrentChange"
/>
</div>
</div>
<baidu-map class="map" :center="center" :zoom="zoom" @ready="handler">
<img class="unfold" v-show="!isShow" src="@/assets/icons/展开.png" @click="handleUnfold">
<bm-view class="map-view"></bm-view>
<bm-navigation anchor="BMAP_ANCHOR_TOP_RIGHT"></bm-navigation>
<bm-marker
v-for="(item, index) in markers"
:key="index"
:position="item.position"
:icon="{url: item.icon, size: {width: 16, height: 16}}"
@click="markerClick(item.id)"
>
</bm-marker>
</baidu-map>
<el-dialog
v-model="dialogVisible"
title="任务详情"
width="500"
>
<div class="item">
<div class="name">{{ currentMarker.rescue_code }}</div>
<div class="time">{{ currentMarker.fill_time }}</div>
<div class="row">
<div class="col">航次<span>{{ currentMarker.voyage_name }}</span></div>
<div class="col">任务状态<span>{{ currentMarker.rescue_status }}</span></div>
</div>
<div class="row">
<div class="col">快速响应等级<span>{{ currentMarker.rescue_response_level }}</span></div>
<div class="col">目标名称<span>{{ currentMarker.rescue_target_name }}</span></div>
</div>
<div class="row">
<div class="col">任务类型<span>{{ currentMarker.rescue_type === 'SAR' ? '应急搜捞' : '专项调查' }}</span></div>
</div>
</div>
</el-dialog>
</div>
</template>
<script setup>
import {ref, onMounted} from 'vue'
import { Search, RefreshRight } from '@element-plus/icons-vue'
import { regPage } from '@/api/task.js'
// 导入静态图片icon
import markerIcon1 from "@/assets/icons/标注点1.png";
import markerIcon2 from "@/assets/icons/标注点2.png";
import markerIcon3 from "@/assets/icons/标注点3.png";
import {BaiduMap} from "vue-baidu-map-3x";
// 左侧数据栏展开与收缩
const isShow = ref(true)
const handleFold = () => {
isShow.value = false
}
const handleUnfold = () => {
isShow.value = true
}
const rescueCode = ref('')
const rescueType = ref('')
const rescueResponseLevel = ref('')
const currentPage = ref(1)
const pageSize = ref(10)
const start = ref(0)
const total = ref(0)
// 列表数据
const dataList = ref([])
const markers = ref([])
const handleCurrentChange = (val) => {
currentPage.value = val
start.value = pageSize.value * (val -1)
getDataList()
}
// 获取列表数据
const getDataList = () => {
regPage({
start: start.value,
limit: 10,
rescue_type: rescueType.value,
rescue_response_level: rescueResponseLevel.value,
rescue_code: rescueCode.value,
}).then(res => {
dataList.value = res.page.records
const data = []
dataList.value.forEach(item => {
if (item.rescue_status === '任务开始') {
data.push({
position: {
lng: item.rescue_target_lon,
lat: item.rescue_target_lat
},
icon: markerIcon1,
id: item.tsy_id
})
}
if (item.rescue_status === '任务处理中') {
data.push({
position: {
lng: item.rescue_target_lon,
lat: item.rescue_target_lat
},
icon: markerIcon2,
id: item.tsy_id
})
}
if (item.rescue_status === '任务已完成') {
data.push({
position: {
lng: item.rescue_target_lon,
lat: item.rescue_target_lat
},
icon: markerIcon3,
id: item.tsy_id
})
}
})
markers.value = data
total.value = res.page.total
})
}
const onReset = () => {
rescueType.value = ''
rescueResponseLevel.value = ''
rescueCode.value = ''
start.value = 0
getDataList()
}
const onSearch = () => {
start.value = 0
getDataList()
}
// 百度地图
const center = ref({ lng: 116.443, lat: 20.422 })
const zoom = ref(7)
const handler = ({ BMap, map }) => {
}
const dialogVisible = ref(false)
const currentMarker = ref(null)
const markerClick = (id) => {
currentMarker.value = dataList.value.find(item => item.tsy_id === id)
dialogVisible.value = true
console.log('标记被点击', currentMarker.value)
}
// 隐藏百度地图未授权水印
const hideWatermark = () => {
const originShadow = Element.prototype.attachShadow;
Element.prototype.attachShadow = (...args) => {
const shadowRoot = originShadow.call(this, ...args)
const style = document.createElement("style")
style.innerHTML = "div { display: none !important; }"
shadowRoot.appendChild(style)
return shadowRoot
};
}
onMounted(() => {
getDataList()
hideWatermark()
})
</script>
<style lang="scss" scoped>
.container {
height: 820px;
display: flex;
.left {
width: 450px;
position: relative;
padding: 30px;
box-sizing: border-box;
.fold {
position: absolute;
top: 350px;
right: 0;
}
.search {
.input-bar {
display: flex;
justify-content: space-between;
:deep(.el-input-group__append) {
background-color: #409eff;
color: white;
box-shadow: none;
}
}
}
.btn-bar {
margin-top: 10px;
display: flex;
justify-content: center;
}
.line {
margin-top: 10px;
width: 100%;
height: 1px;
background-color: #ddd;
}
.list {
color: #333;
height: 640px;
overflow-y: scroll;
scrollbar-width: none; /* Firefox */
-ms-overflow-style: none; /* IE/Edge */
.item {
padding: 30px 0;
border-bottom: 1px solid #dddddd;
&:hover .name {
color: #409eff;
}
.name {
padding-bottom: 5px;
color: #000;
font-weight: bold;
}
.row {
padding: 5px 0;
display: flex;
gap: 20px;
.col {
flex: 1;
color: #999;
span {
color: #333;
}
}
}
}
}
}
.map {
flex: 1;
width: 100%;
height: 100%;
position: relative;
.unfold {
position: absolute;
top: 350px;
left: 0;
}
.map-view {
width: 100%;
height: 100%;
}
&:deep(.BMap_cpyCtrl) {
display: none;
}
&:deep(.anchorBL) {
display: none;
}
}
}
.pagination {
margin: 10px 0 20px;
display: flex;
justify-content: center;
}
</style>