This commit is contained in:
2025-11-28 09:57:25 +08:00
13 changed files with 242 additions and 85 deletions

View File

@ -863,3 +863,6 @@ img {
.el-popup-parent--hidden {
width: 100% !important;
}
.ts-zyl svg:focus {
outline: none;
}

View File

@ -50,6 +50,7 @@ import {useTreeNode} from "../components/tree/hooks/treeNode";
import {$changeComponentShow} from "../../utils/communication";
import {debounce} from '@/utils'
let canCheckType: Array<any> = ['directory', 'gdslImagery', 'terrain', 'tileset', 'arcgisWximagery', 'arcgisBlueImagery', 'gdlwImagery']
const {getSelectedNodes, cusSelectNode, getSameLevel, cusNodeIcon, nodeType} = useTreeNode()
import {showRightMenuTs} from "./tree"
import {TsApi} from "../../api/ts";
@ -238,7 +239,7 @@ const onCheck = (event: any, treeId: any, treeNode: any) => {
if (parentNode) {
checkChildNodes(parentNode);
}
let canCheckType: Array<any> = ['directory', 'gdslImagery', 'terrain', 'tileset', 'arcgisWximagery', 'arcgisBlueImagery', 'gdlwImagery']
// 检查子节点状态,更新父节点
function checkChildNodes(parentNode) {
@ -342,7 +343,14 @@ let rightClick = (event: MouseEvent, treeId: string, treeNode: any) => {
})
if (!event.ctrlKey && (selectNodes.length < 2 || isnewSelect))
cusSelectNode(treeObj.value, treeNode)
const menus = showRightMenuTs(event, treeObj.value, getSelectedNodes(treeObj.value), nodeType)
let menus = showRightMenuTs(event, treeObj.value, getSelectedNodes(treeObj.value), nodeType)
if (canCheckType.includes(treeNode.sourceType) && treeNode.sourceType != 'directory') {
let customView
let entity = window['_entityMap'].get(treeNode.id)
customView = Boolean(entity.customView && entity.customView.orientation)
menus = [...menus, customView ? 'resetView' : 'setView']
}
console.log('menus', menus)
if (menus.length == 0) {
// $changeComponentShow('.rightMenu', false)

View File

@ -5,14 +5,14 @@
<span class="title">{{ eventObj.name }}</span>
<div class="eventDetail">
<template v-if="eventObj.callback&&eventObj.callback=='flicker'">
<div>
闪烁间隔
<el-input v-model="detail.times" style="width: 50%" placeholder="Please input"/>
</div>
<!-- <div>
闪烁间隔
<el-input v-model="detail.times" style="width: 50%" placeholder="Please input"/>
</div>-->
<div>
闪烁次数
<el-input v-model="detail.numbers" style="width: 50%" placeholder="Please input"/>
<el-input v-model="detail.numbers" style="width: 50%" placeholder="请输入闪烁次数"/>
</div>
</template>
@ -35,11 +35,12 @@
<script lang="ts" setup>
import {inject, ref} from 'vue'
import {TsApi} from "../../../api/ts";
import {ElMessage} from "element-plus";
const times = ref(0)
const numbers = ref(0)
const detail:any = ref({})
const detail: any = ref({})
const eventBus: any = inject('bus')
let eventObj: any = ref(null)
@ -63,6 +64,14 @@ eventBus.on('click-event-show-plane', (params) => {
const updateEvent = () => {
// console.log(detail.value)
let obj = eventObj.value
let durationS = eventObj.value.duration_time
if (!durationS)
durationS = (eventObj.value.endTime - eventObj.value.startTime) / 1000
switch (eventObj.value.callback) {
case "flicker":
detail.value.times = Number((durationS / detail.value.numbers).toFixed(2))
break
}
obj.detail = JSON.stringify(detail.value)
console.log(obj)
delete obj.createdAt
@ -70,6 +79,10 @@ const updateEvent = () => {
delete obj.duration_time
TsApi.updateTsEvent(obj).then(res => {
console.log(res)
if (res.code == 200) {
ElMessage({type: "success", message: "操作成功"})
cancel()
}
})
}
const cancel = () => {
@ -77,6 +90,9 @@ const cancel = () => {
detail.value = {}
eventBus.emit('click-cancel-hide-plane',)
}
eventBus.on('delete-event', () => {
cancel()
})
</script>
<style lang="scss" scoped>

View File

@ -4,12 +4,15 @@
<div v-for="item in columns" :style="item.style">{{ item.name }}</div>
</div>
<div class="grid-body">
<div :class="['row',(eventObj&&event.id==eventObj.id)?'selectedRow':'']" :style="getStyle"
v-for="(event) in eventList" @click.right="(e)=>{rightClick(e,event)}">
<template v-for="item in 10">
<div :class="['row',(eventObj&&event.id==eventObj.id)?'selectedRow':'']" :style="getStyle"
v-for="(event) in eventList" @click.right="(e)=>{rightClick(e,event)}">
<span v-for="item in columns" :class="item.key" :style="item.style">{{
format(item.key, event[item.key])
}}</span>
</div>
</div>
</template>
<div :style="style">
<!--aa-->
</div>
@ -52,6 +55,7 @@
import {computed, onMounted, ref, nextTick} from "vue"
import {TsApi} from "../../../api/ts";
import {ElMessage} from "element-plus";
import * as electron from "electron";
const eventBus: any = inject('bus')
const props = defineProps(['eventList',])
@ -61,6 +65,16 @@ const menus = ref([
fun:
() => {
delEvent([rightClickEvent.value.id], () => {
switch (rightClickEvent.value.callback) {
case 'move':
let entityId = rightClickEvent.value.id + 'move' + rightClickEvent.value.sourceId
let entity = window['_entityMap'].get(entityId)
if (entity) {
entity.setMovePositionByTime(0)
window['_entityMap'].delete(entityId)
}
break;
}
ElMessage({message: "操作成功", type: "success"})
rightClickEvent.value = null
@ -80,6 +94,7 @@ const delEvent = (ids, cb) => {
if (res.code == 200) {
eventBus.emit('delete-event', ids)
cb()
hideRightMenu({target: {innerHTML: "sss"}})
}
})
}
@ -114,16 +129,28 @@ let getStyle = computed(() => {
})
const rightClick = (e, eventObj) => {
console.log("右键点击", e)
rightClickEvent.value = eventObj
nextTick(() => {
$(".gridRightMenu")[0].style.top = e.layerY + "px"
$(".gridRightMenu")[0].style.left = e.layerX + "px"
})
if (window['tsObj']._Clock._status !== 'play') {
rightClickEvent.value = eventObj
nextTick(() => {
let parentHeight = parseInt(window.getComputedStyle($(".grid-body")[0]).height)//203
let height = parseInt(window.getComputedStyle($(".gridRightMenu")[0]).height)//65
let maxTop = parentHeight - height//138
$(".gridRightMenu")[0].style.top = e.layerY > maxTop ? maxTop : e.layerY + "px"
$(".gridRightMenu")[0].style.left = e.layerX + "px"
})
} else {
ElMessage({message: "请先暂定或者停止播放"})
}
}
const hideRightMenu = (e) => {
console.log("hideRightMenu", e)
if (e.target.innerHTML != "删除")
if (e && e.target.innerHTML != "删除")
rightClickEvent.value = null
}
eventBus.on('click-event-show-plane', (params) => {

View File

@ -48,6 +48,7 @@ const itemClicks = (item) => {
const initMenus = (arr: any, treeNode: any) => {
let rightMenu: any = []
console.log('rightMenu2222', rightMenu)
console.log('arr', arr)
if (treeNode) {
rightClickTreeNode.value = treeNode
arr.forEach((menuId: any) => {

View File

@ -188,6 +188,49 @@ export const useRightOperate = () => {
const addEvent = (node, eventBus) => {
eventBus.emit('openAddEvent', node)
}
let setOrResetView = (setOrReset, node) => {
let {
id,
sourceName,
sourceType,
sourcePath,
parentId,
isShow,
detail,
params,
planId,
} = node
let entity = window['_entityMap'].get(id)
if (setOrReset)
entity.setCustomView()
else entity.resetCustomView()
const detailobj = {...JSON.parse(detail ?? '{}'), customView: setOrReset ? entity.customView : null};
let obj = {
id,
sourceName,
sourceType,
sourcePath,
parentId,
treeIndex: node.getIndex(),
isShow: isShow ? 1 : 0,
detail: JSON.stringify(detailobj),
params,
planId
}
TsApi.updateTsSource(obj).then(res => {
if (res.code == 200) {
ElMessage({type: "success", message: "操作成功"})
}
})
}
const setView = (node) => {
setOrResetView(true, node)
}
const resetView = (node) => {
setOrResetView(false, node)
}
const rightMenus: any = reactive({
addDirectory: {
key: 'addDirectory',
@ -209,6 +252,16 @@ export const useRightOperate = () => {
key: 'addEvent',
icon: 'addEventTs',
callback: addEvent
},
setView: {
key: 'setView',
icon: 'setView',
callback: setView
},
resetView: {
key: 'resetView',
icon: 'resetView',
callback: resetView
}
})

View File

@ -56,7 +56,7 @@
<!-- 左侧事件列表 -->
<grid :eventList="TSOBJ._Store._tasks"></grid>
<!--右侧时间轴容器-->
<div class="TLContainer" id="custom-container">
<div class="TLContainer " id="custom-container">
<div class="timelineCursorBox" :style="{ left: `${cursorLeft || 0}px` }">
<!--@mousedown="mousedown" :style="cursorStyle"-->
<!--@mouseup="mouseup"-->
@ -69,7 +69,8 @@
:originMainOffset="originMainOffset">
</timeScale>
<!-- 事件色块 -->
<chart :eventList="TSOBJ._Store._tasks" :hr="hr" :originHrOffset="originHrOffset" :scrollLeft="scrollLeft">
<chart :eventList="TSOBJ._Store._tasks" :hr="hr" :originHrOffset="originHrOffset" :scrollLeft="scrollLeft"
class="custom_scroll_bar_ts">
</chart>
</div>
</div>
@ -275,6 +276,8 @@ let eventCallback = () => {
taskIds.push(keys[i]);
}
}
console.log("taskIds", taskIds)
console.log("timeId", timeId)
taskIds.forEach((item) => {
let res = map.get(item);
todoEvent(timeId, res, isEnd);
@ -474,5 +477,24 @@ onBeforeUnmount(() => {
}
</style>
<style lang="scss">
.custom_scroll_bar_ts {
&::-webkit-scrollbar {
width: 8px; /* 竖滚动条宽度(横滚动条用 height */
height: 8px; /* 横滚动条高度不需要可设为0 */
}
&::-webkit-scrollbar-thumb {
border-radius: 1em;
background-color: rgb(0 255 255 / 100%);
}
&::-webkit-scrollbar-track {
-webkit-box-shadow: inset 0 0 1px rgba(0, 0, 0, 0.3);
border-radius: 10px;
background-color: #f5f5f5;
}
}
</style>

View File

@ -124,6 +124,7 @@ import * as domain from "domain";
import {TsApi} from "../../api/ts";
import {ElMessage} from "element-plus";
import {addMapSource} from "../../common/addMapSource";
import {$changeComponentShow} from "../../utils/communication";
const planInfo = ref({})
const isShowPup = ref(false)
@ -227,6 +228,7 @@ let getEventList = () => {
eventBus.on('delete-event', (ids) => {
console.log(ids)
tsOBJ.value._Store._tasks = tsOBJ.value._Store._tasks.filter(item => !ids.includes(item.id))
})
eventBus.on('add-event', (task) => {
tsOBJ.value._Store._tasks = [...tsOBJ.value._Store._tasks, task]
@ -317,6 +319,8 @@ const handleClick = (e) => {
console.log('点击事件触发', e)
let dom = $('.MouseRight')[0]
if (dom) dom.style.display = "none"
$changeComponentShow('.rightMenuTs', false)
}
</script>

View File

@ -163,6 +163,8 @@ const getModelListByType = (id) => {
GraphApi.showModelByType(formData).then((res) => {
res.data.forEach(item => {
item.funName = 'DrawPoint'
item.type = 'military'
})
elementList.value = res.data
})
@ -202,6 +204,10 @@ let addMarker = (item) => {
obj.modelDataUrl = item.modelDataUrl
obj.name = item.modelName
break
case 'military':
obj.militaryDataUrl = item.militaryDataUrl
obj.name = item.militaryName
break
case 'line':
case 'panel':
case 'attackArrow':

View File

@ -18,6 +18,12 @@ export function initMapData(type, data, cb: any = null) {
entityObject = new YJ.Obj.Model(window['earth_ts'], data)
break
case 'military':
data.url = baseURL + data.militaryDataUrl
entityObject = new YJ.Obj.GroundSvg(window['earth_ts'], data)
entityObject.load(() => {
})
break
case 'line':
entityObject = new YJ.Obj.PolylineObject(window['earth_ts'], data)
break

View File

@ -595,10 +595,3 @@ background-color: transparent;
}
</style>
<style lang="scss">
.ts-zyl {
svg:focus {
outline: none;
}
}
</style>

View File

@ -29,6 +29,7 @@
</el-form-item>
<el-form-item label="开始时间">
<el-date-picker
:show-now="false"
popper-class="ts_dark_theme"
v-model="form.datetime"
type="datetime"
@ -72,11 +73,12 @@
</el-form>
<div class="optionbtn">
<el-button @click="addEvent">确定</el-button>
<el-button @click="isShowPup=false">取消</el-button>
</div>
</template>
<div class="optionbtn">
<el-button @click="addEvent">确定</el-button>
<el-button @click="isShowPup=false">取消</el-button>
</div>
</div>
<div class="placeholder"></div>
@ -99,6 +101,8 @@ const currentKey = ref<number | string | null>("flicker");
interface Tree {
label: string
children?: Tree[]
id: any
name: any
}
const eventBus: any = inject('bus')
@ -119,7 +123,8 @@ const positions = ref([])//机动事件的轨迹点
form['datetime'] = new Date(window['tsObj']._Store._currentTimestamp)
const isShowPup = ref(false)
const eventTree: { children: ({ label: string } | { label: string })[]; id: string; label: string }[] = [
// : { children: ({ label: string } | { label: string })[]; id: string; label: string }[]
const eventTree = ref([
{
id: "normal",
label: '常用推演事件',
@ -134,25 +139,17 @@ const eventTree: { children: ({ label: string } | { label: string })[]; id: stri
label: '隐藏事件',
name: '隐藏'
},
{
id: "flicker",
label: '闪烁事件',
name: '闪烁'
},
{
id: "move",
label: '机动事件',
name: '机动'
},
],
},
]
}
])
const defaultProps = {
children: 'children',
label: 'label',
}
const handleNodeClick = (data: Tree, node, TreeNode, event) => {
console.log(data)
reset()
currentKey.value = data.id; // data.id 为节点的唯一 key需与 tree 的 node-key 对应)
form.name = data.name + '-' + zNode.value.sourceName
@ -166,19 +163,19 @@ const drawLine = () => {
const addEvent = () => {
console.log(zNode.value)
let startTime = form.datetime.getTime()
let obj = {}
let obj: any = {}
let duration_S = (hour.value * 3600 + minute.value * 60 + second.value) * 1
switch (currentKey.value) {
case 'flicker':
obj = {
times: times.value,
numbers: numbers.value
}
obj.numbers = numbers.value
obj.times = Number((duration_S / obj.numbers).toFixed(2))
break
case 'move':
let detail = typeof zNode.value.detail == 'string' ? JSON.parse(zNode.value.detail) : JSON.parse(JSON.stringify(zNode.value.detail))
let position = [...positions.value]
if (isContainModelPosition.value) {
position.unshift(detail.positions || detail.position)
position.unshift(detail.positions || detail.position || detail.center)
}
positions.value = position;
obj = {
@ -200,7 +197,7 @@ const addEvent = () => {
ElMessage({message: "机动事件的路径不合法", type: "warning"})
return
}
let duration_S = hour.value * 3600 + minute.value * 60 + second.value
let dbParams = {
id: new YJ.Tools().randomString(),
planId: window.planId,
@ -212,6 +209,7 @@ const addEvent = () => {
"detail": JSON.stringify(obj)
}
console.log("dbParams", dbParams)
// return;
TsApi.addTsEvent(dbParams).then(res => {
if (res.code == 200) {
ElMessage({
@ -253,12 +251,26 @@ const reset = () => {
}
eventBus.on('openAddEvent', (data, cb, type) => {
if (['point', "model", "military"].includes(data.sourceType))
eventTree.value[0].children = [...eventTree.value[0].children, {
id: "flicker",
label: '闪烁事件',
name: '闪烁'
},
{
id: "move",
label: '机动事件',
name: '机动'
},]
console.log("openAddEvent", data)
console.log("openAddEvent", eventTree.value[0].children[0])
// selectCallback = cb
// addType.value = type
zNode.value = data
isShowPup.value = true
form.name = '闪烁-' + data.sourceName
form.name = eventTree.value[0].children[0].name + '-' + data.sourceName
currentKey.value = eventTree.value[0].children[0].id
// if (data) {
// getModelList()
// getSetting()

View File

@ -38,8 +38,8 @@
y2="-6.678619384765625"
gradientUnits="userSpaceOnUse"
>
<stop offset="0" stop-color="rgb(var(--color-base1))" stop-opacity="0.2" />
<stop offset="1" stop-color="rgb(var(--color-base1))" stop-opacity="0" />
<stop offset="0" stop-color="rgb(var(--color-base1))" stop-opacity="0.2"/>
<stop offset="1" stop-color="rgb(var(--color-base1))" stop-opacity="0"/>
</linearGradient>
<linearGradient
id="linear_border_2442_491_0"
@ -49,8 +49,8 @@
y2="29.435516357421875"
gradientUnits="userSpaceOnUse"
>
<stop offset="0.0625" stop-color="rgb(var(--color-base1))" />
<stop offset="1" stop-color="var(--color-border1)" />
<stop offset="0.0625" stop-color="rgb(var(--color-base1))"/>
<stop offset="1" stop-color="var(--color-border1)"/>
</linearGradient>
<filter
id="filter_2442_492"
@ -61,21 +61,21 @@
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB"
>
<feFlood flood-opacity="0" result="feFloodId_2442_492" />
<feFlood flood-opacity="0" result="feFloodId_2442_492"/>
<feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha_2442_492"
/>
<feOffset dx="0" dy="0" />
<feGaussianBlur stdDeviation="2" />
<feComposite in2="hardAlpha_2442_492" operator="out" />
<feOffset dx="0" dy="0"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha_2442_492" operator="out"/>
<feColorMatrix
type="matrix"
values="0 0 0 0 0.1450980392156863 0 0 0 0 0.7686274509803922 0 0 0 0 0.7686274509803922 0 0 0 1 0"
/>
<feBlend mode="normal" in2="feFloodId_2442_492" result="dropShadow_1_2442_492" />
<feBlend mode="normal" in2="feFloodId_2442_492" result="dropShadow_1_2442_492"/>
<feBlend
mode="normal"
in="SourceGraphic"
@ -132,8 +132,8 @@
y2="-131.6942138671875"
gradientUnits="userSpaceOnUse"
>
<stop offset="0" stop-color="rgb(var(--color-base1))" stop-opacity="0.2" />
<stop offset="1" stop-color="rgb(var(--color-base1))" stop-opacity="0" />
<stop offset="0" stop-color="rgb(var(--color-base1))" stop-opacity="0.2"/>
<stop offset="1" stop-color="rgb(var(--color-base1))" stop-opacity="0"/>
</linearGradient>
<linearGradient
id="linear_border_2409_300_0"
@ -143,8 +143,8 @@
y2="580.431640625"
gradientUnits="userSpaceOnUse"
>
<stop offset="0.0625" stop-color="rgb(var(--color-base1))" />
<stop offset="1" stop-color="var(--color-border1)" />
<stop offset="0.0625" stop-color="rgb(var(--color-base1))"/>
<stop offset="1" stop-color="var(--color-border1)"/>
</linearGradient>
</defs>
</svg>
@ -197,7 +197,7 @@
size="small"
@click="searchPlace"
:loading="loading"
>{{ t('btn.search') }}
>{{ t('btn.search') }}
</el-button>
</div>
<div id="selectorBox">
@ -248,22 +248,22 @@
<script setup lang="ts">
// @ts-nocheck
import { debounce } from '@/utils'
import { useI18n } from 'vue-i18n'
import { useTree } from './hooks/tree'
import {debounce} from '@/utils'
import {useI18n} from 'vue-i18n'
import {useTree} from './hooks/tree'
import AMapLoader from '@amap/amap-jsapi-loader'
import rightMenu from './components/rightMenu.vue'
import { $changeComponentShow } from '@/utils/communication'
import { ref, nextTick } from 'vue'
import { ElMessage } from 'element-plus'
import { bus } from '@/utils/bus'
import { TreeApi } from '@/api/tree'
import { PoiApi } from '@/api/poi'
import { get } from 'jquery'
import {$changeComponentShow} from '@/utils/communication'
import {ref, nextTick} from 'vue'
import {ElMessage} from 'element-plus'
import {bus} from '@/utils/bus'
import {TreeApi} from '@/api/tree'
import {PoiApi} from '@/api/poi'
import {get} from 'jquery'
const { initTree, rightMenuRef, initTreeCallBack } = useTree()
const {initTree, rightMenuRef, initTreeCallBack} = useTree()
const { t } = useI18n()
const {t} = useI18n()
const isShow = ref(false)
const select = ref('poi')
const searchKey: any = ref('')
@ -369,7 +369,8 @@ var key =
(localStorage.getItem('AMapKey') && localStorage.getItem('AMapKey').split('|')[0]) ||
'd88fcc689d1aa99866b2d0d83fd36677'
var isOnline = false
var loadAmp = (cb = () => {}) => {
var loadAmp = (cb = () => {
}) => {
AMapLoader.reset()
AMapLoader.load({
key: key, // 申请好的Web端开发者Key首次调用 load 时必填
@ -469,7 +470,7 @@ const searchPlace = debounce(function () {
let string = searchKey.value.trim()
if (string) {
// TreeApi.queryPOI({ name: string, pageNum: 1, pageSize: 1000 }).then((res) => {
PoiApi.searchPoi({ name: string, pageNum: 1, pageSize: 1000 }).then((res) => {
PoiApi.searchPoi({name: string, pageNum: 1, pageSize: 1000}).then((res) => {
console.log(res, 'resres')
poiOptions.value = res.data
if (poiOptions.value.length) {
@ -522,7 +523,7 @@ const locationChange = () => {
// let sg84 = YJ.Global.CoordTransform.GCJ02ToWGS84(item.lng, item.lat);
let params = {
id,
position: { lng: item.lng, lat: item.lat, alt: item.alt ? item.alt : 0 },
position: {lng: item.lng, lat: item.lat, alt: item.alt ? item.alt : 0},
billboard: {
show: true,
image: 'http://localhost:' + availablePort.value + '/' + 'GEMarker1/A-ablu-blank.png',
@ -652,11 +653,12 @@ defineExpose({
text-shadow: 0px 0px 9px var(--color-text-shadow);
font-weight: 700;
background: linear-gradient(
90deg,
rgba(var(--color-base1), 0) 0%,
rgba(var(--color-base1), 0.5) 55.55%,
rgba(var(--color-base1), 0) 100%
90deg,
rgba(var(--color-base1), 0) 0%,
rgba(var(--color-base1), 0.5) 55.55%,
rgba(var(--color-base1), 0) 100%
);
> svg {
margin-right: 10px;
}
@ -797,19 +799,23 @@ defineExpose({
.el-select-dropdown__wrap {
max-height: 260px !important;
}
.custom-dropdown {
margin-top: 75px;
margin-right: 10px;
width: 380px !important;
}
.el-select-dropdown__item.is-hovering {
background-color: unset !important;
color: rgba(var(--color-base1), 1) !important;
}
.el-select-dropdown__item.is-selected {
background-color: unset !important;
color: rgba(var(--color-base1), 1) !important;
}
// .custom-dropdown2 {
// width: 380px !important;
// }