增加机动事件,将事件单个删除改为批量删除

This commit is contained in:
zyl
2025-11-10 09:55:45 +08:00
parent 4f0a18b29a
commit 425c3b8eb0
12 changed files with 405 additions and 199 deletions

Binary file not shown.

View File

@ -33,6 +33,13 @@ export const TsApi = {
data data
}) })
}, },
// /tsSource/delete
deleteTsModelSource: async (data: any) => {
return await request.post({
url: '/tsSource/delete',
data
})
},
queryTsSource: async (data: any) => { queryTsSource: async (data: any) => {
return await request.post({ return await request.post({
url: '/tsSource/query', url: '/tsSource/query',

View File

@ -50,9 +50,15 @@ const initTreeCallBack = () => {
if (res.code == 200) { if (res.code == 200) {
for (let i = res.data.length - 1; i >= 0; i--) { for (let i = res.data.length - 1; i >= 0; i--) {
res.data[i].svg = await cusNodeIcon(res.data[i]); res.data[i].svg = await cusNodeIcon(res.data[i]);
} }
zNodes.value = res.data zNodes.value = res.data
console.log("data", zNodes.value) /*zNodes.value.forEach(item => {
if (typeof item.detail == 'string') {
item.detail = JSON.parse(item.detail)
}
})*/
console.log("zNodes.value", zNodes.value)
treeObj.value = $.fn.zTree.init($(`#treeDemos`), setting, zNodes.value) treeObj.value = $.fn.zTree.init($(`#treeDemos`), setting, zNodes.value)
window.treeObj = treeObj.value window.treeObj = treeObj.value
} }
@ -73,8 +79,8 @@ const initTreeCallBack = () => {
if (arr[i].sourceType === 'directory') { if (arr[i].sourceType === 'directory') {
continue continue
} }
let detail = JSON.parse(arr[i].detail || '{}') let detail = typeof arr[i].detail == 'string' ? JSON.parse(arr[i].detail || '{}') : arr[i].detail
let params = JSON.parse(arr[i].params || '{}') let params = typeof arr[i].params == 'string' ? JSON.parse(arr[i].params || '{}') : arr[i].params
if (!detail.name) { if (!detail.name) {
detail.name = arr[i].sourceName detail.name = arr[i].sourceName
} }
@ -89,10 +95,29 @@ const initTreeCallBack = () => {
} }
) )
} else { } else {
console.log({...detail, ...params})
initMapData(arr[i].sourceType, {...detail, ...params}) initMapData(arr[i].sourceType, {...detail, ...params})
}
}
}
}
//gis实例渲染后查找是否有相关的轨迹运动对象有则渲染
let guijiEvents = window['tsObj']._Store.getTaskByProperty("move", "callback")
guijiEvents.forEach(event => {
let detail = typeof event.detail == 'string' ? JSON.parse(event.detail) : JSON.parse(JSON.stringify(event.detail))
let duration_S = (event.endTime - event.startTime) / 1000
let distance = new YJ.Tools().computeDistance2(detail.line.positions);
let speed = (distance / duration_S) * window['tsObj']._Store._multiplier
detail.speed = speed
console.log("event的detail", detail)
initMapData("guiji", detail, (TrajectoryMotionObject) => {
TrajectoryMotionObject.state = false
TrajectoryMotionObject.oldSpeed = (distance / duration_S) * window['tsObj']._Store._multiplier
(window as any)._entityMap.set(event.id + event.callback + event.sourceId, TrajectoryMotionObject)
let tsEntitys = (window as any)._entityMap.get(event.sourceId);
TrajectoryMotionObject.moveCallBack(tsEntitys)
})
})
layers.sort((obj1, obj2) => { layers.sort((obj1, obj2) => {
return obj1.detail.layerIndex - obj2.detail.layerIndex; return obj1.detail.layerIndex - obj2.detail.layerIndex;
}); });

View File

@ -47,7 +47,10 @@ eventBus.on('click-event-show-plane', (params) => {
console.log('兄弟 B 的方法被触发了!', params) console.log('兄弟 B 的方法被触发了!', params)
eventObj.value = (params ? params : null) eventObj.value = (params ? params : null)
if (eventObj.value) { if (eventObj.value) {
let details = JSON.parse(eventObj.value.detail) let details = eventObj.value.detail
if (typeof details == 'string') {
details = JSON.parse(eventObj.value.detail)
}
switch (params.callback) { switch (params.callback) {
case 'flicker': case 'flicker':
// times.value = detail.times // times.value = detail.times

View File

@ -58,24 +58,35 @@ const props = defineProps(['eventList',])
const menus = ref([ const menus = ref([
{ {
name: "删除", name: "删除",
fun: () => { fun:
let param = new FormData () => {
param.append("id", rightClickEvent.value.id) delEvent([rightClickEvent.value.id], () => {
TsApi.delEvent(param).then(res => {
if (res.code == 200) {
eventBus.emit('delete-event', rightClickEvent.value.id)
ElMessage({message: "操作成功", type: "success"}) ElMessage({message: "操作成功", type: "success"})
rightClickEvent.value = null rightClickEvent.value = null
}
}) })
} }
}, { }, {
name: '定位', fun: () => { name: '定位', fun: () => {
let entity = window['earth_ts'].entityMap.get(rightClickEvent.value.sourceId) let entity = window['earth_ts'].entityMap.get(rightClickEvent.value.sourceId)
entity && entity.flyTo() entity && entity.flyTo()
} }
},]) },]
)
const clicked = ref(false) const clicked = ref(false)
const delEvent = (ids, cb) => {
TsApi.delEvent(ids).then(res => {
if (res.code == 200) {
eventBus.emit('delete-event', ids)
cb()
}
})
}
eventBus.on("del-event-by-source", ids => {
delEvent(ids, () => {
})
})
function onCancel() { function onCancel() {
clicked.value = true clicked.value = true

View File

@ -2,10 +2,10 @@ import {$changeComponentPop} from "../../../utils/communication";
import {ipcRenderer} from "electron"; import {ipcRenderer} from "electron";
import {addMapSource, initMapData} from "../entity"; import {addMapSource, initMapData} from "../entity";
import {TsApi} from "../../../api/ts"; import {TsApi} from "../../../api/ts";
import {ElMessage} from "element-plus"; import {ElMessage, ElMessageBox} from "element-plus";
import {useTreeNode} from "../../components/tree/hooks/treeNode"; import {useTreeNode} from "../../components/tree/hooks/treeNode";
const {cusAddNodes} = useTreeNode() const {cusAddNodes, getSelectedNodes, cusRemoveNode} = useTreeNode()
function getLastPathComponent(path, extensionsToRemove = []) { function getLastPathComponent(path, extensionsToRemove = []) {
// 处理路径分隔符 // 处理路径分隔符
@ -139,8 +139,46 @@ export const useRightOperate = () => {
} }
}) })
} }
const delNode = () => { const delNode = (node, eventBus) => {
console.log("删除节点") console.log("删除节点", eventBus)
ElMessageBox.confirm('此操作将永久删除节点及所有子节点, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(async () => {
let selectNodes = getSelectedNodes(window.treeObj)
let source_ids = cusRemoveNode(window.treeObj, selectNodes)
console.log(source_ids)
TsApi.deleteTsModelSource(source_ids).then(res => {
if (res.code == 0 || res.code == 200) {
ElMessage({
message: '删除成功',
type: 'success'
})
let eventIds = []
source_ids.forEach(item => {
let entity = (window as any).earth_ts.entityMap.get(item)
if (entity) {
entity.remove();
(window as any)._entityMap.delete(entity.options.id)
}
//关闭资源的编辑框,删除相关的事件
// eventBus.emit("destroyComponent", item);
let arr = window['tsObj']._Store.getTaskByProperty(item, "sourceId", "id")
eventIds = eventIds.concat(arr)
});
eventBus.emit("del-event-by-source", eventIds)
}
})
}).catch(() => {
// 用户点击取消,不执行任何操作
})
/*let formData = new FormData()
formData.append("id", "")
TsApi.deleteTsModelSource(formData).then(res => {
})*/
} }
const editNode = () => { const editNode = () => {
console.log("编辑节点") console.log("编辑节点")

View File

@ -36,7 +36,8 @@
</div> </div>
<!-- 时间轴刻度线 --> <!-- 时间轴刻度线 -->
<timeScale :ticTiny="ticTiny" :ticMain="ticMain" :distanceOfTicTiny="distanceOfTicTiny" <timeScale :ticTiny="ticTiny" :ticMain="ticMain" :distanceOfTicTiny="distanceOfTicTiny"
:distanceOfTicMain="distanceOfTicMain" :originOffset="originOffset" :originMainOffset="originMainOffset"> :distanceOfTicMain="distanceOfTicMain" :originOffset="originOffset"
:originMainOffset="originMainOffset">
</timeScale> </timeScale>
<!-- 事件色块 --> <!-- 事件色块 -->
<chart :eventList="TSOBJ._Store._tasks" :hr="hr" :originHrOffset="originHrOffset" :scrollLeft="scrollLeft"> <chart :eventList="TSOBJ._Store._tasks" :hr="hr" :originHrOffset="originHrOffset" :scrollLeft="scrollLeft">
@ -120,6 +121,8 @@ function todoEvent(timeId: number, res: any, isEnd: boolean) {
let tsEntity = window['earth_ts'].entityMap.get(res.sourceId); let tsEntity = window['earth_ts'].entityMap.get(res.sourceId);
tsEntity.flicker(Number(res.detail.times) * 1000, Number(res.detail.numbers)) tsEntity.flicker(Number(res.detail.times) * 1000, Number(res.detail.numbers))
break; break;
case 'move':
break
} }
} }

View File

@ -66,9 +66,9 @@ let getEventList = () => {
}) })
newTS(params, events) newTS(params, events)
} }
eventBus.on('delete-event', (id) => { eventBus.on('delete-event', (ids) => {
console.log(id) console.log(ids)
tsOBJ.value._Store._tasks = tsOBJ.value._Store._tasks.filter(item => item.id != id) tsOBJ.value._Store._tasks = tsOBJ.value._Store._tasks.filter(item => !ids.includes(item.id))
}) })
// 新建态势推演对象 // 新建态势推演对象
let newTS = (params, events) => { let newTS = (params, events) => {

View File

@ -13,6 +13,8 @@ export function initMapData(type, data, cb: any = null) {
entityObject = new YJ.Obj.BillboardObject(window['earth_ts'], data) entityObject = new YJ.Obj.BillboardObject(window['earth_ts'], data)
break break
case 'model': case 'model':
data.url = baseURL + data.modelDataUrl
entityObject = new YJ.Obj.Model(window['earth_ts'], data) entityObject = new YJ.Obj.Model(window['earth_ts'], data)
break break
case 'line': case 'line':
@ -38,6 +40,14 @@ export function initMapData(type, data, cb: any = null) {
}) })
break break
case "guiji":
entityObject = new YJ.Obj.TrajectoryMotionObject(
window['earth_ts'],
data
);
if (cb)
cb(entityObject)
break
} }
if (entityObject) { if (entityObject) {
function getOptions() { function getOptions() {
@ -48,7 +58,14 @@ export function initMapData(type, data, cb: any = null) {
options = getOptions() options = getOptions()
if (entityObject.options.id) { if (entityObject.options.id) {
if (type !== 'guiji')
(window as any)._entityMap.set(entityObject.options.id, entityObject) (window as any)._entityMap.set(entityObject.options.id, entityObject)
/*else (window as any)._entityMap.set(res.ID + res.callback + res.source_id, entityObject)
let tsEntitys = ts_Map.get(Number(res.source_id));
TrajectoryMotionObject.moveCallBack(tsEntitys);*/
} }
return options return options

View File

@ -1,10 +1,9 @@
<template> <template>
<div class="newEvent"> <div class="newEvent" v-if="isShowPup">
<el-dialog v-model="isShowPup" :modal="true" draggable :close-on-click-modal="false"> <!-- <el-dialog v-model="isShowPup" :modal="true" draggable :close-on-click-modal="false">
<template #header> <template #header>
<div class="set_pup_header"> <div class="set_pup_header">
<div class="system_title"> <div class="system_title">
<!--{{ t('model.title') }}-->
态势事件 态势事件
</div> </div>
</div> </div>
@ -72,7 +71,7 @@
<el-form-item label="路径是否包含元素点位" label-width="160"> <el-form-item label="路径是否包含元素点位" label-width="160">
<el-switch v-model="isContainModelPosition"/> <el-switch v-model="isContainModelPosition"/>
</el-form-item> </el-form-item>
<el-button>绘制路径</el-button> <el-button @click="drawLine">绘制路径</el-button>
</template> </template>
@ -88,7 +87,91 @@
</div> </div>
<div class="placeholder"></div> <div class="placeholder"></div>
</div> </div>
</el-dialog> </el-dialog>-->
<div class="set_pup_header">
<div class="system_title">
态势事件
</div>
</div>
<div class="set_detail">
<div class="sort">
<el-tree
ref="treeRef"
style="max-width: 600px"
:data="eventTree"
:props="defaultProps"
node-key="id"
:check-on-click-node="true"
@node-click="handleNodeClick"
:default-expanded-keys="['normal']"
:current-node-key="currentKey"
:class="{'custom-tree': true}"
/>
</div>
<div class="eventDetail">
<template v-if="currentKey&&currentKey!='normal'">
<el-form label-width="auto" :model="form" style="max-width: 600px">
<el-form-item label="事件名称">
<el-input v-model="form.name"/>
</el-form-item>
<el-form-item label="开始时间">
<el-date-picker
v-model="form.datetime"
type="datetime"
placeholder="选择触发时间"
/>
</el-form-item>
<el-form-item label="持续时间">
<div class="duration">
<span>
<el-input v-model="hour"/>
</span>
<span>
<el-input v-model="minute"/>
</span><span>
<el-input v-model="second"/>
</span>
</div>
</el-form-item>
<template v-if="currentKey=='flicker'">
<el-form-item label="闪烁间隔">
<div class="duration">
<span>
<el-input v-model="times"/>
</span>
</div>
</el-form-item>
<el-form-item label="闪烁次数">
<div class="duration">
<span>
<el-input v-model="numbers"/>
</span>
</div>
</el-form-item>
</template>
<template v-if="currentKey=='move'">
<el-form-item label="路径是否包含元素点位" label-width="160">
<el-switch v-model="isContainModelPosition"/>
</el-form-item>
<el-button @click="drawLine">绘制路径</el-button>
</template>
<el-form-item>
<div class="optionbtn">
<el-button @click="addEvent">确定</el-button>
<el-button @click="isShowPup=false">取消</el-button>
</div>
</el-form-item>
</el-form>
</template>
</div>
<div class="placeholder"></div>
</div>
</div> </div>
</template> </template>
@ -98,6 +181,7 @@ import {ref, reactive} from "vue";
import type {RenderContentContext, TreeInstance} from 'element-plus' import type {RenderContentContext, TreeInstance} from 'element-plus'
import {TsApi} from "../../api/ts"; import {TsApi} from "../../api/ts";
import {ElMessage} from "element-plus"; import {ElMessage} from "element-plus";
import {initMapData} from "./entity";
const treeRef = ref<TreeInstance>() const treeRef = ref<TreeInstance>()
// 存储当前需要高亮的节点 key初始为空 // 存储当前需要高亮的节点 key初始为空
@ -108,6 +192,7 @@ interface Tree {
children?: Tree[] children?: Tree[]
} }
const eventBus: any = inject('bus')
let form = reactive({ let form = reactive({
name: '闪烁-', name: '闪烁-',
// datetime: '', // datetime: '',
@ -118,8 +203,10 @@ const minute = ref(0)
const second = ref(0) const second = ref(0)
const times = ref(0)//闪烁间隔 const times = ref(0)//闪烁间隔
const numbers = ref(0)//闪烁次数 const numbers = ref(0)//闪烁次数
const isContainModelPosition = ref(true) const isContainModelPosition = ref(true)
const eventBus: any = inject('bus') const positions = ref([])//机动事件的轨迹点
form['datetime'] = new Date(window['tsObj']._Store._currentTimestamp) form['datetime'] = new Date(window['tsObj']._Store._currentTimestamp)
const isShowPup = ref(false) const isShowPup = ref(false)
@ -150,7 +237,14 @@ const handleNodeClick = (data: Tree, node, TreeNode, event) => {
currentKey.value = data.id; // data.id 为节点的唯一 key需与 tree 的 node-key 对应) currentKey.value = data.id; // data.id 为节点的唯一 key需与 tree 的 node-key 对应)
form.name = data.name + '-' + zNode.value.sourceName form.name = data.name + '-' + zNode.value.sourceName
} }
const drawLine = () => {
let draw = new YJ.Draw.DrawPolyline(window['earth_ts'])
draw.start((error, p) => {
positions.value = p
})
}
const addEvent = () => { const addEvent = () => {
console.log(zNode.value)
let startTime = form.datetime.getTime() let startTime = form.datetime.getTime()
let obj = {} let obj = {}
switch (currentKey.value) { switch (currentKey.value) {
@ -160,7 +254,33 @@ const addEvent = () => {
numbers: numbers.value numbers: numbers.value
} }
break 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)
} }
positions.value = position;
obj = {
ground: false,
show: true,
// speed: 0,
loop: false,
line: {
smooth: false,
show: false,
positions: positions.value,
},
isContainModelPosition: isContainModelPosition.value
}
break
}
// 当事件为机动事件且轨迹点的长度为0时终止
if (obj['positions'] && obj['positions'].length == 0) {
ElMessage({message: "机动事件的路径不合法", type: "warning"})
return
}
let duration_S = hour.value * 3600 + minute.value * 60 + second.value
let dbParams = { let dbParams = {
id: new YJ.Tools().randomString(), id: new YJ.Tools().randomString(),
planId: window.planId, planId: window.planId,
@ -168,9 +288,11 @@ const addEvent = () => {
name: form.name, name: form.name,
callback: currentKey.value, callback: currentKey.value,
startTime, startTime,
endTime: startTime + (hour.value * 3600 + minute.value * 60 + second.value) * 1000, endTime: startTime + duration_S * 1000,
"detail": JSON.stringify(obj) "detail": JSON.stringify(obj)
} }
console.log(obj)
TsApi.addTsEvent(dbParams).then(res => { TsApi.addTsEvent(dbParams).then(res => {
if (res.code == 200) { if (res.code == 200) {
ElMessage({ ElMessage({
@ -179,6 +301,19 @@ const addEvent = () => {
}) })
} }
if (currentKey.value == 'move') {
let params = JSON.parse(JSON.stringify(obj))
let distance = new YJ.Tools().computeDistance2(params.line.positions);
let speeds = (distance / duration_S) * window['tsObj']._Store._multiplier
params.speed = speeds
initMapData("guiji", params, (entityObject) => {
entityObject.state = false
entityObject.oldSpeed = (distance / duration_S) * window['tsObj']._Store._multiplier
(window as any)._entityMap.set(dbParams.id + dbParams.callback + dbParams.sourceId, entityObject)
let tsEntitys = (window as any)._entityMap.get(dbParams.sourceId);
entityObject.moveCallBack(tsEntitys)
})
}
isShowPup.value = false isShowPup.value = false
reset() reset()
@ -195,6 +330,7 @@ const reset = () => {
name: '闪烁-', name: '闪烁-',
// datetime: '', // datetime: '',
} }
form['datetime'] = new Date(window['tsObj']._Store._currentTimestamp)
currentKey.value = "flicker" currentKey.value = "flicker"
} }
@ -218,10 +354,38 @@ eventBus.on('openAddEvent', (data, cb, type) => {
.newEvent { .newEvent {
position: absolute; position: absolute;
z-index: 99; z-index: 99;
//bottom: 200px; top: 40%;
//left: 50%; left: 50%;
//width: 40vw; transform: translate(-50%, -50%);
//height: 50vh; width: 570px;
height: 320px;
border: 1px solid #0ff;
border-radius: 3px;
background: rgba(0, 0, 0, 0.5);
.set_pup_header {
display: flex;
justify-content: center;
align-items: center;
padding-top: 10px;
padding-bottom: 20px;
.system_title {
background: url('@/assets/images/titlebg.png') no-repeat;
background-size: 100% 100%;
width: 229px;
height: 34px;
line-height: 34px;
text-align: center;
font-family: 'alimamashuheiti';
font-size: 18px;
color: #fff;
//margin-bottom: 25px;
//font-weight: 700;
}
}
.set_detail { .set_detail {
display: flex; display: flex;
@ -294,82 +458,9 @@ eventBus.on('openAddEvent', (data, cb, type) => {
} }
} }
:deep(.el-overlay) {
position: absolute;
} }
:deep(.el-overlay-dialog) {
/*position: absolute;
right: auto;*/
bottom: auto;
}
:deep(.el-dialog) {
background: linear-gradient(180deg, rgba(0, 255, 255, 0.2) 0%, rgba(0, 255, 255, 0) 100%),
rgba(0, 0, 0, 0.6);
border: 1px solid #00c9ff;
padding: 0 !important;
//position: absolute;
width: 570px;
height: 323px;
}
:deep(.el-dialog__body) {
padding: 0 !important;
height: calc(100% - 50px);
}
:deep(.el-dialog__headerbtn) {
height: 30px;
width: 30px;
border-bottom-left-radius: 80%;
background-color: #008989;
&:hover {
background-color: #00ffff;
.el-dialog__close {
color: rgba(0, 66, 66, 1); // 悬停时改变关闭图标为红色
}
}
}
:deep(.el-dialog__headerbtn .el-dialog__close) {
color: #fff;
}
.set_pup_header {
width: 100%;
height: 100%;
// background-color: #00ffff;
display: flex;
justify-content: center;
align-items: center;
//padding-bottom: 20px;
.system_title {
background: url('@/assets/images/titlebg.png') no-repeat;
background-size: 100% 100%;
width: 229px;
height: 34px;
line-height: 34px;
text-align: center;
font-family: 'alimamashuheiti';
font-size: 18px;
color: #fff;
//font-weight: 700;
}
}
}
:deep(.el-input__wrapper), :deep(.el-input__inner ) {
background: transparent;
--el-input-placeholder-color: #fff;
color: #fff;
//border: 1px solid #0ff;
}
/* /*
:deep(.el-tree-node__children .is-checked) { :deep(.el-tree-node__children .is-checked) {

View File

@ -36,7 +36,7 @@
<el-form-item> <el-form-item>
<div class="optionbtn"> <div class="optionbtn">
<el-button @click="addPlan(ruleFormRef)">确定</el-button> <el-button @click="addPlan(ruleFormRef)">确定</el-button>
<el-button>取消</el-button> <el-button @click="isShowPup= false">取消</el-button>
</div> </div>
</el-form-item> </el-form-item>
</el-form> </el-form>

View File

@ -30,9 +30,11 @@ export class Store {
_startTimestamp _startTimestamp
_currentTimestamp _currentTimestamp
_tasks _tasks
_multiplier
private _panelWidth //面板宽度 private _panelWidth //面板宽度
constructor(option) { constructor(option) {
this._multiplier = option.multiplier || 1
this._panelWidth = option.panelWidth this._panelWidth = option.panelWidth
this._tasks = option.tasks this._tasks = option.tasks
this._startTimestamp = option.startTimestamp this._startTimestamp = option.startTimestamp
@ -153,4 +155,13 @@ export class Store {
return map return map
} }
// 通过特定的字段名和值来获取事件
getTaskByProperty(value, property = "ID", isReturnPropertyValue = null) {
// console.log("getTaskById", id)
if (isReturnPropertyValue) {
return this._tasks.map(task => task[isReturnPropertyValue])
} else {
return this._tasks.filter(task => (task[property] == value))
}
}
} }