ts/src/views/Hangjing/index.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>