想定编辑基础信息

This commit is contained in:
liaoboping 2025-08-16 18:25:01 +08:00
parent 1ad29f234e
commit 7fd607f5e6
4 changed files with 408 additions and 65 deletions

View File

@ -1,4 +1,5 @@
@import '~ant-design-vue/es/style/themes/default.less'; @import '~ant-design-vue/es/style/themes/default.less';
@import './style/antd.less';
html, html,
body, body,

39
src/style/antd.less Normal file
View File

@ -0,0 +1,39 @@
/* ---- button start ---- */
.text-btn-color-mixin(@base, @hover, @active) {
color: @base;
&:hover:not(.ant-btn-primary):not(.ant-btn-danger) {
color: @hover;
}
&:active:not(.ant-btn-primary):not(.ant-btn-danger) {
color: @active;
}
}
.ant-btn[class*='ant-btn-text'] {
height: auto;
background-color: transparent;
border: none;
padding: 0;
&:hover {
background-color: transparent;
}
}
.ant-btn[class*='ant-btn-text'][disabled] {
color: rgba(0, 0, 0, 0.25) !important;
&:hover,
&:active {
color: rgba(0, 0, 0, 0.25) !important;
}
}
.ant-btn.ant-btn-text-primary {
.text-btn-color-mixin(@blue-6, @blue-5, @blue-7);
}
.ant-btn.ant-btn-text-danger {
.text-btn-color-mixin(@red-6, @red-5, @red-7);
}
.ant-btn.ant-btn-text-success {
.text-btn-color-mixin(@green-6, @green-5, @green-7);
}
.ant-btn.ant-btn-text-warning {
.text-btn-color-mixin(@orange-6, @orange-5, @orange-7);
}
/* ---- button end ---- */

View File

@ -0,0 +1,45 @@
<template>
<div class="lon-lat-input">
<div class="lon-input" style="padding: 10px 0;">
<a-select style="width: 76px;margin-right: 20px;">
<a-select-option value="E">东经</a-select-option>
<a-select-option value="W">西经</a-select-option>
</a-select>
<a-input-number style="width: 72px;"></a-input-number>
<span style="margin: 0 8px;">°</span>
<span style="margin: 0 12px;"></span>
<a-input-number style="width: 60px;"></a-input-number>
<span style="margin: 0 8px;">°</span>
<a-input-number style="width: 60px;"></a-input-number>
<span style="margin: 0 8px;"></span>
<a-input-number style="width: 60px;"></a-input-number>
<span style="margin: 0 8px;"></span>
</div>
<div class="lat-input" style="padding: 10px 0;">
<a-select style="width: 76px;margin-right: 20px;">
<a-select-option value="N">北纬</a-select-option>
<a-select-option value="S">南纬</a-select-option>
</a-select>
<a-input-number style="width: 72px;"></a-input-number>
<span style="margin: 0 8px;">°</span>
<span style="margin: 0 12px;"></span>
<a-input-number style="width: 60px;"></a-input-number>
<span style="margin: 0 8px;">°</span>
<a-input-number style="width: 60px;"></a-input-number>
<span style="margin: 0 8px;"></span>
<a-input-number style="width: 60px;"></a-input-number>
<span style="margin: 0 8px;"></span>
</div>
</div>
</template>
<script>
export default {
props: {
lon: { type: Number, required: true },
lat: { type: Number, required: true },
},
}
</script>
<style lang="less" scoped></style>

View File

@ -3,6 +3,7 @@
<ModuleWrapper title="作战/保障力量" style="grid-column: 1 / 2; grid-row: 1 / 2"> <ModuleWrapper title="作战/保障力量" style="grid-column: 1 / 2; grid-row: 1 / 2">
<div class="normal" style="padding: 5px; overflow-y: auto"> <div class="normal" style="padding: 5px; overflow-y: auto">
<a-tree <a-tree
class="simulation-tree"
:treeData="zb.zbTreeData" :treeData="zb.zbTreeData"
:selectedKeys.sync="zb.selectedKeys" :selectedKeys.sync="zb.selectedKeys"
:replaceFields="{ children: 'children', title: 'name', key: 'id' }" :replaceFields="{ children: 'children', title: 'name', key: 'id' }"
@ -31,37 +32,246 @@
id="cesium-container" id="cesium-container"
style="grid-column: 2 / 3; grid-row: 1 / 7; overflow: hidden" style="grid-column: 2 / 3; grid-row: 1 / 7; overflow: hidden"
></div> ></div>
<ModuleWrapper title="作战单元状态" style="grid-column: 3 / 4; grid-row: 1 / 3"> <ModuleWrapper style="grid-column: 3 / 4; grid-row: 1 / 4">
<template #title>
<a-radio-group v-model="right.radioType" button-style="solid">
<a-radio-button value="jcsx">基础属性</a-radio-button>
<a-radio-button value="zzxd">作战行动</a-radio-button>
<a-radio-button value="dzsx">单装属性</a-radio-button>
</a-radio-group>
</template>
<div class="normal" style="padding: 15px 0"> <div class="normal" style="padding: 15px 0">
<div style="height: 100%; padding: 0 15px; overflow-y: auto"> <div style="height: 100%; padding: 0 15px; overflow-y: auto">
<img class="image" :src="zt.image" /> <div v-if="right.radioType === 'jcsx'">
<div class="name">{{ zt.name }}</div> <a-collapse class="simulation-collapse" :defaultActiveKey="['1', '2', '3', '4', '5', '6', '7', '8', '9']">
<div v-for="item in zt.ztList" :key="item.label" class="zt-item flex ai-c"> <a-collapse-panel class="simulation-collapse-item" key="1" header="基础信息">
<span>{{ item.label }}</span> <img class="image" :src="right.jcsx.image || '/mockData/fe6ad2d8-da11-04d8-f447-0d8175826e28.png'" />
<img :src="item.icon" alt="" /> <div class="name">{{ right.jcsx.name }}</div>
<span>{{ item.text }}</span> <div class="zt-item flex ai-c jc-sb">
<div v-if="'progress' in item" class="progress-bar flex"> <span style="min-width: 100px">推演方</span>
<div class="progress" :style="{ width: item.progress }"></div> <a-select
</div> style="width: 120px"
</div> class="simulation-select"
</div> defaultValue="1"
</div> dropdownClassName="simulation-select-dropdown"
</ModuleWrapper> >
<ModuleWrapper title="作战单元武器" style="grid-column: 3 / 4; grid-row: 3 / 4"> <a-select-option value="1">红方</a-select-option>
<div class="normal" style="padding: 15px 0"> <a-select-option value="2">蓝方</a-select-option>
<div style="height: 100%; padding: 0 15px; overflow-y: auto"> </a-select>
<div v-for="(item, index) in zzdywq.wqList" :key="index" class="wq-item flex"> </div>
<span>{{ item.title }}</span> <div class="zt-item flex ai-c">
<span style="min-width: 100px">类型</span>
<span></span>
</div>
<div class="zt-item flex ai-c">
<span style="min-width: 100px">方向</span>
<span></span>
</div>
<div class="zt-item flex ai-c">
<span style="min-width: 100px">速度</span>
<span>{{ right.jcsx.position.speed }} 公里/</span>
</div>
<div class="zt-item flex ai-c">
<span style="min-width: 100px">经度</span>
<span class="flex-1">{{ right.jcsx.position.lng | lonFormat }}</span>
<a-button
type="text-primary"
icon="edit"
@click="handleOpenLonlatModal(right.jcsx.position.lng, right.jcsx.position.lat)"
></a-button>
</div>
<div class="zt-item flex ai-c">
<span style="min-width: 100px">纬度</span>
<span class="flex-1">{{ right.jcsx.position.lat | latFormat }}</span>
<a-button
type="text-primary"
icon="edit"
@click="handleOpenLonlatModal(right.jcsx.position.lng, right.jcsx.position.lat)"
></a-button>
</div>
<div class="zt-item flex ai-c">
<span style="min-width: 100px">高度/深度</span>
<span class="flex-1">{{ right.jcsx.position.height | numberFormat }} (海拔)</span>
<a-button type="text-primary" icon="edit"></a-button>
</div>
</a-collapse-panel>
<a-collapse-panel class="simulation-collapse-item" key="2" header="人员状态属性">
<div class="zt-item flex ai-c">
<span style="min-width: 100px">人员编制数</span>
<span>{{ right.jcsx.personStatistic.total }} </span>
</div>
<div class="zt-item flex ai-c">
<span style="min-width: 100px">当前人数</span>
<span>{{ right.jcsx.personStatistic.current }} </span>
</div>
<div class="zt-item flex ai-c">
<span style="min-width: 100px">死亡人数</span>
<span>{{ right.jcsx.personStatistic.death }} </span>
</div>
<div class="zt-item flex ai-c">
<span style="min-width: 100px">受伤人数</span>
<span>{{ right.jcsx.personStatistic.injured }} </span>
</div>
</a-collapse-panel>
<a-collapse-panel class="simulation-collapse-item" key="3" header="野战食品状态属性">
<div class="zt-item flex ai-c">
<span style="min-width: 100px">野战食物初始量()</span>
<span>{{ right.jcsx.foodInfo.startNum }}</span>
</div>
<div class="zt-item flex ai-c">
<span style="min-width: 100px">野战食物当前量()</span>
<span>{{ right.jcsx.foodInfo.currentNum }}</span>
</div>
</a-collapse-panel>
<a-collapse-panel class="simulation-collapse-item" key="4" header="用水状态属性">
<div class="zt-item flex ai-c">
<span style="min-width: 100px">用水初始量()</span>
<span>{{ right.jcsx.waterInfo.startNum }}</span>
</div>
<div class="zt-item flex ai-c">
<span style="min-width: 100px">用水当前量()</span>
<span>{{ right.jcsx.waterInfo.currentNum }}</span>
<span></span>
</div>
</a-collapse-panel>
<a-collapse-panel class="simulation-collapse-item" key="5" header="油料状态属性">
<div class="zt-item flex ai-c">
<span style="min-width: 100px">油料初始量()</span>
<span>{{ right.jcsx.oilInfo.startNum }}</span>
</div>
<div class="zt-item flex ai-c">
<span style="min-width: 100px">油料当前量()</span>
<span>{{ right.jcsx.oilInfo.currentNum }}</span>
</div>
</a-collapse-panel>
<a-collapse-panel class="simulation-collapse-item" key="6" header="药材状态属性">
<div class="zt-item flex ai-c">
<span style="min-width: 100px">药材初始量()</span>
<span>{{ right.jcsx.medicalInfo.startNum }}</span>
</div>
<div class="zt-item flex ai-c">
<span style="min-width: 100px">药材当前量()</span>
<span>{{ right.jcsx.medicalInfo.currentNum }}</span>
</div>
</a-collapse-panel>
<a-collapse-panel class="simulation-collapse-item" key="7" header="武器弹药状态属性">
<div class="zt-item flex ai-c">
<span style="min-width: 100px">轻武器弹药量()</span>
<span>{{ right.jcsx.ammunition.lightArms }}</span>
</div>
<div class="zt-item flex ai-c">
<span style="min-width: 100px">压制武器弹药量()</span>
<span>{{ right.jcsx.ammunition.suppressing }}</span>
</div>
<div class="zt-item flex ai-c">
<span style="min-width: 100px">反坦克武器弹药量()</span>
<span>{{ right.jcsx.ammunition.antiTank }}</span>
</div>
<div class="zt-item flex ai-c">
<span style="min-width: 100px">防空反导武器弹药量()</span>
<span>{{ right.jcsx.ammunition.antiAircraft }}</span>
</div>
<div class="zt-item flex ai-c">
<span style="min-width: 100px">布扫雷装备弹药量()</span>
<span>{{ right.jcsx.ammunition.mineLaying }}</span>
</div>
<div class="zt-item flex ai-c">
<span style="min-width: 100px">爆破器材弹药量()</span>
<span>{{ right.jcsx.ammunition.explosiveDevice }}</span>
</div>
<div class="zt-item flex ai-c">
<span style="min-width: 100px">烟火装备弹药量()</span>
<span>{{ right.jcsx.ammunition.smokeDevice }}</span>
</div>
<div class="zt-item flex ai-c">
<span style="min-width: 100px">防化消耗弹药量()</span>
<span>{{ right.jcsx.ammunition.antiChemical }}</span>
</div>
</a-collapse-panel>
<a-collapse-panel class="simulation-collapse-item" key="8" header="保障标准信息">
<div class="zt-item flex ai-c jc-sb">
<span style="min-width: 100px">保障分配类型</span>
<a-select
style="width: 120px"
class="simulation-select"
defaultValue="1"
dropdownClassName="simulation-select-dropdown"
>
<a-select-option value="1">自动分配</a-select-option>
<a-select-option value="2">手动分配</a-select-option>
</a-select>
</div>
</a-collapse-panel>
<a-collapse-panel class="simulation-collapse-item" key="9" header="保障配置">
<div class="zt-item flex ai-c jc-sb">
<a-button type="primary">兵力编组</a-button>
<a-button type="primary">关注</a-button>
</div>
</a-collapse-panel>
</a-collapse>
</div> </div>
<div v-if="right.radioType === 'zzxd'">作战行动</div>
<div v-if="right.radioType === 'dzsx'">单装属性</div>
</div> </div>
</div> </div>
</ModuleWrapper> </ModuleWrapper>
<a-modal v-model="lonlatModal.visible" title="修改单元经纬度">
<LonLatInput :lon.sync="lonlatModal.lon" :lat.sync="lonlatModal.lat" />
</a-modal>
</div> </div>
</template> </template>
<script> <script>
import LonLatInput from './components/LonLatInput.vue'
export default { export default {
name: 'SimulationSceneSceneEditing', name: 'SimulationSceneSceneEditing',
components: {
LonLatInput,
},
filters: {
numberFormat(v) {
if (typeof v === 'number' && v) {
return +v.toFixed(2)
} else {
return v
}
},
lonFormat(v) {
const originValue = Number(v)
if (originValue) {
let result = ''
result += originValue > 0 ? '东经 ' : '西经 '
const num = Math.abs(originValue)
const d = Math.floor(num)
result += `${d}°`
const m = Math.floor(num * 60) % 60
result += `${m}`
const s = Math.floor(num * 3600) % 60
result += `${s}`
return result
} else {
return '0°00″'
}
},
latFormat(v) {
const originValue = Number(v)
if (originValue) {
let result = ''
result += originValue > 0 ? '北纬 ' : '南纬 '
const num = Math.abs(originValue)
const d = Math.floor(num)
result += `${d}°`
const m = Math.floor(num * 60) % 60
result += `${m}`
const s = Math.floor(num * 3600) % 60
result += `${s}`
return result
} else {
return '0°00″'
}
},
},
data() { data() {
return { return {
cesium: null, cesium: null,
@ -100,31 +310,22 @@ export default {
}, },
], ],
}, },
zt: { right: {
image: '/mockData/fe6ad2d8-da11-04d8-f447-0d8175826e28.png', radioType: 'jcsx',
name: '轮式装甲突击车', jcsx: {
ztList: [ position: {},
{ label: '推演方', text: `红方` }, personStatistic: {},
{ label: '航向', text: `0度` }, foodInfo: {},
{ label: '航速', text: `0.00公里/小时(停车)` }, waterInfo: {},
{ label: '经度', text: `东经120°53'56″` }, oilInfo: {},
{ label: '纬度', text: `北纬24°34'17″` }, medicalInfo: {},
{ label: '高度/深度', text: `0.00米` }, ammunition: {},
{ label: '毁伤', text: `0%` }, },
{ label: '系统', progress: `100%` },
{ label: '电量', progress: `90%` },
{ label: '失火', progress: `0%` },
{ label: '状态', text: `未分配任务` },
],
}, },
zzdywq: { lonlatModal: {
placeholder: '&emsp;'.repeat(100), visible: false,
wqList: [ lon: 0,
{ title: '240×7.62毫米高射机炮[20发备弹]' }, lat: 0,
{ title: '16×AT-14型“短号”反坦克导弹' },
{ title: '6×巡飞弹' },
{ title: '4×无人侦察机' },
],
}, },
} }
}, },
@ -167,12 +368,16 @@ export default {
} }
}, },
handleSelectTree(selectedKeys, { node }) { handleSelectTree(selectedKeys, { node }) {
console.log(...arguments) this.right.jcsx = node.dataRef
// node.dataRef
}, },
onSearch(e) { onSearch(e) {
console.log('----', e, e.target.value) console.log('----', e, e.target.value)
}, },
handleOpenLonlatModal(lon, lat) {
this.lonlatModal.lon = lon
this.lonlatModal.lat = lat
this.lonlatModal.visible = true
},
}, },
} }
</script> </script>
@ -181,12 +386,59 @@ export default {
.scene-editing-page { .scene-editing-page {
padding-top: 20px; padding-top: 20px;
} }
.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;
}
}
.ys-image { .ys-image {
width: 74px; width: 74px;
height: 62px; height: 62px;
object-fit: cover; object-fit: cover;
margin: 16px 0 8px; margin: 16px 0 8px;
} }
.simulation-collapse::v-deep {
background-color: transparent;
color: #bbdded;
font-size: 16px;
line-height: 30px;
border: none;
}
.simulation-collapse-item::v-deep {
.ant-collapse-content {
background-color: transparent;
color: #bbdded;
border-top-color: #00baff66;
> .ant-collapse-content-box {
padding: 15px 0 5px;
}
}
}
.simulation-collapse > .simulation-collapse-item::v-deep {
border: none;
> .ant-collapse-header {
padding: 0;
color: #00baff;
font-size: 16px;
line-height: 38px;
display: flex;
align-items: center;
flex-direction: row-reverse;
justify-content: space-between;
.ant-collapse-arrow {
position: initial;
font-size: 16px;
transform: translateY(0);
}
}
}
.image { .image {
width: 100%; width: 100%;
padding: 20px; padding: 20px;
@ -196,28 +448,34 @@ export default {
color: #00baff; color: #00baff;
text-decoration: underline; text-decoration: underline;
font-size: 16px; font-size: 16px;
line-height: 26px;
margin: 10px 0;
} }
.zt-item { .simulation-select::v-deep {
font-size: 16px; .ant-select-selection {
line-height: 30px; background-color: #10475f;
letter-spacing: 2px; border: solid 1px #1d5777;
color: #bbdded; color: #bbdded;
.progress-bar { }
flex: 1; .ant-select-arrow {
height: 20px; color: #bbdded;
background-color: #9da0a1;
.progress {
background-color: #1b9b39;
}
} }
} }
.wq-item { </style>
text-decoration: underline;
font-size: 16px; <style lang="less">
line-height: 26px; .simulation-select-dropdown {
letter-spacing: 0px; background-color: #10475f;
color: #00baff; border: solid 1px #1d5777;
.ant-select-dropdown-menu-item {
color: #bbdded;
}
.ant-select-dropdown-menu-item-selected {
background-color: #bbdded33;
color: #ffffff;
font-weight: normal;
}
.ant-select-dropdown-menu-item:hover:not(.ant-select-dropdown-menu-item-disabled) {
background-color: #bbdded33;
color: #ffffff;
}
} }
</style> </style>