add
This commit is contained in:
parent
f60eaefa37
commit
ab89bed57d
2
components.d.ts
vendored
2
components.d.ts
vendored
@ -22,6 +22,8 @@ declare module '@vue/runtime-core' {
|
|||||||
Modal: typeof import('./src/components/Modal/index.vue')['default']
|
Modal: typeof import('./src/components/Modal/index.vue')['default']
|
||||||
Nav: typeof import('./src/components/Nav/index.vue')['default']
|
Nav: typeof import('./src/components/Nav/index.vue')['default']
|
||||||
NButton: typeof import('naive-ui')['NButton']
|
NButton: typeof import('naive-ui')['NButton']
|
||||||
|
NCheckbox: typeof import('naive-ui')['NCheckbox']
|
||||||
|
NCheckboxGroup: typeof import('naive-ui')['NCheckboxGroup']
|
||||||
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
|
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
|
||||||
NDataTable: typeof import('naive-ui')['NDataTable']
|
NDataTable: typeof import('naive-ui')['NDataTable']
|
||||||
NDatePicker: typeof import('naive-ui')['NDatePicker']
|
NDatePicker: typeof import('naive-ui')['NDatePicker']
|
||||||
|
7
package-lock.json
generated
7
package-lock.json
generated
@ -28,6 +28,7 @@
|
|||||||
"satellite.js": "^5.0.0",
|
"satellite.js": "^5.0.0",
|
||||||
"seemly": "^0.3.9",
|
"seemly": "^0.3.9",
|
||||||
"v-viewer": "^3.0.21",
|
"v-viewer": "^3.0.21",
|
||||||
|
"vanilla-js-wheel-zoom": "^9.0.4",
|
||||||
"viewerjs": "^1.11.7",
|
"viewerjs": "^1.11.7",
|
||||||
"vue": "^3.2.45",
|
"vue": "^3.2.45",
|
||||||
"vue-draggable-plus": "^0.5.6",
|
"vue-draggable-plus": "^0.5.6",
|
||||||
@ -15120,6 +15121,12 @@
|
|||||||
"spdx-expression-parse": "^3.0.0"
|
"spdx-expression-parse": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/vanilla-js-wheel-zoom": {
|
||||||
|
"version": "9.0.4",
|
||||||
|
"resolved": "https://registry.npmmirror.com/vanilla-js-wheel-zoom/-/vanilla-js-wheel-zoom-9.0.4.tgz",
|
||||||
|
"integrity": "sha512-OjmS9ihEKBCRw2OQ7IiIdQGXdC5gTEEmtcAWZcPeNAJaYiS61KCd02Z72YMtIoXLGN5TZP+wliBMylLAsr6wow==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/vdirs": {
|
"node_modules/vdirs": {
|
||||||
"version": "0.1.8",
|
"version": "0.1.8",
|
||||||
"resolved": "https://registry.npmmirror.com/vdirs/-/vdirs-0.1.8.tgz",
|
"resolved": "https://registry.npmmirror.com/vdirs/-/vdirs-0.1.8.tgz",
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
"satellite.js": "^5.0.0",
|
"satellite.js": "^5.0.0",
|
||||||
"seemly": "^0.3.9",
|
"seemly": "^0.3.9",
|
||||||
"v-viewer": "^3.0.21",
|
"v-viewer": "^3.0.21",
|
||||||
|
"vanilla-js-wheel-zoom": "^9.0.4",
|
||||||
"viewerjs": "^1.11.7",
|
"viewerjs": "^1.11.7",
|
||||||
"vue": "^3.2.45",
|
"vue": "^3.2.45",
|
||||||
"vue-draggable-plus": "^0.5.6",
|
"vue-draggable-plus": "^0.5.6",
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
import { defAxios as request } from '@/utils/http'
|
import { defAxios as request } from '@/utils/http'
|
||||||
const baseUrl = window.settings.apis
|
const baseUrl = window.settings.apis
|
||||||
|
// export function getHangjing(data = {}) {
|
||||||
|
// return request({
|
||||||
|
// url: `${baseUrl}/hangjing/list`,
|
||||||
|
// method: 'post',
|
||||||
|
// data,
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
|
||||||
export function getHangjing(data = {}) {
|
export function getHangjing(data = {}) {
|
||||||
return request({
|
return request({
|
||||||
url: `${baseUrl}/hangjing/list`,
|
url: `${baseUrl}/hangjing/shiJianTree`,
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data,
|
data,
|
||||||
})
|
})
|
||||||
|
@ -56,6 +56,9 @@
|
|||||||
);
|
);
|
||||||
|
|
||||||
--color-bg: #1a222966;
|
--color-bg: #1a222966;
|
||||||
|
|
||||||
|
--gradient-bg-title: linear-gradient(to right, #4fd2dd55, #4b877400);
|
||||||
|
--tw-from-opacity: 33%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
|
8
src/assets/detail.scss
Normal file
8
src/assets/detail.scss
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
.detail-container {
|
||||||
|
@apply flex flex-col gap-4;
|
||||||
|
.detail-item-title{
|
||||||
|
@apply font-bold text-xl w-[120px] h-[30px] leading-[30px];
|
||||||
|
background-image: linear-gradient(to right, #4fd2dd55 0%, transparent 100%);
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
@import './base.css';
|
@import './base.css';
|
||||||
@import './naiveui.css';
|
@import './naiveui.css';
|
||||||
|
@import './detail.scss';
|
||||||
|
|
||||||
#app {
|
#app {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
.n-dialog .n-dialog__content {
|
||||||
|
padding-top: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
.n-base-select-option__content {
|
.n-base-select-option__content {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
@ -120,7 +120,7 @@ $radius: 2rem;
|
|||||||
.content-title {
|
.content-title {
|
||||||
@apply h-9 px-5 leading-9 tracking-[5px];
|
@apply h-9 px-5 leading-9 tracking-[5px];
|
||||||
border-radius: $radius $radius 0 0;
|
border-radius: $radius $radius 0 0;
|
||||||
background: linear-gradient(to right, #4fd2dd55, #4b877400);
|
background: var(--gradient-bg-title);
|
||||||
.title-text {
|
.title-text {
|
||||||
@apply font-bold italic;
|
@apply font-bold italic;
|
||||||
color: transparent;
|
color: transparent;
|
||||||
|
@ -62,12 +62,12 @@ async function getHisTraj({
|
|||||||
|
|
||||||
function getMBEntityOpt({
|
function getMBEntityOpt({
|
||||||
id,
|
id,
|
||||||
name,
|
|
||||||
targetType,
|
targetType,
|
||||||
|
name,
|
||||||
}: {
|
}: {
|
||||||
id: string
|
id: string
|
||||||
name?: string
|
|
||||||
targetType: string
|
targetType: string
|
||||||
|
name?: string
|
||||||
}) {
|
}) {
|
||||||
const mubiaoDict = window.settings.mbDict[targetType]
|
const mubiaoDict = window.settings.mbDict[targetType]
|
||||||
|
|
||||||
@ -102,6 +102,25 @@ function getMBEntityOpt({
|
|||||||
scale: 1000,
|
scale: 1000,
|
||||||
minimumPixelSize: 50,
|
minimumPixelSize: 50,
|
||||||
},
|
},
|
||||||
|
ellipsoid: {
|
||||||
|
show: true,
|
||||||
|
radii: new Cesium.Cartesian3(100000, 100000, 100000),
|
||||||
|
innerRadii: new Cesium.Cartesian3(1.0, 1.0, 1.0),
|
||||||
|
maximumCone: Cesium.Math.toRadians(90),
|
||||||
|
minimumCone: Cesium.Math.toRadians(40),
|
||||||
|
minimumClock: Cesium.Math.toRadians(20),
|
||||||
|
maximumClock: Cesium.Math.toRadians(90),
|
||||||
|
material: Cesium.Color.fromCssColorString('#00dcff44'),
|
||||||
|
outline: true,
|
||||||
|
outlineColor: Cesium.Color.fromCssColorString('#00dcff'),
|
||||||
|
outlineWidth: 1,
|
||||||
|
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
|
||||||
|
0.0,
|
||||||
|
10.5e8
|
||||||
|
),
|
||||||
|
slicePartitions: 24,
|
||||||
|
stackPartitions: 36,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
142
src/js/Radar.js
Normal file
142
src/js/Radar.js
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
export default class Radar {
|
||||||
|
// 创建雷达罩
|
||||||
|
constructor(options) {
|
||||||
|
this.radius = options.radius
|
||||||
|
// this.viewer = options.viewer
|
||||||
|
// this.id = options.id
|
||||||
|
// this.entity = null
|
||||||
|
// this.radius = options.radius
|
||||||
|
// ;(this.longitude = options.position[0]),
|
||||||
|
// (this.latitude = options.position[1]),
|
||||||
|
// (this.position = Cesium.Cartesian3.fromDegrees(
|
||||||
|
// options.position[0],
|
||||||
|
// options.position[1]
|
||||||
|
// ))
|
||||||
|
// this.heading = 0
|
||||||
|
// this.positionArr = this.calcPoints(
|
||||||
|
// options.position[0],
|
||||||
|
// options.position[1],
|
||||||
|
// options.radius,
|
||||||
|
// 0
|
||||||
|
// ) //储存脏数据
|
||||||
|
// this.addEntities()
|
||||||
|
}
|
||||||
|
cartesian32LonLat(cartesian3) {
|
||||||
|
const cartographic =
|
||||||
|
this.viewer.scene.globe.ellipsoid.cartesianToCartographic(
|
||||||
|
cartesian3._value
|
||||||
|
)
|
||||||
|
const lat = Cesium.Math.toDegrees(cartographic.latitude)
|
||||||
|
const lon = Cesium.Math.toDegrees(cartographic.longitude)
|
||||||
|
return [lon, lat]
|
||||||
|
}
|
||||||
|
getRadar() {
|
||||||
|
// this.entity = this.viewer.entities.add({
|
||||||
|
// id: this.id,
|
||||||
|
// position: this.position,
|
||||||
|
// wall: {
|
||||||
|
// positions: new Cesium.CallbackProperty(() => {
|
||||||
|
// return Cesium.Cartesian3.fromDegreesArrayHeights(this.positionArr)
|
||||||
|
// }, false),
|
||||||
|
// material: Cesium.Color.fromCssColorString('#00dcff82'),
|
||||||
|
// distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
|
||||||
|
// 0.0,
|
||||||
|
// 10.5e6
|
||||||
|
// ),
|
||||||
|
// },
|
||||||
|
// ellipsoid: {
|
||||||
|
// radii: new Cesium.Cartesian3(
|
||||||
|
// this.radius,
|
||||||
|
// this.radius,
|
||||||
|
// this.radius
|
||||||
|
// ),
|
||||||
|
// maximumCone: Cesium.Math.toRadians(90),
|
||||||
|
// material: Cesium.Color.fromCssColorString('#00dcff82'),
|
||||||
|
// outline: true,
|
||||||
|
// outlineColor: Cesium.Color.fromCssColorString('#00dcff'),
|
||||||
|
// outlineWidth: 1,
|
||||||
|
// distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
|
||||||
|
// 0.0,
|
||||||
|
// 10.5e8
|
||||||
|
// ),
|
||||||
|
// },
|
||||||
|
// })
|
||||||
|
return {
|
||||||
|
// wall: {
|
||||||
|
// positions: new Cesium.CallbackProperty(() => {
|
||||||
|
// return Cesium.Cartesian3.fromDegreesArrayHeights(this.positionArr)
|
||||||
|
// }, false),
|
||||||
|
// material: Cesium.Color.fromCssColorString('#00dcff82'),
|
||||||
|
// distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
|
||||||
|
// 0.0,
|
||||||
|
// 10.5e6
|
||||||
|
// ),
|
||||||
|
// },
|
||||||
|
ellipsoid: {
|
||||||
|
radii: new Cesium.Cartesian3(this.radius, this.radius, this.radius),
|
||||||
|
maximumCone: Cesium.Math.toRadians(90),
|
||||||
|
material: Cesium.Color.fromCssColorString('#00dcff82'),
|
||||||
|
outline: true,
|
||||||
|
outlineColor: Cesium.Color.fromCssColorString('#00dcff'),
|
||||||
|
outlineWidth: 1,
|
||||||
|
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
|
||||||
|
0.0,
|
||||||
|
10.5e8
|
||||||
|
),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
// this.addPostRender()
|
||||||
|
}
|
||||||
|
addPostRender() {
|
||||||
|
this.viewer.clock.onTick.addEventListener(() => {
|
||||||
|
this.heading += 1.0 //可调节转动速度
|
||||||
|
this.positionArr = this.calcPoints(
|
||||||
|
this.longitude,
|
||||||
|
this.latitude,
|
||||||
|
this.radius,
|
||||||
|
this.heading
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
calcPoints(x1, y1, radius, heading) {
|
||||||
|
let m = Cesium.Transforms.eastNorthUpToFixedFrame(
|
||||||
|
Cesium.Cartesian3.fromDegrees(x1, y1)
|
||||||
|
)
|
||||||
|
let rx = radius * Math.cos((heading * Math.PI) / 180.0)
|
||||||
|
let ry = radius * Math.sin((heading * Math.PI) / 180.0)
|
||||||
|
let translation = Cesium.Cartesian3.fromElements(rx, ry, 0)
|
||||||
|
let d = Cesium.Matrix4.multiplyByPoint(
|
||||||
|
m,
|
||||||
|
translation,
|
||||||
|
new Cesium.Cartesian3()
|
||||||
|
)
|
||||||
|
let c = Cesium.Cartographic.fromCartesian(d)
|
||||||
|
let x2 = Cesium.Math.toDegrees(c.longitude)
|
||||||
|
let y2 = Cesium.Math.toDegrees(c.latitude)
|
||||||
|
return this.computeCirclularFlight(x1, y1, x2, y2, 0, 90)
|
||||||
|
}
|
||||||
|
computeCirclularFlight(x1, y1, x2, y2, fx, angle) {
|
||||||
|
let positionArr = []
|
||||||
|
positionArr.push(x1)
|
||||||
|
positionArr.push(y1)
|
||||||
|
positionArr.push(0)
|
||||||
|
let radius = Cesium.Cartesian3.distance(
|
||||||
|
Cesium.Cartesian3.fromDegrees(x1, y1),
|
||||||
|
Cesium.Cartesian3.fromDegrees(x2, y2)
|
||||||
|
)
|
||||||
|
for (let i = fx; i <= fx + angle; i++) {
|
||||||
|
let h = radius * Math.sin((i * Math.PI) / 180.0)
|
||||||
|
let r = Math.cos((i * Math.PI) / 180.0)
|
||||||
|
let x = (x2 - x1) * r + x1
|
||||||
|
let y = (y2 - y1) * r + y1
|
||||||
|
positionArr.push(x)
|
||||||
|
positionArr.push(y)
|
||||||
|
positionArr.push(h)
|
||||||
|
}
|
||||||
|
return positionArr
|
||||||
|
}
|
||||||
|
removeEntity() {
|
||||||
|
this.entity && this.viewer.entities.remove(this.entity)
|
||||||
|
this.entity = null
|
||||||
|
}
|
||||||
|
}
|
@ -22,7 +22,7 @@ class SatelliteEntity {
|
|||||||
this.entity = null
|
this.entity = null
|
||||||
this._underPoint = false
|
this._underPoint = false
|
||||||
this.underPointEntity = null
|
this.underPointEntity = null
|
||||||
this._sensorType = 'rectangle'
|
this._sensorType = 'conic'
|
||||||
this._listener = null
|
this._listener = null
|
||||||
}
|
}
|
||||||
get sensorType() {
|
get sensorType() {
|
||||||
@ -443,9 +443,8 @@ class SatelliteEntity {
|
|||||||
},
|
},
|
||||||
polyline: {
|
polyline: {
|
||||||
positions: points,
|
positions: points,
|
||||||
|
|
||||||
width: 1,
|
width: 1,
|
||||||
material: Cesium.Color.RED,
|
material: color,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
70
src/views/BaseMB/components/HisImages/components/LImage.jsx
Normal file
70
src/views/BaseMB/components/HisImages/components/LImage.jsx
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
import { NImage } from 'naive-ui'
|
||||||
|
import WZoom from 'vanilla-js-wheel-zoom/dist/wheel-zoom.min.js'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
props: {
|
||||||
|
imageList: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
setup(props) {
|
||||||
|
// const { images, activeIndex } = toRefs(props)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.imageList,
|
||||||
|
() => {
|
||||||
|
if (props.imageList.length > 1) {
|
||||||
|
nextTick(() => {
|
||||||
|
props.imageList.map(image => {
|
||||||
|
const imageElement = document
|
||||||
|
.getElementById(`image-${image.id}`)
|
||||||
|
.querySelector('img')
|
||||||
|
|
||||||
|
const wz = WZoom.create(`#image-${image.id}`, {
|
||||||
|
type: 'html',
|
||||||
|
maxScale: 3,
|
||||||
|
minScale: 0.2,
|
||||||
|
// zoomOnDoubleClick: true,
|
||||||
|
width: imageElement.naturalWidth,
|
||||||
|
height: imageElement.naturalHeight,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return () => (
|
||||||
|
<div class="l-image-container flex h-full w-full gap-4">
|
||||||
|
{props.imageList.map(image => (
|
||||||
|
<div class="flex h-full flex-1 flex-col gap-2">
|
||||||
|
<div>{image.createTime}</div>
|
||||||
|
<div class="h-0 flex-1 overflow-hidden">
|
||||||
|
{props.imageList.length > 1 ? (
|
||||||
|
<div
|
||||||
|
id={`image-${image.id}`}
|
||||||
|
class="flex h-full w-full cursor-grab items-center justify-center"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
class="w-full"
|
||||||
|
src={image.imgPath}
|
||||||
|
draggable="false"
|
||||||
|
// alt="image"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<NImage
|
||||||
|
class="flex justify-center object-contain w-h-full"
|
||||||
|
object-fit="contain"
|
||||||
|
src={image.imgPath}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="line-clamp-3 pb-4">{image.detailContent}</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
})
|
@ -4,6 +4,7 @@
|
|||||||
import { ImageOutline } from '@vicons/ionicons5'
|
import { ImageOutline } from '@vicons/ionicons5'
|
||||||
import { useHisImage } from './hooks/hisImage'
|
import { useHisImage } from './hooks/hisImage'
|
||||||
import Panel from '@/components/Panel/index.vue'
|
import Panel from '@/components/Panel/index.vue'
|
||||||
|
import LImage from './components/LImage'
|
||||||
|
|
||||||
const { sheshiData, showOrHideHisImage, getHisImages } = useHisImage()
|
const { sheshiData, showOrHideHisImage, getHisImages } = useHisImage()
|
||||||
|
|
||||||
@ -61,12 +62,47 @@ const getImage = async () => {
|
|||||||
// })
|
// })
|
||||||
imageList.value = new Array(10).fill(1).map((item, index) => {
|
imageList.value = new Array(10).fill(1).map((item, index) => {
|
||||||
return {
|
return {
|
||||||
|
id: index,
|
||||||
imgPath: `https://picsum.photos/300/200?random=${index}`,
|
imgPath: `https://picsum.photos/300/200?random=${index}`,
|
||||||
imgId: index,
|
imgId: index,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// console.log(imageList.value, 'imageList')
|
// console.log(imageList.value, 'imageList')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const checkedImage = ref<null | string[]>(null)
|
||||||
|
|
||||||
|
const checkValue = e => {
|
||||||
|
e.stopPropagation()
|
||||||
|
if (checkedImage.value && checkedImage.value.length > 2) {
|
||||||
|
checkedImage.value.pop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// watch(checkedImage, newCheck => {
|
||||||
|
// // console.log(newCheck, 'newCheck')
|
||||||
|
// })
|
||||||
|
const isCompare = ref(false)
|
||||||
|
const compareImages = () => {
|
||||||
|
if (!isCompare.value) {
|
||||||
|
if (checkedImage.value && checkedImage.value.length === 2) {
|
||||||
|
isCompare.value = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
isCompare.value = false
|
||||||
|
checkedImage.value = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const largeImageList = computed(() => {
|
||||||
|
if (isCompare.value) {
|
||||||
|
return imageList.value.filter(img => checkedImage.value.includes(img.id))
|
||||||
|
} else {
|
||||||
|
return imageList.value[previewIndex.value - 1]
|
||||||
|
? [imageList.value[previewIndex.value - 1]]
|
||||||
|
: []
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -79,23 +115,8 @@ const getImage = async () => {
|
|||||||
>
|
>
|
||||||
<div class="flex flex-col w-h-full">
|
<div class="flex flex-col w-h-full">
|
||||||
<div class="large-container">
|
<div class="large-container">
|
||||||
<div>
|
<l-image :imageList="largeImageList" />
|
||||||
{{ previewIndex > 0 ? imageList[previewIndex - 1].createTime : '' }}
|
|
||||||
</div>
|
|
||||||
<!-- <vue-viewer :images="imageList" :options="{ inline: true }"> -->
|
|
||||||
<div class="h-0 flex-1">
|
|
||||||
<n-image
|
|
||||||
class="flex justify-center object-contain w-h-full"
|
|
||||||
object-fit="contain"
|
|
||||||
:src="previewIndex > 0 ? imageList[previewIndex - 1].imgPath : ''"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="line-clamp-3 pb-4">
|
|
||||||
{{
|
|
||||||
previewIndex > 0 ? imageList[previewIndex - 1].detailContent : ''
|
|
||||||
}}
|
|
||||||
</div>
|
|
||||||
<!-- </vue-viewer> -->
|
<!-- </vue-viewer> -->
|
||||||
</div>
|
</div>
|
||||||
<div ref="scrollRef" class="flex h-[178px] flex-col">
|
<div ref="scrollRef" class="flex h-[178px] flex-col">
|
||||||
@ -109,12 +130,19 @@ const getImage = async () => {
|
|||||||
format="yyyy-MM-dd HH:mm:ss"
|
format="yyyy-MM-dd HH:mm:ss"
|
||||||
/>
|
/>
|
||||||
<n-button type="primary" @click="getImage">搜索</n-button>
|
<n-button type="primary" @click="getImage">搜索</n-button>
|
||||||
|
<n-button type="primary" @click="compareImages">{{
|
||||||
|
isCompare ? '取消对比' : '对比'
|
||||||
|
}}</n-button>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="imageList.length === 0" class="m-auto flex">
|
<div v-if="imageList.length === 0" class="m-auto flex">
|
||||||
<n-empty description="暂无数据"> </n-empty>
|
<n-empty description="暂无数据"> </n-empty>
|
||||||
</div>
|
</div>
|
||||||
<n-scrollbar v-else x-scrollable>
|
<n-scrollbar v-else x-scrollable>
|
||||||
<div class="flex h-full flex-nowrap">
|
<!-- <div> -->
|
||||||
|
<n-checkbox-group
|
||||||
|
class="flex h-full flex-nowrap"
|
||||||
|
v-model:value="checkedImage"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
class="flex h-full w-[140px] cursor-pointer p-2"
|
class="flex h-full w-[140px] cursor-pointer p-2"
|
||||||
v-for="(i, index) in imageList"
|
v-for="(i, index) in imageList"
|
||||||
@ -128,6 +156,12 @@ const getImage = async () => {
|
|||||||
index + 1 === previewIndex,
|
index + 1 === previewIndex,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
|
<n-checkbox
|
||||||
|
class="absolute"
|
||||||
|
:value="i.id"
|
||||||
|
label=""
|
||||||
|
@click.stop="checkValue"
|
||||||
|
/>
|
||||||
<n-image
|
<n-image
|
||||||
class="m-auto"
|
class="m-auto"
|
||||||
object-fit="contain"
|
object-fit="contain"
|
||||||
@ -143,7 +177,8 @@ const getImage = async () => {
|
|||||||
</n-image>
|
</n-image>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</n-checkbox-group>
|
||||||
|
<!-- </div> -->
|
||||||
</n-scrollbar>
|
</n-scrollbar>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -154,6 +189,7 @@ const getImage = async () => {
|
|||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.pre-container {
|
.pre-container {
|
||||||
transition: all 0.3s ease-in-out;
|
transition: all 0.3s ease-in-out;
|
||||||
|
|
||||||
.large-container {
|
.large-container {
|
||||||
@apply flex h-0 flex-1 flex-col gap-2 overflow-hidden text-center;
|
@apply flex h-0 flex-1 flex-col gap-2 overflow-hidden text-center;
|
||||||
//
|
//
|
||||||
|
@ -43,6 +43,10 @@ const nodeProps = ({ option }: { option: TreeOption }) => {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const renderSuffix = ({ option }: { option: TreeOption }) => {
|
||||||
|
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import moment from 'moment-timezone'
|
import moment from 'moment-timezone'
|
||||||
|
import { useRoute } from 'vue-router'
|
||||||
import { time2FormatWithTimezone } from '@/utils/date'
|
import { time2FormatWithTimezone } from '@/utils/date'
|
||||||
import WidgetNav from '../WidgetNav'
|
import WidgetNav from '../WidgetNav'
|
||||||
|
|
||||||
@ -38,6 +39,8 @@ onMounted(() => {
|
|||||||
getTime()
|
getTime()
|
||||||
getLocalTime()
|
getLocalTime()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -64,7 +67,7 @@ onMounted(() => {
|
|||||||
{{ worldTime }}
|
{{ worldTime }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<widget-nav />
|
<widget-nav v-if="route.path === '\/'" />
|
||||||
<div class="time-container bgc-animation">
|
<div class="time-container bgc-animation">
|
||||||
<div class="bgc-animation">{{ localeTime }}</div>
|
<div class="bgc-animation">{{ localeTime }}</div>
|
||||||
<div class="time-title">作战时</div>
|
<div class="time-title">作战时</div>
|
||||||
|
@ -1,15 +1,13 @@
|
|||||||
import { NIcon, NPopover } from 'naive-ui'
|
import { NIcon, NPopover } from 'naive-ui'
|
||||||
import { useEntity } from '@/hooks/entity'
|
import { useSatellite } from '@/views/Satellite/hooks/satellite'
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
setup() {
|
setup() {
|
||||||
const { satelliteMap } = useEntity()
|
const { showPoint, showPointUnderSat } = useSatellite()
|
||||||
|
|
||||||
const show = ref(false)
|
// const show = ref(false)
|
||||||
const showPointUnderSatellite = () => {
|
const showPointUnderSatellite = () => {
|
||||||
show.value = !show.value
|
showPoint.value = !showPoint.value
|
||||||
;[...satelliteMap.values()].forEach(satellite => {
|
showPointUnderSat()
|
||||||
satellite.underPoint = show.value
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
return () => (
|
return () => (
|
||||||
<>
|
<>
|
||||||
@ -18,7 +16,10 @@ export default defineComponent({
|
|||||||
placement="bottom"
|
placement="bottom"
|
||||||
v-slots={{
|
v-slots={{
|
||||||
trigger: () => (
|
trigger: () => (
|
||||||
<div class="btn-class" onClick={showPointUnderSatellite}>
|
<div
|
||||||
|
class={`btn-class ${showPoint.value ? 'checked' : ''}`}
|
||||||
|
onClick={showPointUnderSatellite}
|
||||||
|
>
|
||||||
<NIcon size="15">
|
<NIcon size="15">
|
||||||
<svg
|
<svg
|
||||||
t="1736493475776"
|
t="1736493475776"
|
||||||
|
@ -54,7 +54,7 @@ const types = [
|
|||||||
{ name: 'XW', value: 'wzbXw' },
|
{ name: 'XW', value: 'wzbXw' },
|
||||||
]
|
]
|
||||||
|
|
||||||
const showPanelName = ref('wx')
|
const showPanelName = ref('hj-2')
|
||||||
|
|
||||||
const panelList = [
|
const panelList = [
|
||||||
// {
|
// {
|
||||||
@ -122,17 +122,9 @@ const showOrHideTextReport = () => {
|
|||||||
|
|
||||||
<div class="grid flex-1 grid-cols-[1.5fr_3fr_1.5fr] grid-rows-1 gap-1">
|
<div class="grid flex-1 grid-cols-[1.5fr_3fr_1.5fr] grid-rows-1 gap-1">
|
||||||
<div class="left-panel pl-8">
|
<div class="left-panel pl-8">
|
||||||
<div
|
<div class="radio-group absolute -left-4 top-[15%] z-30 flex w-12 translate-y-[-50%] transform flex-col">
|
||||||
class="radio-group absolute -left-4 top-[15%] z-30 flex w-12 translate-y-[-50%] transform flex-col"
|
|
||||||
>
|
|
||||||
<template v-for="panel in panelList" :key="panel.id">
|
<template v-for="panel in panelList" :key="panel.id">
|
||||||
<input
|
<input type="radio" :id="panel.id" name="selector" v-model="showPanelName" :value="panel.value" />
|
||||||
type="radio"
|
|
||||||
:id="panel.id"
|
|
||||||
name="selector"
|
|
||||||
v-model="showPanelName"
|
|
||||||
:value="panel.value"
|
|
||||||
/>
|
|
||||||
<label for="wx" @click="hidePanel($event, panel.value)">{{
|
<label for="wx" @click="hidePanel($event, panel.value)">{{
|
||||||
panel.name
|
panel.name
|
||||||
}}</label>
|
}}</label>
|
||||||
@ -187,20 +179,10 @@ const showOrHideTextReport = () => {
|
|||||||
</div>
|
</div>
|
||||||
<!-- <div class="z-20 grid grid-cols-1 grid-rows-3 gap-1"> -->
|
<!-- <div class="z-20 grid grid-cols-1 grid-rows-3 gap-1"> -->
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div class="btn-transform z-20 w-h-full" :class="showTextReport ? '' : 'btn-transform-pos'">
|
||||||
class="btn-transform z-20 w-h-full"
|
<n-button class="absolute -left-[16px] top-5 z-30 border border-[#29baf1] bg-[var(--color-bg)]" size="tiny"
|
||||||
:class="showTextReport ? '' : 'btn-transform-pos'"
|
@click="showOrHideTextReport">
|
||||||
>
|
<n-icon class="btn-transform" :class="showTextReport ? '' : 'icon-transform'"><arrow-right /></n-icon>
|
||||||
<n-button
|
|
||||||
class="absolute -left-[16px] top-5 z-30 border border-[#29baf1] bg-[var(--color-bg)]"
|
|
||||||
size="tiny"
|
|
||||||
@click="showOrHideTextReport"
|
|
||||||
>
|
|
||||||
<n-icon
|
|
||||||
class="btn-transform"
|
|
||||||
:class="showTextReport ? '' : 'icon-transform'"
|
|
||||||
><arrow-right
|
|
||||||
/></n-icon>
|
|
||||||
</n-button>
|
</n-button>
|
||||||
<!-- <transition name="slide2">.slice(0, 3) -->
|
<!-- <transition name="slide2">.slice(0, 3) -->
|
||||||
<panel title="文字报"><text-report :tabs="types" /></panel>
|
<panel title="文字报"><text-report :tabs="types" /></panel>
|
||||||
@ -220,14 +202,8 @@ const showOrHideTextReport = () => {
|
|||||||
</div>
|
</div>
|
||||||
<div class="absolute bottom-0 flex h-full w-full flex-col justify-end">
|
<div class="absolute bottom-0 flex h-full w-full flex-col justify-end">
|
||||||
<text-message class="absolute z-30 h-[200px]"></text-message>
|
<text-message class="absolute z-30 h-[200px]"></text-message>
|
||||||
<mubiao-his-trajectory
|
<mubiao-his-trajectory v-if="showHisTrajCom" class="z-30 h-[260px]"></mubiao-his-trajectory>
|
||||||
v-if="showHisTrajCom"
|
<multi-his-trajectory v-if="showMultiHisTrajCom" class="z-30 h-[260px]"></multi-his-trajectory>
|
||||||
class="z-30 h-[260px]"
|
|
||||||
></mubiao-his-trajectory>
|
|
||||||
<multi-his-trajectory
|
|
||||||
v-if="showMultiHisTrajCom"
|
|
||||||
class="z-30 h-[260px]"
|
|
||||||
></multi-his-trajectory>
|
|
||||||
<his-images v-if="showHisImageCom" class="z-30 h-[260px]"></his-images>
|
<his-images v-if="showHisImageCom" class="z-30 h-[260px]"></his-images>
|
||||||
</div>
|
</div>
|
||||||
<details-modal></details-modal>
|
<details-modal></details-modal>
|
||||||
@ -239,9 +215,11 @@ const showOrHideTextReport = () => {
|
|||||||
|
|
||||||
.time-bg {
|
.time-bg {
|
||||||
background-color: rgba(26, 34, 41, 0.4);
|
background-color: rgba(26, 34, 41, 0.4);
|
||||||
|
|
||||||
.time-container {
|
.time-container {
|
||||||
@apply flex items-center justify-center gap-2;
|
@apply flex items-center justify-center gap-2;
|
||||||
font-family: Digital;
|
font-family: Digital;
|
||||||
|
|
||||||
.time-title {
|
.time-title {
|
||||||
@apply h-6 border border-[#29baf1] px-2 text-sm leading-5 text-[#29baf1];
|
@apply h-6 border border-[#29baf1] px-2 text-sm leading-5 text-[#29baf1];
|
||||||
}
|
}
|
||||||
@ -256,31 +234,39 @@ const showOrHideTextReport = () => {
|
|||||||
background-clip: text;
|
background-clip: text;
|
||||||
color: transparent;
|
color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title-container {
|
.title-container {
|
||||||
@apply absolute left-[50%] top-3 z-20 h-20 text-5xl font-bold tracking-[18px];
|
@apply absolute left-[50%] top-3 z-20 h-20 text-5xl font-bold tracking-[18px];
|
||||||
|
|
||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes gradientAnimation {
|
@keyframes gradientAnimation {
|
||||||
0% {
|
0% {
|
||||||
background-position: 200% 50%;
|
background-position: 200% 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
50% {
|
50% {
|
||||||
background-position: 100% 50%;
|
background-position: 100% 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
100% {
|
100% {
|
||||||
background-position: 0% 50%;
|
background-position: 0% 50%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-bg {
|
.header-bg {
|
||||||
background: url('./header.svg') no-repeat;
|
background: url('./header.svg') no-repeat;
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.left-panel {
|
.left-panel {
|
||||||
@apply relative z-20 w-h-full;
|
@apply relative z-20 w-h-full;
|
||||||
|
|
||||||
&-wrapper {
|
&-wrapper {
|
||||||
@apply absolute h-full;
|
@apply absolute h-full;
|
||||||
width: calc(100% - 2rem);
|
width: calc(100% - 2rem);
|
||||||
|
|
||||||
.left-panel-content {
|
.left-panel-content {
|
||||||
@apply absolute right-[-37px] top-[78px];
|
@apply absolute right-[-37px] top-[78px];
|
||||||
}
|
}
|
||||||
@ -312,6 +298,7 @@ const showOrHideTextReport = () => {
|
|||||||
.btn-transform {
|
.btn-transform {
|
||||||
transition: transform 0.8s ease;
|
transition: transform 0.8s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-transform-pos {
|
.btn-transform-pos {
|
||||||
transform: translateX(99%);
|
transform: translateX(99%);
|
||||||
}
|
}
|
||||||
@ -386,5 +373,4 @@ const showOrHideTextReport = () => {
|
|||||||
// // background: var(--gradient-bg);
|
// // background: var(--gradient-bg);
|
||||||
// // background-clip: text;
|
// // background-clip: text;
|
||||||
// }
|
// }
|
||||||
// }
|
// }</style>
|
||||||
</style>
|
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
|
import { difference } from 'lodash'
|
||||||
import { useWebSocket } from '@vueuse/core'
|
import { useWebSocket } from '@vueuse/core'
|
||||||
|
import { useTree } from '@/utils/tree'
|
||||||
import { useHjPolygon } from './hangjingPolygon'
|
import { useHjPolygon } from './hangjingPolygon'
|
||||||
interface IPolygonData {
|
interface IPolygonData {
|
||||||
id: string
|
id: string
|
||||||
@ -6,6 +8,8 @@ interface IPolygonData {
|
|||||||
color?: string
|
color?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { filterTreeNodeByField } = useTree()
|
||||||
|
|
||||||
const hangjingMap: Map<string, any> = new Map()
|
const hangjingMap: Map<string, any> = new Map()
|
||||||
|
|
||||||
const { addHangjingPolygon, removeHangjingPolygon } = useHjPolygon(hangjingMap)
|
const { addHangjingPolygon, removeHangjingPolygon } = useHjPolygon(hangjingMap)
|
||||||
@ -13,8 +17,8 @@ export const useHangjing = () => {
|
|||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
initWebSocket()
|
initWebSocket()
|
||||||
})
|
})
|
||||||
const addHangjing = (data: Record<string, any>[]) => {
|
const addHangjing = (ids, hangjingData) => {
|
||||||
addHangjingPolygon(data)
|
addHangjingPolygon(ids, hangjingData)
|
||||||
}
|
}
|
||||||
|
|
||||||
const removeHangjing = (id: string) => {
|
const removeHangjing = (id: string) => {
|
||||||
|
34
src/views/Hangjing/hooks/hangjingDetail.jsx
Normal file
34
src/views/Hangjing/hooks/hangjingDetail.jsx
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import { useModal } from '@/views/Content/hooks/modal'
|
||||||
|
const { openDetailsModal } = useModal()
|
||||||
|
import { useHangjingStyle } from './hangjingStyle'
|
||||||
|
|
||||||
|
const { renderStyleContent } = useHangjingStyle()
|
||||||
|
export const useHangjingDetail = () => {
|
||||||
|
return { showDetailsModal }
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderDetailsContent(data) {
|
||||||
|
return () => (
|
||||||
|
<div class="detail-container">
|
||||||
|
<div class="detail-item-title">基本信息</div>
|
||||||
|
<div>
|
||||||
|
{Object.keys(data)
|
||||||
|
.filter(key => key !== 'geom')
|
||||||
|
.map(key => (
|
||||||
|
<div>
|
||||||
|
{key}:{data[key]}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<div class="detail-item-title">样式配置</div>
|
||||||
|
{renderStyleContent(data)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function showDetailsModal(title, data) {
|
||||||
|
openDetailsModal({
|
||||||
|
titleString: title,
|
||||||
|
contentSlot: renderDetailsContent(data),
|
||||||
|
})
|
||||||
|
}
|
@ -1,22 +0,0 @@
|
|||||||
import { h } from 'vue'
|
|
||||||
import { useModal } from '@/views/Content/hooks/modal'
|
|
||||||
const { openDetailsModal } = useModal()
|
|
||||||
|
|
||||||
export const useHangjingDetail = () => {
|
|
||||||
return { showDetailsModal }
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderDetailsContent(data: Record<string, any>) {
|
|
||||||
return h(
|
|
||||||
'div',
|
|
||||||
{},
|
|
||||||
Object.keys(data).map(key => h('div', {}, `${key}:${data[key]}`))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function showDetailsModal(title: string, data: Record<string, any>) {
|
|
||||||
openDetailsModal({
|
|
||||||
titleString: title,
|
|
||||||
contentSlot: renderDetailsContent(data),
|
|
||||||
})
|
|
||||||
}
|
|
@ -5,37 +5,44 @@ import { difference } from 'lodash'
|
|||||||
import { polygonGradient } from '@/js/polygonGradient'
|
import { polygonGradient } from '@/js/polygonGradient'
|
||||||
import { polygonMaterial } from '@/js/polygon'
|
import { polygonMaterial } from '@/js/polygon'
|
||||||
import { centerOfMass } from '@turf/turf'
|
import { centerOfMass } from '@turf/turf'
|
||||||
|
import { useTree } from '@/utils/tree'
|
||||||
|
|
||||||
import { useHangjingPopup } from './hangjingPopup'
|
import { useHangjingPopup } from './hangjingPopup'
|
||||||
|
|
||||||
const { createPopup } = useHangjingPopup()
|
const { createPopup } = useHangjingPopup()
|
||||||
|
const { filterTreeNodeByField } = useTree()
|
||||||
|
|
||||||
export const useHjPolygon = (polygonMap: Map<string | number, any>) => {
|
export const useHjPolygon = (polygonMap: Map<string | number, any>) => {
|
||||||
let subscriber: Subscriber | null = null
|
let subscriber: Subscriber | null = null
|
||||||
|
|
||||||
const colors = new Map()
|
const colors = new Map()
|
||||||
|
|
||||||
function addHangjingPolygon(data: Record<string, any>[]) {
|
function addHangjingPolygon(ids, data) {
|
||||||
subscriber = new Subscriber(viewer, {
|
subscriber = new Subscriber(viewer, {
|
||||||
pickResult: {
|
pickResult: {
|
||||||
enable: true,
|
enable: true,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const ids = data.map(item => item.id)
|
// const ids = data.map(item => item.id)
|
||||||
const addIds = difference(ids, [...polygonMap.keys()])
|
const addIds = difference(ids, [...polygonMap.keys()])
|
||||||
const removeIds = difference([...polygonMap.keys()], ids)
|
const removeIds = difference([...polygonMap.keys()], ids)
|
||||||
// 添加
|
// 添加
|
||||||
if (addIds.length > 0) {
|
if (addIds.length > 0) {
|
||||||
addIds.forEach(id => {
|
const nodes = filterTreeNodeByField({
|
||||||
const item = data.find(item => item.id === id)
|
treeData: data.value,
|
||||||
if (item) {
|
params: addIds,
|
||||||
if (item.zoneList.length > 0) {
|
paramName: 'dataId',
|
||||||
item.zoneList.forEach(zone => {
|
})
|
||||||
|
nodes.forEach(({ data: hjData, dataId: id }) => {
|
||||||
|
// const item = data.find(item => item.id === id)
|
||||||
|
if (hjData) {
|
||||||
|
if (hjData.zoneList.length > 0) {
|
||||||
|
hjData.zoneList.forEach(zone => {
|
||||||
addPolygon(zone, id)
|
addPolygon(zone, id)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
addPolygon(item)
|
addPolygon(hjData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -51,12 +58,14 @@ export const useHjPolygon = (polygonMap: Map<string | number, any>) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function addPolygon(item, parentId: number | null = null) {
|
function addPolygon(item, parentId: number | null = null) {
|
||||||
const { id, geom } = item
|
const { id, geom, title } = item
|
||||||
const feature = parseWKT(geom)
|
const feature = parseWKT(geom)
|
||||||
const position = feature.coordinates[0].map(pos => {
|
const position = feature.coordinates[0].map(pos => {
|
||||||
return Cesium.Cartesian3.fromDegrees(...pos)
|
return Cesium.Cartesian3.fromDegrees(...pos)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const labels = addTextAlongCurve('Cesium中文垂直排列测试', position)
|
||||||
|
|
||||||
// console.log(item, id, position, 'id, position, color')
|
// console.log(item, id, position, 'id, position, color')
|
||||||
// const randomColor =
|
// const randomColor =
|
||||||
// '#' + Math.random().toString(16).substring(2, 8).padEnd(6, '0')
|
// '#' + Math.random().toString(16).substring(2, 8).padEnd(6, '0')
|
||||||
@ -68,6 +77,7 @@ export const useHjPolygon = (polygonMap: Map<string | number, any>) => {
|
|||||||
// if (zoneId) {
|
// if (zoneId) {
|
||||||
// if()
|
// if()
|
||||||
// }
|
// }
|
||||||
|
|
||||||
const curId = parentId || id
|
const curId = parentId || id
|
||||||
|
|
||||||
if (!colors.has(curId)) {
|
if (!colors.has(curId)) {
|
||||||
@ -214,3 +224,121 @@ export const useHjPolygon = (polygonMap: Map<string | number, any>) => {
|
|||||||
removeHangjingPolygon,
|
removeHangjingPolygon,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addTextAlongCurve(text, polygonPoints) {
|
||||||
|
// 创建 Billboard 集合
|
||||||
|
const billboardCollection = viewer.scene.primitives.add(
|
||||||
|
new Cesium.BillboardCollection()
|
||||||
|
)
|
||||||
|
|
||||||
|
// 创建文字绘制的辅助函数
|
||||||
|
function createTextTexture(text, angle) {
|
||||||
|
const canvas = document.createElement('canvas')
|
||||||
|
const context = canvas.getContext('2d')
|
||||||
|
|
||||||
|
// 设置 Canvas 大小
|
||||||
|
canvas.width = 20
|
||||||
|
canvas.height = 20
|
||||||
|
|
||||||
|
// 设置文字样式
|
||||||
|
context.font = '20px sans-serif' // 支持中文
|
||||||
|
context.fillStyle = 'blue'
|
||||||
|
context.textAlign = 'center'
|
||||||
|
context.textBaseline = 'middle'
|
||||||
|
|
||||||
|
// 将文字绘制到 Canvas,并进行旋转
|
||||||
|
context.clearRect(0, 0, canvas.width, canvas.height)
|
||||||
|
context.save()
|
||||||
|
|
||||||
|
// 旋转文字
|
||||||
|
context.translate(canvas.width / 2, canvas.height / 2)
|
||||||
|
context.rotate(angle)
|
||||||
|
context.fillText(text, 0, 0)
|
||||||
|
|
||||||
|
context.restore()
|
||||||
|
|
||||||
|
return canvas
|
||||||
|
}
|
||||||
|
|
||||||
|
// 动态生成字符标注
|
||||||
|
function generateLabels(cameraHeight) {
|
||||||
|
billboardCollection.removeAll() // 清除之前的标注
|
||||||
|
|
||||||
|
let charIndex = 0 // 当前字符索引
|
||||||
|
for (let i = 0; i < polygonPoints.length - 1; i++) {
|
||||||
|
const start = polygonPoints[i] // 当前边的起点
|
||||||
|
const end = polygonPoints[i + 1] // 当前边的终点
|
||||||
|
|
||||||
|
// 计算线段的方向向量
|
||||||
|
const direction = Cesium.Cartesian3.subtract(
|
||||||
|
end,
|
||||||
|
start,
|
||||||
|
new Cesium.Cartesian3()
|
||||||
|
)
|
||||||
|
Cesium.Cartesian3.normalize(direction, direction)
|
||||||
|
|
||||||
|
// 计算垂直于线段的方向向量
|
||||||
|
const perpendicular = Cesium.Cartesian3.cross(
|
||||||
|
direction,
|
||||||
|
Cesium.Cartesian3.UNIT_Z, // 使用 Z 轴(垂直地球表面)计算垂直方向
|
||||||
|
new Cesium.Cartesian3()
|
||||||
|
)
|
||||||
|
Cesium.Cartesian3.normalize(perpendicular, perpendicular)
|
||||||
|
|
||||||
|
// 计算线段的长度
|
||||||
|
const length = Cesium.Cartesian3.distance(start, end)
|
||||||
|
|
||||||
|
// 动态调整字符间隔,基于相机高度
|
||||||
|
const baseSpacing = 50 // 基础字符间隔
|
||||||
|
const charSpacing = Math.max((baseSpacing * cameraHeight) / 5000000, 30)
|
||||||
|
|
||||||
|
// 按字符间隔放置文字
|
||||||
|
let distance = 0
|
||||||
|
while (distance < length && charIndex < text.length) {
|
||||||
|
// 计算字符的位置
|
||||||
|
const fraction = distance / length // 当前字符在边上的位置比例
|
||||||
|
const position = Cesium.Cartesian3.lerp(
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
fraction,
|
||||||
|
new Cesium.Cartesian3()
|
||||||
|
)
|
||||||
|
|
||||||
|
// 计算旋转角度,使文字垂直于线段
|
||||||
|
const angle = Math.atan2(perpendicular.y, perpendicular.x)
|
||||||
|
|
||||||
|
// 创建带旋转的文字纹理
|
||||||
|
const canvas = createTextTexture(text[charIndex], angle)
|
||||||
|
|
||||||
|
// 添加 Billboard 显示文字
|
||||||
|
billboardCollection.add({
|
||||||
|
position: position,
|
||||||
|
image: canvas, // 使用生成的文字纹理
|
||||||
|
// pixelOffset: new Cesium.Cartesian2(10, 0),
|
||||||
|
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||||
|
})
|
||||||
|
|
||||||
|
// 更新字符索引和距离
|
||||||
|
charIndex++
|
||||||
|
console.log(charSpacing)
|
||||||
|
distance += charSpacing * 2000
|
||||||
|
// distance *= 2
|
||||||
|
console.log(distance)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果字符已用完,跳出循环
|
||||||
|
if (charIndex >= text.length) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化标注(根据初始相机高度)
|
||||||
|
generateLabels(viewer.camera.positionCartographic.height)
|
||||||
|
|
||||||
|
// 监听相机变化事件,动态更新字符间隔
|
||||||
|
viewer.camera.changed.addEventListener(() => {
|
||||||
|
const cameraHeight = viewer.camera.positionCartographic.height
|
||||||
|
generateLabels(cameraHeight)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
115
src/views/Hangjing/hooks/hangjingStyle.jsx
Normal file
115
src/views/Hangjing/hooks/hangjingStyle.jsx
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
import {
|
||||||
|
NForm,
|
||||||
|
NFormItem,
|
||||||
|
NInput,
|
||||||
|
NColorPicker,
|
||||||
|
NSelect,
|
||||||
|
NInputNumber,
|
||||||
|
NButton,
|
||||||
|
} from 'naive-ui'
|
||||||
|
import { useModal } from '@/views/Content/hooks/modal'
|
||||||
|
const { openDetailsModal } = useModal()
|
||||||
|
|
||||||
|
const styleForm = ref({
|
||||||
|
fontFamily: '微软雅黑',
|
||||||
|
fontSize: 14,
|
||||||
|
textColor: 'rgba(255,255,0,1)',
|
||||||
|
polygonColor: 'rgba(255,0,0,0.3)',
|
||||||
|
lineColor: 'rgba(255,0,0,1)',
|
||||||
|
lineWidth: 1,
|
||||||
|
lineType: 'solid',
|
||||||
|
})
|
||||||
|
export const useHangjingStyle = () => {
|
||||||
|
return { renderStyleContent, showStyleModal }
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderStyleContent(data) {
|
||||||
|
return (
|
||||||
|
<div class="flex flex-col gap-2 pt-4">
|
||||||
|
<NForm
|
||||||
|
model={styleForm.value}
|
||||||
|
labelPlacement="left"
|
||||||
|
//labelWidth: 100,
|
||||||
|
rules={{
|
||||||
|
fontFamily: [{ required: true, message: '请选择文字字体' }],
|
||||||
|
fontSize: [{ required: true, message: '请选择文字大小' }],
|
||||||
|
textColor: [{ required: true, message: '请选择文字颜色' }],
|
||||||
|
polygonColor: [{ required: true, message: '请选择区域颜色' }],
|
||||||
|
lineColor: [{ required: true, message: '请选择边框颜色' }],
|
||||||
|
lineType: [{ required: true, message: '请选择边框类型' }],
|
||||||
|
lineWidth: [{ required: true, message: '请选择边框宽度' }],
|
||||||
|
}}
|
||||||
|
class="grid grid-cols-2 gap-4"
|
||||||
|
>
|
||||||
|
<NFormItem label="文字字体" path="fontFamily">
|
||||||
|
<NSelect
|
||||||
|
v-model:value={styleForm.value.fontFamily}
|
||||||
|
options={[
|
||||||
|
{ label: '微软雅黑', value: '微软雅黑' },
|
||||||
|
{ label: '楷体', value: '楷体' },
|
||||||
|
{ label: '宋体', value: '宋体' },
|
||||||
|
]}
|
||||||
|
></NSelect>
|
||||||
|
</NFormItem>
|
||||||
|
<NFormItem label="边框颜色" path="lineColor">
|
||||||
|
<NColorPicker
|
||||||
|
v-model:value={styleForm.value.lineColor}
|
||||||
|
></NColorPicker>
|
||||||
|
</NFormItem>
|
||||||
|
<NFormItem label="文字大小" path="fontSize">
|
||||||
|
<NInputNumber
|
||||||
|
v-model:value={styleForm.value.fontSize}
|
||||||
|
min={1}
|
||||||
|
max={100}
|
||||||
|
></NInputNumber>
|
||||||
|
</NFormItem>
|
||||||
|
|
||||||
|
<NFormItem label="边框宽度" path="lineWidth">
|
||||||
|
<NInputNumber
|
||||||
|
v-model:value={styleForm.value.lineWidth}
|
||||||
|
min={1}
|
||||||
|
max={100}
|
||||||
|
></NInputNumber>
|
||||||
|
</NFormItem>
|
||||||
|
|
||||||
|
<NFormItem label="文字颜色" path="textColor">
|
||||||
|
<NColorPicker
|
||||||
|
v-model:value={styleForm.value.textColor}
|
||||||
|
></NColorPicker>
|
||||||
|
</NFormItem>
|
||||||
|
<NFormItem label="边框类型" path="lineType">
|
||||||
|
<NSelect
|
||||||
|
v-model:value={styleForm.value.lineType}
|
||||||
|
options={[
|
||||||
|
{ label: '实线', value: 'solid' },
|
||||||
|
{ label: '虚线', value: 'dashed' },
|
||||||
|
]}
|
||||||
|
></NSelect>
|
||||||
|
</NFormItem>
|
||||||
|
|
||||||
|
<NFormItem label="区域颜色" path="polygonColor">
|
||||||
|
<NColorPicker
|
||||||
|
v-model:value={styleForm.value.polygonColor}
|
||||||
|
></NColorPicker>
|
||||||
|
</NFormItem>
|
||||||
|
</NForm>
|
||||||
|
<div class="flex justify-end gap-2">
|
||||||
|
<NButton type="primary" onClick={updateStyle}>
|
||||||
|
确定
|
||||||
|
</NButton>
|
||||||
|
<NButton onClick={updateStyle}>取消</NButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function showStyleModal(title, data) {
|
||||||
|
openDetailsModal({
|
||||||
|
titleString: title,
|
||||||
|
contentSlot: renderStyleContent(data),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateStyle() {
|
||||||
|
// TODO: 更新样式
|
||||||
|
}
|
@ -9,9 +9,10 @@ import { getHangjing } from '@/api/Hangjing'
|
|||||||
import { useHangjing } from './hooks/hangjing'
|
import { useHangjing } from './hooks/hangjing'
|
||||||
import { convertToWKT } from '@/utils/parseWKT'
|
import { convertToWKT } from '@/utils/parseWKT'
|
||||||
import { useHangjingDetail } from './hooks/hangjingDetail'
|
import { useHangjingDetail } from './hooks/hangjingDetail'
|
||||||
import { useHangjingStyle } from './hooks/hangjingStyle'
|
// import { useHangjingStyle } from './hooks/hangjingStyle'
|
||||||
|
import Tree from '@/components/Tree/index.vue'
|
||||||
|
|
||||||
|
|
||||||
const { addHangjing } = useHangjing()
|
|
||||||
|
|
||||||
const timeRange = ref(null)
|
const timeRange = ref(null)
|
||||||
|
|
||||||
@ -101,70 +102,45 @@ const drawArea = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { showDetailsModal } = useHangjingDetail()
|
const { showDetailsModal } = useHangjingDetail()
|
||||||
const { showStyleModal } = useHangjingStyle()
|
// const { showStyleModal } = useHangjingStyle()
|
||||||
const columns = [
|
|
||||||
{
|
|
||||||
type: 'selection',
|
|
||||||
// disabled(row) {
|
|
||||||
// return row.name === 'Edward King 3'
|
|
||||||
// },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Name',
|
|
||||||
key: 'title',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Type',
|
|
||||||
key: 'hjType',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Action',
|
|
||||||
key: 'actions',
|
|
||||||
render(row) {
|
|
||||||
return h('div', { class: 'flex gap-2' }, [
|
|
||||||
h(
|
|
||||||
NButton,
|
|
||||||
{
|
|
||||||
strong: true,
|
|
||||||
tertiary: true,
|
|
||||||
size: 'small',
|
|
||||||
onClick: () => showDetailsModal(`${row.title}详情`, row),
|
|
||||||
},
|
|
||||||
{ default: () => '详情' }
|
|
||||||
),
|
|
||||||
h(
|
|
||||||
NButton,
|
|
||||||
{
|
|
||||||
strong: true,
|
|
||||||
tertiary: true,
|
|
||||||
size: 'small',
|
|
||||||
onClick: () => showStyleModal(`${row.title}样式配置`, row),
|
|
||||||
},
|
|
||||||
{ default: () => '样式配置' }
|
|
||||||
),
|
|
||||||
])
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
const data = ref([])
|
const data = ref([])
|
||||||
|
|
||||||
const paginationReactive = reactive({
|
const renderSuffix = ({ option }: { option: TreeOption }) => {
|
||||||
page: 1,
|
return option.data ? h('div', { class: 'flex items-center gap-2 pr-2' }, [
|
||||||
pageSize: 50,
|
h(
|
||||||
showSizePicker: true,
|
NButton,
|
||||||
pageSizes: [20, 50, 100],
|
{
|
||||||
onChange: page => {
|
text: true,
|
||||||
paginationReactive.page = page
|
size: 'tiny',
|
||||||
},
|
type: 'info',
|
||||||
onUpdatePageSize: pageSize => {
|
onClick: () => showDetailsModal(`${option.data.title}详情`, option.data),
|
||||||
paginationReactive.pageSize = pageSize
|
|
||||||
paginationReactive.page = 1
|
|
||||||
},
|
},
|
||||||
|
{ default: () => '详情' }
|
||||||
|
),
|
||||||
|
// h(
|
||||||
|
// NButton,
|
||||||
|
// {
|
||||||
|
// text: true,
|
||||||
|
// size: 'tiny',
|
||||||
|
// type: 'info',
|
||||||
|
// onClick: () => showStyleModal(`${option.data.title}样式配置`, option.data),
|
||||||
|
// },
|
||||||
|
// { default: () => '样式配置' }
|
||||||
|
// ),
|
||||||
|
]) : null
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkedKeys = ref<Array<string | number>>([])
|
||||||
|
|
||||||
|
const { addHangjing } = useHangjing()
|
||||||
|
|
||||||
|
watch(checkedKeys, val => {
|
||||||
|
addHangjing(val, data)
|
||||||
})
|
})
|
||||||
|
|
||||||
const handleCheck = (rowKeys: DataTableRowKey[]) => {
|
const handleCheck = (rowKeys: DataTableRowKey[]) => {
|
||||||
const selectedList = data.value.filter(item => rowKeys.includes(item.id))
|
const selectedList = data.value.filter(item => rowKeys.includes(item.id))
|
||||||
|
|
||||||
addHangjing(selectedList)
|
addHangjing(selectedList)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,7 +150,7 @@ const getHangjingData = async (params = {}) => {
|
|||||||
const { code, data: resData } = await getHangjing(params)
|
const { code, data: resData } = await getHangjing(params)
|
||||||
|
|
||||||
if (code === '200') {
|
if (code === '200') {
|
||||||
data.value = resData || []
|
data.value = [resData]
|
||||||
}
|
}
|
||||||
isLoading.value = false
|
isLoading.value = false
|
||||||
}
|
}
|
||||||
@ -204,14 +180,8 @@ const clearSelected = () => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col gap-2 w-h-full" v-loading="isLoading">
|
<div class="flex flex-col gap-2 w-h-full" v-loading="isLoading">
|
||||||
<n-date-picker
|
<n-date-picker v-model:formatted-value="timeRange" clearable type="datetimerange" :shortcuts="rangeShortcuts"
|
||||||
v-model:formatted-value="timeRange"
|
:update-value-on-close="true" format="yyyy-MM-dd HH:mm:ss" />
|
||||||
clearable
|
|
||||||
type="datetimerange"
|
|
||||||
:shortcuts="rangeShortcuts"
|
|
||||||
:update-value-on-close="true"
|
|
||||||
format="yyyy-MM-dd HH:mm:ss"
|
|
||||||
/>
|
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<n-input class="w-auto" v-model:value="searchTitle" />
|
<n-input class="w-auto" v-model:value="searchTitle" />
|
||||||
<n-select class="w-40" v-model:value="type" :options="typeOptions" />
|
<n-select class="w-40" v-model:value="type" :options="typeOptions" />
|
||||||
@ -239,15 +209,12 @@ const clearSelected = () => {
|
|||||||
<n-button type="primary" @click="searchHangjing">检索</n-button>
|
<n-button type="primary" @click="searchHangjing">检索</n-button>
|
||||||
</n-input-group>
|
</n-input-group>
|
||||||
</div>
|
</div>
|
||||||
<n-data-table
|
<!-- <n-data-table class="flex-1" :columns="columns" :data="data" :row-key="(rowData: Record<string, any>) => rowData.id"
|
||||||
class="flex-1"
|
flex-height @update:checked-row-keys="handleCheck" /> -->
|
||||||
:columns="columns"
|
|
||||||
:data="data"
|
|
||||||
:row-key="(rowData: Record<string, any>) => rowData.id"
|
|
||||||
flex-height
|
|
||||||
@update:checked-row-keys="handleCheck"
|
|
||||||
/>
|
|
||||||
<!-- :pagination="paginationReactive" -->
|
<!-- :pagination="paginationReactive" -->
|
||||||
|
|
||||||
|
<tree :data="data" :key-field="'dataId'" :label-field="'nodeName'" v-model:checked="checkedKeys" showSearch
|
||||||
|
:renderSuffix="renderSuffix" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ export const useMubiao = () => {
|
|||||||
// 获取目标坐标
|
// 获取目标坐标
|
||||||
const mbPos = await getMubiaoCurPos(targetIdList)
|
const mbPos = await getMubiaoCurPos(targetIdList)
|
||||||
|
|
||||||
console.log('mbPos', mbPos)
|
// console.log('mbPos', mbPos)
|
||||||
|
|
||||||
nodes.forEach(({ data, dataId: id }: IMubiao) => {
|
nodes.forEach(({ data, dataId: id }: IMubiao) => {
|
||||||
const { target_time, target_geom } =
|
const { target_time, target_geom } =
|
||||||
@ -105,6 +105,7 @@ export const useMubiao = () => {
|
|||||||
id,
|
id,
|
||||||
targetType,
|
targetType,
|
||||||
})
|
})
|
||||||
|
|
||||||
const mubiaoEntity = viewer.entities.add({
|
const mubiaoEntity = viewer.entities.add({
|
||||||
name: id,
|
name: id,
|
||||||
position: Cesium.Cartesian3.fromDegrees(...(position as number[])),
|
position: Cesium.Cartesian3.fromDegrees(...(position as number[])),
|
||||||
|
127
src/views/Mubiao/hooks/mubiaoDetail.jsx
Normal file
127
src/views/Mubiao/hooks/mubiaoDetail.jsx
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
// import { h } from 'vue'
|
||||||
|
import { NDataTable, NInputNumber, NSwitch } from 'naive-ui'
|
||||||
|
import { useModal } from '@/views/Content/hooks/modal'
|
||||||
|
const { openDetailsModal } = useModal()
|
||||||
|
export const useMubiaoDetail = () => {
|
||||||
|
return { showDetailsMubiao }
|
||||||
|
}
|
||||||
|
|
||||||
|
const detectingLoadColumns = [
|
||||||
|
{
|
||||||
|
title: '垂直起始角',
|
||||||
|
key: 'minimumClock',
|
||||||
|
width: 180,
|
||||||
|
render(row) {
|
||||||
|
return (
|
||||||
|
<NInputNumber
|
||||||
|
v-model:value={row.minimumClock}
|
||||||
|
// disabled={['光学', '雷达'].includes(row.type)}
|
||||||
|
></NInputNumber>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// title: '垂直终止角',
|
||||||
|
// key: 'maximumClock',
|
||||||
|
// width: 180,
|
||||||
|
// render(row) {
|
||||||
|
// return (
|
||||||
|
// <NInputNumber
|
||||||
|
// v-model:value={row.maximumClock}
|
||||||
|
// // disabled={['光学', '雷达'].includes(row.type)}
|
||||||
|
// ></NInputNumber>
|
||||||
|
// )
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
title: '水平起始角',
|
||||||
|
key: 'minimumCone',
|
||||||
|
width: 180,
|
||||||
|
render(row) {
|
||||||
|
return (
|
||||||
|
<NInputNumber
|
||||||
|
v-model:value={row.minimumCone}
|
||||||
|
// disabled={['光学', '雷达'].includes(row.type)}
|
||||||
|
></NInputNumber>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '水平终止角',
|
||||||
|
key: 'maximumCone',
|
||||||
|
width: 180,
|
||||||
|
render(row) {
|
||||||
|
return (
|
||||||
|
<NInputNumber
|
||||||
|
v-model:value={row.maximumCone}
|
||||||
|
// disabled={['光学', '雷达'].includes(row.type)}
|
||||||
|
></NInputNumber>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '半径',
|
||||||
|
key: 'radius',
|
||||||
|
width: 180,
|
||||||
|
render(row) {
|
||||||
|
return (
|
||||||
|
<NInputNumber
|
||||||
|
v-model:value={row.radius}
|
||||||
|
// disabled={['光学', '雷达'].includes(row.type)}
|
||||||
|
></NInputNumber>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '是否开启',
|
||||||
|
key: 'status',
|
||||||
|
render(row) {
|
||||||
|
return <NSwitch v-model:value={row.status}></NSwitch>
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const data = ref([
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
radius: 5000,
|
||||||
|
minimumClock: 20.0,
|
||||||
|
maximumClock: 110.0,
|
||||||
|
minimumCone: 20.0,
|
||||||
|
maximumCone: 90.0,
|
||||||
|
height: 100,
|
||||||
|
status: true,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
function renderMubiaoDetailsContent(mbData) {
|
||||||
|
// return h(
|
||||||
|
// 'div',
|
||||||
|
// {},
|
||||||
|
// Object.keys(mbData).map(key => h('div', {}, `${key}:${mbData[key]}`))
|
||||||
|
// )
|
||||||
|
return () => (
|
||||||
|
<div class="detail-container">
|
||||||
|
<div class="detail-item-title">基本信息</div>
|
||||||
|
<div>
|
||||||
|
{Object.keys(mbData).map(key => (
|
||||||
|
<div>
|
||||||
|
{key}:{mbData[key]}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<div class="detail-item-title">探测载荷</div>
|
||||||
|
<NDataTable
|
||||||
|
key={row => row.id}
|
||||||
|
columns={detectingLoadColumns}
|
||||||
|
data={data.value}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
function showDetailsMubiao(mbData) {
|
||||||
|
openDetailsModal({
|
||||||
|
titleString: 'zb详情',
|
||||||
|
contentSlot: renderMubiaoDetailsContent(mbData),
|
||||||
|
})
|
||||||
|
}
|
@ -1,19 +0,0 @@
|
|||||||
import { h } from 'vue'
|
|
||||||
import { useModal } from '@/views/Content/hooks/modal'
|
|
||||||
const { openDetailsModal } = useModal()
|
|
||||||
export const useMubiaoDetail = () => {
|
|
||||||
return { showDetailsMubiao }
|
|
||||||
}
|
|
||||||
function renderMubiaoDetailsContent(mbData: Record<string, any>) {
|
|
||||||
return h(
|
|
||||||
'div',
|
|
||||||
{},
|
|
||||||
Object.keys(mbData).map(key => h('div', {}, `${key}:${mbData[key]}`))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
function showDetailsMubiao(mbData: Record<string, any>) {
|
|
||||||
openDetailsModal({
|
|
||||||
titleString: 'zb详情',
|
|
||||||
contentSlot: renderMubiaoDetailsContent(mbData),
|
|
||||||
})
|
|
||||||
}
|
|
18
src/views/Mubiao/hooks/mubiaoLoad.jsx
Normal file
18
src/views/Mubiao/hooks/mubiaoLoad.jsx
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { useModal } from '@/views/Content/hooks/modal'
|
||||||
|
const { openDetailsModal } = useModal()
|
||||||
|
export const useMubiaoDetail = () => {
|
||||||
|
return { showDetailsMubiao }
|
||||||
|
}
|
||||||
|
function renderMubiaoDetailsContent(mbData) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div></div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
function showDetailsMubiao(mbData) {
|
||||||
|
openDetailsModal({
|
||||||
|
titleString: '载荷',
|
||||||
|
contentSlot: renderMubiaoDetailsContent(mbData),
|
||||||
|
})
|
||||||
|
}
|
@ -51,6 +51,16 @@ const renderSuffix = ({ option }: { option: TreeOption }) => {
|
|||||||
},
|
},
|
||||||
{ default: () => '详情' }
|
{ default: () => '详情' }
|
||||||
),
|
),
|
||||||
|
// h(
|
||||||
|
// NButton,
|
||||||
|
// {
|
||||||
|
// text: true,
|
||||||
|
// size: 'tiny',
|
||||||
|
// type: 'info',
|
||||||
|
// onClick: () => showDetailsMubiao(option.data),
|
||||||
|
// },
|
||||||
|
// { default: () => '载荷' }
|
||||||
|
// ),
|
||||||
h(
|
h(
|
||||||
NButton,
|
NButton,
|
||||||
{
|
{
|
||||||
@ -89,14 +99,8 @@ const renderSuffix = ({ option }: { option: TreeOption }) => {
|
|||||||
@update:checked-row-keys="handleCheck"
|
@update:checked-row-keys="handleCheck"
|
||||||
/> -->
|
/> -->
|
||||||
<div class="h-0 flex-1">
|
<div class="h-0 flex-1">
|
||||||
<tree
|
<tree :data="data" :key-field="'dataId'" :label-field="'nodeName'" v-model:checked="checkedKeys" showSearch
|
||||||
:data="data"
|
:renderSuffix="renderSuffix" />
|
||||||
:key-field="'dataId'"
|
|
||||||
:label-field="'nodeName'"
|
|
||||||
v-model:checked="checkedKeys"
|
|
||||||
showSearch
|
|
||||||
:renderSuffix="renderSuffix"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- :nodeProps="nodeProps" -->
|
<!-- :nodeProps="nodeProps" -->
|
||||||
|
127
src/views/Satellite/components/SatDetail.jsx
Normal file
127
src/views/Satellite/components/SatDetail.jsx
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
import { useModal } from '@/views/Content/hooks/modal'
|
||||||
|
import { NDataTable, NSelect, NInputNumber, NSwitch } from 'naive-ui'
|
||||||
|
|
||||||
|
const { openDetailsModal } = useModal()
|
||||||
|
|
||||||
|
const detectingLoadColumns = [
|
||||||
|
// {
|
||||||
|
// title: '载荷类型',
|
||||||
|
// key: 'type',
|
||||||
|
// render(row) {
|
||||||
|
// return (
|
||||||
|
// <NSelect
|
||||||
|
// v-model:value={row.type}
|
||||||
|
// options={[
|
||||||
|
// { label: '电子', value: '电子' },
|
||||||
|
// { label: '雷达', value: '雷达' },
|
||||||
|
// { label: '光学', value: '光学' },
|
||||||
|
// ]}
|
||||||
|
// ></NSelect>
|
||||||
|
// )
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
title: '开合角',
|
||||||
|
key: 'angle',
|
||||||
|
width: 120,
|
||||||
|
render(row) {
|
||||||
|
return (
|
||||||
|
<NInputNumber
|
||||||
|
v-model:value={row.angle}
|
||||||
|
max={120}
|
||||||
|
min={0}
|
||||||
|
// disabled={['光学', '雷达'].includes(row.type)}
|
||||||
|
></NInputNumber>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// title: '水平半角',
|
||||||
|
// key: 'xHalfAngle',
|
||||||
|
// width: 120,
|
||||||
|
// render(row) {
|
||||||
|
// return (
|
||||||
|
// <NInputNumber
|
||||||
|
// v-model:value={row.angle}
|
||||||
|
// max={120}
|
||||||
|
// min={0}
|
||||||
|
// disabled={['电子'].includes(row.type)}
|
||||||
|
// ></NInputNumber>
|
||||||
|
// )
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: '垂直半角',
|
||||||
|
// key: 'yHalfAngle',
|
||||||
|
// width: 120,
|
||||||
|
// render(row) {
|
||||||
|
// return (
|
||||||
|
// <NInputNumber
|
||||||
|
// v-model:value={row.angle}
|
||||||
|
// max={120}
|
||||||
|
// min={0}
|
||||||
|
// disabled={['电子'].includes(row.type)}
|
||||||
|
// ></NInputNumber>
|
||||||
|
// )
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
title: '是否开启',
|
||||||
|
key: 'status',
|
||||||
|
render(row) {
|
||||||
|
return <NSwitch v-model:value={row.status}></NSwitch>
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const data = ref([
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
angle: 30,
|
||||||
|
// xHalfAngle: 20,
|
||||||
|
// yHalfAngle: 25,
|
||||||
|
// type: '电子',
|
||||||
|
status: true,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
export function showDetailsSatellite(option) {
|
||||||
|
openDetailsModal({
|
||||||
|
titleString: '' + option.name + ' 详情',
|
||||||
|
contentSlot: () => (
|
||||||
|
<div class="detail-container">
|
||||||
|
<div class="detail-item-title">基本信息</div>
|
||||||
|
<div>
|
||||||
|
<div>卫星编号:{option.name}</div>
|
||||||
|
<div class="flex">
|
||||||
|
<div>两行根数:</div>
|
||||||
|
<div>
|
||||||
|
<p>{option.tle.split('\n')[0]}</p>
|
||||||
|
<p>{option.tle.split('\n')[1]}</p>
|
||||||
|
<p>{option.tle.split('\n')[2]}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="detail-item-title">探测载荷</div>
|
||||||
|
<NDataTable
|
||||||
|
key={row => row.id}
|
||||||
|
columns={detectingLoadColumns}
|
||||||
|
data={data.value}
|
||||||
|
/>
|
||||||
|
<div class="detail-item-title">通信载荷</div>
|
||||||
|
{/* <NDataTable
|
||||||
|
key={row => row.id}
|
||||||
|
columns={detectingLoadColumns}
|
||||||
|
data={data.value}
|
||||||
|
/> */}
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// export default defineComponent({
|
||||||
|
// name: 'SatDetail',
|
||||||
|
// setup(props) {
|
||||||
|
// return () => <></>
|
||||||
|
// },
|
||||||
|
// })
|
@ -2,11 +2,10 @@ import SatelliteEntity from '@/js/SatelliteEntity'
|
|||||||
import { difference } from 'lodash'
|
import { difference } from 'lodash'
|
||||||
import { useEntity } from '@/hooks/entity'
|
import { useEntity } from '@/hooks/entity'
|
||||||
// import CreateFrustum from '@/js/Sensor'
|
// import CreateFrustum from '@/js/Sensor'
|
||||||
import * as CesiumSensorVolumes from 'cesium-sensors-es6'
|
|
||||||
|
|
||||||
interface ISatellite {
|
interface ISatellite {
|
||||||
name: string
|
name: string
|
||||||
id: number | string
|
id: string
|
||||||
tle: string
|
tle: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -18,6 +17,17 @@ interface IBaseFilterParam {
|
|||||||
const satelliteList = ref<ISatellite[]>([])
|
const satelliteList = ref<ISatellite[]>([])
|
||||||
|
|
||||||
const { satelliteMap } = useEntity()
|
const { satelliteMap } = useEntity()
|
||||||
|
|
||||||
|
const showPoint = ref(true)
|
||||||
|
function showPointUnderSat(id?: string) {
|
||||||
|
if (id) {
|
||||||
|
satelliteMap.get(id).underPoint = true
|
||||||
|
} else {
|
||||||
|
;[...satelliteMap.values()].forEach(satellite => {
|
||||||
|
satellite.underPoint = showPoint.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
export function useSatellite() {
|
export function useSatellite() {
|
||||||
function addSatellites(ids: Array<string | number>) {
|
function addSatellites(ids: Array<string | number>) {
|
||||||
const addIds = difference(ids, [...satelliteMap.keys()])
|
const addIds = difference(ids, [...satelliteMap.keys()])
|
||||||
@ -33,6 +43,9 @@ export function useSatellite() {
|
|||||||
nodes.forEach(node => {
|
nodes.forEach(node => {
|
||||||
const entity = addSatellite(node)
|
const entity = addSatellite(node)
|
||||||
satelliteMap.set(node.id, entity)
|
satelliteMap.set(node.id, entity)
|
||||||
|
if (showPoint.value) {
|
||||||
|
showPointUnderSat(node.id)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,9 +60,10 @@ export function useSatellite() {
|
|||||||
// const result = viewer.entities.add(cesiumSateEntity)
|
// const result = viewer.entities.add(cesiumSateEntity)
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
satellite.sensorType = Math.random() > 0.5 ? 'conic' : 'rectangle'
|
// satellite.sensorType = Math.random() > 0.5 ? 'conic' : 'rectangle'
|
||||||
satellite.sensor = true
|
satellite.sensor = true
|
||||||
}, 1000)
|
}, 1000)
|
||||||
|
|
||||||
// viewer.clock.multiplier = 100
|
// viewer.clock.multiplier = 100
|
||||||
|
|
||||||
return satellite
|
return satellite
|
||||||
@ -85,7 +99,7 @@ export function useSatellite() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return { satelliteList, addSatellites }
|
return { satelliteList, addSatellites, showPoint, showPointUnderSat }
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterTreeNodeByField({
|
function filterTreeNodeByField({
|
||||||
|
@ -4,6 +4,7 @@ import { NButton } from 'naive-ui'
|
|||||||
import Tree from '@/components/Tree/index.vue'
|
import Tree from '@/components/Tree/index.vue'
|
||||||
import { getSatellite } from '@/api/Satellite'
|
import { getSatellite } from '@/api/Satellite'
|
||||||
import { useSatellite } from './hooks/satellite'
|
import { useSatellite } from './hooks/satellite'
|
||||||
|
import { showDetailsSatellite } from './components/SatDetail'
|
||||||
|
|
||||||
const { satelliteList, addSatellites } = useSatellite()
|
const { satelliteList, addSatellites } = useSatellite()
|
||||||
|
|
||||||
@ -35,7 +36,7 @@ const renderSuffix = ({ option }: { option: TreeOption }) => {
|
|||||||
text: true,
|
text: true,
|
||||||
size: 'tiny',
|
size: 'tiny',
|
||||||
type: 'info',
|
type: 'info',
|
||||||
// onClick: () => showDetailsSatellite(option),
|
onClick: () => showDetailsSatellite(option),
|
||||||
},
|
},
|
||||||
{ default: () => '详情' }
|
{ default: () => '详情' }
|
||||||
),
|
),
|
||||||
@ -67,5 +68,6 @@ const renderSuffix = ({ option }: { option: TreeOption }) => {
|
|||||||
showSearch
|
showSearch
|
||||||
:renderSuffix="renderSuffix"
|
:renderSuffix="renderSuffix"
|
||||||
/>
|
/>
|
||||||
|
<!-- <sat-detail /> -->
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
Loading…
Reference in New Issue
Block a user