LSSE-front/src/views/subsystem/scene/presetting.vue
liaoboping efbdc9ce71 推演
2025-09-20 16:58:19 +08:00

531 lines
17 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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">
<div class="tool-wrapper" style="grid-area: 1 / 1 / 2 / 4">
<a-button type="text-primary">保障流程</a-button>
</div>
<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>
<div v-loading.dark="zzbzll.loading" class="normal" style="padding: 5px; overflow-y: auto">
<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>
<a-radio-group v-model="fd.type" button-style="solid" @change="getFdListData">
<a-radio-button :value="5">作战分队</a-radio-button>
<a-radio-button :value="6">保障分队</a-radio-button>
</a-radio-group>
</template>
<template #extra>
<AntOriginSelect v-model="fd.force" :dataSource="forceSource" width="80px" />
</template>
<Flex v-loading.dark="fd.loading" class="normal" fd="co" style="padding: 5px">
<Flex class="flex-1 scroller-y" fw="w" ac="fs">
<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>
</Flex>
</Flex>
</Flex>
</ModuleWrapper>
</div>
<Grid class="pr zi1" :rows="rightRows" gap="0px" style="grid-area: 2 / 3 / 3 / 4">
<ModuleWrapper title="兵力编组">
<template #extra>
<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 = ''" />
</template>
<div v-loading.dark="blbz.loading" class="normal" style="padding: 5px; overflow-y: auto">
<a-tree
class="simulation-tree"
:treeData="showBlbzCheckedTreeData"
:selectable="false"
:replaceFields="{ children: 'children', title: 'title', key: 'id' }"
>
</a-tree>
</div>
</ModuleWrapper>
<ModuleWrapper title="基础属性">
<template #extra>
<template v-if="zzbzll.selectedFd">
<a-button
type="text-primary"
icon="sync"
style="font-size: 20px"
@click="getJcsxModelData()"
></a-button>
</template>
<Zoom :max="rightViewer === 'jcsx'" @zoom-max="rightViewer = 'jcsx'" @zoom-min="rightViewer = ''" />
</template>
<div v-loading.dark="jcsx.loading" class="normal" style="padding: 15px 0">
<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"
:modelData="jcsx.modelData"
@request="getJcsxModelData()"
/>
</div>
</ModuleWrapper>
<ModuleWrapper :title="xdrw.resourceTypeMapTitle[zzbzll.selectedFd?.resourceType] || '行动任务'">
<template #extra>
<template v-if="zzbzll.selectedFd">
<a-button
type="text-primary"
icon="sync"
style="font-size: 20px"
@click="getXdrwActionList()"
></a-button>
</template>
<Zoom :max="rightViewer === 'xdrw'" @zoom-max="rightViewer = 'xdrw'" @zoom-min="rightViewer = ''" />
</template>
<div v-loading.dark="xdrw.loading" class="normal" style="padding: 0">
<Zzxd
ref="xdrw"
v-if="zzbzll.selectedFd"
:scenarioId="scenarioId"
:resourceId="zzbzll.selectedFd.id"
:resourceType="zzbzll.selectedFd.resourceType"
:actionList="xdrw.actionList"
@request="getXdrwActionList()"
/>
</div>
</ModuleWrapper>
</Grid>
</Grid>
</Flex>
</template>
<script>
import { getAction, postAction } from '@/api/manage'
import Zoom from './components/Zoom.vue'
import BlbzModal from './components/BlbzModal.vue'
import Jcsx from './components/Jcsx.vue'
import Zzxd from './components/Zzxd.vue'
export default {
name: 'SubsystemScenePresetting',
components: {
Zoom,
BlbzModal,
Jcsx,
Zzxd,
},
data() {
return {
scenarioId: '',
scenarioName: '',
cesium: null,
zzbzll: {
loading: false,
treeData: [],
selectedKeys: [],
selectedFd: null,
},
zzbzllModal: {
title: '修改名称',
visible: false,
formItems: [
{ label: '原名称', prop: 'originName', customRender: (text) => text },
{ label: '新名称', prop: 'resourceName', required: true },
],
formRules: {},
formData: {},
},
fd: {
force: 0,
type: 5,
loading: false,
listData: [],
},
blbz: {
loading: false,
treeData: [],
showKeys: [],
modalVisible: false,
fdData: null,
modalCheckedKeys: [],
},
rightViewer: '',
jcsx: {
loading: false,
modelData: {},
},
xdrw: {
resourceTypeMapTitle: {
5: '作战行动',
6: '保障任务',
},
loading: false,
actionList: [],
},
}
},
computed: {
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]
}
},
showBlbzCheckedTreeData() {
const target = []
this.getTree(target, this.blbz.treeData, this.blbz.showKeys)
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)
this.getFdListData()
},
methods: {
getTree(target, treeData, showKeys) {
treeData.forEach((item) => {
const newChildren = []
if (item.children && item.children.length > 0) {
this.getTree(newChildren, item.children, showKeys)
}
if (newChildren.length > 0 || showKeys.includes(item.key)) {
target.push({ ...item, children: newChildren })
}
})
},
async getZzbzllTreeData(initPlot = false) {
try {
this.zzbzll.loading = true
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)
} finally {
this.zzbzll.loading = false
}
},
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)
}
},
async getFdListData() {
try {
this.fd.loading = true
const res = await getAction(`/baseData/scenario/resources/${this.fd.type}`)
this.fd.listData = res.data
} catch (error) {
console.log(error)
} finally {
this.fd.loading = false
}
},
forceSource() {
return {
data: [
{ title: '红方', id: 0 },
{ title: '蓝方', id: 1 },
],
}
},
dragend(item, e) {
const minX = this.$refs['scene-presetting-cesium-container'].offsetLeft
const maxX =
this.$refs['scene-presetting-cesium-container'].offsetLeft +
this.$refs['scene-presetting-cesium-container'].offsetWidth
const minY = this.$refs['scene-presetting-cesium-container'].offsetTop
const maxY =
this.$refs['scene-presetting-cesium-container'].offsetTop +
this.$refs['scene-presetting-cesium-container'].offsetHeight
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 })
this.savePlot(this.fd.force, item, { plotId, longitude, latitude })
},
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)
}
},
handleSelectZzbzll(selectedKeys, { node }) {
this.cesium.setClientByCenter({ longitude: +node.dataRef.lng, latitude: +node.dataRef.lat })
this.zzbzll.selectedFd = node.dataRef
this.getBlbzTreeData()
this.getJcsxModelData()
this.getXdrwActionList()
},
async getBlbzTreeData() {
try {
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
} catch (error) {
console.log(error)
} finally {
this.blbz.loading = false
}
},
async handleOpenBlbzModal() {
if (!this.zzbzll.selectedFd) {
this.$message.error('未选择分队!')
return
}
this.blbz.modalCheckedKeys = [...this.blbz.showKeys]
this.blbz.modalVisible = true
},
async handleSubmitBlbz() {
try {
const { type, id: resourceId, scenarioId } = this.zzbzll.selectedFd
const res = await postAction('/scenarioOrgPost/batchSave', {
type,
resourceId,
scenarioId,
orgIdList: this.blbz.modalCheckedKeys,
})
this.blbz.modalVisible = false
this.$message.success(res.message)
this.getBlbzTreeData()
} catch (error) {
console.log(error)
}
},
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
}
},
},
}
</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 {
.distance-legend {
left: 320px;
}
.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;
}
}
.fd-item {
width: calc(100% / 3);
.fd-image {
width: 74px;
height: 62px;
object-fit: cover;
margin: 16px 0 8px;
}
.fd-name {
white-space: nowrap;
max-width: 100%;
overflow: hidden;
text-overflow: ellipsis;
}
}
.fd-item:hover {
.fd-name {
overflow: visible;
}
}
</style>