You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

411 lines
13 KiB

<script>
import { getCanvasImageAndViewPoint } from '@/utils';
import { getSceneConfig, getLayerTreeBySceneId, updateSceneConfig } from '@/api/aiSupervision/layerConfigApi';
import LayerTree from '../layerTree/index.vue';
import { addLayer, removeLayer, zoomToLayer } from '../layerTree/index.js';
let viewer = undefined;
export default {
name: 'SceneConfig',
components: {
LayerTree
},
props: {
sceneId: {
type: String,
default: ''
},
defaultCheckedKeys: {
type: Array,
default: () => []
}
},
data() {
return {
activeNames: ['1', '2', '3'],
viewForm: { image: '', lng: '', lat: '', alt: '', heading: '', pitch: '', roll: '' },
initForm: {
initTime: '',
initWeather: 1,
ambientLightIntensity: '',
weatherIntensity: '',
movementSensitivity: '',
rotationSensitivity: '',
zoomSensitivity: ''
},
weatherOptions: [
{ label: '晴天', value: 1 },
{ label: '多云', value: 2 },
{ label: '阴天', value: 3 },
{ label: '小雨', value: 4 },
{ label: '中雨', value: 5 },
{ label: '暴雨', value: 6 },
{ label: '雪天', value: 7 },
{ label: '雾天', value: 8 }
],
isEdit: false,
treeData: [],
defaultProps: { children: 'children', label: 'text' },
defaultViewProps: { children: 'children', label: 'text', disabled: this.disabledNode }
};
},
methods: {
initData() {
this.initMap();
this.fetchSceneConfig();
this.fetchLayerTree();
},
disabledNode(data, node) {
if (node.isLeaf) {
const checkedKeys = this.$refs.layerTree.getCheckedKeys();
node.checked = checkedKeys.includes(data.id);
}
return true;
},
fetchSceneConfig() {
getSceneConfig(this.sceneId).then((res) => {
if (res.success && res.data) {
const {
initTime,
initWeather,
ambientLightIntensity,
weatherIntensity,
movementSensitivity,
rotationSensitivity,
zoomSensitivity,
cameraPosture,
viewImg,
layerId,
id
} = res.data;
this.initForm.id = id;
this.initForm.initTime = initTime;
this.initForm.initWeather = initWeather;
this.initForm.ambientLightIntensity = ambientLightIntensity;
this.initForm.weatherIntensity = weatherIntensity;
this.initForm.movementSensitivity = movementSensitivity;
this.initForm.rotationSensitivity = rotationSensitivity;
this.initForm.zoomSensitivity = zoomSensitivity;
this.viewForm = JSON.parse(cameraPosture);
this.viewForm.image = viewImg;
const layerIds = JSON.parse(layerId);
this.$emit('set-checked-keys', layerIds);
this.$nextTick(() => {
if (this.viewForm.image) {
const { lng, lat, alt, heading, pitch, roll } = this.viewForm;
setTimeout(() => {
window.viewer.scene.camera.setView({
destination: new Cesium.Cartesian3.fromDegrees(lng, lat, alt),
orientation: {
heading,
pitch,
roll
}
});
}, 1000);
}
});
}
});
},
fetchLayerTree() {
getLayerTreeBySceneId(this.sceneId).then((res) => {
if (res.success && res.data) {
this.treeData = this.restructTreeData([res.data]);
this.$nextTick(() => {
const checkedNodes = this.$refs.layerTree.getCheckedNodes(true);
checkedNodes.forEach((node, index) => {
this.onCheck(node);
});
});
}
});
},
restructTreeData(data) {
return data.map((item) => {
if (item.children && item.children.length) {
item.children = this.restructTreeData(item.children);
}
item.children = item.children || [];
if (item.layers && item.layers.length) {
const layers = item.layers.map((layer) => {
return {
...layer,
children: []
};
});
item.children = item.children.concat(layers);
}
return item;
});
},
initMap() {
viewer = new sycim.Viewer('cesiumContainer');
window.viewer = viewer;
let baseLayer = sycim.ImageryLayerFactory.createImageryLayer(sycim.ImageryType.ARCGIS, {
url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer'
});
viewer.addBaseLayer(baseLayer);
},
fetchView() {
const { imageSrc, position, heading, pitch, roll } = getCanvasImageAndViewPoint(viewer);
const { lng, lat, alt } = sycim.T.transformCartesianToWGS84(position);
this.viewForm.lng = lng;
this.viewForm.lat = lat;
this.viewForm.alt = alt;
this.viewForm.heading = heading;
this.viewForm.pitch = pitch;
this.viewForm.roll = roll;
this.viewForm.image = imageSrc;
},
handleEvent() {
if (this.isEdit) {
this.saveSceneConfig();
}
this.isEdit = !this.isEdit;
},
onCheck(data) {
if (!data.iconCls) {
// 获取树的勾选值,不一定是默认勾选的值
const checkedKeys = this.$refs.layerTree.getCheckedKeys();
this.handleCheckChange(data, { checkedKeys });
}
},
handleCheckChange(data, checkedData) {
const { id } = data;
const { checkedKeys } = checkedData;
const nodes = [data];
if (data.children?.length > 0) {
this.flattenTree(data.children, nodes);
}
const checked = checkedKeys.includes(id);
this.toggleLayer(nodes, checked);
},
flattenTree(tree, flatArray = []) {
tree.forEach((node) => {
const { children, ...rest } = node;
flatArray.push(rest);
if (children && children.length > 0) {
flattenTree(children, flatArray);
}
});
return flatArray;
},
toggleLayer(nodes, checked) {
if (Array.isArray(nodes)) {
nodes.forEach((node) => {
if (checked) {
addLayer(node);
} else {
removeLayer(node);
}
});
}
},
goPosition(node) {
zoomToLayer(node.data);
},
saveSceneConfig() {
const form = JSON.parse(JSON.stringify(this.viewForm));
delete form.image;
const layerId = this.$refs.layerConfigTree.getCheckedKeys();
const params = {
sceneId: this.sceneId,
...this.initForm,
viewImg: this.viewForm.image,
layerId: JSON.stringify(layerId),
cameraPosture: JSON.stringify({ ...form })
};
updateSceneConfig(params).then((res) => {
if (res.success) {
this.$message.success('保存成功');
}
});
},
cancelEvent() {
this.isEdit = false;
}
}
};
</script>
<template>
<div class="box-wrapper">
<div class="left-panel">
<el-collapse class="sy-collapse" v-model="activeNames">
<el-collapse-item title="初始环境配置" name="1">
<el-form :model="initForm" label-width="100px" :disabled="!isEdit">
<el-form-item label="时间模式" prop="initTime">
<el-time-select
v-model="initForm.initTime"
:picker-options="{
start: '00:00',
step: '00:15',
end: '23:45'
}"
placeholder="选择时间"
>
</el-time-select>
</el-form-item>
<el-form-item label="天气模式" prop="initWeather">
<el-select v-model="initForm.initWeather">
<el-option v-for="(item, index) in weatherOptions" :label="item.label" :value="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="环境光强度" prop="ambientLightIntensity">
<el-input v-model="initForm.ambientLightIntensity"></el-input>
</el-form-item>
<el-form-item label="天气强度" prop="weatherIntensity">
<el-input v-model="initForm.weatherIntensity"></el-input>
</el-form-item>
<el-form-item label="移动灵敏度" prop="movementSensitivity">
<el-input v-model="initForm.movementSensitivity"></el-input>
</el-form-item>
<el-form-item label="旋转灵敏度" prop="rotationSensitivity">
<el-input v-model="initForm.rotationSensitivity"></el-input>
</el-form-item>
<el-form-item label="缩放灵敏度" prop="zoomSensitivity">
<el-input v-model="initForm.zoomSensitivity"></el-input>
</el-form-item>
</el-form>
</el-collapse-item>
<el-collapse-item title="初始视角配置" name="2">
<el-form :model="viewForm" label-width="80px" :disabled="!isEdit">
<el-form-item class="mix" label="缩略图" prop="image">
<el-button v-show="isEdit" type="text" @click="fetchView">捕获当前视角</el-button>
<el-image v-if="viewForm.image" :src="viewForm.image"></el-image>
</el-form-item>
<el-form-item label="视角位置"></el-form-item>
<el-form-item label="经度" prop="lng">
<el-input v-model="viewForm.lng"></el-input>
</el-form-item>
<el-form-item label="纬度" prop="lat">
<el-input v-model="viewForm.lat"></el-input>
</el-form-item>
<el-form-item label="高度" prop="alt">
<el-input v-model="viewForm.alt"></el-input>
</el-form-item>
<el-form-item label="偏航角" prop="heading">
<el-input v-model="viewForm.heading"></el-input>
</el-form-item>
<el-form-item label="俯仰角" prop="pitch">
<el-input v-model="viewForm.pitch"></el-input>
</el-form-item>
<el-form-item label="翻滚角" prop="roll">
<el-input v-model="viewForm.roll"></el-input>
</el-form-item>
</el-form>
</el-collapse-item>
<el-collapse-item title="初始化图层配置" name="3">
<layer-tree
ref="layerConfigTree"
:show-search="true"
:show-checkbox="true"
:default-checked-keys="defaultCheckedKeys"
:default-props="defaultViewProps"
:data="treeData"
></layer-tree>
</el-collapse-item>
</el-collapse>
<div class="footer-panel">
<el-button v-show="isEdit" class="btn" @click="cancelEvent">取 消</el-button>
<el-button type="primary" class="btn" @click="handleEvent">{{ isEdit ? '保 存' : '编 辑' }}</el-button>
</div>
</div>
<div class="right-panel">
<div id="cesiumContainer"></div>
<el-popover class="layer-btn" placement="left-start" width="320" trigger="click">
<div class="layer-wrapper">
<div class="title-box">
<span class="title">项目图层资源目录</span>
</div>
<layer-tree
ref="layerTree"
:show-checkbox="true"
:show-search="true"
:show-btns="true"
:default-checked-keys="defaultCheckedKeys"
:data="treeData"
:default-props="defaultProps"
@check-change="onCheck"
@location="goPosition"
></layer-tree>
</div>
<el-button slot="reference" icon="el-icon-menu"></el-button>
</el-popover>
</div>
</div>
</template>
<style lang="less">
.layer-wrapper {
.title-box {
margin-bottom: 12px;
.title {
font-size: 16px;
}
}
}
</style>
<style lang="less" scoped>
.box-wrapper {
width: 100%;
height: 100%;
display: flex;
.left-panel {
flex: 1;
height: 100%;
padding: 0 12px;
.sy-collapse {
height: calc(100% - 50px);
overflow: auto;
.el-form {
.el-form-item {
&.mix {
text-align: right;
.el-form-item__content {
display: flex;
flex-direction: column;
align-items: flex-end;
.el-button {
width: 100px;
}
.el-image {
width: 100%;
height: 300px;
}
}
}
.el-date-editor,
.el-select {
width: 100%;
}
}
}
}
.footer-panel {
height: 50px;
line-height: 50px;
text-align: center;
}
}
.right-panel {
position: relative;
width: 70%;
height: 100%;
#cesiumContainer {
width: 100%;
height: 100%;
}
.layer-btn {
position: absolute;
top: 20px;
right: 20px;
z-index: 1;
}
}
}
</style>