增加环境效果功能
This commit is contained in:
parent
47c42f5e93
commit
ef40b81a50
BIN
public/images/plane.png
Normal file
BIN
public/images/plane.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.9 KiB |
|
@ -0,0 +1,91 @@
|
||||||
|
import * as Cesium from 'cesium'
|
||||||
|
|
||||||
|
// 作战区域 1 保障区域 2 模型 3 图片 4
|
||||||
|
export const ENTITY_TYPES = {
|
||||||
|
WARZONE: 1,
|
||||||
|
SAFEZONE: 2,
|
||||||
|
|
||||||
|
MODEL: 3,
|
||||||
|
IMAGE: 4,
|
||||||
|
ROUTE: 5,
|
||||||
|
|
||||||
|
LINE: 6, // 两个模型之间的连线
|
||||||
|
POINT_PLANNING: 7, // 规划点
|
||||||
|
|
||||||
|
GRAPHICS: 8, // 折线
|
||||||
|
|
||||||
|
AIR_ROUTE: 9, // 航路
|
||||||
|
ROAMING_PLANE: 10,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class BaseDraw {
|
||||||
|
/**
|
||||||
|
* @type {Cesium.Viewer}
|
||||||
|
* @description Cesium Viewer 实例
|
||||||
|
*/
|
||||||
|
viewer = null
|
||||||
|
isComplete = false
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {Cesium.ScreenSpaceEventHandler}
|
||||||
|
*/
|
||||||
|
handler = null
|
||||||
|
constructor(viewer) {
|
||||||
|
if (!viewer) throw new Error('viewer is null')
|
||||||
|
this.viewer = viewer
|
||||||
|
this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas)
|
||||||
|
}
|
||||||
|
|
||||||
|
start() {
|
||||||
|
throw new Error('start() is not implemented')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将 Cartesian3 坐标转换为海拔高度(WGS84 高度)
|
||||||
|
* @param {Cesium.Cartesian3} cartesian - Cartesian3 坐标
|
||||||
|
* @returns {Number} 海拔高度(米)
|
||||||
|
*/
|
||||||
|
getAltitudeFromCartesian(cartesian) {
|
||||||
|
const ellipsoid = Cesium.Ellipsoid.WGS84
|
||||||
|
const cartographic = ellipsoid.cartesianToCartographic(cartesian)
|
||||||
|
// 如果需要考虑地形高度,可以使用 sampleTerrain 提取真实地形高度
|
||||||
|
return cartographic.height || 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取高度的文本
|
||||||
|
* @param {Cesium.Cartesian3} position
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
getHeightText(position) {
|
||||||
|
return `${this.getAltitudeFromCartesian(position).toFixed(1)}m`
|
||||||
|
}
|
||||||
|
|
||||||
|
calculateDistance(position0, position1) {
|
||||||
|
const distance = Cesium.Cartesian3.distance(position0, position1)
|
||||||
|
return distance
|
||||||
|
}
|
||||||
|
|
||||||
|
formatDistance(distance, precision = 1) {
|
||||||
|
if (distance > 1000) {
|
||||||
|
return `${(distance / 1000).toFixed(precision)}km`
|
||||||
|
}
|
||||||
|
return `${distance.toFixed(precision)}m`
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 未完成时的清理
|
||||||
|
*/
|
||||||
|
clear() {
|
||||||
|
console.warn('clear() is not implemented')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 销毁事件处理器
|
||||||
|
*/
|
||||||
|
destroyHandler() {
|
||||||
|
if (!this.handler) return
|
||||||
|
this.handler.destroy()
|
||||||
|
this.handler = null
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,107 @@
|
||||||
|
import * as Cesium from 'cesium'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 兼容模型和地形上坐标拾取
|
||||||
|
* @param {Cesium.Viewer} viewer
|
||||||
|
* @param {*} px
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const getCatesian3FromPX = (viewer, px) => {
|
||||||
|
const picks = viewer.scene.drillPick(px)
|
||||||
|
viewer.scene.render()
|
||||||
|
let cartesian
|
||||||
|
let isOn3dtiles = false
|
||||||
|
for (var i = 0; i < picks.length; i++) {
|
||||||
|
if (
|
||||||
|
picks[i] &&
|
||||||
|
picks[i].primitive &&
|
||||||
|
picks[i].primitive instanceof Cesium.Cesium3DTileset
|
||||||
|
) {
|
||||||
|
//模型上拾取
|
||||||
|
isOn3dtiles = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isOn3dtiles) {
|
||||||
|
cartesian = viewer.scene.pickPosition(px)
|
||||||
|
} else {
|
||||||
|
var ray = viewer.camera.getPickRay(px)
|
||||||
|
if (!ray) return null
|
||||||
|
cartesian = viewer.scene.globe.pick(ray, viewer.scene)
|
||||||
|
}
|
||||||
|
return cartesian
|
||||||
|
}
|
||||||
|
|
||||||
|
// catesian3坐标转经纬度坐标
|
||||||
|
export function getLngLatFromCartisian3(cartesian3) {
|
||||||
|
const { longitude, latitude, height } =
|
||||||
|
Cesium.Cartographic.fromCartesian(cartesian3)
|
||||||
|
return {
|
||||||
|
longitude: radiansToDegrees(longitude),
|
||||||
|
latitude: radiansToDegrees(latitude),
|
||||||
|
height,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将弧度值转换为角度值
|
||||||
|
* @param {number} radians - 弧度值
|
||||||
|
* @return {number} 角度值
|
||||||
|
*/
|
||||||
|
export const radiansToDegrees = (radians) => {
|
||||||
|
return Cesium.Math.toDegrees(radians)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const degreesToRadians = (degrees) => {
|
||||||
|
return Cesium.Math.toRadians(degrees)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const mixDegree = (west, south, east, north) => {
|
||||||
|
return [
|
||||||
|
[west, north],
|
||||||
|
[east, north],
|
||||||
|
[east, south],
|
||||||
|
[west, south],
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {Cesium.Viewer} viewer
|
||||||
|
* @param {Cesium.Cartesian2} position
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const getCartesian3ByPosition = (viewer, position) => {
|
||||||
|
const _position = viewer.scene.globe.pick(
|
||||||
|
viewer.camera.getPickRay(position),
|
||||||
|
viewer.scene
|
||||||
|
)
|
||||||
|
|
||||||
|
if (Cesium.defined(position)) {
|
||||||
|
return _position
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 获取模型自身参数
|
||||||
|
* @param {Cesium.Viewer} viewer
|
||||||
|
* @param {Cesium.Entity} entity
|
||||||
|
* @returns {Promise<{ center: Cesium.Cartesian3; radius: number }>}
|
||||||
|
*/
|
||||||
|
export const getSphere = (viewer, entity) => {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
// entity没有加载完成时 state 不会等于0 所以设置定时器直到获取到为止
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
const sphere = new Cesium.BoundingSphere()
|
||||||
|
const state = viewer._dataSourceDisplay.getBoundingSphere(
|
||||||
|
entity,
|
||||||
|
false,
|
||||||
|
sphere
|
||||||
|
)
|
||||||
|
if (state === Cesium.BoundingSphereState.DONE) {
|
||||||
|
clearInterval(interval)
|
||||||
|
resolve(sphere)
|
||||||
|
}
|
||||||
|
}, 100)
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
/*
|
||||||
|
* @Descripttion: 雨粒子效果
|
||||||
|
* @Author: 笙痞
|
||||||
|
* @Date: 2023-01-04 15:01:03
|
||||||
|
* @LastEditors: 笙痞77
|
||||||
|
* @LastEditTime: 2023-05-19 09:54:15
|
||||||
|
*/
|
||||||
|
import * as Cesium from 'cesium'
|
||||||
|
|
||||||
|
class RainEffect {
|
||||||
|
constructor(viewer, options) {
|
||||||
|
if (!viewer) throw new Error('no viewer object!')
|
||||||
|
options = options || {}
|
||||||
|
//倾斜角度,负数向右,正数向左
|
||||||
|
this.tiltAngle = Cesium.defaultValue(options.tiltAngle, -0.6)
|
||||||
|
this.rainSize = Cesium.defaultValue(options.rainSize, 0.3)
|
||||||
|
this.rainSpeed = Cesium.defaultValue(options.rainSpeed, 120.0)
|
||||||
|
this.viewer = viewer
|
||||||
|
this.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
this.rainStage = new Cesium.PostProcessStage({
|
||||||
|
name: 'czm_rain',
|
||||||
|
fragmentShader: this.rain(),
|
||||||
|
uniforms: {
|
||||||
|
tiltAngle: () => {
|
||||||
|
return this.tiltAngle
|
||||||
|
},
|
||||||
|
rainSize: () => {
|
||||||
|
return this.rainSize
|
||||||
|
},
|
||||||
|
rainSpeed: () => {
|
||||||
|
return this.rainSpeed
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
this.viewer.scene.postProcessStages.add(this.rainStage)
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy() {
|
||||||
|
if (!this.viewer || !this.rainStage) return
|
||||||
|
this.viewer.scene.postProcessStages.remove(this.rainStage)
|
||||||
|
const isDestroyed = this.rainStage.isDestroyed()
|
||||||
|
// 先检查是否被销毁过,如果已经被销毁过再调用destroy会报错
|
||||||
|
if (!isDestroyed) {
|
||||||
|
this.rainStage.destroy()
|
||||||
|
}
|
||||||
|
delete this.tiltAngle
|
||||||
|
delete this.rainSize
|
||||||
|
delete this.rainSpeed
|
||||||
|
}
|
||||||
|
|
||||||
|
show(visible) {
|
||||||
|
this.rainStage.enabled = visible
|
||||||
|
}
|
||||||
|
|
||||||
|
rain() {
|
||||||
|
return 'uniform sampler2D colorTexture;\n\
|
||||||
|
varying vec2 v_textureCoordinates;\n\
|
||||||
|
uniform float tiltAngle;\n\
|
||||||
|
uniform float rainSize;\n\
|
||||||
|
uniform float rainSpeed;\n\
|
||||||
|
float hash(float x) {\n\
|
||||||
|
return fract(sin(x * 133.3) * 13.13);\n\
|
||||||
|
}\n\
|
||||||
|
void main(void) {\n\
|
||||||
|
float time = czm_frameNumber / rainSpeed;\n\
|
||||||
|
vec2 uv = (gl_FragCoord.xy - czm_viewport.xy) / czm_viewport.zw;\n\
|
||||||
|
vec3 c = vec3(.6, .7, .8);\n\
|
||||||
|
float a = tiltAngle;\n\
|
||||||
|
float si = sin(a), co = cos(a);\n\
|
||||||
|
uv *= mat2(co, -si, si, co);\n\
|
||||||
|
uv *= length(uv + vec2(0, 4.9)) * rainSize + 1.;\n\
|
||||||
|
float v = 1. - sin(hash(floor(uv.x * 100.)) * 2.);\n\
|
||||||
|
float b = clamp(abs(sin(20. * time * v + uv.y * (5. / (2. + v)))) - .95, 0., 1.) * 20.;\n\
|
||||||
|
c *= v * b;\n\
|
||||||
|
gl_FragColor = mix(texture2D(colorTexture, v_textureCoordinates), vec4(c, 1), .5);\n\
|
||||||
|
}\n\
|
||||||
|
'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default RainEffect
|
|
@ -0,0 +1,84 @@
|
||||||
|
/*
|
||||||
|
* @Descripttion: 雪花粒子类
|
||||||
|
* @Author: 笙痞
|
||||||
|
* @Date: 2023-01-04 14:01:07
|
||||||
|
* @LastEditors: 笙痞77
|
||||||
|
* @LastEditTime: 2023-05-19 09:52:52
|
||||||
|
*/
|
||||||
|
|
||||||
|
import * as Cesium from 'cesium'
|
||||||
|
class SnowEffect {
|
||||||
|
constructor(viewer, options) {
|
||||||
|
if (!viewer) throw new Error('no viewer object!')
|
||||||
|
options = options || {}
|
||||||
|
this.snowSize = Cesium.defaultValue(options.snowSize, 0.02)// ❄️大小,最好小于0.02
|
||||||
|
this.snowSpeed = Cesium.defaultValue(options.snowSpeed, 60.0) // 速度
|
||||||
|
this.viewer = viewer
|
||||||
|
this.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
this.snowStage = new Cesium.PostProcessStage({
|
||||||
|
name: 'czm_snow',
|
||||||
|
fragmentShader: this.snow(),
|
||||||
|
uniforms: {
|
||||||
|
snowSize: () => {
|
||||||
|
return this.snowSize
|
||||||
|
},
|
||||||
|
snowSpeed: () => {
|
||||||
|
return this.snowSpeed
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
this.viewer.scene.postProcessStages.add(this.snowStage)
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy() {
|
||||||
|
if (!this.viewer || !this.snowStage) return
|
||||||
|
this.viewer.scene.postProcessStages.remove(this.snowStage)
|
||||||
|
const isDestroyed = this.snowStage.isDestroyed()
|
||||||
|
// 先检查是否被销毁过,如果已经被销毁过再调用destroy会报错
|
||||||
|
if (!isDestroyed) {
|
||||||
|
this.snowStage.destroy()
|
||||||
|
}
|
||||||
|
delete this.snowSize
|
||||||
|
delete this.snowSpeed
|
||||||
|
}
|
||||||
|
show(visible) {
|
||||||
|
this.snowStage.enabled = visible
|
||||||
|
}
|
||||||
|
|
||||||
|
snow() {
|
||||||
|
return 'uniform sampler2D colorTexture;\n\
|
||||||
|
varying vec2 v_textureCoordinates;\n\
|
||||||
|
uniform float snowSpeed;\n\
|
||||||
|
uniform float snowSize;\n\
|
||||||
|
float snow(vec2 uv,float scale)\n\
|
||||||
|
{\n\
|
||||||
|
float time=czm_frameNumber/snowSpeed;\n\
|
||||||
|
float w=smoothstep(1.,0.,-uv.y*(scale/10.));if(w<.1)return 0.;\n\
|
||||||
|
uv+=time/scale;uv.y+=time*2./scale;uv.x+=sin(uv.y+time*.5)/scale;\n\
|
||||||
|
uv*=scale;vec2 s=floor(uv),f=fract(uv),p;float k=3.,d;\n\
|
||||||
|
p=.5+.35*sin(11.*fract(sin((s+p+scale)*mat2(7,3,6,5))*5.))-f;d=length(p);k=min(d,k);\n\
|
||||||
|
k=smoothstep(0.,k,sin(f.x+f.y)*snowSize);\n\
|
||||||
|
return k*w;\n\
|
||||||
|
}\n\
|
||||||
|
void main(void){\n\
|
||||||
|
vec2 resolution=czm_viewport.zw;\n\
|
||||||
|
vec2 uv=(gl_FragCoord.xy*2.-resolution.xy)/min(resolution.x,resolution.y);\n\
|
||||||
|
vec3 finalColor=vec3(0);\n\
|
||||||
|
float c=0.;\n\
|
||||||
|
c+=snow(uv,30.)*.0;\n\
|
||||||
|
c+=snow(uv,20.)*.0;\n\
|
||||||
|
c+=snow(uv,15.)*.0;\n\
|
||||||
|
c+=snow(uv,10.);\n\
|
||||||
|
c+=snow(uv,8.);\n\
|
||||||
|
c+=snow(uv,6.);\n\
|
||||||
|
c+=snow(uv,5.);\n\
|
||||||
|
finalColor=(vec3(c));\n\
|
||||||
|
gl_FragColor=mix(texture2D(colorTexture,v_textureCoordinates),vec4(finalColor,1),.5);\n\
|
||||||
|
}\n\
|
||||||
|
'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default SnowEffect
|
|
@ -0,0 +1,233 @@
|
||||||
|
<template>
|
||||||
|
<Flex fd="co" class="zzxd-wrapper">
|
||||||
|
<Flex class="zzxd-header" ai="c" jc="sb">
|
||||||
|
<div class="zzxd-title">保障任务</div>
|
||||||
|
<div>
|
||||||
|
<a-button type="text-primary" icon="menu"></a-button>
|
||||||
|
<a-button type="text-primary" icon="plus" @click="handleOpenAddActionModal"></a-button>
|
||||||
|
<a-button type="text-primary" icon="edit" @click="handleOpenEditActionModal"></a-button>
|
||||||
|
<a-button type="text-primary" icon="delete" @click="handleDeleteAction"></a-button>
|
||||||
|
</div>
|
||||||
|
<a-modal
|
||||||
|
v-model="actionModal.visible"
|
||||||
|
:title="actionModal.title" :maskClosable="false" :destroyOnClose="true"
|
||||||
|
@ok="handleSubmilAction">
|
||||||
|
<a-form-model
|
||||||
|
:model="actionModal.formData"
|
||||||
|
layout="horizontal" :labelCol="{ span: 6 }"
|
||||||
|
:wrapperCol="{ span: 15 }">
|
||||||
|
<a-form-model-item v-for="item in actionModal.formItems" :key="item.prop" v-bind="item">
|
||||||
|
<component
|
||||||
|
:is="item.component || 'a-input'"
|
||||||
|
v-model="actionModal.formData[item.prop]"
|
||||||
|
v-bind="item.options" />
|
||||||
|
</a-form-model-item>
|
||||||
|
</a-form-model>
|
||||||
|
</a-modal>
|
||||||
|
</Flex>
|
||||||
|
<div class="flex-1 scroller-y">
|
||||||
|
<div v-for="item in actionList" :key="item.id" class="action-item flex" @click="checkedAction = item">
|
||||||
|
<div class="action-icon">
|
||||||
|
<div class="action-line"></div>
|
||||||
|
<a-radio :checked="checkedAction && checkedAction.id === item.id" style="margin-right: 0"></a-radio>
|
||||||
|
</div>
|
||||||
|
<div class="flex-1">
|
||||||
|
<div class="action-title">{{ item.name || '- -' }}</div>
|
||||||
|
<div class="action-time">任务类型:{{ handleGetTaskType(item.taskType) }}</div>
|
||||||
|
<div class="action-time">开始时间:{{ item.startTime }}</div>
|
||||||
|
<div class="action-time">结束时间:{{ item.endTime }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Flex>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
scenarioId: { type: String, required: true },
|
||||||
|
resourceid: { type: String, required: true },
|
||||||
|
type: { type: Number, required: true },
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
checkedAction: null,
|
||||||
|
actionModal: {
|
||||||
|
visible: false,
|
||||||
|
formItems: [
|
||||||
|
{ label: '任务名称', prop: 'name' },
|
||||||
|
{
|
||||||
|
label: '任务类型',
|
||||||
|
prop: 'taskType',
|
||||||
|
component: 'AntOriginSelect',
|
||||||
|
options: {
|
||||||
|
dataSource: () => ({
|
||||||
|
data: [
|
||||||
|
{ id: '1', title: '机动任务' },
|
||||||
|
{ id: '2', title: '战斗任务' },
|
||||||
|
{ id: '3', title: '整备任务' },
|
||||||
|
{ id: '4', title: '弹药保障' },
|
||||||
|
{ id: '5', title: '水保障' },
|
||||||
|
{ id: '6', title: '油保障' },
|
||||||
|
{ id: '7', title: '食品保障' }
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '开始时间', prop: 'startTime', component: 'a-date-picker', options: {
|
||||||
|
showTime: true,
|
||||||
|
format: 'YYYY-MM-DD HH:mm:ss',
|
||||||
|
valueFormat: 'YYYY-MM-DD HH:mm:ss'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '结束时间', prop: 'endTime', component: 'a-date-picker', options: {
|
||||||
|
showTime: true,
|
||||||
|
format: 'YYYY-MM-DD HH:mm:ss',
|
||||||
|
valueFormat: 'YYYY-MM-DD HH:mm:ss'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ label: '开始经度', prop: 'fromLng' },
|
||||||
|
{ label: '开始纬度', prop: 'fromLat' },
|
||||||
|
{ label: '目标经度', prop: 'toLng' },
|
||||||
|
{ label: '目标纬度', prop: 'toLat' },
|
||||||
|
],
|
||||||
|
formData: {},
|
||||||
|
},
|
||||||
|
actionList: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
if (this.scenarioId && this.resourceid) {
|
||||||
|
this.handleGetTaskList()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
resourceid: {
|
||||||
|
handler(newValue, oldValue) {
|
||||||
|
this.handleGetTaskList()
|
||||||
|
},
|
||||||
|
deep: true // 重要:开启深层监听
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleGetTaskType(type) {
|
||||||
|
switch (type) {
|
||||||
|
case '1':
|
||||||
|
return '机动任务'
|
||||||
|
case '2':
|
||||||
|
return '战斗任务'
|
||||||
|
case '3':
|
||||||
|
return '整备任务'
|
||||||
|
case '4':
|
||||||
|
return '弹药保障'
|
||||||
|
case '5':
|
||||||
|
return '水保障'
|
||||||
|
case '6':
|
||||||
|
return '油保障'
|
||||||
|
case '7':
|
||||||
|
return '食品保障'
|
||||||
|
default:
|
||||||
|
return '- -'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleGetTaskList() {
|
||||||
|
this.$http({
|
||||||
|
url: '/scenarioTask/taskList',
|
||||||
|
method: 'post',
|
||||||
|
data: { scenarioId: parseInt(this.scenarioId), resourceId: this.resourceid },
|
||||||
|
}).then(res => {
|
||||||
|
this.actionList = res.data
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleOpenAddActionModal() {
|
||||||
|
this.actionModal.title = '添加任务'
|
||||||
|
this.actionModal.formData = {
|
||||||
|
type: this.type,
|
||||||
|
scenarioId: parseInt(this.scenarioId),
|
||||||
|
resourceId: this.resourceid
|
||||||
|
}
|
||||||
|
this.actionModal.visible = true
|
||||||
|
},
|
||||||
|
handleOpenEditActionModal() {
|
||||||
|
this.actionModal.title = '修改任务'
|
||||||
|
this.actionModal.formData = { ...this.checkedAction }
|
||||||
|
this.actionModal.visible = true
|
||||||
|
},
|
||||||
|
async handleSubmilAction() {
|
||||||
|
try {
|
||||||
|
await this.$http({
|
||||||
|
url: '/scenarioTask/save',
|
||||||
|
method: 'post',
|
||||||
|
data: this.actionModal.formData,
|
||||||
|
})
|
||||||
|
this.$message.success(`${this.actionModal.title}成功`)
|
||||||
|
this.actionModal.visible = false
|
||||||
|
this.handleGetTaskList()
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async handleDeleteAction() {
|
||||||
|
try {
|
||||||
|
await this.$confirm('确认删除所选任务吗?')
|
||||||
|
await this.$http({
|
||||||
|
url: '/scenarioTask/remove/' + this.checkedAction.id,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
this.$message.success(`删除任务成功`)
|
||||||
|
this.handleGetTaskList()
|
||||||
|
} catch (error) {
|
||||||
|
this.$message.success(`删除任务失败`)
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.zzxd-wrapper {
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
.zzxd-header {
|
||||||
|
padding: 5px 0;
|
||||||
|
border-bottom: 1px solid #00baff22;
|
||||||
|
|
||||||
|
.zzxd-title {
|
||||||
|
color: #00baff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-item {
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 5px 0;
|
||||||
|
|
||||||
|
.action-icon {
|
||||||
|
padding: 5px 16px;
|
||||||
|
position: relative;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
.action-line {
|
||||||
|
position: absolute;
|
||||||
|
right: 50%;
|
||||||
|
top: 21px;
|
||||||
|
width: 1px;
|
||||||
|
height: 100%;
|
||||||
|
background-color: #00baff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-item:last-of-type {
|
||||||
|
.action-line {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-item:hover {
|
||||||
|
background-color: #bae7ff44;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,446 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<a-collapse class="simulation-collapse" :defaultActiveKey="['1', '2', '3', '4', '5', '6', '7', '8', '9']">
|
||||||
|
<a-collapse-panel class="simulation-collapse-item" key="1" header="基础信息">
|
||||||
|
<img class="image" :src="modelData.image || '/mockData/fe6ad2d8-da11-04d8-f447-0d8175826e28.png'" />
|
||||||
|
<div class="name">
|
||||||
|
{{ modelData.team.teamName }}
|
||||||
|
<a-button v-if="hasDetail" type="text-primary" icon="edit" @click="handleOpenMcModal"></a-button>
|
||||||
|
</div>
|
||||||
|
<a-modal
|
||||||
|
v-model="mcModal.visible"
|
||||||
|
title="编辑单元名称"
|
||||||
|
:maskClosable="false"
|
||||||
|
width="400px"
|
||||||
|
:destroyOnClose="true"
|
||||||
|
@ok="handleSubmilMc"
|
||||||
|
>
|
||||||
|
<a-row>
|
||||||
|
<a-col :span="6">
|
||||||
|
<span>名称</span>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="18">
|
||||||
|
<a-input v-model="mcModal.mc" style="width: 100%" />
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</a-modal>
|
||||||
|
<div class="zt-item flex ai-c">
|
||||||
|
<span style="min-width: 100px">推演方:</span>
|
||||||
|
<span>{{ modelData.team.type | forceFormat }}</span>
|
||||||
|
</div>
|
||||||
|
<!-- <div class="zt-item flex ai-c">
|
||||||
|
<span style="min-width: 100px">类型:</span>
|
||||||
|
<span>{{ modelData.position.logisticType | logisticTypeFormat }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="zt-item flex ai-c">
|
||||||
|
<span style="min-width: 100px">方向:</span>
|
||||||
|
<span>{{ modelData.position.direction | numberFormat }}°</span>
|
||||||
|
</div>
|
||||||
|
<div class="zt-item flex ai-c">
|
||||||
|
<span style="min-width: 100px">速度:</span>
|
||||||
|
<span>{{ modelData.position.speed }} 公里/时</span>
|
||||||
|
</div> -->
|
||||||
|
<div class="zt-item flex ai-c">
|
||||||
|
<span style="min-width: 100px">经度:</span>
|
||||||
|
<span class="flex-1">{{ modelData.team.lng | lonFormat }}</span>
|
||||||
|
<a-button v-if="hasDetail" type="text-primary" icon="edit" @click="handleOpenLonlatModal"></a-button>
|
||||||
|
</div>
|
||||||
|
<div class="zt-item flex ai-c">
|
||||||
|
<span style="min-width: 100px">纬度:</span>
|
||||||
|
<span class="flex-1">{{ modelData.team.lat | latFormat }}</span>
|
||||||
|
<a-button v-if="hasDetail" type="text-primary" icon="edit" @click="handleOpenLonlatModal"></a-button>
|
||||||
|
</div>
|
||||||
|
<a-modal
|
||||||
|
v-model="lonlatModal.visible"
|
||||||
|
title="修改单元经纬度"
|
||||||
|
:maskClosable="false"
|
||||||
|
width="600px"
|
||||||
|
:destroyOnClose="true"
|
||||||
|
@ok="handleSubmilLonlat"
|
||||||
|
>
|
||||||
|
<LonLatInput :lon.sync="lonlatModal.lon" :lat.sync="lonlatModal.lat" />
|
||||||
|
</a-modal>
|
||||||
|
<!-- <div class="zt-item flex ai-c">
|
||||||
|
<span style="min-width: 100px">高度/深度:</span>
|
||||||
|
<span class="flex-1">{{ modelData.position.height | numberFormat }} 米(海拔)</span>
|
||||||
|
<a-button v-if="hasDetail" type="text-primary" icon="edit" @click="handleOpenHdModal()"></a-button>
|
||||||
|
</div>
|
||||||
|
<a-modal
|
||||||
|
v-model="hdModal.visible"
|
||||||
|
title="设置单元高度/深度"
|
||||||
|
:maskClosable="false"
|
||||||
|
width="400px"
|
||||||
|
:destroyOnClose="true"
|
||||||
|
@ok="handleSubmilHd"
|
||||||
|
>
|
||||||
|
<a-row>
|
||||||
|
<a-col :span="12">
|
||||||
|
<span>高度/深度</span>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-input-number v-model="hdModal.hd" :min="0" style="width: 100%" />
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</a-modal> -->
|
||||||
|
</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>{{ modelData.person.total }} 人</span>
|
||||||
|
</div>
|
||||||
|
<div class="zt-item flex ai-c">
|
||||||
|
<span style="min-width: 100px">当前人数:</span>
|
||||||
|
<span>{{ modelData.person.current }} 人</span>
|
||||||
|
</div>
|
||||||
|
<div class="zt-item flex ai-c">
|
||||||
|
<span style="min-width: 100px">死亡人数:</span>
|
||||||
|
<span>{{ modelData.person.death }} 人</span>
|
||||||
|
</div>
|
||||||
|
<div class="zt-item flex ai-c">
|
||||||
|
<span style="min-width: 100px">受伤人数:</span>
|
||||||
|
<span>{{ modelData.person.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>{{ modelData.foodInfo.startNum }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="zt-item flex ai-c">
|
||||||
|
<span style="min-width: 100px">野战食物当前量(份):</span>
|
||||||
|
<span>{{ modelData.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>{{ modelData.waterInfo.startNum }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="zt-item flex ai-c">
|
||||||
|
<span style="min-width: 100px">用水当前量(吨):</span>
|
||||||
|
<span>{{ modelData.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>{{ modelData.oilInfo.startNum }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="zt-item flex ai-c">
|
||||||
|
<span style="min-width: 100px">油料当前量(份):</span>
|
||||||
|
<span>{{ modelData.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>{{ modelData.medicalInfo.startNum }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="zt-item flex ai-c">
|
||||||
|
<span style="min-width: 100px">药材当前量(份):</span>
|
||||||
|
<span>{{ modelData.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>{{ modelData.ammunition.lightArms }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="zt-item flex ai-c">
|
||||||
|
<span style="min-width: 100px">压制武器弹药量(吨):</span>
|
||||||
|
<span>{{ modelData.ammunition.suppressing }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="zt-item flex ai-c">
|
||||||
|
<span style="min-width: 100px">反坦克武器弹药量(吨):</span>
|
||||||
|
<span>{{ modelData.ammunition.antiTank }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="zt-item flex ai-c">
|
||||||
|
<span style="min-width: 100px">防空反导武器弹药量(吨):</span>
|
||||||
|
<span>{{ modelData.ammunition.antiAircraft }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="zt-item flex ai-c">
|
||||||
|
<span style="min-width: 100px">布扫雷装备弹药量(吨):</span>
|
||||||
|
<span>{{ modelData.ammunition.mineLaying }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="zt-item flex ai-c">
|
||||||
|
<span style="min-width: 100px">爆破器材弹药量(吨):</span>
|
||||||
|
<span>{{ modelData.ammunition.explosiveDevice }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="zt-item flex ai-c">
|
||||||
|
<span style="min-width: 100px">烟火装备弹药量(吨):</span>
|
||||||
|
<span>{{ modelData.ammunition.smokeDevice }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="zt-item flex ai-c">
|
||||||
|
<span style="min-width: 100px">防化消耗弹药量(吨):</span>
|
||||||
|
<span>{{ modelData.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>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import LonLatInput from './LonLatInput.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
scenarioId: { type: String, required: true },
|
||||||
|
modelData: { type: Object, default: () => ({}) },
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
LonLatInput,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
cesium: null,
|
||||||
|
mcModal: {
|
||||||
|
visible: false,
|
||||||
|
mc: '',
|
||||||
|
},
|
||||||
|
lonlatModal: {
|
||||||
|
visible: false,
|
||||||
|
lon: 0,
|
||||||
|
lat: 0,
|
||||||
|
},
|
||||||
|
hdModal: {
|
||||||
|
visible: false,
|
||||||
|
hd: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
hasDetail() {
|
||||||
|
return Boolean(this.modelData.id)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
filters: {
|
||||||
|
logisticTypeFormat(v) {
|
||||||
|
return {
|
||||||
|
1: '信息对抗分队',
|
||||||
|
2: '边防作战分队',
|
||||||
|
3: '防化保障分队',
|
||||||
|
4: '火力打击分队',
|
||||||
|
5: '餐饮保障分队',
|
||||||
|
6: '运输保障分队',
|
||||||
|
7: '医疗分队',
|
||||||
|
8: '工兵分队',
|
||||||
|
}[v]
|
||||||
|
},
|
||||||
|
forceFormat(v) {
|
||||||
|
return ['红方', '蓝方'][v]
|
||||||
|
},
|
||||||
|
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°0′0″'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
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°0′0″'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleOpenMcModal() {
|
||||||
|
this.mcModal.mc = this.modelData.team.teamName
|
||||||
|
this.mcModal.visible = true
|
||||||
|
},
|
||||||
|
async handleSubmilMc() {
|
||||||
|
try {
|
||||||
|
this.$http({
|
||||||
|
url: `/scenario/power/modifyUnit/${this.scenarioId}`,
|
||||||
|
method: 'post',
|
||||||
|
data: {
|
||||||
|
id: this.modelData.id,
|
||||||
|
name: this.mcModal.mc,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
this.$message.success('编辑单元名称成功')
|
||||||
|
this.modelData.team.teamName = this.mcModal.mc
|
||||||
|
this.mcModal.visible = false
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
handleOpenLonlatModal() {
|
||||||
|
this.lonlatModal.lon = Number(this.modelData.position.lng) || 0
|
||||||
|
this.lonlatModal.lat = Number(this.modelData.position.lat) || 0
|
||||||
|
this.lonlatModal.visible = true
|
||||||
|
},
|
||||||
|
async handleSubmilLonlat() {
|
||||||
|
try {
|
||||||
|
this.$http({
|
||||||
|
url: `/scenario/power/modifyUnit/${this.scenarioId}`,
|
||||||
|
method: 'post',
|
||||||
|
data: {
|
||||||
|
id: this.modelData.id,
|
||||||
|
position: {
|
||||||
|
lng: this.lonlatModal.lon,
|
||||||
|
lat: this.lonlatModal.lat,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
this.$message.success('修改单元经纬度成功')
|
||||||
|
this.modelData.position.lng = '' + this.lonlatModal.lon
|
||||||
|
this.modelData.position.lat = '' + this.lonlatModal.lat
|
||||||
|
this.lonlatModal.visible = false
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
handleOpenHdModal() {
|
||||||
|
this.hdModal.hd = Number(this.modelData.position.height) || 0
|
||||||
|
this.hdModal.visible = true
|
||||||
|
},
|
||||||
|
async handleSubmilHd() {
|
||||||
|
try {
|
||||||
|
this.$http({
|
||||||
|
url: `/scenario/power/modifyUnit/${this.scenarioId}`,
|
||||||
|
method: 'post',
|
||||||
|
data: {
|
||||||
|
id: this.modelData.id,
|
||||||
|
position: {
|
||||||
|
height: this.hdModal.hd,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
this.$message.success('修改单元高度/深度成功')
|
||||||
|
this.modelData.position.height = this.hdModal.hd
|
||||||
|
this.hdModal.visible = false
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.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 {
|
||||||
|
width: 100%;
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #0c3040;
|
||||||
|
}
|
||||||
|
.name {
|
||||||
|
color: #00baff;
|
||||||
|
text-decoration: underline;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
.simulation-select::v-deep {
|
||||||
|
.ant-select-selection {
|
||||||
|
background-color: #10475f;
|
||||||
|
border: solid 1px #1d5777;
|
||||||
|
color: #bbdded;
|
||||||
|
}
|
||||||
|
.ant-select-arrow {
|
||||||
|
color: #bbdded;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<style lang="less">
|
||||||
|
.simulation-select-dropdown {
|
||||||
|
background-color: #10475f;
|
||||||
|
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>
|
|
@ -0,0 +1,143 @@
|
||||||
|
<template>
|
||||||
|
<div class="lon-lat-input">
|
||||||
|
<div class="lon-input" style="padding: 10px 0">
|
||||||
|
<a-select v-model="lonSelect" style="width: 76px; margin-right: 20px">
|
||||||
|
<a-select-option :value="1">东经</a-select-option>
|
||||||
|
<a-select-option :value="-1">西经</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
<a-input-number v-model="lonNumber" :min="0" :max="180" :precision="8" style="width: 152px" />
|
||||||
|
<span style="margin: 0 8px">°</span>
|
||||||
|
<span style="margin: 0 12px">或</span>
|
||||||
|
<a-input-number v-model="lonDegree" :min="0" :max="180" :step="1" :precision="0" style="width: 60px" />
|
||||||
|
<span style="margin: 0 8px">°</span>
|
||||||
|
<a-input-number v-model="lonMinute" :min="0" :max="60" :step="1" :precision="0" style="width: 60px" />
|
||||||
|
<span style="margin: 0 8px">′</span>
|
||||||
|
<a-input-number v-model="lonSecond" :min="0" :max="60" :step="1" :precision="0" style="width: 60px" />
|
||||||
|
<span style="margin: 0 8px">″</span>
|
||||||
|
</div>
|
||||||
|
<div class="lat-input" style="padding: 10px 0">
|
||||||
|
<a-select v-model="latSelect" style="width: 76px; margin-right: 20px">
|
||||||
|
<a-select-option :value="1">北纬</a-select-option>
|
||||||
|
<a-select-option :value="-1">南纬</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
<a-input-number v-model="latNumber" :min="0" :max="180" :precision="8" style="width: 152px" />
|
||||||
|
<span style="margin: 0 8px">°</span>
|
||||||
|
<span style="margin: 0 12px">或</span>
|
||||||
|
<a-input-number v-model="latDegree" :min="0" :max="180" :step="1" :precision="0" style="width: 60px" />
|
||||||
|
<span style="margin: 0 8px">°</span>
|
||||||
|
<a-input-number v-model="latMinute" :min="0" :max="60" :step="1" :precision="0" style="width: 60px" />
|
||||||
|
<span style="margin: 0 8px">′</span>
|
||||||
|
<a-input-number v-model="latSecond" :min="0" :max="60" :step="1" :precision="0" style="width: 60px" />
|
||||||
|
<span style="margin: 0 8px">″</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
lon: { type: Number, required: true },
|
||||||
|
lat: { type: Number, required: true },
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
EWSelect: 1,
|
||||||
|
NSSelect: 1,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
lonSelect: {
|
||||||
|
get() {
|
||||||
|
return this.lon ? this.lon / this.lonNumber : this.EWSelect
|
||||||
|
},
|
||||||
|
set(v) {
|
||||||
|
this.$emit('update:lon', this.lonNumber * v)
|
||||||
|
this.EWSelect = v
|
||||||
|
},
|
||||||
|
},
|
||||||
|
lonNumber: {
|
||||||
|
get() {
|
||||||
|
return Math.abs(this.lon)
|
||||||
|
},
|
||||||
|
set(v) {
|
||||||
|
this.$emit('update:lon', Math.abs(v) * this.lonSelect)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
lonDegree: {
|
||||||
|
get() {
|
||||||
|
return Math.floor(this.lonNumber)
|
||||||
|
},
|
||||||
|
set(v) {
|
||||||
|
this.$emit('update:lon', Math.abs(v) * this.lonSelect + this.lonMinute / 60 + this.lonSecond / 3600)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
lonMinute: {
|
||||||
|
get() {
|
||||||
|
return Math.floor(this.lonNumber * 60) % 60
|
||||||
|
},
|
||||||
|
set(v) {
|
||||||
|
this.$emit('update:lon', this.lonDegree * this.lonSelect + Math.abs(v) / 60 + this.lonSecond / 3600)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
lonSecond: {
|
||||||
|
get() {
|
||||||
|
return Math.floor(this.lonNumber * 3600) % 60
|
||||||
|
},
|
||||||
|
set(v) {
|
||||||
|
this.$emit('update:lon', this.lonDegree * this.lonSelect + this.lonMinute / 60 + Math.abs(v) / 3600)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
latSelect: {
|
||||||
|
get() {
|
||||||
|
return this.lat ? this.lat / this.latNumber : this.NSSelect
|
||||||
|
},
|
||||||
|
set(v) {
|
||||||
|
this.$emit('update:lat', this.latNumber * v)
|
||||||
|
this.NSSelect = v
|
||||||
|
},
|
||||||
|
},
|
||||||
|
latNumber: {
|
||||||
|
get() {
|
||||||
|
return Math.abs(this.lat)
|
||||||
|
},
|
||||||
|
set(v) {
|
||||||
|
this.$emit('update:lat', Math.abs(v) * this.latSelect)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
latDegree: {
|
||||||
|
get() {
|
||||||
|
return Math.floor(this.latNumber)
|
||||||
|
},
|
||||||
|
set(v) {
|
||||||
|
this.$emit('update:lat', Math.abs(v) * this.latSelect + this.latMinute / 60 + this.latSecond / 3600)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
latMinute: {
|
||||||
|
get() {
|
||||||
|
return Math.floor(this.latNumber * 60) % 60
|
||||||
|
},
|
||||||
|
set(v) {
|
||||||
|
this.$emit('update:lat', this.latDegree * this.latSelect + Math.abs(v) / 60 + this.latSecond / 3600)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
latSecond: {
|
||||||
|
get() {
|
||||||
|
return Math.floor(this.latNumber * 3600) % 60
|
||||||
|
},
|
||||||
|
set(v) {
|
||||||
|
this.$emit('update:lat', this.latDegree * this.latSelect + this.latMinute / 60 + Math.abs(v) / 3600)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
if (this.lon < 0) {
|
||||||
|
this.EWSelect = 'W'
|
||||||
|
}
|
||||||
|
if (this.lat < 0) {
|
||||||
|
this.NSSelect = 'S'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped></style>
|
|
@ -0,0 +1,166 @@
|
||||||
|
<template>
|
||||||
|
<Flex fd="co" class="zzxd-wrapper">
|
||||||
|
<Flex class="zzxd-header" ai="c" jc="sb">
|
||||||
|
<div class="zzxd-title">作战行动</div>
|
||||||
|
<div>
|
||||||
|
<a-button type="text-primary" icon="menu"></a-button>
|
||||||
|
<a-button type="text-primary" icon="plus" @click="handleOpenAddActionModal"></a-button>
|
||||||
|
<a-button type="text-primary" icon="edit" @click="handleOpenEditActionModal"></a-button>
|
||||||
|
<a-button type="text-primary" icon="delete" @click="handleDeleteAction"></a-button>
|
||||||
|
</div>
|
||||||
|
<a-modal
|
||||||
|
v-model="actionModal.visible"
|
||||||
|
:title="actionModal.title"
|
||||||
|
:maskClosable="false"
|
||||||
|
:destroyOnClose="true"
|
||||||
|
@ok="handleSubmilAction"
|
||||||
|
>
|
||||||
|
<a-form-model
|
||||||
|
:model="actionModal.formData"
|
||||||
|
layout="horizontal"
|
||||||
|
:labelCol="{ span: 6 }"
|
||||||
|
:wrapperCol="{ span: 15 }"
|
||||||
|
>
|
||||||
|
<a-form-model-item v-for="item in actionModal.formItems" :key="item.prop" v-bind="item">
|
||||||
|
<component
|
||||||
|
:is="item.component || 'a-input'"
|
||||||
|
v-model="actionModal.formData[item.prop]"
|
||||||
|
v-bind="item.options"
|
||||||
|
/>
|
||||||
|
</a-form-model-item>
|
||||||
|
</a-form-model>
|
||||||
|
</a-modal>
|
||||||
|
</Flex>
|
||||||
|
<div class="flex-1 scroller-y">
|
||||||
|
<div v-for="item in actionList" :key="item.id" class="action-item flex" @click="checkedAction = item">
|
||||||
|
<div class="action-icon">
|
||||||
|
<div class="action-line"></div>
|
||||||
|
<a-radio :checked="checkedAction && checkedAction.id === item.id" style="margin-right: 0"></a-radio>
|
||||||
|
</div>
|
||||||
|
<div class="flex-1">
|
||||||
|
<div class="action-title">{{ item.typeName || '- -' }}</div>
|
||||||
|
<div class="action-time">开始时间:{{ item.beginDateTime }}</div>
|
||||||
|
<div class="action-time">结束时间:{{ item.endDateTime }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Flex>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
actionList: { type: Array, default: () => [] },
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
checkedAction: null,
|
||||||
|
actionModal: {
|
||||||
|
visible: false,
|
||||||
|
formItems: [
|
||||||
|
{ label: '事件名称', prop: 'typeName' },
|
||||||
|
{
|
||||||
|
label: '事件类型',
|
||||||
|
prop: 'typeType',
|
||||||
|
component: 'AntOriginSelect',
|
||||||
|
options: {
|
||||||
|
dataSource: () => ({
|
||||||
|
data: [
|
||||||
|
{ id: '1', title: '机动任务' },
|
||||||
|
{ id: '2', title: '战斗任务' },
|
||||||
|
{ id: '3', title: '整备任务' },
|
||||||
|
{ id: '4', title: '弹药保障' },
|
||||||
|
{ id: '5', title: '水保障' },
|
||||||
|
{ id: '6', title: '油保障' },
|
||||||
|
{ id: '7', title: '食品保障' }
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ label: '开始时间', prop: 'beginDateTime', component: 'a-date-picker', options: { showTime: true } },
|
||||||
|
{ label: '结束时间', prop: 'endDateTime', component: 'a-date-picker', options: { showTime: true } },
|
||||||
|
{ label: '目标经度', prop: 'lon', component: 'a-input-number' },
|
||||||
|
{ label: '目标纬度', prop: 'lat', component: 'a-input-number' },
|
||||||
|
],
|
||||||
|
formData: {},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleOpenAddActionModal() {
|
||||||
|
this.actionModal.title = '添加事件信息'
|
||||||
|
this.actionModal.formData = {}
|
||||||
|
this.actionModal.visible = true
|
||||||
|
},
|
||||||
|
handleOpenEditActionModal() {
|
||||||
|
this.actionModal.title = '修改事件信息'
|
||||||
|
this.actionModal.formData = { ...this.checkedAction }
|
||||||
|
this.actionModal.visible = true
|
||||||
|
},
|
||||||
|
async handleSubmilAction() {
|
||||||
|
try {
|
||||||
|
await this.$http({
|
||||||
|
url: '/save',
|
||||||
|
method: 'post',
|
||||||
|
data: this.actionModal.formData,
|
||||||
|
})
|
||||||
|
this.$message.success(`${this.actionModal.title}成功`)
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async handleDeleteAction() {
|
||||||
|
try {
|
||||||
|
await this.$confirm('确认删除所选事件吗?')
|
||||||
|
await this.$http({
|
||||||
|
url: '/delete',
|
||||||
|
method: 'delete',
|
||||||
|
params: { id: this.checkedAction.id },
|
||||||
|
})
|
||||||
|
this.$message.success(`删除事件成功`)
|
||||||
|
} catch (error) {
|
||||||
|
this.$message.success(`删除事件失败`)
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.zzxd-wrapper {
|
||||||
|
height: 100%;
|
||||||
|
.zzxd-header {
|
||||||
|
padding: 5px 0;
|
||||||
|
border-bottom: 1px solid #00baff22;
|
||||||
|
.zzxd-title {
|
||||||
|
color: #00baff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.action-item {
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 5px 0;
|
||||||
|
.action-icon {
|
||||||
|
padding: 5px 16px;
|
||||||
|
position: relative;
|
||||||
|
flex-shrink: 0;
|
||||||
|
.action-line {
|
||||||
|
position: absolute;
|
||||||
|
right: 50%;
|
||||||
|
top: 21px;
|
||||||
|
width: 1px;
|
||||||
|
height: 100%;
|
||||||
|
background-color: #00baff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.action-item:last-of-type {
|
||||||
|
.action-line {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.action-item:hover {
|
||||||
|
background-color: #bae7ff44;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,246 @@
|
||||||
|
<template>
|
||||||
|
<Grid class="simulation-model-page" :columns="['320px', 1, '320px']" :rows="[45, 15, 40]" gap="0px">
|
||||||
|
<ModuleWrapper title="作战/保障力量" style="grid-column: 1 / 2; grid-row: 1 / 2">
|
||||||
|
<div class="normal" style="padding: 5px; overflow-y: auto">
|
||||||
|
<a-tree
|
||||||
|
class="simulation-tree"
|
||||||
|
:treeData="zb.zbTreeData"
|
||||||
|
:selectedKeys.sync="zb.selectedKeys"
|
||||||
|
:replaceFields="{ children: 'children', title: 'name', key: 'id' }"
|
||||||
|
@select="handleSelectTree"
|
||||||
|
>
|
||||||
|
</a-tree>
|
||||||
|
</div>
|
||||||
|
</ModuleWrapper>
|
||||||
|
<ModuleWrapper style="grid-column: 1 / 2; grid-row: 2 / 4">
|
||||||
|
<template #title>
|
||||||
|
<a-radio-group v-model="qd.qdlx" button-style="solid">
|
||||||
|
<a-radio-button value="xqqd">需求清单</a-radio-button>
|
||||||
|
<a-radio-button value="bzqd">保障清单</a-radio-button>
|
||||||
|
</a-radio-group>
|
||||||
|
</template>
|
||||||
|
<div class="normal" style="padding: 5px">
|
||||||
|
<a-table
|
||||||
|
class="simulation-table-plain"
|
||||||
|
rowKey="id"
|
||||||
|
:columns="qd.qdColumns"
|
||||||
|
:dataSource="qd.qdList"
|
||||||
|
:pagination="false"
|
||||||
|
:bordered="true"
|
||||||
|
></a-table>
|
||||||
|
</div>
|
||||||
|
</ModuleWrapper>
|
||||||
|
<div
|
||||||
|
class="cesium-container"
|
||||||
|
id="cesium-container"
|
||||||
|
style="grid-column: 2 / 3; grid-row: 1 / 4; overflow: hidden"
|
||||||
|
></div>
|
||||||
|
<ModuleWrapper title="保障实体属性" style="grid-column: 3 / 4; grid-row: 1 / 3">
|
||||||
|
<div class="normal" style="padding: 15px 0">
|
||||||
|
<div style="height: 100%; padding: 0 15px; overflow-y: auto">
|
||||||
|
<img class="image" :src="sx.image" />
|
||||||
|
<div class="name">{{ sx.name }}</div>
|
||||||
|
<div v-for="item in sx.sxList" :key="item.label" class="sx-item">
|
||||||
|
<span>{{ item.label }}:</span>
|
||||||
|
<img :src="item.icon" alt="" />
|
||||||
|
<span>{{ item.text }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ModuleWrapper>
|
||||||
|
<ModuleWrapper title="资源" style="grid-column: 3 / 4; grid-row: 3 / 4">
|
||||||
|
<div class="normal" style="padding: 15px 0">
|
||||||
|
<div style="height: 100%; padding: 0 15px; overflow-y: auto">
|
||||||
|
<div v-for="item in zy.zyList" :key="item.label" class="zy-item flex">
|
||||||
|
<span>{{ item.label }}:</span>
|
||||||
|
<span style="flex: 1; white-space: nowrap; overflow: hidden" v-html="zy.placeholder"></span>
|
||||||
|
<span>{{ item.text }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ModuleWrapper>
|
||||||
|
</Grid>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'SimulationSceneSimulationModel',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
cesium: null,
|
||||||
|
zb: {
|
||||||
|
zbTreeData: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
name: '红方',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
id: '1-1',
|
||||||
|
name: '作战力量',
|
||||||
|
children: [
|
||||||
|
{ id: '1-1-1', name: '左翼夺控群火力分队' },
|
||||||
|
{ id: '1-1-2', name: '左翼攻击分队' },
|
||||||
|
{ id: '1-1-3', name: '右翼攻击分队' },
|
||||||
|
{ id: '1-1-4', name: '右翼夺控群反装甲分队' },
|
||||||
|
{ id: '1-1-5', name: '防空火力队' },
|
||||||
|
{ id: '1-1-6', name: '左翼牵制群右翼攻击分队' },
|
||||||
|
{ id: '1-1-7', name: '电子对抗兵队超短波干扰分队' },
|
||||||
|
{ id: '1-1-8', name: '纵深夺控群火力分队' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '1-2',
|
||||||
|
name: '保障力量',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
name: '蓝方',
|
||||||
|
children: [
|
||||||
|
{ id: '1-1', name: '作战力量' },
|
||||||
|
{ id: '1-2', name: '保障力量' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
selectedKeys: [],
|
||||||
|
},
|
||||||
|
qd: {
|
||||||
|
qdlx: 'xqqd',
|
||||||
|
qdColumns: [
|
||||||
|
{
|
||||||
|
dataIndex: 'dj',
|
||||||
|
title: '等级',
|
||||||
|
width: '62px',
|
||||||
|
align: 'center',
|
||||||
|
customRender: (text) => ['', '紧急', '加急', '一般'][text],
|
||||||
|
customCell: (record) => ({ style: { color: ['', '#ff3838', '#feba29', '#ffffff'][record.dj] } }),
|
||||||
|
},
|
||||||
|
{ dataIndex: 'bzxq', title: '保障需求' },
|
||||||
|
],
|
||||||
|
qdList: [
|
||||||
|
{ id: '1', dj: '1', bzxq: '500枚防空导弹、6辆装甲车' },
|
||||||
|
{ id: '2', dj: '2', bzxq: '5吨汽油、100套军装' },
|
||||||
|
{ id: '3', dj: '3', bzxq: '15箱消炎药、6箱葡萄糖滴' },
|
||||||
|
{ id: '4', dj: '3', bzxq: '一吨饮用水' },
|
||||||
|
{ id: '5', dj: '3', bzxq: '1吨燃油、厨房抽烟机设备一' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
sx: {
|
||||||
|
image: '/mockData/cb8917d8-6658-cf7f-dd4e-ea2e670edea8.png',
|
||||||
|
name: '医院',
|
||||||
|
sxList: [
|
||||||
|
{ label: '推演方', text: `红方` },
|
||||||
|
{ label: '经度', text: `东经120°12'03″` },
|
||||||
|
{ label: '纬度', text: `北纬24°51'09″` },
|
||||||
|
{ label: '高度/深度', text: `326米` },
|
||||||
|
{ label: '图标', icon: '/mockData/9d47c8c8-30d8-3e78-944f-d48ca8084c58.png' },
|
||||||
|
{ label: '医师', text: `36人` },
|
||||||
|
{ label: '护士', text: `100人` },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
zy: {
|
||||||
|
placeholder: ' '.repeat(100),
|
||||||
|
zyList: [
|
||||||
|
{ label: '血液', text: `100L` },
|
||||||
|
{ label: '药材', text: `1.5吨` },
|
||||||
|
{ label: '氧气', text: `100m3` },
|
||||||
|
{ label: '床位', text: `56个` },
|
||||||
|
{ label: '手术台', text: `10台` },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.$bus.$emit('set-trainer-system-title', '仿真模型子系统')
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.cesium = new window.MyCesium('cesium-container')
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleSelectTree() {},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.simulation-model-page {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.simulation-table-plain::v-deep {
|
||||||
|
.ant-table {
|
||||||
|
color: #a1c2d0;
|
||||||
|
}
|
||||||
|
.ant-table-body > table {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
.ant-table-thead > tr > th {
|
||||||
|
background-color: #083a52;
|
||||||
|
color: #ffffff;
|
||||||
|
border-bottom-color: #05628e;
|
||||||
|
border-top: 1px solid #05628e;
|
||||||
|
&:last-child {
|
||||||
|
border-right-color: #05628e;
|
||||||
|
}
|
||||||
|
&:not(:last-child) {
|
||||||
|
border-right-color: #05628e3b;
|
||||||
|
}
|
||||||
|
&:first-child {
|
||||||
|
border-left: 1px solid #05628e;
|
||||||
|
}
|
||||||
|
&:not(:first-child) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ant-table-tbody > tr > td {
|
||||||
|
border-bottom-color: #064766;
|
||||||
|
&:last-child {
|
||||||
|
border-right-color: #064766;
|
||||||
|
}
|
||||||
|
&:not(:last-child) {
|
||||||
|
border-right-color: #05628e3b;
|
||||||
|
}
|
||||||
|
&:first-child {
|
||||||
|
border-left: 1px solid #064766;
|
||||||
|
}
|
||||||
|
&:not(:first-child) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.image {
|
||||||
|
width: 100%;
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #0c3040;
|
||||||
|
}
|
||||||
|
.name {
|
||||||
|
color: #00baff;
|
||||||
|
text-decoration: underline;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 26px;
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
.sx-item {
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 30px;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
color: #bbdded;
|
||||||
|
}
|
||||||
|
.zy-item {
|
||||||
|
text-decoration: underline;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 26px;
|
||||||
|
letter-spacing: 0px;
|
||||||
|
color: #00baff;
|
||||||
|
}
|
||||||
|
</style>
|
Loading…
Reference in New Issue
Block a user