Compare commits

...

2 Commits

Author SHA1 Message Date
c1370dcbc0 Merge branch 'main' of https://work.rangutech.cn:85/yiqiuyang/kxfx 2025-09-10 08:48:38 +08:00
8ea0f436b1 1 2025-09-10 08:47:28 +08:00
5 changed files with 473 additions and 335 deletions

View File

@ -15,7 +15,7 @@
"scene3DOnly": false, "scene3DOnly": false,
"shadows": false, "shadows": false,
"removeDblClick": true, "removeDblClick": true,
"sceneMode": 3, "sceneMode": 2,
"showSun": true, "showSun": true,
"showMoon": true, "showMoon": true,
"showSkyBox": true, "showSkyBox": true,

4
public/data/road.json Normal file
View File

@ -0,0 +1,4 @@
{
"leftTop": "114.33,27.8",
"rightBottom": "114.34,27.79"
}

View File

@ -31,6 +31,10 @@ export default {
mounted() { mounted() {
this.activeIndex = getStorage('activeIndex') || 1 this.activeIndex = getStorage('activeIndex') || 1
}, },
beforeDestroy() {
setStorage('activeIndex', 1)
},
methods: { methods: {
setActiveIndex(id) { setActiveIndex(id) {
if (this.activeIndex !== id) { if (this.activeIndex !== id) {

View File

@ -30,19 +30,33 @@
:model="form" :model="form"
> >
<el-form-item label="起点"> <el-form-item label="起点">
<el-input v-model="form.startPoint" @blur="pointsChange('startPoint')"></el-input> <el-input
v-model="form.startPoint"
@blur="pointsChange('startPoint')"
></el-input>
</el-form-item> </el-form-item>
<el-form-item label="终点"> <el-form-item label="终点">
<el-input v-model="form.endPoint" @blur="pointsChange('endPoint')"></el-input> <el-input
v-model="form.endPoint"
@blur="pointsChange('endPoint')"
></el-input>
</el-form-item> </el-form-item>
<el-form-item label="途径点"> <el-form-item label="途径点">
<div v-for="(item, index) in form.viaPoints" :key="index"> <div v-for="(item, index) in form.viaPoints" :key="index">
<el-input v-model="item.points" placeholder="" @blur="pointsChange('viaPoints', item)"></el-input> <el-input
v-model="item.points"
placeholder=""
@blur="pointsChange('viaPoints', item)"
></el-input>
</div> </div>
</el-form-item> </el-form-item>
<el-form-item label="避让点"> <el-form-item label="避让点">
<div v-for="(item, index) in form.avoidPoints" :key="index"> <div v-for="(item, index) in form.avoidPoints" :key="index">
<el-input v-model="item.points" placeholder="" @blur="pointsChange('avoidPoints', item)"></el-input> <el-input
v-model="item.points"
placeholder=""
@blur="pointsChange('avoidPoints', item)"
></el-input>
</div> </div>
</el-form-item> </el-form-item>
<el-form-item label="避让区域"> <el-form-item label="避让区域">
@ -61,7 +75,12 @@
<el-button @click="clear">清除所有</el-button> <el-button @click="clear">清除所有</el-button>
</el-form-item> --> </el-form-item> -->
</el-form> </el-form>
<input type="file" ref="fileInput" @change="handleFileUpload" style="display: none;" /> <input
type="file"
ref="fileInput"
@change="handleFileUpload"
style="display: none"
/>
<div class="importJson" @click="triggerFileUpload">导入json文件</div> <div class="importJson" @click="triggerFileUpload">导入json文件</div>
</div> </div>
<div class="control-panel"> <div class="control-panel">
@ -79,7 +98,10 @@
<el-input v-model="inputform.load" placeholder=""></el-input> <el-input v-model="inputform.load" placeholder=""></el-input>
</el-form-item> </el-form-item>
<el-form-item label="最小转弯半径"> <el-form-item label="最小转弯半径">
<el-input v-model="inputform.minTurnRadius" placeholder=""></el-input> <el-input
v-model="inputform.minTurnRadius"
placeholder=""
></el-input>
</el-form-item> </el-form-item>
</el-form> </el-form>
<div class="importJson" @click="openDialog">数据选择</div> <div class="importJson" @click="openDialog">数据选择</div>
@ -87,21 +109,28 @@
</div> </div>
<div id="map"></div> <div id="map"></div>
<!-- <div id="mapbox"></div> --> <!-- <div id="mapbox"></div> -->
<div class="main-container" style="width: 452px;"> <div class="main-container" style="width: 452px">
<div class="control-panel" style="width: 452px;"> <div class="control-panel" style="width: 452px">
<div style="font-size: 14px;margin-bottom: 10px;"> <div style="font-size: 14px; margin-bottom: 10px">
详细路线<br /> 详细路线<br />
起点{{form.startPoint}} 起点{{ form.startPoint }} 途径点{{
途径点{{form.viaPoints.length > 0 && form.viaPoints[0].points ? form.viaPoints.map(item => item.points).join(";") : ''}}), form.viaPoints.length > 0 && form.viaPoints[0].points
避让点{{form.avoidPoints.length > 0 && form.avoidPoints[0].points ? form.avoidPoints.map(item => item.points).join(";") : ''}}), ? form.viaPoints.map((item) => item.points).join(';')
终点{{form.endPoint}}, : ''
避让区域{{form.avoidAreas.length > 0 && form.avoidAreas[0].points ? form.avoidAreas.map(item => item.points).join(";") : ''}})<br/> }}), 避让点{{
装备参数:最大车辆宽度{{inputform.width || 0}},最小转弯半径{{inputform.minTurnRadius || 0}}最大车辆载重{{inputform.load || 0}} form.avoidPoints.length > 0 && form.avoidPoints[0].points
? form.avoidPoints.map((item) => item.points).join(';')
: ''
}}), 终点{{ form.endPoint }}, 避让区域{{
form.avoidAreas.length > 0 && form.avoidAreas[0].points
? form.avoidAreas.map((item) => item.points).join(';')
: ''
}})<br />
装备参数:最大车辆宽度{{ inputform.width || 0 }},最小转弯半径{{
inputform.minTurnRadius || 0
}}最大车辆载重{{ inputform.load || 0 }}
</div> </div>
<vxe-table <vxe-table ref="xTable" :data="infoList">
ref="xTable"
:data="infoList"
>
<vxe-column field="编码" title="编码" width="65px"></vxe-column> <vxe-column field="编码" title="编码" width="65px"></vxe-column>
<vxe-column field="名称" title="名称" width="80px"></vxe-column> <vxe-column field="名称" title="名称" width="80px"></vxe-column>
<vxe-column field="宽度" title="路宽"></vxe-column> <vxe-column field="宽度" title="路宽"></vxe-column>
@ -135,7 +164,7 @@
</template> </template>
<script> <script>
import router from '@/router'; import router from '@/router'
export default { export default {
data() { data() {
@ -146,7 +175,7 @@ export default {
inputform: { inputform: {
width: '', width: '',
load: '', load: '',
minTurnRadius: '' minTurnRadius: '',
}, },
form: { form: {
startPoint: '', startPoint: '',
@ -201,18 +230,22 @@ export default {
.catch((error) => {}) .catch((error) => {})
}, },
async initMap() { async initMap() {
this.viewer = new window.mars3d.Map('map', { this.viewer = new window.mars3d.Map(
'map',
{
...this.mapOptions, ...this.mapOptions,
scene: { scene: {
// mode: Cesium.SceneMode.SCENE2D,
center: { center: {
lat: 27.729862392917948, lat: 27.729862392917948,
lng: 114.27980291774088, lng: 114.27980291774088,
alt: 3808, alt: 3808,
heading: 5, heading: 5,
pitch: -35 pitch: -35,
}
}, },
} || {}) },
} || {}
)
this.graphicLayer = new window.mars3d.layer.GraphicLayer() this.graphicLayer = new window.mars3d.layer.GraphicLayer()
this.viewer.addLayer(this.graphicLayer) this.viewer.addLayer(this.graphicLayer)
@ -321,123 +354,143 @@ export default {
this.dialogVisible = true; this.dialogVisible = true;
}, },
handleSelectionChange({records}) { handleSelectionChange({records}) {
this.multipleSelection = records; this.multipleSelection = records
}, },
confirmSelection() { confirmSelection() {
if (this.multipleSelection.length === 0) { if (this.multipleSelection.length === 0) {
this.$message.warning('请至少选择一行数据'); this.$message.warning('请至少选择一行数据')
return; return
} }
const maxValues = this.multipleSelection.reduce((acc, item) => { const maxValues = this.multipleSelection.reduce(
acc.width = Math.max(acc.width, item.width); (acc, item) => {
acc.load = Math.max(acc.load, item.load); acc.width = Math.max(acc.width, item.width)
acc.minTurnRadius = Math.max(acc.minTurnRadius, item.minTurnRadius); acc.load = Math.max(acc.load, item.load)
return acc; acc.minTurnRadius = Math.max(acc.minTurnRadius, item.minTurnRadius)
}, { width: 0, load: 0, minTurnRadius: 0 }); return acc
this.inputform.width = maxValues.width; },
this.inputform.load = maxValues.load; {width: 0, load: 0, minTurnRadius: 0}
this.inputform.minTurnRadius = maxValues.minTurnRadius; )
this.dialogVisible = false; this.inputform.width = maxValues.width
this.inputform.load = maxValues.load
this.inputform.minTurnRadius = maxValues.minTurnRadius
this.dialogVisible = false
}, },
// 导入json文件 // 导入json文件
triggerFileUpload() { triggerFileUpload() {
this.$refs.fileInput.click(); this.$refs.fileInput.click()
}, },
handleFileUpload(event) { handleFileUpload(event) {
const file = event.target.files[0]; const file = event.target.files[0]
if (file) { if (file) {
const reader = new FileReader(); const reader = new FileReader()
reader.onload = (e) => { reader.onload = (e) => {
try { try {
const uploadedJson = JSON.parse(e.target.result); const uploadedJson = JSON.parse(e.target.result)
this.importJson(uploadedJson); this.importJson(uploadedJson)
} catch (error) { } catch (error) {
console.error('解析 JSON 文件失败:', error); console.error('解析 JSON 文件失败:', error)
this.$message.error('解析 JSON 文件失败'); this.$message.error('解析 JSON 文件失败')
} }
}; }
reader.readAsText(file); reader.readAsText(file)
} }
}, },
async importJson(uploadedJson) { async importJson(uploadedJson) {
if (!uploadedJson) { if (!uploadedJson) {
this.$message.warning('请先选择一个 JSON 文件'); this.$message.warning('请先选择一个 JSON 文件')
return; return
}; }
// 清除现有数据 // 清除现有数据
this.clear(); this.clear()
// 加载起点 // 加载起点
if (uploadedJson.startPoint) { if (uploadedJson.startPoint) {
this.form.startPoint = uploadedJson.startPoint this.form.startPoint = uploadedJson.startPoint
this.addPointToMap('startPoint', this.form.startPoint); this.addPointToMap('startPoint', this.form.startPoint)
} }
// 加载终点 // 加载终点
if (uploadedJson.endPoint) { if (uploadedJson.endPoint) {
this.form.endPoint = uploadedJson.endPoint this.form.endPoint = uploadedJson.endPoint
this.addPointToMap('endPoint', this.form.endPoint); this.addPointToMap('endPoint', this.form.endPoint)
} }
// 加载途径点 // 加载途径点
if (uploadedJson.viaPoints) { if (uploadedJson.viaPoints) {
this.form.viaPoints = uploadedJson.viaPoints this.form.viaPoints = uploadedJson.viaPoints
uploadedJson.viaPoints.forEach(viaPoint => { uploadedJson.viaPoints.forEach((viaPoint) => {
this.addPointToMap('viaPoints', viaPoint, viaPoint.time); this.addPointToMap('viaPoints', viaPoint, viaPoint.time)
}); })
} }
// 加载避让点 // 加载避让点
if (uploadedJson.avoidPoints) { if (uploadedJson.avoidPoints) {
this.form.avoidPoints = uploadedJson.avoidPoints this.form.avoidPoints = uploadedJson.avoidPoints
uploadedJson.avoidPoints.forEach(avoidPoint => { uploadedJson.avoidPoints.forEach((avoidPoint) => {
this.addPointToMap('avoidPoints', avoidPoint, avoidPoint.time); this.addPointToMap('avoidPoints', avoidPoint, avoidPoint.time)
}); })
} }
// 加载避让区域 // 加载避让区域
if (uploadedJson.avoidAreas) { if (uploadedJson.avoidAreas) {
this.form.avoidAreas = uploadedJson.avoidAreas this.form.avoidAreas = uploadedJson.avoidAreas
uploadedJson.avoidAreas.forEach(avoidArea => { uploadedJson.avoidAreas.forEach((avoidArea) => {
const time = Date.now(); const time = Date.now()
this.addPolygonToMap('avoidAreas', avoidArea, avoidArea.time); this.addPolygonToMap('avoidAreas', avoidArea, avoidArea.time)
}); })
} }
}, },
addPointToMap(type, point, time) { addPointToMap(type, point, time) {
const coords = time ? point.points.split(',').map(Number) : point.split(',').map(Number); const coords = time
? point.points.split(',').map(Number)
: point.split(',').map(Number)
const graphic = new window.mars3d.graphic.PointEntity({ const graphic = new window.mars3d.graphic.PointEntity({
position: new window.mars3d.LngLatPoint(coords[0], coords[1]), position: new window.mars3d.LngLatPoint(coords[0], coords[1]),
style: { style: {
pixelSize: 10, pixelSize: 10,
color: type === 'startPoint' ? 'red' : type === 'endPoint' ? 'red' : type === 'viaPoints' ? 'blue' : 'orange', color:
type === 'startPoint'
? 'red'
: type === 'endPoint'
? 'red'
: type === 'viaPoints'
? 'blue'
: 'orange',
label: { label: {
text: type === 'startPoint' ? '起点' : type === 'endPoint' ? '终点' : type === 'viaPoints' ? '途径点' : '避让点', text:
type === 'startPoint'
? '起点'
: type === 'endPoint'
? '终点'
: type === 'viaPoints'
? '途径点'
: '避让点',
font_size: 20, font_size: 20,
color: '#ffffff', color: '#ffffff',
outline: true, outline: true,
outlineColor: '#000000', outlineColor: '#000000',
pixelOffsetY: -20, pixelOffsetY: -20,
}, },
time: time time: time,
}, },
}); })
this.graphicLayer.addGraphic(graphic); this.graphicLayer.addGraphic(graphic)
if (type === 'startPoint') { if (type === 'startPoint') {
this.pointQD = graphic; this.pointQD = graphic
} else if (type === 'endPoint') { } else if (type === 'endPoint') {
this.pointZD = graphic; this.pointZD = graphic
} else if (type === 'viaPoints') { } else if (type === 'viaPoints') {
this.viaPoints.push(graphic); this.viaPoints.push(graphic)
} else if (type === 'avoidPoints') { } else if (type === 'avoidPoints') {
this.avoidPoints.push(graphic); this.avoidPoints.push(graphic)
} }
}, },
addPolygonToMap(type, area, time) { addPolygonToMap(type, area, time) {
const coords = JSON.parse(area.points); const coords = JSON.parse(area.points)
const graphic = new window.mars3d.graphic.PolygonEntity({ const graphic = new window.mars3d.graphic.PolygonEntity({
positions: coords.map(coord => new window.mars3d.LngLatPoint(coord[0], coord[1])), positions: coords.map(
(coord) => new window.mars3d.LngLatPoint(coord[0], coord[1])
),
style: { style: {
color: 'red', color: 'red',
opacity: 0.4, opacity: 0.4,
@ -445,103 +498,164 @@ export default {
outline: true, outline: true,
outlineWidth: 1, outlineWidth: 1,
outlineColor: '#ffffff', outlineColor: '#ffffff',
time: time time: time,
}, },
}); })
this.graphicLayer.addGraphic(graphic); this.graphicLayer.addGraphic(graphic)
if (type === 'avoidAreas') { if (type === 'avoidAreas') {
this.avoidAreas.push(graphic); this.avoidAreas.push(graphic)
} }
}, },
// 输入框失去焦点 反向编辑点 // 输入框失去焦点 反向编辑点
pointsChange(type, row) { pointsChange(type, row) {
if (type === 'startPoint') { if (type === 'startPoint') {
if ((!this.form.startPoint || this.form.startPoint == '' || this.form.startPoint == null || this.form.startPoint == undefined) && this.pointQD) { if (
(!this.form.startPoint ||
this.form.startPoint == '' ||
this.form.startPoint == null ||
this.form.startPoint == undefined) &&
this.pointQD
) {
this.pointQD.remove() this.pointQD.remove()
this.pointQD = null; this.pointQD = null
return return
} }
this.updatePointPosition(this.pointQD, this.form.startPoint); this.updatePointPosition(this.pointQD, this.form.startPoint)
} else if (type === 'endPoint') { } else if (type === 'endPoint') {
if ((!this.form.endPoint || this.form.endPoint == '' || this.form.endPoint == null || this.form.endPoint == undefined) && this.pointZD) { if (
(!this.form.endPoint ||
this.form.endPoint == '' ||
this.form.endPoint == null ||
this.form.endPoint == undefined) &&
this.pointZD
) {
this.pointZD.remove() this.pointZD.remove()
this.pointZD = null; this.pointZD = null
return return
} }
this.updatePointPosition(this.pointZD, this.form.endPoint); this.updatePointPosition(this.pointZD, this.form.endPoint)
} else if (type === 'viaPoints') { } else if (type === 'viaPoints') {
if (!row.points) { if (!row.points) {
const graphic = this.viaPoints.find(viaPoint => viaPoint.style.time === row.time); const graphic = this.viaPoints.find(
if (this.form.viaPoints.length === 1 && this.form.viaPoints[0].points === '') { (viaPoint) => viaPoint.style.time === row.time
)
if (
this.form.viaPoints.length === 1 &&
this.form.viaPoints[0].points === ''
) {
// 如果只剩下一个空项,不删除图形,清空输入框值 // 如果只剩下一个空项,不删除图形,清空输入框值
this.form.viaPoints[0].points = ''; this.form.viaPoints[0].points = ''
graphic?.remove(); graphic?.remove()
this.viaPoints = this.viaPoints.filter(viaPoint => viaPoint.style.time !== row.time); this.viaPoints = this.viaPoints.filter(
(viaPoint) => viaPoint.style.time !== row.time
)
} else { } else {
this.form.viaPoints = this.form.viaPoints.filter(viaPoint => viaPoint.time !== row.time); this.form.viaPoints = this.form.viaPoints.filter(
(viaPoint) => viaPoint.time !== row.time
)
} }
graphic?.remove(); graphic?.remove()
this.viaPoints = this.viaPoints.filter(viaPoint => viaPoint.style.time !== row.time); this.viaPoints = this.viaPoints.filter(
(viaPoint) => viaPoint.style.time !== row.time
)
} else { } else {
const graphic = this.viaPoints.find(viaPoint => viaPoint.style.time === row.time); const graphic = this.viaPoints.find(
this.updatePointPosition(graphic, row.points); (viaPoint) => viaPoint.style.time === row.time
)
this.updatePointPosition(graphic, row.points)
} }
} else if (type === 'avoidPoints') { } else if (type === 'avoidPoints') {
if (!row.points) { if (!row.points) {
const graphic = this.avoidPoints.find(avoidPoint => avoidPoint.style.time === row.time); const graphic = this.avoidPoints.find(
if (this.form.avoidPoints.length === 1 && this.form.avoidPoints[0].points === '') { (avoidPoint) => avoidPoint.style.time === row.time
)
if (
this.form.avoidPoints.length === 1 &&
this.form.avoidPoints[0].points === ''
) {
// 如果只剩下一个空项,不删除图形,清空输入框值 // 如果只剩下一个空项,不删除图形,清空输入框值
this.form.avoidPoints[0].points = ''; this.form.avoidPoints[0].points = ''
} else { } else {
this.form.avoidPoints = this.form.avoidPoints.filter(avoidPoint => avoidPoint.time !== row.time); this.form.avoidPoints = this.form.avoidPoints.filter(
(avoidPoint) => avoidPoint.time !== row.time
)
} }
graphic?.remove(); graphic?.remove()
this.avoidPoints = this.avoidPoints.filter(avoidPoint => avoidPoint.style.time !== row.time); this.avoidPoints = this.avoidPoints.filter(
(avoidPoint) => avoidPoint.style.time !== row.time
)
} else { } else {
const graphic = this.avoidPoints.find(avoidPoint => avoidPoint.style.time === row.time); const graphic = this.avoidPoints.find(
this.updatePointPosition(graphic, row.points); (avoidPoint) => avoidPoint.style.time === row.time
)
this.updatePointPosition(graphic, row.points)
} }
} else if (type === 'avoidAreas') { } else if (type === 'avoidAreas') {
if (!row.points) { if (!row.points) {
const graphic = this.avoidAreas.find(avoidArea => avoidArea.style.time === row.time); const graphic = this.avoidAreas.find(
if (this.form.avoidAreas.length === 1 && this.form.avoidAreas[0].points === '') { (avoidArea) => avoidArea.style.time === row.time
)
if (
this.form.avoidAreas.length === 1 &&
this.form.avoidAreas[0].points === ''
) {
// 如果只剩下一个空项,不删除图形,清空输入框值 // 如果只剩下一个空项,不删除图形,清空输入框值
this.form.avoidAreas[0].points = ''; this.form.avoidAreas[0].points = ''
} else { } else {
this.form.avoidAreas = this.form.avoidAreas.filter(avoidArea => avoidArea.time !== row.time); this.form.avoidAreas = this.form.avoidAreas.filter(
(avoidArea) => avoidArea.time !== row.time
)
} }
graphic?.remove(); graphic?.remove()
this.avoidAreas = this.avoidAreas.filter(avoidArea => avoidArea.style.time !== row.time); this.avoidAreas = this.avoidAreas.filter(
(avoidArea) => avoidArea.style.time !== row.time
)
} else { } else {
const graphic = this.avoidAreas.find(avoidArea => avoidArea.style.time === row.time); const graphic = this.avoidAreas.find(
this.updatePolygonPosition(graphic, row.points); (avoidArea) => avoidArea.style.time === row.time
)
this.updatePolygonPosition(graphic, row.points)
} }
} }
}, },
handleEmptyArray(type) { handleEmptyArray(type) {
if (type === 'viaPoints' && this.form.viaPoints.length === 1 && this.form.viaPoints[0].points === '') { if (
this.form.viaPoints = []; type === 'viaPoints' &&
} else if (type === 'avoidPoints' && this.form.avoidPoints.length === 1 && this.form.avoidPoints[0].points === '') { this.form.viaPoints.length === 1 &&
this.form.avoidPoints = []; this.form.viaPoints[0].points === ''
} else if (type === 'avoidAreas' && this.form.avoidAreas.length === 1 && this.form.avoidAreas[0].points === '') { ) {
this.form.avoidAreas = []; this.form.viaPoints = []
} else if (
type === 'avoidPoints' &&
this.form.avoidPoints.length === 1 &&
this.form.avoidPoints[0].points === ''
) {
this.form.avoidPoints = []
} else if (
type === 'avoidAreas' &&
this.form.avoidAreas.length === 1 &&
this.form.avoidAreas[0].points === ''
) {
this.form.avoidAreas = []
} }
}, },
updatePointPosition(graphic, pointsStr) { updatePointPosition(graphic, pointsStr) {
if (!graphic) return; if (!graphic) return
const coords = pointsStr.split(',').map(Number); const coords = pointsStr.split(',').map(Number)
if (coords.length === 2) { if (coords.length === 2) {
graphic.position = new window.mars3d.LngLatPoint(coords[0], coords[1]); graphic.position = new window.mars3d.LngLatPoint(coords[0], coords[1])
} }
}, },
updatePolygonPosition(graphic, pointsStr) { updatePolygonPosition(graphic, pointsStr) {
if (!graphic) return; if (!graphic) return
try { try {
const coords = JSON.parse(pointsStr); const coords = JSON.parse(pointsStr)
graphic.positions = coords.map(coord => new window.mars3d.LngLatPoint(coord[0], coord[1])); graphic.positions = coords.map(
(coord) => new window.mars3d.LngLatPoint(coord[0], coord[1])
)
} catch (error) { } catch (error) {
graphic.remove(); graphic.remove()
} }
}, },
drawStartPoint() { drawStartPoint() {
@ -566,7 +680,10 @@ export default {
}, },
success: (graphic) => { success: (graphic) => {
this.pointQD = graphic this.pointQD = graphic
this.form.startPoint = [graphic.toGeoJSON().geometry.coordinates[0],graphic.toGeoJSON().geometry.coordinates[1]].join(","); this.form.startPoint = [
graphic.toGeoJSON().geometry.coordinates[0],
graphic.toGeoJSON().geometry.coordinates[1],
].join(',')
}, },
}) })
}, },
@ -592,13 +709,16 @@ export default {
}, },
success: (graphic) => { success: (graphic) => {
this.pointZD = graphic this.pointZD = graphic
this.form.endPoint = [graphic.toGeoJSON().geometry.coordinates[0],graphic.toGeoJSON().geometry.coordinates[1]].join(","); this.form.endPoint = [
graphic.toGeoJSON().geometry.coordinates[0],
graphic.toGeoJSON().geometry.coordinates[1],
].join(',')
}, },
}) })
}, },
// 途径点 // 途径点
drawViaPoint() { drawViaPoint() {
const time = Date.now(); const time = Date.now()
this.graphicLayer.startDraw({ this.graphicLayer.startDraw({
type: 'point', type: 'point',
style: { style: {
@ -612,12 +732,19 @@ export default {
outlineColor: '#000000', outlineColor: '#000000',
pixelOffsetY: -20, pixelOffsetY: -20,
}, },
time: time time: time,
}, },
success: (graphic) => { success: (graphic) => {
this.viaPoints.push(graphic) this.viaPoints.push(graphic)
const points = [graphic.toGeoJSON().geometry.coordinates[0],graphic.toGeoJSON().geometry.coordinates[1]].join(",") const points = [
if(this.form.viaPoints.length == 1 && this.form.viaPoints[0].points == '' && !this.form.viaPoints[0].points){ graphic.toGeoJSON().geometry.coordinates[0],
graphic.toGeoJSON().geometry.coordinates[1],
].join(',')
if (
this.form.viaPoints.length == 1 &&
this.form.viaPoints[0].points == '' &&
!this.form.viaPoints[0].points
) {
this.form.viaPoints[0].points = points this.form.viaPoints[0].points = points
this.form.viaPoints[0].time = time this.form.viaPoints[0].time = time
} else { } else {
@ -628,7 +755,7 @@ export default {
}, },
// 避让点 // 避让点
drawAvoidPoint() { drawAvoidPoint() {
const time = Date.now(); const time = Date.now()
this.graphicLayer.startDraw({ this.graphicLayer.startDraw({
type: 'point', type: 'point',
style: { style: {
@ -642,12 +769,19 @@ export default {
outlineColor: '#000000', outlineColor: '#000000',
pixelOffsetY: -20, pixelOffsetY: -20,
}, },
time: time time: time,
}, },
success: (graphic) => { success: (graphic) => {
this.avoidPoints.push(graphic) this.avoidPoints.push(graphic)
const points = [graphic.toGeoJSON().geometry.coordinates[0],graphic.toGeoJSON().geometry.coordinates[1]].join(",") const points = [
if(this.form.avoidPoints.length == 1 && this.form.avoidPoints[0].points == '' && !this.form.avoidPoints[0].points){ graphic.toGeoJSON().geometry.coordinates[0],
graphic.toGeoJSON().geometry.coordinates[1],
].join(',')
if (
this.form.avoidPoints.length == 1 &&
this.form.avoidPoints[0].points == '' &&
!this.form.avoidPoints[0].points
) {
this.form.avoidPoints[0].points = points this.form.avoidPoints[0].points = points
this.form.avoidPoints[0].time = time this.form.avoidPoints[0].time = time
} else { } else {
@ -658,7 +792,7 @@ export default {
}, },
// 避让区域 // 避让区域
drawAvoidArea() { drawAvoidArea() {
const time = Date.now(); const time = Date.now()
this.graphicLayer.startDraw({ this.graphicLayer.startDraw({
type: 'polygon', type: 'polygon',
drawEndEventType: window.mars3d.EventType.dblClick, drawEndEventType: window.mars3d.EventType.dblClick,
@ -669,13 +803,19 @@ export default {
outline: true, outline: true,
outlineWidth: 1, outlineWidth: 1,
outlineColor: '#ffffff', outlineColor: '#ffffff',
time: time time: time,
}, },
success: (graphic) => { success: (graphic) => {
this.avoidAreas.push(graphic) this.avoidAreas.push(graphic)
const avoidAreasGeoJSON = graphic.toGeoJSON() const avoidAreasGeoJSON = graphic.toGeoJSON()
const points = JSON.stringify(avoidAreasGeoJSON.geometry.coordinates[0]) const points = JSON.stringify(
if(this.form.avoidAreas.length == 1 && this.form.avoidAreas[0].points == '' && !this.form.avoidAreas[0].points){ avoidAreasGeoJSON.geometry.coordinates[0]
)
if (
this.form.avoidAreas.length == 1 &&
this.form.avoidAreas[0].points == '' &&
!this.form.avoidAreas[0].points
) {
this.form.avoidAreas[0].points = points this.form.avoidAreas[0].points = points
this.form.avoidAreas[0].time = time this.form.avoidAreas[0].time = time
} else { } else {
@ -883,7 +1023,7 @@ export default {
}, },
}) })
this.shortestPathLayer.addGraphic(polyline) this.shortestPathLayer.addGraphic(polyline)
this.infoList = path.infoList.map(item => item.properties) this.infoList = path.infoList.map((item) => item.properties)
}, },
}, },
} }

View File

@ -2,7 +2,7 @@
<div id="page"> <div id="page">
<div class="header"> <div class="header">
<div class="images flex a-c" v-for="item in imagesList" :key="item.id"> <div class="images flex a-c" v-for="item in imagesList" :key="item.id">
<img :src="item.src" /> <img :src="item.src" @click="drawRectangle" />
<el-button <el-button
class="form-btn" class="form-btn"
type="primary" type="primary"
@ -11,7 +11,6 @@
>确定</el-button >确定</el-button
> >
</div> </div>
<el-button class="btn" type="primary" size="mini">确定</el-button>
</div> </div>
<div class="content flex j-s a-c"> <div class="content flex j-s a-c">
@ -21,12 +20,21 @@
<div class="control-panel"> <div class="control-panel">
<div class="title">范围</div> <div class="title">范围</div>
<el-form-item label="左上角"> <el-form-item label="左上角">
<el-input v-model="form.leftTop"></el-input> <el-input v-model="form.leftTop" @blur="updateArea"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="右下角"> <el-form-item label="右下角">
<el-input v-model="form.rightBottom"></el-input> <el-input v-model="form.rightBottom" @blur="updateArea">
</el-input>
</el-form-item> </el-form-item>
<div class="importJson flex j-c a-c">导入json文件</div> <input
type="file"
ref="fileInput"
@change="handleFileUpload"
style="display: none"
/>
<div class="importJson flex j-c a-c" @click="triggerFileUpload">
导入json文件
</div>
</div> </div>
<!-- 权重 --> <!-- 权重 -->
@ -85,9 +93,9 @@
v-if="roadLineList.length > 0" v-if="roadLineList.length > 0"
> >
<vxe-column type="seq" width="70"></vxe-column> <vxe-column type="seq" width="70"></vxe-column>
<vxe-column field="name" title="Name"></vxe-column> <vxe-column field="编码" title="编码"></vxe-column>
<vxe-column field="sex" title="Sex"></vxe-column> <vxe-column field="A" title="名称"></vxe-column>
<vxe-column field="age" title="Age"></vxe-column> <vxe-column field="图形特" title="图形特"></vxe-column>
</vxe-table> </vxe-table>
<!-- 水点 --> <!-- 水点 -->
<vxe-table <vxe-table
@ -126,114 +134,14 @@ export default {
data() { data() {
return { return {
imagesList: [{id: 1, src: require('@/assets/image/crop.png')}], imagesList: [{id: 1, src: require('@/assets/image/crop.png')}],
roadPointList: [ roadPointList: [],
{ roadLineList: [],
id: 10001, waterPointList: [],
name: 'Test1', waterLineList: [],
role: 'Develop',
sex: 'Man',
age: 28,
address: 'test abc',
},
{
id: 10001,
name: 'Test1',
role: 'Develop',
sex: 'Man',
age: 28,
address: 'test abc',
},
{
id: 10001,
name: 'Test1',
role: 'Develop',
sex: 'Man',
age: 28,
address: 'test abc',
},
],
roadLineList: [
{
id: 10001,
name: 'Test1',
role: 'Develop',
sex: 'Man',
age: 28,
address: 'test abc',
},
{
id: 10001,
name: 'Test1',
role: 'Develop',
sex: 'Man',
age: 28,
address: 'test abc',
},
{
id: 10001,
name: 'Test1',
role: 'Develop',
sex: 'Man',
age: 28,
address: 'test abc',
},
],
waterPointList: [
{
id: 10001,
name: 'Test1',
role: 'Develop',
sex: 'Man',
age: 28,
address: 'test abc',
},
{
id: 10001,
name: 'Test1',
role: 'Develop',
sex: 'Man',
age: 28,
address: 'test abc',
},
{
id: 10001,
name: 'Test1',
role: 'Develop',
sex: 'Man',
age: 28,
address: 'test abc',
},
],
waterLineList: [
{
id: 10001,
name: 'Test1',
role: 'Develop',
sex: 'Man',
age: 28,
address: 'test abc',
},
{
id: 10001,
name: 'Test1',
role: 'Develop',
sex: 'Man',
age: 28,
address: 'test abc',
},
{
id: 10001,
name: 'Test1',
role: 'Develop',
sex: 'Man',
age: 28,
address: 'test abc',
},
],
form: { form: {
leftTop: '114.33,27.8', leftTop: '',
rightBottom: '114.34, 27.79', rightBottom: '',
slopePer: 0.5, slopePer: 0.5,
peoplePer: 0.2, peoplePer: 0.2,
plantPer: 0.2, plantPer: 0.2,
@ -245,9 +153,12 @@ export default {
}, },
analyzing: false, analyzing: false,
rectCount: 0, rectCount: 0,
isHand: false,
selectedRect: null, selectedRect: null,
rectangles: [], rectangles: [],
labels: [],
peopleGeo: null, peopleGeo: null,
plantGeo: null, plantGeo: null,
soilGeo: null, soilGeo: null,
@ -283,22 +194,14 @@ export default {
}, },
}, },
watch: {
positions: {
deep: true,
handler(val) {
this.drawInitialArea(val)
},
},
},
mounted() { mounted() {
this.getMapJson() this.getMapJson()
this.getColorList() this.getColorList()
}, },
beforeDestroy() { beforeDestroy() {
delete window.mars3d delete window.viewer
delete window.graphicLayer
}, },
methods: { methods: {
@ -321,6 +224,46 @@ export default {
}) })
}, },
// 导入json文件
triggerFileUpload() {
this.$refs.fileInput.click()
},
handleFileUpload(event) {
const file = event.target.files[0]
if (file) {
const reader = new FileReader()
reader.onload = (e) => {
try {
const uploadedJson = JSON.parse(e.target.result)
this.importJson(uploadedJson)
} catch (error) {
console.error('解析 JSON 文件失败:', error)
this.$message.error('解析 JSON 文件失败')
}
}
reader.readAsText(file)
}
},
async importJson(uploadedJson) {
if (!uploadedJson) {
this.$message.warning('请先选择一个 JSON 文件')
return
}
// 清除现有矩形
if (
this.polygon &&
(uploadedJson?.leftTop || uploadedJson?.rightBottom)
) {
window.graphicLayer.removeGraphic(this.polygon)
}
this.form.leftTop = uploadedJson.leftTop
this.form.rightBottom = uploadedJson.rightBottom
this.drawInitialArea()
},
getColorList() { getColorList() {
this.colorList = colorMap.createColormap({ this.colorList = colorMap.createColormap({
colormap: 'jet', colormap: 'jet',
@ -342,7 +285,7 @@ export default {
window.shortestPathLayer = new window.mars3d.layer.GraphicLayer() window.shortestPathLayer = new window.mars3d.layer.GraphicLayer()
window.viewer.addLayer(window.shortestPathLayer) window.viewer.addLayer(window.shortestPathLayer)
this.drawInitialArea() // this.drawInitialArea()
this.loadGeoJson() this.loadGeoJson()
}, },
@ -375,10 +318,12 @@ export default {
} }
// 默认只加载一个,其他按需加载 // 默认只加载一个,其他按需加载
this.loadLayers(['people', 'plant', 'soil'], (results) => { // this.loadLayers(['people', 'plant', 'soil'], (results) => {
console.log('所有图层加载完成', results) // console.log('所有图层加载完成', results)
}) // })
// this.loadLayer('people') this.loadLayer('people')
this.loadLayer('plant', false)
this.loadLayer('soil', false)
}, },
createLayerConfig(url, color, type = 'polygon') { createLayerConfig(url, color, type = 'polygon') {
@ -449,7 +394,7 @@ export default {
return baseConfig return baseConfig
}, },
async loadLayer(layerName) { async loadLayer(layerName, isLoad = true) {
if (this.layers[layerName].layer) { if (this.layers[layerName].layer) {
this.layers[layerName].layer.show = !this.layers[layerName].layer.show this.layers[layerName].layer.show = !this.layers[layerName].layer.show
return return
@ -459,11 +404,11 @@ export default {
this.layers[layerName].config this.layers[layerName].config
) )
await window.viewer.addLayer(this.layers[layerName].layer) isLoad ? await window.viewer.addLayer(this.layers[layerName].layer) : null
}, },
// 新增方法:同时加载多个图层 // 新增方法:同时加载多个图层
async loadLayers(names = [], cb) { async loadLayers(names = [], cb, show = true) {
const tasks = names.map((name) => { const tasks = names.map((name) => {
const cfg = this.layers[name] const cfg = this.layers[name]
if (!cfg) return Promise.resolve(null) // 无配置直接过 if (!cfg) return Promise.resolve(null) // 无配置直接过
@ -544,14 +489,20 @@ export default {
}, },
// 判断矩形与 mars3d GeoJSON 图层是否相交(不转 GeoJSON // 判断矩形与 mars3d GeoJSON 图层是否相交(不转 GeoJSON
getIntersectId(position, layer, bufferDistance = 0.001) { getIntersectId(position, layer) {
console.log('position===>', position, layer) console.log('position===>', position, layer)
if (!position || !layer || !layer.graphics) return null if (!position || !layer || !layer.graphics) return null
const rectCoords = position.concat([position[0]]) // 闭合 const rectCoords = position.concat([position[0]]) // 闭合
console.log('rectCoords===>', rectCoords)
const rectPoly = turf.polygon([rectCoords]) const rectPoly = turf.polygon([rectCoords])
console.log('rectPoly===>', rectPoly)
const [minX, minY, maxX, maxY] = turf.bbox(rectPoly) // 矩形 bbox const [minX, minY, maxX, maxY] = turf.bbox(rectPoly) // 矩形 bbox
console.log('minX, minY, maxX, maxY===>', minX, minY, maxX, maxY)
let fc = this._polyCache.get(layer) let fc = this._polyCache.get(layer)
if (!fc) { if (!fc) {
@ -636,7 +587,13 @@ export default {
// 手动绘制矩形 // 手动绘制矩形
async drawRectangle(clampToGround) { async drawRectangle(clampToGround) {
const graphic = await window.graphicLayer.startDraw({ this.clearRectangles()
if (this.polygon) {
window.graphicLayer.removeGraphic(this.polygon)
}
this.isHand = true
let isEntityGraphic = false
this.polygon = await window.graphicLayer.startDraw({
type: isEntityGraphic ? 'rectangle' : 'rectangleP', type: isEntityGraphic ? 'rectangle' : 'rectangleP',
style: { style: {
color: clampToGround ? '#ffff00' : '#3388ff', color: clampToGround ? '#ffff00' : '#3388ff',
@ -648,7 +605,9 @@ export default {
}, },
}) })
console.log('标绘完成', graphic.toJSON()) let positions = this.polygon.toJSON().positions
this.form.leftTop = positions[0][0] + ',' + positions[0][1]
this.form.rightBottom = positions[1][0] + ',' + positions[1][1]
}, },
// 绘制矩形区域 // 绘制矩形区域
@ -660,7 +619,7 @@ export default {
Cesium.Cartesian3.fromDegrees(p[0], p[1], 0) Cesium.Cartesian3.fromDegrees(p[0], p[1], 0)
), ),
style: { style: {
color: '#00ff00', color: '#ffff00',
opacity: 0.3, opacity: 0.3,
outline: true, outline: true,
outlineColor: '#ffffff', outlineColor: '#ffffff',
@ -687,11 +646,15 @@ export default {
} }
}, },
updateArea(val) { updateArea() {
if (this.isHand) {
this.isHand = false
return
}
if (!this.polygon) return if (!this.polygon) return
// 将经纬度转换为笛卡尔坐标 // 将经纬度转换为笛卡尔坐标
const cartesianPositions = val.map((p) => const cartesianPositions = this.positions.map((p) =>
Cesium.Cartesian3.fromDegrees(p[0], p[1], 0) Cesium.Cartesian3.fromDegrees(p[0], p[1], 0)
) )
@ -703,11 +666,15 @@ export default {
this.polygon.update() this.polygon.update()
} }
console.log('区域已更新', val) console.log('区域已更新', this.positions)
}, },
// 分析平均坡度 // 分析平均坡度
async analyzeAverageSlope() { async analyzeAverageSlope() {
if (!this.form.leftTop || !this.form.rightBottom) {
return this.$message.warning('请选择范围!')
}
console.log('开始坡度分析') console.log('开始坡度分析')
this.analyzing = true this.analyzing = true
this.selectedRect = null this.selectedRect = null
@ -844,7 +811,7 @@ export default {
} }
} catch (e) { } catch (e) {
console.error('坡度分析失败', e) console.error('坡度分析失败', e)
alert('坡度分析失败,请检查地形数据') this.$message.error('坡度分析失败,请检查地形数据')
} finally { } finally {
this.drawLabelAndRec() this.drawLabelAndRec()
} }
@ -919,32 +886,26 @@ export default {
} }
/* 3. 批量创建 Graphic底层一次性构造避免反复 new */ /* 3. 批量创建 Graphic底层一次性构造避免反复 new */
const rectGraphics = rectOpts.map( this.rectangles = rectOpts.map(
(opt) => new mars3d.graphic.PolygonEntity(opt) (opt) => new mars3d.graphic.PolygonEntity(opt)
) )
const labelGraphics = labelOpts.map( this.labels = labelOpts.map((opt) => new mars3d.graphic.LabelEntity(opt))
(opt) => new mars3d.graphic.LabelEntity(opt)
)
/* 4. 一次性添加到图层mars3d 支持数组)*/ /* 4. 一次性添加到图层mars3d 支持数组)*/
window.graphicLayer.addGraphic(rectGraphics) window.graphicLayer.addGraphic(this.rectangles)
window.graphicLayer.addGraphic(labelGraphics) window.graphicLayer.addGraphic(this.labels)
/* 5. 图层级事件委托:只监听矩形图形的点击事件 */ /* 5. 图层级事件委托:只监听矩形图形的点击事件 */
window.graphicLayer.off(mars3d.EventType.click, this._selectRect, this) // 先清旧监听 window.graphicLayer.off(mars3d.EventType.click, this._selectRect, this) // 先清旧监听
// 为每个矩形图形单独绑定点击事件 // 为每个矩形图形单独绑定点击事件
rectGraphics.forEach((rectGraphic) => { this.rectangles.forEach((rectGraphic) => {
rectGraphic.on(mars3d.EventType.click, (event) => { rectGraphic.on(mars3d.EventType.click, (event) => {
this._selectRect(event) this._selectRect(event)
}) })
}) })
/* 6. 保存引用 */ /* 6. 事件处理函数 */
this.rectangles = rectGraphics
this.labels = labelGraphics
/* 7. 事件处理函数 */
this._selectRect = (event) => { this._selectRect = (event) => {
const graphic = event.graphic const graphic = event.graphic
// 确保只有矩形图形会触发选择 // 确保只有矩形图形会触发选择
@ -952,6 +913,7 @@ export default {
this.selectRectangle(graphic) this.selectRectangle(graphic)
} }
} }
this.$message.success('计算成功!')
}, },
/** /**
@ -1058,15 +1020,11 @@ export default {
id: rect.id, id: rect.id,
center: rect.center, center: rect.center,
} }
if (!this.roadPointGeo) {
this.loadLayer('roadPoint') this.roadPointList = []
} else if (!this.roadLineGeo) { this.roadLineList = []
this.loadLayer('roadLine') this.waterPointList = []
} else if (!this.waterPointGeo) { this.waterLineList = []
this.loadLayer('waterPoint')
} else if (!this.waterLineGeo) {
this.loadLayer('waterLine')
}
if (!this.roadWaterLock) { if (!this.roadWaterLock) {
this.loadLayers( this.loadLayers(
@ -1082,38 +1040,69 @@ export default {
}, },
getRoadWaterIds(rect) { getRoadWaterIds(rect) {
const positions = rect.points.map((d) => [d.lng, d.lat])
let roadPointId = this.getIntersectId( let roadPointId = this.getIntersectId(
rect.points, positions,
this.layers['roadPoint'].layer this.layers['roadPoint'].layer
) )
let roadLineId = this.getIntersectId( let roadLineId = this.getIntersectId(
rect.points, positions,
this.layers['roadLine'].layer this.layers['roadLine'].layer
) )
let waterPointId = this.getIntersectId( let waterPointId = this.getIntersectId(
rect.points, positions,
this.layers['waterPoint'].layer this.layers['waterPoint'].layer
) )
let waterLineId = this.getIntersectId( let waterLineId = this.getIntersectId(
rect.points, positions,
this.layers['waterLine'].layer this.layers['waterLine'].layer
) )
if (roadPointId) {
this.roadPointList.push(
this.layers['roadPoint'].layer.getGraphicById(roadPointId).options
.attr
)
} else if (roadLineId) {
this.roadLineList.push(
this.layers['roadLine'].layer.getGraphicById(roadLineId).options.attr
)
} else if (waterPointId) {
this.waterPointList.push(
this.layers['waterPoint'].layer.getGraphicById(waterPointId).options
.attr
)
} else if (waterLineId) {
this.waterLineList.push(
this.layers['waterLine'].layer.getGraphicById(waterLineId).options
.attr
)
}
console.log( console.log(
'roadPointId===>', 'roadPointId===>',
roadPointId, this.roadPointList,
roadLineId, this.roadLineList,
waterPointId, this.waterPointList,
waterLineId this.waterLineList
) )
}, },
// 清除所有矩形 // 清除所有矩形
clearRectangles() { clearRectangles() {
if (this.rectangles.length > 0) {
this.rectangles.forEach((rect) => { this.rectangles.forEach((rect) => {
window.graphicLayer.removeGraphic(rect) window.graphicLayer.removeGraphic(rect)
}) })
}
if (this.labels.length > 0) {
this.labels.forEach((label) => {
window.graphicLayer.removeGraphic(label)
})
}
this.rectangles = [] this.rectangles = []
this.labels = []
}, },
}, },
} }
@ -1202,6 +1191,7 @@ export default {
width: 452px; width: 452px;
height: 100%; height: 100%;
background-color: #d4e5db; background-color: #d4e5db;
padding-left: 20px;
overflow: auto; overflow: auto;
.item { .item {