LSSE-front/src/views/subsystem/scene/presetting.vue

531 lines
17 KiB
Vue
Raw Normal View History

2025-09-18 09:34:18 +08:00
<template>
<Flex fd="co" class="page-scene-presetting">
<Flex ai="c" jc="sb" class="page-scene-presetting-header">
<span class="page-scene-presetting-title">场景编辑子系统</span>
<span class="page-scene-presetting-title">编辑想定{{ scenarioId }}-{{ scenarioName }}</span>
<span class="page-scene-presetting-title" style="color: transparent">场景编辑子系统</span>
</Flex>
<Grid class="page-scene-presetting-main flex-1 oh" :columns="['320px', 1, '320px']" :rows="['30px', 1]" gap="0px">
2025-09-20 16:58:19 +08:00
<div class="tool-wrapper" style="grid-area: 1 / 1 / 2 / 4">
<a-button type="text-primary">保障流程</a-button>
</div>
2025-09-18 09:34:18 +08:00
<div
ref="scene-presetting-cesium-container"
class="scene-presetting-cesium-container"
id="scene-presetting-cesium-container"
style="grid-area: 2 / 1 / 3 / 4"
></div>
<div class="pr zi1" style="grid-area: 2 / 1 / 3 / 2">
<ModuleWrapper title="作战/保障力量" height="45%">
<template #extra>
<a-button type="text-primary" icon="sync" style="font-size: 20px" @click="getZzbzllTreeData()"></a-button>
</template>
2025-09-20 10:54:37 +08:00
<div v-loading.dark="zzbzll.loading" class="normal" style="padding: 5px; overflow-y: auto">
2025-09-18 09:34:18 +08:00
<a-tree
class="simulation-tree"
:treeData="zzbzll.treeData"
:selectedKeys.sync="zzbzll.selectedKeys"
:replaceFields="{ children: 'children', title: 'title', key: 'id' }"
@select="handleSelectZzbzll"
>
<template #title="{ id, dataRef }">
<a-dropdown :trigger="['contextmenu']">
<span>{{ dataRef.resourceName || dataRef.title }}</span>
<template #overlay>
<Flex>
<a-button
type="text-primary"
icon="edit"
title="修改名称"
@click="handleOpenEditZzbzllModal(id, dataRef)"
></a-button>
<AntFormModal
:visible.sync="zzbzllModal.visible"
:title="zzbzllModal.title"
:formItems="zzbzllModal.formItems"
:formRules="zzbzllModal.formRules"
:formData="zzbzllModal.formData"
:onSubmit="handleSubmitZzbzll"
@success="handleSubmitZzbzllSuccess"
></AntFormModal>
<a-button
type="text-danger"
icon="delete"
title="删除"
@click="handleDeleteZzbzll(id, dataRef)"
></a-button>
</Flex>
</template>
</a-dropdown>
</template>
</a-tree>
</div>
</ModuleWrapper>
<ModuleWrapper height="55%">
<template #title>
2025-09-20 10:54:37 +08:00
<a-radio-group v-model="fd.type" button-style="solid" @change="getFdListData">
2025-09-18 09:34:18 +08:00
<a-radio-button :value="5">作战分队</a-radio-button>
<a-radio-button :value="6">保障分队</a-radio-button>
</a-radio-group>
</template>
2025-09-20 14:11:12 +08:00
<template #extra>
<AntOriginSelect v-model="fd.force" :dataSource="forceSource" width="80px" />
</template>
2025-09-20 10:54:37 +08:00
<Flex v-loading.dark="fd.loading" class="normal" fd="co" style="padding: 5px">
2025-09-18 09:34:18 +08:00
<Flex class="flex-1 scroller-y" fw="w" ac="fs">
2025-09-20 10:54:37 +08:00
<Flex v-for="item in fd.listData" :key="item.id" class="fd-item" fd="co" ai="c">
<img class="fd-image" :src="item.imgBase64" :draggable="true" @dragend="dragend(item, $event)" />
<span class="fd-name">{{ item.name }}</span>
2025-09-18 09:34:18 +08:00
</Flex>
</Flex>
</Flex>
</ModuleWrapper>
</div>
2025-09-20 10:54:37 +08:00
<Grid class="pr zi1" :rows="rightRows" gap="0px" style="grid-area: 2 / 3 / 3 / 4">
2025-09-20 16:58:19 +08:00
<ModuleWrapper title="兵力编组">
2025-09-18 09:34:18 +08:00
<template #extra>
2025-09-20 10:54:37 +08:00
<template v-if="zzbzll.selectedFd">
<a-button
type="text-primary"
icon="setting"
style="font-size: 20px"
@click="handleOpenBlbzModal()"
></a-button>
<BlbzModal
:visible.sync="blbz.modalVisible"
:fdData="zzbzll.selectedFd"
v-model="blbz.modalCheckedKeys"
@ok="handleSubmitBlbz"
/>
<a-button type="text-primary" icon="sync" style="font-size: 20px" @click="getBlbzTreeData()"></a-button>
</template>
<Zoom :max="rightViewer === 'blbz'" @zoom-max="rightViewer = 'blbz'" @zoom-min="rightViewer = ''" />
2025-09-18 09:34:18 +08:00
</template>
2025-09-20 10:54:37 +08:00
<div v-loading.dark="blbz.loading" class="normal" style="padding: 5px; overflow-y: auto">
2025-09-18 09:34:18 +08:00
<a-tree
class="simulation-tree"
:treeData="showBlbzCheckedTreeData"
:selectable="false"
:replaceFields="{ children: 'children', title: 'title', key: 'id' }"
>
</a-tree>
</div>
</ModuleWrapper>
2025-09-20 16:58:19 +08:00
<ModuleWrapper title="基础属性">
2025-09-20 10:54:37 +08:00
<template #extra>
<template v-if="zzbzll.selectedFd">
<a-button
type="text-primary"
icon="sync"
style="font-size: 20px"
2025-09-20 16:58:19 +08:00
@click="getJcsxModelData()"
2025-09-20 10:54:37 +08:00
></a-button>
</template>
<Zoom :max="rightViewer === 'jcsx'" @zoom-max="rightViewer = 'jcsx'" @zoom-min="rightViewer = ''" />
2025-09-18 09:34:18 +08:00
</template>
2025-09-20 16:58:19 +08:00
<div v-loading.dark="jcsx.loading" class="normal" style="padding: 15px 0">
2025-09-20 10:54:37 +08:00
<Jcsx
ref="jcsx"
v-if="zzbzll.selectedFd"
:scenarioId="scenarioId"
:resourceId="zzbzll.selectedFd.id"
:resourceName="zzbzll.selectedFd.title"
:resourceType="zzbzll.selectedFd.resourceType"
:type="zzbzll.selectedFd.type"
2025-09-20 16:58:19 +08:00
:modelData="jcsx.modelData"
@request="getJcsxModelData()"
2025-09-20 10:54:37 +08:00
/>
2025-09-18 09:34:18 +08:00
</div>
</ModuleWrapper>
2025-09-20 16:58:19 +08:00
<ModuleWrapper :title="xdrw.resourceTypeMapTitle[zzbzll.selectedFd?.resourceType] || '行动任务'">
2025-09-20 10:54:37 +08:00
<template #extra>
<template v-if="zzbzll.selectedFd">
<a-button
type="text-primary"
icon="sync"
style="font-size: 20px"
2025-09-20 16:58:19 +08:00
@click="getXdrwActionList()"
2025-09-20 10:54:37 +08:00
></a-button>
</template>
<Zoom :max="rightViewer === 'xdrw'" @zoom-max="rightViewer = 'xdrw'" @zoom-min="rightViewer = ''" />
</template>
2025-09-20 16:58:19 +08:00
<div v-loading.dark="xdrw.loading" class="normal" style="padding: 0">
2025-09-20 10:54:37 +08:00
<Zzxd
ref="xdrw"
v-if="zzbzll.selectedFd"
:scenarioId="scenarioId"
:resourceId="zzbzll.selectedFd.id"
:resourceType="zzbzll.selectedFd.resourceType"
2025-09-20 16:58:19 +08:00
:actionList="xdrw.actionList"
@request="getXdrwActionList()"
2025-09-20 10:54:37 +08:00
/>
</div>
</ModuleWrapper>
</Grid>
2025-09-18 09:34:18 +08:00
</Grid>
</Flex>
</template>
<script>
import { getAction, postAction } from '@/api/manage'
2025-09-20 10:54:37 +08:00
import Zoom from './components/Zoom.vue'
import BlbzModal from './components/BlbzModal.vue'
2025-09-18 09:34:18 +08:00
import Jcsx from './components/Jcsx.vue'
import Zzxd from './components/Zzxd.vue'
export default {
name: 'SubsystemScenePresetting',
components: {
2025-09-20 10:54:37 +08:00
Zoom,
BlbzModal,
2025-09-18 09:34:18 +08:00
Jcsx,
Zzxd,
},
data() {
return {
scenarioId: '',
scenarioName: '',
cesium: null,
zzbzll: {
2025-09-20 10:54:37 +08:00
loading: false,
2025-09-18 09:34:18 +08:00
treeData: [],
selectedKeys: [],
2025-09-20 10:54:37 +08:00
selectedFd: null,
2025-09-18 09:34:18 +08:00
},
zzbzllModal: {
title: '修改名称',
visible: false,
formItems: [
{ label: '原名称', prop: 'originName', customRender: (text) => text },
{ label: '新名称', prop: 'resourceName', required: true },
],
formRules: {},
formData: {},
},
2025-09-20 10:54:37 +08:00
fd: {
2025-09-20 14:11:12 +08:00
force: 0,
2025-09-18 09:34:18 +08:00
type: 5,
2025-09-20 10:54:37 +08:00
loading: false,
2025-09-18 09:34:18 +08:00
listData: [],
},
blbz: {
2025-09-20 10:54:37 +08:00
loading: false,
2025-09-18 09:34:18 +08:00
treeData: [],
2025-09-20 10:54:37 +08:00
showKeys: [],
modalVisible: false,
fdData: null,
modalCheckedKeys: [],
2025-09-18 09:34:18 +08:00
},
2025-09-20 10:54:37 +08:00
rightViewer: '',
2025-09-20 16:58:19 +08:00
jcsx: {
loading: false,
modelData: {},
},
2025-09-20 10:54:37 +08:00
xdrw: {
resourceTypeMapTitle: {
5: '作战行动',
6: '保障任务',
2025-09-18 09:34:18 +08:00
},
2025-09-20 16:58:19 +08:00
loading: false,
actionList: [],
2025-09-18 09:34:18 +08:00
},
}
},
computed: {
2025-09-20 10:54:37 +08:00
rightRows() {
switch (this.rightViewer) {
case 'blbz':
return [8, 1, 1]
case 'jcsx':
return [1, 8, 1]
case 'xdrw':
return [1, 1, 8]
default:
return [4, 3, 3]
}
},
2025-09-18 09:34:18 +08:00
showBlbzCheckedTreeData() {
const target = []
2025-09-20 10:54:37 +08:00
this.getTree(target, this.blbz.treeData, this.blbz.showKeys)
2025-09-18 09:34:18 +08:00
return target
},
},
created() {
this.scenarioId = this.$route.params.scenarioId
this.scenarioName = this.$route.params.scenarioName
},
mounted() {
this.cesium = new window.MyCesium('scene-presetting-cesium-container')
this.getZzbzllTreeData(true)
2025-09-20 10:54:37 +08:00
this.getFdListData()
2025-09-18 09:34:18 +08:00
},
methods: {
2025-09-20 10:54:37 +08:00
getTree(target, treeData, showKeys) {
2025-09-18 09:34:18 +08:00
treeData.forEach((item) => {
const newChildren = []
if (item.children && item.children.length > 0) {
2025-09-20 10:54:37 +08:00
this.getTree(newChildren, item.children, showKeys)
2025-09-18 09:34:18 +08:00
}
2025-09-20 10:54:37 +08:00
if (newChildren.length > 0 || showKeys.includes(item.key)) {
2025-09-18 09:34:18 +08:00
target.push({ ...item, children: newChildren })
}
})
},
async getZzbzllTreeData(initPlot = false) {
try {
2025-09-20 10:54:37 +08:00
this.zzbzll.loading = true
2025-09-18 09:34:18 +08:00
const res = await postAction(`/scenario/resource/`, {
scenarioId: this.scenarioId,
})
this.zzbzll.treeData = [
{
id: '0',
title: '红方',
selectable: false,
children: res.data.filter((item) => item.type === 0),
},
{
id: '1',
title: '蓝方',
selectable: false,
children: res.data.filter((item) => item.type === 1),
},
]
if (initPlot) {
this.initPlot(res.data)
}
} catch (error) {
console.log(error)
2025-09-20 10:54:37 +08:00
} finally {
this.zzbzll.loading = false
2025-09-18 09:34:18 +08:00
}
},
initPlot(plots) {
plots.forEach((item) => {
if (item.lng && item.lat) {
this.cesium.addPlotByLonLat(item.imgBase64, { lon: +item.lng, lat: +item.lat }, item.id)
}
})
},
handleOpenEditZzbzllModal(id, data) {
this.zzbzllModal.formData = { id, originName: data.resourceName || data.title }
this.zzbzllModal.visible = true
this.zzbzllModal.originData = data
},
handleSubmitZzbzll(formData) {
return postAction('/scenario/resource/save', formData)
},
handleSubmitZzbzllSuccess() {
this.$set(this.zzbzllModal.originData, 'resourceName', this.zzbzllModal.formData.resourceName)
},
async handleDeleteZzbzll(id, data) {
try {
await this.$confirm({ content: `确定删除${data.resourceName || data.title}` })
const res = await getAction(`/scenario/resource/remove/${id}`)
this.$message.success(res.message)
this.cesium.removePlotById(id)
this.getZzbzllTreeData()
} catch (error) {
console.log(error)
}
},
2025-09-20 10:54:37 +08:00
async getFdListData() {
2025-09-18 09:34:18 +08:00
try {
2025-09-20 10:54:37 +08:00
this.fd.loading = true
const res = await getAction(`/baseData/scenario/resources/${this.fd.type}`)
this.fd.listData = res.data
2025-09-18 09:34:18 +08:00
} catch (error) {
console.log(error)
2025-09-20 10:54:37 +08:00
} finally {
this.fd.loading = false
2025-09-18 09:34:18 +08:00
}
},
2025-09-20 14:11:12 +08:00
forceSource() {
return {
data: [
{ title: '红方', id: 0 },
{ title: '蓝方', id: 1 },
],
}
},
2025-09-18 19:57:55 +08:00
dragend(item, e) {
const minX = this.$refs['scene-presetting-cesium-container'].offsetLeft
2025-09-20 10:54:37 +08:00
const maxX =
this.$refs['scene-presetting-cesium-container'].offsetLeft +
this.$refs['scene-presetting-cesium-container'].offsetWidth
2025-09-18 19:57:55 +08:00
const minY = this.$refs['scene-presetting-cesium-container'].offsetTop
2025-09-20 10:54:37 +08:00
const maxY =
this.$refs['scene-presetting-cesium-container'].offsetTop +
this.$refs['scene-presetting-cesium-container'].offsetHeight
2025-09-18 19:57:55 +08:00
if (e.x < minX || e.x > maxX || e.Y < minY || e.Y > maxY) return
const x = e.x - this.$refs['scene-presetting-cesium-container'].offsetLeft
const y = e.y - this.$refs['scene-presetting-cesium-container'].offsetTop
const { plotId, longitude, latitude } = this.cesium.addPlotByOffset(item.imgBase64, { x, y })
2025-09-20 14:11:12 +08:00
this.savePlot(this.fd.force, item, { plotId, longitude, latitude })
2025-09-18 19:57:55 +08:00
},
async savePlot(force, item, { plotId, longitude, latitude }) {
try {
await postAction('/scenario/resource/save', {
id: plotId,
scenarioId: this.scenarioId,
type: force,
resourceType: item.type,
resourceId: item.id,
lng: longitude,
lat: latitude,
})
this.getZzbzllTreeData()
} catch (error) {
console.log(error)
}
},
2025-09-18 09:34:18 +08:00
handleSelectZzbzll(selectedKeys, { node }) {
this.cesium.setClientByCenter({ longitude: +node.dataRef.lng, latitude: +node.dataRef.lat })
2025-09-20 10:54:37 +08:00
this.zzbzll.selectedFd = node.dataRef
2025-09-18 09:34:18 +08:00
this.getBlbzTreeData()
2025-09-20 16:58:19 +08:00
this.getJcsxModelData()
this.getXdrwActionList()
2025-09-18 09:34:18 +08:00
},
async getBlbzTreeData() {
try {
2025-09-20 10:54:37 +08:00
this.blbz.loading = true
const { type, id: resourceId, scenarioId } = this.zzbzll.selectedFd
const res = await Promise.all([
getAction('/tree/organization'),
postAction('/scenarioOrgPost/getPost', { type, resourceId, scenarioId }),
])
this.blbz.treeData = res[0].data
this.blbz.showKeys = res[1].data
2025-09-18 09:34:18 +08:00
} catch (error) {
console.log(error)
2025-09-20 10:54:37 +08:00
} finally {
this.blbz.loading = false
2025-09-18 09:34:18 +08:00
}
},
async handleOpenBlbzModal() {
2025-09-20 10:54:37 +08:00
if (!this.zzbzll.selectedFd) {
2025-09-18 09:34:18 +08:00
this.$message.error('未选择分队!')
return
}
2025-09-20 10:54:37 +08:00
this.blbz.modalCheckedKeys = [...this.blbz.showKeys]
this.blbz.modalVisible = true
2025-09-18 09:34:18 +08:00
},
async handleSubmitBlbz() {
try {
2025-09-20 10:54:37 +08:00
const { type, id: resourceId, scenarioId } = this.zzbzll.selectedFd
2025-09-18 09:34:18 +08:00
const res = await postAction('/scenarioOrgPost/batchSave', {
type,
resourceId,
scenarioId,
2025-09-20 10:54:37 +08:00
orgIdList: this.blbz.modalCheckedKeys,
2025-09-18 09:34:18 +08:00
})
2025-09-20 10:54:37 +08:00
this.blbz.modalVisible = false
2025-09-18 09:34:18 +08:00
this.$message.success(res.message)
this.getBlbzTreeData()
} catch (error) {
console.log(error)
}
},
2025-09-20 16:58:19 +08:00
async getJcsxModelData() {
try {
this.jcsx.loading = true
const res = await getAction('/statistic/info', {
type: this.zzbzll.selectedFd.type,
resourceId: this.zzbzll.selectedFd.id,
scenarioId: this.scenarioId,
})
this.jcsx.modelData = res.data
} catch (error) {
console.log(error)
} finally {
this.jcsx.loading = false
}
},
async getXdrwActionList() {
try {
this.xdrw.loading = true
const res = await postAction('/scenarioTask/taskList', {
scenarioId: this.scenarioId,
resourceId: this.zzbzll.selectedFd.id,
})
this.xdrw.actionList = res.data
} catch (error) {
console.log(error)
} finally {
this.xdrw.loading = false
}
},
2025-09-18 09:34:18 +08:00
},
}
</script>
<style lang="less" scoped>
.page-scene-presetting {
height: 100%;
color: #ffffff;
.page-scene-presetting-header {
height: 50px;
background-color: #0a2a3d;
padding: 0 20px;
.page-scene-presetting-title {
color: #00d5fe;
font-size: 18px;
font-weight: bolder;
letter-spacing: 2px;
}
}
.page-scene-presetting-main {
background-color: #022234;
}
}
.scene-presetting-cesium-container {
width: 100%;
height: 100%;
overflow: hidden;
}
::v-deep {
2025-09-18 19:57:55 +08:00
.distance-legend {
left: 320px;
}
2025-09-18 09:34:18 +08:00
.compass {
right: 320px;
}
.navigation-controls {
right: 350px;
}
}
.simulation-tree::v-deep {
color: #a1c2d0;
li .ant-tree-node-content-wrapper {
color: #a1c2d0;
}
li .ant-tree-node-content-wrapper.ant-tree-node-selected {
background-color: #bae7ff44;
}
li .ant-tree-node-content-wrapper:hover {
background-color: #bae7ff22;
}
}
2025-09-20 10:54:37 +08:00
.fd-item {
2025-09-18 09:34:18 +08:00
width: calc(100% / 3);
2025-09-20 10:54:37 +08:00
.fd-image {
2025-09-18 09:34:18 +08:00
width: 74px;
height: 62px;
object-fit: cover;
margin: 16px 0 8px;
}
2025-09-20 10:54:37 +08:00
.fd-name {
2025-09-18 09:34:18 +08:00
white-space: nowrap;
max-width: 100%;
overflow: hidden;
text-overflow: ellipsis;
}
}
2025-09-20 10:54:37 +08:00
.fd-item:hover {
.fd-name {
2025-09-18 09:34:18 +08:00
overflow: visible;
}
}
</style>