RESCUEWeb/src/views/TaskDemand.vue

433 lines
12 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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">
<p class="rule-text">编号规则:任务类型_目标类型_4位编号</p>
<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>
<div class="map">
<div id="cesiumContainer" style="width: 100%; height: 100%;"></div>
<img class="unfold" v-show="!isShow" src="@/assets/icons/展开.png" alt="" @click="handleUnfold">
</div>
<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 * as Cesium from "cesium";
import {ref, onMounted} from 'vue'
import { Search, RefreshRight } from '@element-plus/icons-vue'
import { regPage, getParam } from '@/api/task.js'
import { modifyCesiumMouseWheel, setImageryViewModels } from '@/utils/common'
// 导入静态图片icon
import markerIcon1 from "@/assets/icons/标注点1.png";
import markerIcon2 from "@/assets/icons/标注点2.png";
import markerIcon3 from "@/assets/icons/标注点3.png";
// 左侧数据栏展开与收缩
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 CesiumHostAddr = ref('')
// 获取系统参数列表
const getParamsList = () => {
// 判断当前环境
if (import.meta.env.VITE_APP_ENV === 'development') {
// 开发环境:直接使用环境变量中的值
CesiumHostAddr.value = import.meta.env.VITE_APP_DS_API
initMap();
} else {
// 生产环境:通过接口获取参数
getParam().then(res => {
const data = res.array.find(item => item.param_name === 'CesiumHostAddr')
if (data?.param_value) {
CesiumHostAddr.value = data.param_value
} else {
// 备用方案基于当前窗口位置构建URL[1](@ref)
CesiumHostAddr.value = `${window.location.protocol}//${window.location.hostname}:${window.location.port}/tiles/`
}
initMap();
})
}
}
let viewer;
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJkY2Y5NWY2Ni1mODQ1LTQ3YTUtYjc4Zi1jYzhjMGI2YzcxMWYiLCJpZCI6MTI5ODMwLCJpYXQiOjE2Nzk0Njk5NTd9.DTH54ioOH-HLqeNIetBe9hFyrPOX2Vp1AQmZzw8TIZ4';
const cesiumConfig = {
sceneMode: Cesium.SceneMode.SCENE2D,
// 主页按钮
homeButton: false,
// 场景模式选择器
sceneModePicker: false,
// 全屏按钮
fullscreenButton: false,
// 是否显示点击要素之后显示的信息
infoBox: false,
// 要素选中框
selectionIndicator: false,
// 影像切换
baseLayerPicker: false,
// 启用了阴影效果
shadows: true,
// 启用动画
shouldAnimate: true,
// 是否显示动画控件
animation: false,
// 是否显示时间线控件
timeline: false,
// 是否显示地名查找控件
geocoder: false,
// 是否显示帮助信息控件
navigationHelpButton: false,
contextOptions: {
contextType: 2, // Webgl2:2 ; WebGPU:3
},
// 版权信息
creditContainer: document.createElement('div')
}
const initMap = () => {
viewer = new Cesium.Viewer('cesiumContainer',cesiumConfig)
viewer._cesiumWidget._creditContainer.style.display = 'none'
viewer.scene.sun.show = false
viewer.scene.moon.show = false
viewer.scene.fog.enabled = false
viewer.scene.skyAtmosphere.show = false
viewer.scene.sun.show = false
viewer.scene.skyBox.show = false
viewer.scene.globe.enableLighting = false
viewer.shadowMap.darkness = 0.8
viewer.scene._sunBloom = false
viewer.scene.globe.showGroundAtmosphere = false
viewer.scene.postProcessStages.fxaa.enabled = true
viewer.camera.setView({
// 指定相机初始位置
destination: Cesium.Cartesian3.fromDegrees(112, 18, 4000000)
});
// 改写 Cesium 原生鼠标滚轮事件,地图缩放改为按下 Ctrl + 鼠标滚轮
modifyCesiumMouseWheel(viewer);
// 沉船摄影拼接图
const shipline = new Cesium.WebMapTileServiceImageryProvider(
{
url: CesiumHostAddr.value + 'geoserver/gwc/service/wmts/rest/ougp:正射影像图_GM输出_20240516/{TileMatrixSet}/{TileMatrixSet}:{TileMatrix}/{TileRow}/{TileCol}?format=image/png',
layer: 'ougp:正射影像图_GM输出_20240516',
style: 'default',
format: 'image/png',
tileMatrixSetID: 'EPSG:4326',
tilingScheme: new Cesium.GeographicTilingScheme()
}
)
viewer.imageryLayers.addImageryProvider(shipline)
// 增加6000米等深线
const contour6000 = new Cesium.WebMapTileServiceImageryProvider(
{
url: CesiumHostAddr.value + 'geoserver/gwc/service/wmts/rest/ougp:contour6000/{TileMatrixSet}/{TileMatrixSet}:{TileMatrix}/{TileRow}/{TileCol}?format=image/png',
layer: 'ougp:contour6000',
style: 'default',
format: 'image/png',
tileMatrixSetID: 'EPSG:4326',
tilingScheme: new Cesium.GeographicTilingScheme()
}
)
viewer.imageryLayers.addImageryProvider(contour6000)
const point_options = {
show: true, // 是否展示
pixelSize: 10, // 点的大小
color: Cesium.Color.RED, // 颜色
outlineColor: Cesium.Color.SKYBLUE, // 边框颜色
outlineWidth: 2 // 边框宽度
};
viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(113.27, 18.13),
point: point_options
});
}
onMounted(() => {
getParamsList()
getDataList()
})
</script>
<style lang="scss" scoped>
.container {
height: 820px;
display: flex;
.left {
width: 450px;
position: relative;
padding: 0 30px 30px;
box-sizing: border-box;
.fold {
position: absolute;
top: 350px;
right: 0;
}
.rule-text {
color: #000;
}
.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: 620px;
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;
}
}
}
.pagination {
margin: 10px 0 20px;
display: flex;
justify-content: center;
}
</style>