|
|
@@ -558,57 +558,364 @@ export default {
|
|
|
},
|
|
|
|
|
|
// 路网导出
|
|
|
- handleNetworkExport() {
|
|
|
- // 实际的导出逻辑应该在这里实现
|
|
|
- setTimeout(() => {
|
|
|
+ async handleNetworkExport() {
|
|
|
+ try {
|
|
|
+ // 检查是否有路网数据可导出
|
|
|
+ if (!this.resourcesFeature || this.resourcesFeature.length === 0) {
|
|
|
+ this.$message.warning('当前地图没有路网数据可导出');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 显示导出进度
|
|
|
+ const loading = this.$loading({
|
|
|
+ lock: true,
|
|
|
+ text: '正在准备导出数据...',
|
|
|
+ spinner: 'el-icon-loading',
|
|
|
+ background: 'rgba(0, 0, 0, 0.7)'
|
|
|
+ });
|
|
|
+
|
|
|
try {
|
|
|
- // TODO: 实现实际的路网导出逻辑
|
|
|
- // 这里可以调用后端API或者生成文件下载
|
|
|
- console.log('导出路网数据...');
|
|
|
- // 成功后不需要再显示消息,因为RightPanel已经处理了
|
|
|
- } catch (error) {
|
|
|
- this.$message.error('路网导出失败:' + error.message);
|
|
|
+ // 构建导出的GeoJSON数据
|
|
|
+ const geoJsonData = this.buildGeoJsonData();
|
|
|
+
|
|
|
+ // 添加导出时间戳和元数据
|
|
|
+ const exportData = {
|
|
|
+ ...geoJsonData,
|
|
|
+ metadata: {
|
|
|
+ exportTime: new Date().toISOString(),
|
|
|
+ mapName: this.mapName,
|
|
|
+ elementCount: geoJsonData.features.length,
|
|
|
+ version: '1.0'
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // 创建文件内容
|
|
|
+ const fileContent = JSON.stringify(exportData, null, 2);
|
|
|
+ const blob = new Blob([fileContent], { type: 'application/json' });
|
|
|
+
|
|
|
+ // 生成文件名
|
|
|
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
|
|
|
+ const fileName = `roadmap_${this.mapName}_${timestamp}.json`;
|
|
|
+
|
|
|
+ // 创建下载链接
|
|
|
+ const url = window.URL.createObjectURL(blob);
|
|
|
+ const link = document.createElement('a');
|
|
|
+ link.href = url;
|
|
|
+ link.download = fileName;
|
|
|
+
|
|
|
+ // 触发下载
|
|
|
+ document.body.appendChild(link);
|
|
|
+ link.click();
|
|
|
+ document.body.removeChild(link);
|
|
|
+
|
|
|
+ // 清理URL对象
|
|
|
+ window.URL.revokeObjectURL(url);
|
|
|
+
|
|
|
+ this.$message.success(`路网数据已导出:${fileName}`);
|
|
|
+ } finally {
|
|
|
+ loading.close();
|
|
|
}
|
|
|
- }, 200);
|
|
|
+ } catch (error) {
|
|
|
+ console.error('路网导出失败:', error);
|
|
|
+ this.$message.error('路网导出失败:' + (error.message || '未知错误'));
|
|
|
+ }
|
|
|
},
|
|
|
|
|
|
// 路网导入
|
|
|
handleNetworkImport(type) {
|
|
|
- // 实际的导入逻辑应该在这里实现
|
|
|
- setTimeout(() => {
|
|
|
+ const typeMap = {
|
|
|
+ 'import': '导入',
|
|
|
+ 'replace': '覆盖导入',
|
|
|
+ 'merge': '合并导入',
|
|
|
+ 'incremental': '增量导入'
|
|
|
+ };
|
|
|
+
|
|
|
+ // 创建文件输入元素
|
|
|
+ const fileInput = document.createElement('input');
|
|
|
+ fileInput.type = 'file';
|
|
|
+ fileInput.accept = '.json';
|
|
|
+ fileInput.style.display = 'none';
|
|
|
+
|
|
|
+ // 文件选择处理
|
|
|
+ fileInput.addEventListener('change', async (event) => {
|
|
|
+ const file = event.target.files[0];
|
|
|
+ if (!file) return;
|
|
|
+
|
|
|
try {
|
|
|
- const typeMap = {
|
|
|
- 'import': '导入',
|
|
|
- 'replace': '覆盖导入',
|
|
|
- 'merge': '合并导入',
|
|
|
- 'incremental': '增量导入'
|
|
|
- };
|
|
|
-
|
|
|
- // TODO: 实现实际的路网导入逻辑
|
|
|
- // 这里可以调用后端API或者打开文件选择对话框
|
|
|
- console.log(`${typeMap[type] || '导入'}路网数据...`, type);
|
|
|
-
|
|
|
- // 根据不同类型执行不同的导入策略
|
|
|
- switch (type) {
|
|
|
- case 'import':
|
|
|
- // 普通导入逻辑
|
|
|
- break;
|
|
|
- case 'replace':
|
|
|
- // 覆盖导入:先清空现有数据,再导入新数据
|
|
|
- break;
|
|
|
- case 'merge':
|
|
|
- // 合并导入:保留现有数据,添加新数据
|
|
|
- break;
|
|
|
- case 'incremental':
|
|
|
- // 增量导入:只导入不存在的新元素
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- // 成功后不需要再显示消息,因为RightPanel已经处理了
|
|
|
+ await this.processImportFile(file, type, typeMap[type] || '导入');
|
|
|
} catch (error) {
|
|
|
- this.$message.error(`路网${typeMap[type] || '导入'}失败:` + error.message);
|
|
|
+ console.error('导入处理失败:', error);
|
|
|
+ this.$message.error(`路网${typeMap[type] || '导入'}失败:` + (error.message || '未知错误'));
|
|
|
+ } finally {
|
|
|
+ // 清理文件输入元素
|
|
|
+ document.body.removeChild(fileInput);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // 添加到页面并触发点击
|
|
|
+ document.body.appendChild(fileInput);
|
|
|
+ fileInput.click();
|
|
|
+ },
|
|
|
+
|
|
|
+ // 处理导入文件
|
|
|
+ async processImportFile(file, importType, typeName) {
|
|
|
+ // 显示加载进度
|
|
|
+ const loading = this.$loading({
|
|
|
+ lock: true,
|
|
|
+ text: `正在${typeName}路网数据...`,
|
|
|
+ spinner: 'el-icon-loading',
|
|
|
+ background: 'rgba(0, 0, 0, 0.7)'
|
|
|
+ });
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 读取文件内容
|
|
|
+ const fileContent = await this.readFileContent(file);
|
|
|
+
|
|
|
+ // 解析JSON数据
|
|
|
+ let importData;
|
|
|
+ try {
|
|
|
+ importData = JSON.parse(fileContent);
|
|
|
+ } catch (parseError) {
|
|
|
+ throw new Error('文件格式错误:无法解析JSON数据');
|
|
|
}
|
|
|
- }, 200);
|
|
|
+
|
|
|
+ // 验证数据格式
|
|
|
+ this.validateImportData(importData);
|
|
|
+
|
|
|
+ // 根据不同导入类型执行相应策略
|
|
|
+ await this.executeImportStrategy(importData, importType);
|
|
|
+
|
|
|
+ // 刷新地图显示
|
|
|
+ await this.refreshMapAfterImport();
|
|
|
+
|
|
|
+ // 保存到服务器
|
|
|
+ await this.saveRoute();
|
|
|
+
|
|
|
+ this.$message.success(`路网${typeName}成功!共处理${importData.features.length}个元素`);
|
|
|
+ } finally {
|
|
|
+ loading.close();
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 读取文件内容
|
|
|
+ readFileContent(file) {
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
+ const reader = new FileReader();
|
|
|
+ reader.onload = e => resolve(e.target.result);
|
|
|
+ reader.onerror = () => reject(new Error('文件读取失败'));
|
|
|
+ reader.readAsText(file);
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ // 验证导入数据格式
|
|
|
+ validateImportData(data) {
|
|
|
+ // 检查基本结构
|
|
|
+ if (!data || typeof data !== 'object') {
|
|
|
+ throw new Error('无效的数据格式');
|
|
|
+ }
|
|
|
+
|
|
|
+ if (data.type !== 'FeatureCollection') {
|
|
|
+ throw new Error('数据类型错误:期望FeatureCollection格式');
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!Array.isArray(data.features)) {
|
|
|
+ throw new Error('数据格式错误:缺少features数组');
|
|
|
+ }
|
|
|
+
|
|
|
+ if (data.features.length === 0) {
|
|
|
+ throw new Error('导入文件中没有路网元素');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 验证每个feature的格式
|
|
|
+ data.features.forEach((feature, index) => {
|
|
|
+ if (!feature.type || feature.type !== 'Feature') {
|
|
|
+ throw new Error(`第${index + 1}个元素格式错误:不是有效的Feature`);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!feature.properties || !feature.properties.id) {
|
|
|
+ throw new Error(`第${index + 1}个元素缺少ID属性`);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!feature.geometry || !feature.geometry.type) {
|
|
|
+ throw new Error(`第${index + 1}个元素缺少几何信息`);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ // 执行不同的导入策略
|
|
|
+ async executeImportStrategy(importData, importType) {
|
|
|
+ const features = importData.features;
|
|
|
+
|
|
|
+ switch (importType) {
|
|
|
+ case 'replace':
|
|
|
+ // 覆盖导入:清空现有数据,导入新数据
|
|
|
+ await this.replaceImport(features);
|
|
|
+ break;
|
|
|
+ case 'merge':
|
|
|
+ // 合并导入:保留现有数据,添加新数据(处理ID冲突)
|
|
|
+ await this.mergeImport(features);
|
|
|
+ break;
|
|
|
+ case 'incremental':
|
|
|
+ // 增量导入:只导入不存在的新元素
|
|
|
+ await this.incrementalImport(features);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ // 普通导入:直接添加到现有数据
|
|
|
+ await this.normalImport(features);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 覆盖导入
|
|
|
+ async replaceImport(features) {
|
|
|
+ // 清空现有数据
|
|
|
+ this.clearAllMapElements();
|
|
|
+
|
|
|
+ // 导入新数据
|
|
|
+ await this.importFeaturesToMap(features);
|
|
|
+ },
|
|
|
+
|
|
|
+ // 合并导入
|
|
|
+ async mergeImport(features) {
|
|
|
+ const conflictFeatures = [];
|
|
|
+ const newFeatures = [];
|
|
|
+
|
|
|
+ // 检查ID冲突
|
|
|
+ features.forEach(feature => {
|
|
|
+ const existingFeature = this.resourcesFeature.find(f => f.getId() === feature.properties.id);
|
|
|
+ if (existingFeature) {
|
|
|
+ conflictFeatures.push(feature);
|
|
|
+ } else {
|
|
|
+ newFeatures.push(feature);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // 处理冲突
|
|
|
+ if (conflictFeatures.length > 0) {
|
|
|
+ const conflictIds = conflictFeatures.map(f => f.properties.id).join(', ');
|
|
|
+ const result = await this.$confirm(
|
|
|
+ `发现${conflictFeatures.length}个ID冲突的元素:${conflictIds}。是否覆盖现有元素?`,
|
|
|
+ 'ID冲突处理',
|
|
|
+ {
|
|
|
+ confirmButtonText: '覆盖现有',
|
|
|
+ cancelButtonText: '跳过冲突',
|
|
|
+ type: 'warning'
|
|
|
+ }
|
|
|
+ );
|
|
|
+
|
|
|
+ if (result) {
|
|
|
+ // 覆盖冲突的元素
|
|
|
+ await this.replaceConflictFeatures(conflictFeatures);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 导入新元素
|
|
|
+ if (newFeatures.length > 0) {
|
|
|
+ await this.importFeaturesToMap(newFeatures);
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 增量导入
|
|
|
+ async incrementalImport(features) {
|
|
|
+ const newFeatures = features.filter(feature => {
|
|
|
+ return !this.resourcesFeature.find(f => f.getId() === feature.properties.id);
|
|
|
+ });
|
|
|
+
|
|
|
+ if (newFeatures.length === 0) {
|
|
|
+ this.$message.info('所有元素均已存在,无需导入');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ await this.importFeaturesToMap(newFeatures);
|
|
|
+ this.$message.info(`跳过${features.length - newFeatures.length}个已存在的元素`);
|
|
|
+ },
|
|
|
+
|
|
|
+ // 普通导入
|
|
|
+ async normalImport(features) {
|
|
|
+ await this.importFeaturesToMap(features);
|
|
|
+ },
|
|
|
+
|
|
|
+ // 清空所有地图元素
|
|
|
+ clearAllMapElements() {
|
|
|
+ if (this.$refs.olmap && this.$refs.olmap.clearAllElements) {
|
|
|
+ this.$refs.olmap.clearAllElements();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 清空数据数组
|
|
|
+ this.pointData = [];
|
|
|
+ this.lineData = [];
|
|
|
+ this.bowData = [];
|
|
|
+ this.shapeData = [];
|
|
|
+ this.resourcesFeature = [];
|
|
|
+ this.currentFeature = {};
|
|
|
+ },
|
|
|
+
|
|
|
+ // 替换冲突的特征
|
|
|
+ async replaceConflictFeatures(conflictFeatures) {
|
|
|
+ for (const feature of conflictFeatures) {
|
|
|
+ // 删除现有元素
|
|
|
+ if (this.$refs.olmap && this.$refs.olmap.removeElement) {
|
|
|
+ this.$refs.olmap.removeElement(feature.properties.id);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 从数据数组中删除
|
|
|
+ this.removeFeatureFromArrays(feature.properties.id);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 导入新的特征
|
|
|
+ await this.importFeaturesToMap(conflictFeatures);
|
|
|
+ },
|
|
|
+
|
|
|
+ // 从数据数组中删除特征
|
|
|
+ removeFeatureFromArrays(id) {
|
|
|
+ const removeFromArray = (array) => {
|
|
|
+ const index = array.findIndex(item => item.id === id);
|
|
|
+ if (index !== -1) {
|
|
|
+ array.splice(index, 1);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ if (id.startsWith('p')) {
|
|
|
+ removeFromArray(this.pointData);
|
|
|
+ } else if (id.startsWith('l')) {
|
|
|
+ removeFromArray(this.lineData);
|
|
|
+ } else if (id.startsWith('b')) {
|
|
|
+ removeFromArray(this.bowData);
|
|
|
+ } else if (id.startsWith('s')) {
|
|
|
+ removeFromArray(this.shapeData);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 从resourcesFeature中删除
|
|
|
+ const index = this.resourcesFeature.findIndex(f => f.getId() === id);
|
|
|
+ if (index !== -1) {
|
|
|
+ this.resourcesFeature.splice(index, 1);
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 将特征导入到地图
|
|
|
+ async importFeaturesToMap(features) {
|
|
|
+ if (!this.$refs.olmap || !this.$refs.olmap.importGeoJsonFeatures) {
|
|
|
+ throw new Error('地图组件未就绪,无法导入数据');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 调用地图组件的导入方法
|
|
|
+ const geoJsonData = {
|
|
|
+ type: 'FeatureCollection',
|
|
|
+ features: features
|
|
|
+ };
|
|
|
+
|
|
|
+ await this.$refs.olmap.importGeoJsonFeatures(geoJsonData);
|
|
|
+ },
|
|
|
+
|
|
|
+ // 导入后刷新地图
|
|
|
+ async refreshMapAfterImport() {
|
|
|
+ // 等待地图组件处理完成
|
|
|
+ await this.$nextTick();
|
|
|
+
|
|
|
+ // 如果地图组件有刷新方法,调用它
|
|
|
+ if (this.$refs.olmap && this.$refs.olmap.refresh) {
|
|
|
+ this.$refs.olmap.refresh();
|
|
|
+ }
|
|
|
},
|
|
|
|
|
|
// === Inspector事件处理 ===
|
|
|
@@ -826,11 +1133,13 @@ export default {
|
|
|
}
|
|
|
});
|
|
|
// 对分类后的数组按数字部分排序
|
|
|
- this.pointData.sort((a, b) => parseInt(a.id.split('_')[1]) - parseInt(b.id.split('_')[1]));
|
|
|
- this.lineData.sort((a, b) => parseInt(a.id.split('_')[1]) - parseInt(b.id.split('_')[1]));
|
|
|
- this.bowData.sort((a, b) => parseInt(a.id.split('_')[1]) - parseInt(b.id.split('_')[1]));
|
|
|
- this.shapeData.sort((a, b) => parseInt(a.id.split('_')[1]) - parseInt(b.id.split('_')[1]));
|
|
|
- this.resourcesFeature = features;
|
|
|
+ this.pointData.sort((a, b) => parseInt(a.id.split('_')[1]) - parseInt(b.id.split('_')[1]));
|
|
|
+ this.lineData.sort((a, b) => parseInt(a.id.split('_')[1]) - parseInt(b.id.split('_')[1]));
|
|
|
+ this.bowData.sort((a, b) => parseInt(a.id.split('_')[1]) - parseInt(b.id.split('_')[1]));
|
|
|
+ this.shapeData.sort((a, b) => parseInt(a.id.split('_')[1]) - parseInt(b.id.split('_')[1]));
|
|
|
+ // 过滤掉null值,确保resourcesFeature数组中只包含有效的feature对象
|
|
|
+ this.resourcesFeature = features.filter(feature => feature !== null && feature !== undefined && typeof feature.getGeometry === 'function');
|
|
|
+ console.log(`elementRoadInitEnd: 原始feature数量=${features.length}, 有效feature数量=${this.resourcesFeature.length}`);
|
|
|
},
|
|
|
// 某个元素绘制完成的回调
|
|
|
elementRoadDrawEnd(feature) {
|
|
|
@@ -950,7 +1259,7 @@ export default {
|
|
|
}
|
|
|
|
|
|
// 删除源features中的此元素
|
|
|
- const index = this.resourcesFeature.findIndex(feature => feature.getId() == id);
|
|
|
+ const index = this.resourcesFeature.findIndex(feature => feature && feature.getId && feature.getId() == id);
|
|
|
if (index !== -1) {
|
|
|
console.log('从resourcesFeature中删除元素:', id);
|
|
|
this.resourcesFeature.splice(index, 1);
|
|
|
@@ -959,6 +1268,9 @@ export default {
|
|
|
console.warn('在resourcesFeature中找不到要删除的元素:', id);
|
|
|
}
|
|
|
|
|
|
+ // 清理可能存在的null值
|
|
|
+ this.resourcesFeature = this.resourcesFeature.filter(feature => feature !== null && feature !== undefined && typeof feature.getGeometry === 'function');
|
|
|
+
|
|
|
this.haveDraw = true;
|
|
|
},
|
|
|
// 初始化点位元素基础和高级参数
|
|
|
@@ -969,9 +1281,14 @@ export default {
|
|
|
feature.set('isyawfix', feature.get('isyawfix') ? true : false); // 偏航使能
|
|
|
feature.set('taskid', 0);
|
|
|
feature.set('offset', 0);
|
|
|
- feature.set('pitch', 0)
|
|
|
- feature.set('roll', 0)
|
|
|
+ feature.set('pitch', 0)
|
|
|
+ feature.set('roll', 0)
|
|
|
+ // 验证feature有效性后再添加
|
|
|
+ if (feature && typeof feature.getGeometry === 'function') {
|
|
|
this.resourcesFeature.push(feature);
|
|
|
+ } else {
|
|
|
+ console.warn('尝试添加无效的point feature:', feature);
|
|
|
+ }
|
|
|
},
|
|
|
// 初始化执行元素基础和高级参数
|
|
|
initElelmentParamsBowOrLine(feature) {
|
|
|
@@ -998,9 +1315,14 @@ export default {
|
|
|
feature.set('e2sforward', 0) // 机器人沿当前线段从终点到达起点时多行驶的距离,单位为米,默认为0
|
|
|
feature.set('thtolerance', 0) // 角度容差
|
|
|
feature.set('mintheta', 0) // 最小转向角
|
|
|
- feature.set('maxtheta', 1) // 最大转向角
|
|
|
+ feature.set('maxtheta', 1) // 最大转向角
|
|
|
|
|
|
+ // 验证feature有效性后再添加
|
|
|
+ if (feature && typeof feature.getGeometry === 'function') {
|
|
|
this.resourcesFeature.push(feature);
|
|
|
+ } else {
|
|
|
+ console.warn('尝试添加无效的line/bow feature:', feature);
|
|
|
+ }
|
|
|
},
|
|
|
// 初始化面元素基础和高级参数
|
|
|
initElelmentParamsSnape(feature) {
|
|
|
@@ -1011,9 +1333,14 @@ export default {
|
|
|
// 2:禁行区域,不允许机器人进入该区域;3:会车管制区,特定场景使用;
|
|
|
// 4:道闸管控区,特定场景使用;11:GPS定位区,进入该区域后,从激光定位切换到GPS定位;
|
|
|
// 22:动态禁行区,特定场景使用。
|
|
|
- feature.set('type', 1);
|
|
|
- feature.set('transparent', 200);
|
|
|
+ feature.set('type', 1);
|
|
|
+ feature.set('transparent', 200);
|
|
|
+ // 验证feature有效性后再添加
|
|
|
+ if (feature && typeof feature.getGeometry === 'function') {
|
|
|
this.resourcesFeature.push(feature);
|
|
|
+ } else {
|
|
|
+ console.warn('尝试添加无效的shape feature:', feature);
|
|
|
+ }
|
|
|
},
|
|
|
/**
|
|
|
* 点位坐标修改
|
|
|
@@ -1100,6 +1427,26 @@ export default {
|
|
|
}
|
|
|
},
|
|
|
|
|
|
+ // 清理坐标数据,将null值替换为0
|
|
|
+ cleanCoordinates(coordinates) {
|
|
|
+ if (!coordinates) return coordinates;
|
|
|
+
|
|
|
+ // 递归处理多维数组
|
|
|
+ if (Array.isArray(coordinates)) {
|
|
|
+ return coordinates.map(coord => {
|
|
|
+ if (Array.isArray(coord)) {
|
|
|
+ // 如果是嵌套数组,递归处理
|
|
|
+ return this.cleanCoordinates(coord);
|
|
|
+ } else {
|
|
|
+ // 如果是数值,将null或undefined替换为0
|
|
|
+ return (coord === null || coord === undefined) ? 0 : coord;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ return coordinates;
|
|
|
+ },
|
|
|
+
|
|
|
// 构建GeoJSON数据
|
|
|
buildGeoJsonData() {
|
|
|
// 验证resourcesFeature数组
|
|
|
@@ -1112,12 +1459,22 @@ export default {
|
|
|
};
|
|
|
}
|
|
|
|
|
|
- console.log('构建GeoJSON数据,元素数量:', this.resourcesFeature.length);
|
|
|
-
|
|
|
- const features = this.resourcesFeature.map(feature => {
|
|
|
- try {
|
|
|
- const properties = { ...feature.getProperties() };
|
|
|
- const geometry = feature.getGeometry();
|
|
|
+ console.log('构建GeoJSON数据,元素数量:', this.resourcesFeature.length);
|
|
|
+
|
|
|
+ // 首先过滤掉null或undefined的feature对象
|
|
|
+ const validFeatures = this.resourcesFeature.filter(feature => feature !== null && feature !== undefined);
|
|
|
+ console.log('有效元素数量:', validFeatures.length);
|
|
|
+
|
|
|
+ const features = validFeatures.map(feature => {
|
|
|
+ try {
|
|
|
+ // 再次确认feature是有效的
|
|
|
+ if (!feature || typeof feature.getProperties !== 'function') {
|
|
|
+ console.warn('发现无效的feature对象:', feature);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ const properties = { ...feature.getProperties() };
|
|
|
+ const geometry = feature.getGeometry();
|
|
|
|
|
|
// 验证几何对象
|
|
|
if (!geometry) {
|
|
|
@@ -1137,12 +1494,16 @@ export default {
|
|
|
delete cleanProperties.directList; // 删除临时方向列表属性
|
|
|
delete cleanProperties.geometry; // 删除OpenLayers几何对象,避免嵌套
|
|
|
|
|
|
+ // 获取原始坐标并清理null值
|
|
|
+ const originalCoordinates = geometry.getCoordinates();
|
|
|
+ const cleanedCoordinates = this.cleanCoordinates(originalCoordinates);
|
|
|
+
|
|
|
return {
|
|
|
type: "Feature",
|
|
|
properties: cleanProperties,
|
|
|
geometry: {
|
|
|
type: geometry.getType(),
|
|
|
- coordinates: geometry.getCoordinates()
|
|
|
+ coordinates: cleanedCoordinates
|
|
|
}
|
|
|
};
|
|
|
} catch (error) {
|
|
|
@@ -1214,8 +1575,8 @@ export default {
|
|
|
{ yaw: this.currentRobotRecord.angle },
|
|
|
{ isyawfix: this.currentRobotRecord.angleEnable }
|
|
|
];
|
|
|
- this.$refs.olmap && this.$refs.olmap.createPointAtCoordinate &&
|
|
|
- this.$refs.olmap.createPointAtCoordinate(
|
|
|
+ this.$refs.olmap && this.$refs.olmap.createPointAtCoordinateForImport &&
|
|
|
+ this.$refs.olmap.createPointAtCoordinateForImport(
|
|
|
[this.currentRobotRecord.x, this.currentRobotRecord.y, this.currentRobotRecord.z || 0],
|
|
|
'',
|
|
|
data
|