diff --git a/ruoyi-ui/.env.development b/ruoyi-ui/.env.development
index 0e7127a..4d098ba 100644
--- a/ruoyi-ui/.env.development
+++ b/ruoyi-ui/.env.development
@@ -8,7 +8,7 @@ ENV = 'development'
VUE_APP_BASE_API = '/dev-api'
# 访问地址(绕过 /dev-api 代理,用于解决静态资源/图片访问 401 认证问题)
-VUE_APP_BACKEND_URL = 'http://127.0.0.1:8080'
+VUE_APP_BACKEND_URL = 'http://localhost:8080'
# 路由懒加载
VUE_CLI_BABEL_TRANSPILE_MODULES = true
diff --git a/ruoyi-ui/src/views/cesiumMap/ContextMenu.vue b/ruoyi-ui/src/views/cesiumMap/ContextMenu.vue
index 65487ff..796c828 100644
--- a/ruoyi-ui/src/views/cesiumMap/ContextMenu.vue
+++ b/ruoyi-ui/src/views/cesiumMap/ContextMenu.vue
@@ -148,7 +148,7 @@
@@ -307,7 +307,7 @@ export default {
],
presetWidths: [1, 2, 3, 4, 5, 6, 8, 10, 12],
presetSizes: [6, 8, 10, 12, 14, 16, 18, 20, 24],
- presetOpacities: [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0],
+ presetOpacities: [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0],
presetFontSizes: [8, 10, 12, 14, 16, 18, 20, 24, 28, 32]
}
},
diff --git a/ruoyi-ui/src/views/cesiumMap/MeasurementPanel.vue b/ruoyi-ui/src/views/cesiumMap/MeasurementPanel.vue
index d09f8d4..703075d 100644
--- a/ruoyi-ui/src/views/cesiumMap/MeasurementPanel.vue
+++ b/ruoyi-ui/src/views/cesiumMap/MeasurementPanel.vue
@@ -8,7 +8,7 @@
面积:
- {{ result.area.toFixed(2) }} 平方米
+ {{ (result.area / 1000000).toFixed(2) }} 平方千米
半径:
diff --git a/ruoyi-ui/src/views/cesiumMap/index.vue b/ruoyi-ui/src/views/cesiumMap/index.vue
index 552d41d..9843259 100644
--- a/ruoyi-ui/src/views/cesiumMap/index.vue
+++ b/ruoyi-ui/src/views/cesiumMap/index.vue
@@ -156,10 +156,10 @@ export default {
defaultStyles: {
point: { color: '#FF0000', size: 12 },
line: { color: '#00FF00', width: 3 },
- polygon: { color: '#0000FF', opacity: 0.5, width: 2 },
- rectangle: { color: '#FFA500', opacity: 0.3, width: 2 },
- circle: { color: '#800080', opacity: 0.4, width: 2 },
- sector: { color: '#FF6347', opacity: 0.5, width: 2 },
+ polygon: { color: '#0000FF', opacity: 0, width: 4 },
+ rectangle: { color: '#FFA500', opacity: 0, width: 4 },
+ circle: { color: '#800080', opacity: 0, width: 4 },
+ sector: { color: '#FF6347', opacity: 0, width: 3 },
arrow: { color: '#FF0000', width: 6 },
text: { color: '#000000', font: '48px Microsoft YaHei, PingFang SC, sans-serif', backgroundColor: 'rgba(255, 255, 255, 0.8)' },
image: { width: 150, height: 150 }
@@ -200,60 +200,60 @@ export default {
methods: {
updateScaleFromConfig(config) {
if (!config || !this.viewer) return
-
+
const { scaleNumerator, scaleDenominator, unit } = config
if (!scaleDenominator || scaleDenominator <= 0) return
-
+
let displayValue = ''
let metersPerPixel = 0
-
+
const standardDPI = 96
const pixelsPerCm = standardDPI * 0.393701
-
+
const scaleFactor = scaleDenominator / scaleNumerator
-
+
switch (unit) {
case 'm':
- displayValue = `1:${scaleDenominator}`
+ displayValue = `${scaleDenominator}`
metersPerPixel = scaleFactor / pixelsPerCm
break
case 'km':
- displayValue = `1:${scaleDenominator}`
+ displayValue = `${scaleDenominator}`
metersPerPixel = (scaleFactor * 1000) / pixelsPerCm
break
default:
- displayValue = `1:${scaleDenominator}`
+ displayValue = `${scaleDenominator}`
metersPerPixel = scaleFactor / pixelsPerCm
}
-
+
console.log('比例尺设置:', displayValue, '每像素米数:', metersPerPixel.toFixed(4))
-
+
this.isApplyingScale = true
this.useCustomScale = true
this.customScaleText = displayValue
this.currentScaleUnit = unit
-
+
this.applyScaleToCamera(metersPerPixel)
this.updateScaleBar()
this.$forceUpdate()
-
+
setTimeout(() => {
this.isApplyingScale = false
}, 1000)
},
-
+
applyScaleToCamera(metersPerPixel) {
if (!this.viewer || !this.viewer.camera) return
-
+
const canvas = this.viewer.scene.canvas
const width = canvas.clientWidth
const height = canvas.clientHeight
-
+
if (width <= 0 || height <= 0) return
-
+
const camera = this.viewer.camera
const scene = this.viewer.scene
-
+
if (scene.mode === Cesium.SceneMode.SCENE2D) {
const frustumWidth = width * metersPerPixel
camera.frustum.right = frustumWidth / 2
@@ -264,19 +264,19 @@ export default {
} else {
const cameraPosition = camera.positionCartographic
const groundWidth = width * metersPerPixel
-
+
const fov = camera.frustum.fov || Cesium.Math.PI_OVER_THREE
const aspectRatio = width / height
const verticalFov = fov / aspectRatio
-
+
const targetHeight = (groundWidth / 2) / Math.tan(fov / 2)
-
+
const destination = Cesium.Cartesian3.fromRadians(
cameraPosition.longitude,
cameraPosition.latitude,
targetHeight
)
-
+
camera.flyTo({
destination: destination,
duration: 0.5,
@@ -1375,15 +1375,28 @@ export default {
const bearing = bearingType === 'magnetic'
? this.calculateMagneticBearing(currentSegmentPositions)
: this.calculateTrueBearing(currentSegmentPositions);
- // 显示小框提示
- this.hoverTooltip = {
- visible: true,
- content: `累计长度:${cumulativeLength.toFixed(2)} 米\n${bearingType === 'magnetic' ? '磁方位' : '真方位'}:${bearing.toFixed(2)}°`,
- position: {
- x: movement.endPosition.x + 10,
- y: movement.endPosition.y - 10
- }
- };
+ // 根据工具模式决定显示格式
+ if (this.toolMode === 'ranging') {
+ // 测距模式:使用千米,简化格式
+ this.hoverTooltip = {
+ visible: true,
+ content: `${(cumulativeLength / 1000).toFixed(1)}km ,${bearingType === 'magnetic' ? '磁' : '真'}:${bearing.toFixed(1)}°`,
+ position: {
+ x: movement.endPosition.x + 10,
+ y: movement.endPosition.y - 10
+ }
+ };
+ } else {
+ // 空域模式:使用米,完整格式
+ this.hoverTooltip = {
+ visible: true,
+ content: `累计长度:${cumulativeLength.toFixed(2)} 米\n${bearingType === 'magnetic' ? '磁方位' : '真方位'}:${bearing.toFixed(2)}°`,
+ position: {
+ x: movement.endPosition.x + 10,
+ y: movement.endPosition.y - 10
+ }
+ };
+ }
} else {
// 如果没有找到对应的段,隐藏信息
this.hoverTooltip.visible = false;
@@ -1669,15 +1682,28 @@ export default {
const length = this.calculateLineLength(tempPositions);
// 默认为真方位,因为绘制过程中还没有bearingType属性
const bearing = this.calculateTrueBearing(tempPositions);
- // 更新小框提示,显示实时长度和真方位角
- this.hoverTooltip = {
- visible: true,
- content: `长度:${length.toFixed(2)} 米\n真方位:${bearing.toFixed(2)}°`,
- position: {
- x: movement.endPosition.x + 10,
- y: movement.endPosition.y - 10
- }
- };
+ // 根据工具模式决定显示格式
+ if (this.toolMode === 'ranging') {
+ // 测距模式:使用千米,简化格式
+ this.hoverTooltip = {
+ visible: true,
+ content: `${(length / 1000).toFixed(1)}km ,真:${bearing.toFixed(1)}°`,
+ position: {
+ x: movement.endPosition.x + 10,
+ y: movement.endPosition.y - 10
+ }
+ };
+ } else {
+ // 空域模式:使用米,完整格式
+ this.hoverTooltip = {
+ visible: true,
+ content: `长度:${length.toFixed(2)} 米\n真方位:${bearing.toFixed(2)}°`,
+ position: {
+ x: movement.endPosition.x + 10,
+ y: movement.endPosition.y - 10
+ }
+ };
+ }
} else {
// 如果没有点,隐藏提示
this.hoverTooltip.visible = false;
@@ -1833,8 +1859,8 @@ export default {
}
return new Cesium.PolygonHierarchy(this.drawingPoints);
}, false),
- // 使用半透明颜色,方便看到地图底图
- material: Cesium.Color.fromCssColorString(this.defaultStyles.polygon.color).withAlpha(0.5),
+ // 不填充颜色
+ material: Cesium.Color.TRANSPARENT,
// 确保贴地
perPositionHeight: false
},
@@ -1848,12 +1874,9 @@ export default {
}
return this.drawingPoints;
}, false),
- width: this.defaultStyles.line.width,
- // 边框使用虚线,表示正在编辑中
- material: new Cesium.PolylineDashMaterialProperty({
- color: Cesium.Color.fromCssColorString(this.defaultStyles.line.color),
- dashLength: 16
- }),
+ width: this.defaultStyles.polygon.width,
+ // 边框使用实线,表示正在编辑中
+ material: Cesium.Color.fromCssColorString(this.defaultStyles.polygon.color),
clampToGround: true
}
});
@@ -1912,6 +1935,7 @@ export default {
this.activeCursorPosition = position; // 初始化鼠标位置
// 创建动态预览矩形
this.tempEntity = this.viewer.entities.add({
+ // 填充部分
rectangle: {
// 关键:使用 CallbackProperty 动态计算矩形范围
coordinates: new Cesium.CallbackProperty(() => {
@@ -1921,11 +1945,35 @@ export default {
}
return Cesium.Rectangle.fromDegrees(0, 0, 0, 0);
}, false),
- // 样式:半透明填充 + 边框
- material: Cesium.Color.fromCssColorString(this.defaultStyles.polygon.color).withAlpha(0.5),
- outline: true,
- outlineColor: Cesium.Color.fromCssColorString(this.defaultStyles.line.color),
- outlineWidth: 2,
+ // 设置填充颜色
+ material: Cesium.Color.fromCssColorString(this.defaultStyles.rectangle.color).withAlpha(this.defaultStyles.rectangle.opacity),
+ clampToGround: true // 贴地
+ },
+ // 边框部分
+ polyline: {
+ // 关键:使用 CallbackProperty 动态计算矩形边框线
+ positions: new Cesium.CallbackProperty(() => {
+ if (this.drawingPoints.length > 0 && this.activeCursorPosition) {
+ // 计算矩形的四个角点
+ const rect = Cesium.Rectangle.fromCartesianArray([this.drawingPoints[0], this.activeCursorPosition]);
+ const west = rect.west;
+ const south = rect.south;
+ const east = rect.east;
+ const north = rect.north;
+
+ // 创建四个角点的笛卡尔坐标
+ const southwest = Cesium.Cartesian3.fromRadians(west, south);
+ const southeast = Cesium.Cartesian3.fromRadians(east, south);
+ const northeast = Cesium.Cartesian3.fromRadians(east, north);
+ const northwest = Cesium.Cartesian3.fromRadians(west, north);
+
+ // 返回闭合的边框线位置数组
+ return [southwest, southeast, northeast, northwest, southwest];
+ }
+ return [];
+ }, false),
+ width: this.defaultStyles.rectangle.width,
+ material: Cesium.Color.fromCssColorString(this.defaultStyles.rectangle.color),
clampToGround: true // 贴地
}
});
@@ -1956,14 +2004,36 @@ export default {
// 3. 创建最终显示的静态实体
this.entityCounter++;
const id = `rectangle_${this.entityCounter}`;
+
+ // 计算矩形的四个角点
+ const west = rect.west;
+ const south = rect.south;
+ const east = rect.east;
+ const north = rect.north;
+
+ // 创建四个角点的笛卡尔坐标
+ const southwest = Cesium.Cartesian3.fromRadians(west, south);
+ const southeast = Cesium.Cartesian3.fromRadians(east, south);
+ const northeast = Cesium.Cartesian3.fromRadians(east, north);
+ const northwest = Cesium.Cartesian3.fromRadians(west, north);
+
+ // 创建边框线的位置数组(闭合)
+ const borderPositions = [southwest, southeast, northeast, northwest, southwest];
+
+ // 创建一个复合实体,包含填充和边框
const finalEntity = this.viewer.entities.add({
id: id,
+ // 填充部分
rectangle: {
coordinates: rect,
- material: Cesium.Color.fromCssColorString(this.defaultStyles.polygon.color).withAlpha(this.defaultStyles.polygon.opacity),
- outline: true,
- outlineColor: Cesium.Color.fromCssColorString(this.defaultStyles.polygon.color),
- outlineWidth: this.defaultStyles.polygon.width,
+ material: Cesium.Color.fromCssColorString(this.defaultStyles.rectangle.color).withAlpha(this.defaultStyles.rectangle.opacity),
+ clampToGround: true
+ },
+ // 边框部分
+ polyline: {
+ positions: borderPositions,
+ width: this.defaultStyles.rectangle.width,
+ material: Cesium.Color.fromCssColorString(this.defaultStyles.rectangle.color),
clampToGround: true
}
});
@@ -1974,9 +2044,10 @@ export default {
points: this.drawingPoints.map(p => this.cartesianToLatLng(p)),
positions: this.drawingPoints,
entity: finalEntity,
- color: this.defaultStyles.polygon.color,
- opacity: this.defaultStyles.polygon.opacity,
- width: this.defaultStyles.polygon.width,
+ color: this.defaultStyles.rectangle.color, // 填充颜色
+ borderColor: this.defaultStyles.rectangle.color, // 边框颜色
+ opacity: this.defaultStyles.rectangle.opacity,
+ width: this.defaultStyles.rectangle.width,
label: `矩形 ${this.entityCounter}`
};
this.allEntities.push(entityData);
@@ -2108,12 +2179,33 @@ export default {
return initialRadius;
}
}, false),
- // 样式设置
- material: Cesium.Color.fromCssColorString(this.defaultStyles.polygon.color).withAlpha(0.5),
- outline: true,
- outlineColor: Cesium.Color.fromCssColorString(this.defaultStyles.line.color),
- outlineWidth: 2,
- // height: 0, // 如果需要贴地可开启或使用 heightReference
+ // 设置填充颜色
+ material: Cesium.Color.fromCssColorString(this.defaultStyles.circle.color).withAlpha(this.defaultStyles.circle.opacity),
+ // 移除 outline 属性,改用 polyline 绘制边框
+ clampToGround: true
+ },
+ // 边框部分
+ polyline: {
+ // 关键:使用 CallbackProperty 动态计算圆形边框线
+ positions: new Cesium.CallbackProperty(() => {
+ try {
+ if (this.activeCursorPosition && this.drawingPoints.length > 0 && this.drawingPoints[0]) {
+ const center = this.drawingPoints[0];
+ const edge = this.activeCursorPosition;
+ if (center && edge && typeof center.x === 'number' && typeof edge.x === 'number') {
+ const radius = Cesium.Cartesian3.distance(center, edge);
+ const validRadius = isFinite(radius) && radius > 0 ? radius : initialRadius;
+ return this.generateCirclePositions(center, validRadius);
+ }
+ }
+ return [];
+ } catch (e) {
+ return [];
+ }
+ }, false),
+ width: this.defaultStyles.circle.width,
+ material: Cesium.Color.fromCssColorString(this.defaultStyles.circle.color),
+ clampToGround: true
}
});
}
@@ -2152,16 +2244,28 @@ export default {
// 3. 创建最终显示的静态实体
this.entityCounter++;
const id = `circle_${this.entityCounter}`;
+
+ // 生成圆形的点,用于绘制边框线
+ const circlePositions = this.generateCirclePositions(centerPoint, radius);
+
+ // 创建一个复合实体,包含填充和边框
const finalEntity = this.viewer.entities.add({
id: id,
position: centerPoint,
+ // 填充部分
ellipse: {
semiMajorAxis: radius,
semiMinorAxis: radius,
- material: Cesium.Color.fromCssColorString(this.defaultStyles.polygon.color).withAlpha(this.defaultStyles.polygon.opacity),
- outline: true,
- outlineColor: Cesium.Color.fromCssColorString(this.defaultStyles.polygon.color),
- outlineWidth: this.defaultStyles.polygon.width
+ // 设置填充颜色
+ material: Cesium.Color.fromCssColorString(this.defaultStyles.circle.color).withAlpha(this.defaultStyles.circle.opacity),
+ clampToGround: true
+ },
+ // 边框部分
+ polyline: {
+ positions: circlePositions,
+ width: this.defaultStyles.circle.width,
+ material: Cesium.Color.fromCssColorString(this.defaultStyles.circle.color),
+ clampToGround: true
}
});
// 4. 记录实体
@@ -2171,9 +2275,10 @@ export default {
points: [centerPoint, edgePosition].map(p => this.cartesianToLatLng(p)),
positions: [centerPoint, edgePosition],
entity: finalEntity,
- color: this.defaultStyles.polygon.color,
- opacity: this.defaultStyles.polygon.opacity,
- width: this.defaultStyles.polygon.width,
+ color: this.defaultStyles.circle.color, // 填充颜色
+ borderColor: this.defaultStyles.circle.color, // 边框颜色
+ opacity: this.defaultStyles.circle.opacity,
+ width: this.defaultStyles.circle.width,
radius: radius,
label: `圆形 ${this.entityCounter}`
};
@@ -2267,6 +2372,7 @@ export default {
}
// 创建动态预览扇形
this.tempEntity = this.viewer.entities.add({
+ // 填充部分
polygon: {
hierarchy: new Cesium.CallbackProperty(() => {
if (this.drawingPoints.length > 1 && this.activeCursorPosition) {
@@ -2282,10 +2388,29 @@ export default {
}
return new Cesium.PolygonHierarchy([]);
}, false),
- material: Cesium.Color.fromCssColorString(this.defaultStyles.sector.color).withAlpha(0.5),
- outline: true,
- outlineColor: Cesium.Color.fromCssColorString(this.defaultStyles.sector.color),
- outlineWidth: this.defaultStyles.sector.width
+ // 设置填充颜色
+ material: Cesium.Color.fromCssColorString(this.defaultStyles.sector.color).withAlpha(this.defaultStyles.sector.opacity),
+ clampToGround: true
+ },
+ // 边框部分
+ polyline: {
+ positions: new Cesium.CallbackProperty(() => {
+ if (this.drawingPoints.length > 1 && this.activeCursorPosition) {
+ const centerPoint = this.drawingPoints[0];
+ const radiusPoint = this.drawingPoints[1];
+ if (!isFinite(fixedRadius) || fixedRadius === 0) {
+ return [];
+ }
+ const startAngle = this.calculatePointAngle(centerPoint, radiusPoint);
+ const endAngle = this.calculatePointAngle(centerPoint, this.activeCursorPosition);
+ const positions = this.generateSectorPositions(centerPoint, fixedRadius, startAngle, endAngle);
+ return positions;
+ }
+ return [];
+ }, false),
+ width: this.defaultStyles.sector.width,
+ material: Cesium.Color.fromCssColorString(this.defaultStyles.sector.color),
+ clampToGround: true
}
});
}
@@ -2319,13 +2444,19 @@ export default {
const finalEntity = this.viewer.entities.add({
id: 'sector-' + new Date().getTime(),
name: `扇形 ${this.entityCounter}`,
+ // 填充部分
polygon: {
hierarchy: new Cesium.PolygonHierarchy(positions),
- material: Cesium.Color.fromCssColorString(this.defaultStyles.sector.color).withAlpha(0.5),
- outline: true,
- outlineColor: Cesium.Color.fromCssColorString(this.defaultStyles.sector.color),
- outlineWidth: this.defaultStyles.sector.width,
- perPositionHeight: false
+ // 设置填充颜色
+ material: Cesium.Color.fromCssColorString(this.defaultStyles.sector.color).withAlpha(this.defaultStyles.sector.opacity),
+ clampToGround: true
+ },
+ // 边框部分
+ polyline: {
+ positions: positions,
+ width: this.defaultStyles.sector.width,
+ material: Cesium.Color.fromCssColorString(this.defaultStyles.sector.color),
+ clampToGround: true
}
});
// 4. 记录实体
@@ -2339,7 +2470,8 @@ export default {
endAngle: endAngle,
positions: positions,
entity: finalEntity,
- color: this.defaultStyles.sector.color,
+ color: this.defaultStyles.sector.color, // 填充颜色
+ borderColor: this.defaultStyles.sector.color, // 边框颜色
opacity: 0.5,
width: this.defaultStyles.sector.width,
label: `扇形 ${this.entityCounter}`
@@ -2348,6 +2480,35 @@ export default {
// 5. 重置状态,保持绘制状态以继续绘制
this.drawingPoints = [];
},
+ // 生成圆形的点,用于绘制边框线
+ generateCirclePositions(center, radius, numPoints = 128) {
+ const positions = [];
+ const ellipsoid = this.viewer.scene.globe.ellipsoid;
+
+ // 计算圆心的经纬度
+ const centerCartographic = Cesium.Cartographic.fromCartesian(center);
+ const centerLatitude = centerCartographic.latitude;
+ const centerLongitude = centerCartographic.longitude;
+
+ // 生成圆形的点
+ for (let i = 0; i <= numPoints; i++) {
+ const angle = (i / numPoints) * Math.PI * 2;
+
+ // 计算点的经纬度
+ // 注意:这里使用简单的方法计算,实际应该考虑地球曲率
+ const deltaLatitude = (radius / ellipsoid.maximumRadius) * Math.sin(angle);
+ const deltaLongitude = (radius / ellipsoid.maximumRadius) * Math.cos(angle) / Math.cos(centerLatitude);
+
+ const latitude = centerLatitude + deltaLatitude;
+ const longitude = centerLongitude + deltaLongitude;
+
+ // 转换为笛卡尔坐标
+ const position = Cesium.Cartesian3.fromRadians(longitude, latitude);
+ positions.push(position);
+ }
+
+ return positions;
+ },
// 计算角度
calculateAngle(center, start, end) {
const startLL = Cesium.Cartographic.fromCartesian(start);
@@ -2397,7 +2558,7 @@ export default {
// 确保角度差不为零
angleDiff = Math.max(0.01, angleDiff);
// 计算扇形的顶点数(根据角度差确定,确保平滑)
- const numPoints = Math.max(5, Math.ceil(angleDiff * 180 / Math.PI / 10));
+ const numPoints = Math.max(10, Math.ceil(angleDiff * 180 / Math.PI / 5));
const angleStep = angleDiff / (numPoints - 1);
// 生成扇形的顶点(顺时针方向)
for (let i = 0; i < numPoints; i++) {
@@ -2822,16 +2983,23 @@ export default {
const id = `polygon_${this.entityCounter}`
// 闭合多边形
const polygonPositions = [...positions, positions[0]]
+ // 创建一个复合实体,包含填充和边框
const entity = this.viewer.entities.add({
id: id,
name: `面 ${this.entityCounter}`,
+ // 填充部分
polygon: {
hierarchy: new Cesium.PolygonHierarchy(polygonPositions),
- material: Cesium.Color.fromCssColorString(this.defaultStyles.polygon.color)
- .withAlpha(this.defaultStyles.polygon.opacity),
- outline: true,
- outlineColor: Cesium.Color.fromCssColorString(this.defaultStyles.polygon.color),
- outlineWidth: this.defaultStyles.polygon.width
+ // 初始无填充
+ material: Cesium.Color.TRANSPARENT,
+ clampToGround: true
+ },
+ // 边框部分
+ polyline: {
+ positions: polygonPositions,
+ width: this.defaultStyles.polygon.width,
+ material: Cesium.Color.fromCssColorString(this.defaultStyles.polygon.color),
+ clampToGround: true
}
})
const entityData = {
@@ -2841,7 +3009,8 @@ export default {
positions: polygonPositions,
entity: entity,
color: this.defaultStyles.polygon.color,
- opacity: this.defaultStyles.polygon.opacity,
+ borderColor: this.defaultStyles.polygon.color,
+ opacity: 0,
width: this.defaultStyles.polygon.width,
label: `面 ${this.entityCounter}`
}
@@ -2860,8 +3029,8 @@ export default {
name: `矩形 ${this.entityCounter}`,
rectangle: {
coordinates: coordinates,
- material: Cesium.Color.fromCssColorString(this.defaultStyles.rectangle.color)
- .withAlpha(this.defaultStyles.rectangle.opacity),
+ // 移除填充颜色,只显示边框
+ material: Cesium.Color.TRANSPARENT,
outline: true,
outlineColor: Cesium.Color.fromCssColorString(this.defaultStyles.rectangle.color),
outlineWidth: this.defaultStyles.rectangle.width
@@ -2884,8 +3053,8 @@ export default {
ellipse: {
semiMinorAxis: validRadius, // 半短轴 = 半径
semiMajorAxis: validRadius, // 半长轴 = 半径
- material: Cesium.Color.fromCssColorString(this.defaultStyles.circle.color)
- .withAlpha(this.defaultStyles.circle.opacity),
+ // 移除填充颜色,只显示边框
+ material: Cesium.Color.TRANSPARENT,
outline: true,
outlineColor: Cesium.Color.fromCssColorString(this.defaultStyles.circle.color),
outlineWidth: this.defaultStyles.circle.width
@@ -2907,6 +3076,13 @@ export default {
lng: Cesium.Math.toDegrees(cartographic.longitude)
}
},
+ degreesToDMS(decimalDegrees) {
+ const degrees = Math.floor(decimalDegrees)
+ const minutesDecimal = (decimalDegrees - degrees) * 60
+ const minutes = Math.floor(minutesDecimal)
+ const seconds = ((minutesDecimal - minutes) * 60).toFixed(2)
+ return `${degrees}°${minutes}'${seconds}"`
+ },
calculateRectangle(start, end) {
const startLL = this.cartesianToLatLng(start)
const endLL = this.cartesianToLatLng(end)
@@ -2980,20 +3156,45 @@ export default {
let declination;
if (lngDeg >= 73 && lngDeg <= 135 && latDeg >= 18 && latDeg <= 53) {
- // 中国地区简化磁偏角模型
- // 基于2020年数据,每年约变化0.1度
+ // 中国地区简化磁偏角模型(基于WMM2025模型数据)
+ // 注意:中国大部分地区磁偏角偏西(负值),只有新疆、西藏等少数地区偏东(正值)
+ // 数据来源:NOAA WMM-2025模型
const year = new Date().getFullYear();
- const yearOffset = (year - 2020) * 0.1;
+ const yearOffset = (year - 2025) * 0.04;
if (lngDeg < 100) {
- // 西部地区
- declination = 2.0 - yearOffset;
+ // 西部地区(新疆、西藏等)
+ if (latDeg > 40) {
+ // 西北地区(新疆北部)
+ declination = 3.0 - yearOffset;
+ } else if (latDeg > 32) {
+ // 西南地区(四川、重庆等)
+ declination = -2.0 - yearOffset;
+ } else {
+ // 西藏地区
+ declination = 1.0 - yearOffset;
+ }
} else if (lngDeg < 115) {
- // 中部地区
- declination = 1.0 - yearOffset;
+ // 中部地区(华北、华中)
+ if (latDeg > 38) {
+ // 华北地区(北京等)
+ declination = -7.5 - yearOffset;
+ } else if (latDeg > 32) {
+ // 华中北部
+ declination = -5.0 - yearOffset;
+ } else {
+ // 华中南部
+ declination = -3.5 - yearOffset;
+ }
} else {
- // 东部地区
- declination = 0.5 - yearOffset;
+ // 东部地区(华东、华南)
+ if (latDeg > 35) {
+ // 华东地区(上海等)
+ declination = -5.5 - yearOffset;
+ } else {
+ // 华南地区(广州、深圳等)
+ declination = -2.5 - yearOffset;
+ }
}
} else {
// 其他地区默认磁偏角为0
@@ -3020,8 +3221,8 @@ export default {
// 计算磁偏角
const declination = this.calculateMagneticDeclination(startLat, startLng);
- // 计算磁方位角(真方位角加上磁偏角)
- let magneticBearing = trueBearing + declination;
+ // 计算磁方位角(真方位角减去磁偏角)
+ let magneticBearing = trueBearing - declination;
// 调整到0-360范围
return (magneticBearing + 360) % 360;
@@ -3078,22 +3279,28 @@ export default {
case 'polygon':
if (entity.polygon) {
entity.polygon.material = Cesium.Color.fromCssColorString(data.color).withAlpha(data.opacity)
- entity.polygon.outlineColor = Cesium.Color.fromCssColorString(data.color)
- entity.polygon.outlineWidth = data.width
+ }
+ if (entity.polyline) {
+ entity.polyline.material = Cesium.Color.fromCssColorString(data.borderColor || data.color)
+ entity.polyline.width = data.width
}
break
case 'rectangle':
if (entity.rectangle) {
entity.rectangle.material = Cesium.Color.fromCssColorString(data.color).withAlpha(data.opacity)
- entity.rectangle.outlineColor = Cesium.Color.fromCssColorString(data.color)
- entity.rectangle.outlineWidth = data.width
+ }
+ if (entity.polyline) {
+ entity.polyline.material = Cesium.Color.fromCssColorString(data.borderColor || data.color)
+ entity.polyline.width = data.width
}
break
case 'circle':
if (entity.ellipse) {
entity.ellipse.material = Cesium.Color.fromCssColorString(data.color).withAlpha(data.opacity)
- entity.ellipse.outlineColor = Cesium.Color.fromCssColorString(data.color)
- entity.ellipse.outlineWidth = data.width
+ }
+ if (entity.polyline) {
+ entity.polyline.material = Cesium.Color.fromCssColorString(data.borderColor || data.color)
+ entity.polyline.width = data.width
}
break
case 'ellipse':
@@ -3114,8 +3321,10 @@ export default {
case 'sector':
if (entity.polygon) {
entity.polygon.material = Cesium.Color.fromCssColorString(data.color).withAlpha(data.opacity)
- entity.polygon.outlineColor = Cesium.Color.fromCssColorString(data.color)
- entity.polygon.outlineWidth = data.width
+ }
+ if (entity.polyline) {
+ entity.polyline.material = Cesium.Color.fromCssColorString(data.borderColor || data.color)
+ entity.polyline.width = data.width
}
break
case 'arrow':
@@ -3166,6 +3375,10 @@ export default {
const entityData = this.contextMenu.entityData
// 更新实体数据
entityData[property] = value
+ // 当修改填充色时,默认设置透明度为 20%
+ if (property === 'color' && (entityData.type === 'polygon' || entityData.type === 'rectangle' || entityData.type === 'circle' || entityData.type === 'sector')) {
+ entityData.opacity = 0.2
+ }
// 更新实体样式
this.updateEntityStyle(entityData)
// 隐藏右键菜单
@@ -3203,49 +3416,102 @@ export default {
}
}
},
- clearAll() {
- // 1. 检查数组是否有内容
- if (this.allEntities && this.allEntities.length > 0) {
- // 2. 遍历每一个对象进行删除
- this.allEntities.forEach(item => {
- try {
- // 情况 A: 数组里存的是原生的 Cesium Entity (点、线通常是这种情况)
- if (item instanceof Cesium.Entity) {
- this.viewer.entities.remove(item);
- }
- // 情况 B: 数组里存的是包装对象 (你的矩形、圆可能是这种 { entity: ... })
- else if (item.entity && item.entity instanceof Cesium.Entity) {
- this.viewer.entities.remove(item.entity);
- }
- // 情况 C: 兜底方案,尝试通过 ID 删除
- else if (item.id) {
- this.viewer.entities.removeById(item.id);
- }
- // 移除线实体相关的点实体
- if (item.type === 'line' && item.pointEntities) {
- item.pointEntities.forEach(pointEntity => {
- this.viewer.entities.remove(pointEntity);
- });
+ clearAll(showConfirm = true) {
+ if (showConfirm) {
+ this.$confirm('是否清除所有编辑内容?', '提示', {
+ confirmButtonText: '确定',
+ cancelButtonText: '取消',
+ type: 'warning'
+ }).then(() => {
+ this.executeClearAll();
+ }).catch(() => {
+ // 用户点击取消,不做任何操作
+ });
+ } else {
+ this.executeClearAll();
+ }
+ },
+ executeClearAll() {
+ // 1. 检查数组是否有内容
+ if (this.allEntities && this.allEntities.length > 0) {
+ // 2. 遍历每一个对象进行删除
+ this.allEntities.forEach(item => {
+ try {
+ let entity = null;
+
+ // 情况 A: 数组里存的是原生的 Cesium Entity (点、线通常是这种情况)
+ if (item instanceof Cesium.Entity) {
+ entity = item;
+ }
+ // 情况 B: 数组里存的是包装对象 (你的矩形、圆可能是这种 { entity: ... })
+ else if (item.entity && item.entity instanceof Cesium.Entity) {
+ entity = item.entity;
+ }
+ // 情况 C: 兜底方案,尝试通过 ID 删除
+ else if (item.id) {
+ entity = this.viewer.entities.getById(item.id);
+ }
+
+ // 检查是否是航线实体,如果是则跳过删除
+ if (entity && entity.properties) {
+ const isMissionWaypoint = entity.properties.isMissionWaypoint;
+ const isMissionRouteLine = entity.properties.isMissionRouteLine;
+ if (isMissionWaypoint || isMissionRouteLine) {
+ return; // 跳过航线相关实体
+ }
+ }
+
+ // 删除非航线实体
+ if (entity) {
+ this.viewer.entities.remove(entity);
+ }
+
+ // 移除线实体相关的点实体
+ if (item.type === 'line' && item.pointEntities) {
+ item.pointEntities.forEach(pointEntity => {
+ this.viewer.entities.remove(pointEntity);
+ });
+ }
+ } catch (e) {
+ console.warn('删除实体失败:', e);
}
- } catch (e) {
- console.warn('删除实体失败:', e);
+ });
+ }
+ // 3. 清空数组(只保留航线实体)
+ this.allEntities = this.allEntities.filter(item => {
+ let entity = null;
+ if (item instanceof Cesium.Entity) {
+ entity = item;
+ } else if (item.entity && item.entity instanceof Cesium.Entity) {
+ entity = item.entity;
+ } else if (item.id) {
+ entity = this.viewer.entities.getById(item.id);
+ }
+
+ if (entity && entity.properties) {
+ const isMissionWaypoint = entity.properties.isMissionWaypoint;
+ const isMissionRouteLine = entity.properties.isMissionRouteLine;
+ return isMissionWaypoint || isMissionRouteLine;
}
+ return false;
+ });
+ // 4. 清理可能残留的绘制过程中的临时图形
+ if (this.tempEntity) {
+ this.viewer.entities.remove(this.tempEntity);
+ this.tempEntity = null;
+ }
+ if (this.tempPreviewEntity) {
+ this.viewer.entities.remove(this.tempPreviewEntity);
+ this.tempPreviewEntity = null;
+ }
+ // 5. 重置其他状态(如测量面板、绘制状态)
+ this.measurementResult = null;
+ this.stopDrawing();
+
+ this.$message({
+ type: 'success',
+ message: '清除成功!'
});
- }
- // 3. 清空数组
- this.allEntities = [];
- // 4. 清理可能残留的绘制过程中的临时图形
- if (this.tempEntity) {
- this.viewer.entities.remove(this.tempEntity);
- this.tempEntity = null;
- }
- if (this.tempPreviewEntity) {
- this.viewer.entities.remove(this.tempPreviewEntity);
- this.tempPreviewEntity = null;
- }
- // 5. 重置其他状态(如测量面板、绘制状态)
- this.measurementResult = null;
- this.stopDrawing();
},
// ================== 其他方法 ==================
getTypeName(type) {
@@ -3540,7 +3806,7 @@ export default {
},
duration: 2
})
- this.$message.success(`已定位到经度 ${lng.toFixed(4)},纬度 ${lat.toFixed(4)}`)
+ this.$message.success(`已定位到经度 ${this.degreesToDMS(lng)},纬度 ${this.degreesToDMS(lat)}`)
}
},
@@ -3812,7 +4078,7 @@ export default {
const cartographic = Cesium.Cartographic.fromCartesian(cartesian)
const longitude = Cesium.Math.toDegrees(cartographic.longitude)
const latitude = Cesium.Math.toDegrees(cartographic.latitude)
- this.coordinatesText = `经度: ${longitude.toFixed(6)}, 纬度: ${latitude.toFixed(6)}`
+ this.coordinatesText = `经度: ${this.degreesToDMS(longitude)}, 纬度: ${this.degreesToDMS(latitude)}`
} else {
this.coordinatesText = '经度: --, 纬度: --'
}
@@ -3820,7 +4086,7 @@ export default {
},
destroyViewer() {
this.stopDrawing()
- this.clearAll()
+ this.clearAll(false)
if (this.pointMovementHandler) {
this.pointMovementHandler.destroy()
diff --git a/ruoyi-ui/src/views/childRoom/RightPanel.vue b/ruoyi-ui/src/views/childRoom/RightPanel.vue
index 3187dc1..17eaaa0 100644
--- a/ruoyi-ui/src/views/childRoom/RightPanel.vue
+++ b/ruoyi-ui/src/views/childRoom/RightPanel.vue
@@ -375,13 +375,6 @@ export default {
if (plan) {
this.$emit('select-plan', plan)
}
- // 仅加载并显示当前新方案的航线
- const planRoutes = this.routes.filter(r => r.scenarioId === planId)
- planRoutes.forEach(route => {
- if (!this.activeRouteIds.includes(route.id)) {
- this.handleSelectRoute(route)
- }
- })
}
},
diff --git a/ruoyi-ui/src/views/childRoom/index.vue b/ruoyi-ui/src/views/childRoom/index.vue
index ba97f03..25b46c6 100644
--- a/ruoyi-ui/src/views/childRoom/index.vue
+++ b/ruoyi-ui/src/views/childRoom/index.vue
@@ -423,13 +423,13 @@ export default {
showScaleDialog: false,
currentScale: {
scaleNumerator: 1,
- scaleDenominator: 1000,
- unit: 'm'
+ scaleDenominator: 20,
+ unit: 'km'
},
scaleConfig: {
scaleNumerator: 1,
- scaleDenominator: 1000,
- unit: 'm'
+ scaleDenominator: 20,
+ unit: 'km'
},
showExternalParamsDialog: false,
currentExternalParams: {},
diff --git a/ruoyi-ui/vue.config.js b/ruoyi-ui/vue.config.js
index 462f379..daef08e 100644
--- a/ruoyi-ui/vue.config.js
+++ b/ruoyi-ui/vue.config.js
@@ -15,14 +15,13 @@ const CompressionPlugin = require('compression-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const name = process.env.VUE_APP_TITLE || '若依管理系统' // 网页标题
-const baseUrl = 'http://127.0.0.1:8080' // 后端接口
+const baseUrl = 'http://localhost:8080' // 后端接口
const port = process.env.port || process.env.npm_config_port || 80 // 端口
// 定义 Cesium 源码路径
const cesiumSource = 'node_modules/cesium/Build/Cesium'
module.exports = {
-
// 部署生产环境和开发环境下的URL。
publicPath: process.env.NODE_ENV === "production" ? "/" : "/",
outputDir: 'dist',