241 lines
5.9 KiB
Vue
241 lines
5.9 KiB
Vue
<script setup lang="ts">
|
|
import { h } from 'vue'
|
|
import { polygon } from '@turf/turf'
|
|
import type { DataTableRowKey } from 'naive-ui'
|
|
import { NButton } from 'naive-ui'
|
|
// import { useDrawer } from '@/hooks/draw'
|
|
import type { TType } from '@/hooks/draw'
|
|
import { getHangjing } from '@/api/Hangjing'
|
|
import { useHangjing } from './hooks/hangjing'
|
|
import { convertToWKT } from '@/utils/parseWKT'
|
|
import { useHangjingDetail } from './hooks/hangjingDetail'
|
|
import { useEarth } from '../Earth/hooks/earth'
|
|
import { parseWKT } from '@/utils/parseWKT'
|
|
import { centerOfMass } from '@turf/turf'
|
|
// import { useHangjingStyle } from './hooks/hangjingStyle'
|
|
import Tree from '@/components/Tree/index.vue'
|
|
|
|
const rangeShortcuts = {
|
|
近一天: () => {
|
|
const cur = new Date().getTime()
|
|
return [cur - 24 * 60 * 60 * 1000, cur]
|
|
},
|
|
近一周: () => {
|
|
const cur = new Date().getTime()
|
|
return [cur - 7 * 24 * 60 * 60 * 1000, cur]
|
|
},
|
|
近一月: () => {
|
|
const cur = new Date().getTime()
|
|
return [cur - 30 * 24 * 60 * 60 * 1000, cur]
|
|
},
|
|
近一年: () => {
|
|
const cur = new Date().getTime()
|
|
return [cur - 365 * 24 * 60 * 60 * 1000, cur]
|
|
},
|
|
}
|
|
|
|
const typeOptions = [
|
|
{
|
|
label: '全',
|
|
value: '',
|
|
},
|
|
{
|
|
label: '空',
|
|
value: 'KONG',
|
|
},
|
|
{
|
|
label: '海',
|
|
value: 'HAI',
|
|
},
|
|
]
|
|
|
|
const color = ref('#18A05855')
|
|
|
|
const drawType = ref<TType | null>(null)
|
|
const drawTypeOptions = [
|
|
{
|
|
label: '矩形',
|
|
value: 'RECTANGLE',
|
|
},
|
|
{
|
|
label: '多边形',
|
|
value: 'POLYGON',
|
|
},
|
|
// {
|
|
// label: '圆',
|
|
// value: 'CIRCLE',
|
|
// },
|
|
]
|
|
|
|
const drawnArea = ref<string | null>(null)
|
|
const drawnAreaEntities = []
|
|
const drawArea = () => {
|
|
if (!drawType.value) {
|
|
return
|
|
}
|
|
// TODO: 画图
|
|
const { drawAreaFromType } = useDrawer()
|
|
|
|
drawAreaFromType(drawType.value, (entity, positions) => {
|
|
drawnAreaEntities.push(entity)
|
|
console.log('画图完成', positions)
|
|
if (positions) {
|
|
const ellipsoid = viewer.scene.globe.ellipsoid
|
|
|
|
const posList = positions.map(pos => {
|
|
const cartographic = Cesium.Cartographic.fromCartesian(pos, ellipsoid)
|
|
const latitude = Cesium.Math.toDegrees(cartographic.latitude)
|
|
const longitude = Cesium.Math.toDegrees(cartographic.longitude)
|
|
return [longitude, latitude]
|
|
})
|
|
const area = polygon([[...posList, posList[0]]])
|
|
|
|
const wkt = convertToWKT(area)
|
|
wkt && (drawnArea.value = wkt)
|
|
}
|
|
})
|
|
}
|
|
|
|
const { showDetailsModal } = useHangjingDetail()
|
|
const { flyTo } = useEarth()
|
|
const renderLabel = ({ option }) => {
|
|
// if()
|
|
if (option.data) {
|
|
const textColor = option.data.styleJsonData
|
|
? JSON.parse(option.data.styleJsonData).textColor
|
|
: 'rgba(255,255,255,1)'
|
|
|
|
return h('span', { style: `color:${textColor}` }, option.data.title)
|
|
} else {
|
|
return option.nodeName
|
|
}
|
|
}
|
|
const nodeProps = ({ option }: { option: TreeOption }) => {
|
|
return {
|
|
onclick: () => {
|
|
if (option.children) {
|
|
return
|
|
}
|
|
const {
|
|
dataId,
|
|
data: { geom },
|
|
} = option
|
|
const feature = parseWKT(geom)
|
|
const [lon, lat] = centerOfMass(feature).geometry.coordinates
|
|
if (checkedKeys.value.includes(dataId as string)) {
|
|
flyTo({ lon, lat })
|
|
}
|
|
},
|
|
}
|
|
}
|
|
const renderSuffix = ({ option }) => {
|
|
return (
|
|
option.data &&
|
|
h('div', { class: 'flex items-center gap-2 pr-2' }, [
|
|
h(
|
|
NButton,
|
|
{
|
|
text: true,
|
|
size: 'tiny',
|
|
type: 'info',
|
|
onClick: () =>
|
|
showDetailsModal(`${option.data.title}详情`, option.data),
|
|
},
|
|
{ default: () => '详情' }
|
|
),
|
|
// h(
|
|
// NButton,
|
|
// {
|
|
// text: true,
|
|
// size: 'tiny',
|
|
// type: 'info',
|
|
// onClick: () => showStyleModal(`${option.data.title}样式配置`, option.data),
|
|
// },
|
|
// { default: () => '样式配置' }
|
|
// ),
|
|
])
|
|
)
|
|
}
|
|
|
|
// const checkedKeys = ref<Array<string | number>>([])
|
|
|
|
const {
|
|
initWebSocket,
|
|
addHangjing,
|
|
hjTreeData,
|
|
isLoading,
|
|
timeRange,
|
|
searchTitle,
|
|
type,
|
|
searchHangjing,
|
|
clearSelected,
|
|
getHangjingData,
|
|
checkedKeys,
|
|
} = useHangjing()
|
|
|
|
watch(checkedKeys, val => {
|
|
addHangjing(val)
|
|
})
|
|
|
|
onMounted(() => {
|
|
initWebSocket()
|
|
getHangjingData()
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<div class="flex flex-col gap-2 w-h-full" v-loading="isLoading">
|
|
<n-date-picker
|
|
v-model:formatted-value="timeRange"
|
|
clearable
|
|
type="datetimerange"
|
|
:shortcuts="rangeShortcuts"
|
|
:update-value-on-close="true"
|
|
format="yyyy-MM-dd HH:mm:ss"
|
|
/>
|
|
<div class="flex gap-2">
|
|
<n-input class="w-auto" v-model:value="searchTitle" />
|
|
<n-select class="w-40" v-model:value="type" :options="typeOptions" />
|
|
<!-- <n-color-picker
|
|
v-model:value="color"
|
|
:modes="['rgb', 'hex']"
|
|
:swatches="[
|
|
'#FFFFFF55',
|
|
'#18A05855',
|
|
'#2080F055',
|
|
'#F0A02055',
|
|
'rgba(208, 48, 80, 0.5)',
|
|
]"
|
|
/> -->
|
|
<!-- <n-input-group>
|
|
<n-select
|
|
v-model:value="drawType"
|
|
:options="drawTypeOptions"
|
|
placeholder="区域查询绘制类型"
|
|
/>
|
|
<n-button type="info" @click="drawArea">绘制</n-button>
|
|
</n-input-group> -->
|
|
<n-input-group class="flex-1">
|
|
<n-button @click="clearSelected">重置</n-button>
|
|
<n-button type="primary" @click="searchHangjing">检索</n-button>
|
|
</n-input-group>
|
|
</div>
|
|
<!-- <n-data-table class="flex-1" :columns="columns" :data="data" :row-key="(rowData: Record<string, any>) => rowData.id"
|
|
flex-height @update:checked-row-keys="handleCheck" /> -->
|
|
<!-- :pagination="paginationReactive" -->
|
|
|
|
<tree
|
|
:data="hjTreeData"
|
|
:key-field="'dataId'"
|
|
:label-field="'nodeName'"
|
|
v-model:checked="checkedKeys"
|
|
showSearch
|
|
:renderSuffix="renderSuffix"
|
|
:renderLabel="renderLabel"
|
|
:nodeProps="nodeProps"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<style lang="scss" scoped></style>
|