From 65ed6b13d93c0de34d433682cad7994751bb664f Mon Sep 17 00:00:00 2001 From: ctw <1051735452@qq.com> Date: Fri, 23 Jan 2026 09:38:59 +0800 Subject: [PATCH 1/6] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=89=80=E6=9C=89?= =?UTF-8?q?=E5=9C=B0=E5=9B=BE=E7=BB=98=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-ui/src/views/cesiumMap/index.vue | 327 ++++++++++++++++++++------------- 1 file changed, 199 insertions(+), 128 deletions(-) diff --git a/ruoyi-ui/src/views/cesiumMap/index.vue b/ruoyi-ui/src/views/cesiumMap/index.vue index d0a99ec..0f69877 100644 --- a/ruoyi-ui/src/views/cesiumMap/index.vue +++ b/ruoyi-ui/src/views/cesiumMap/index.vue @@ -69,6 +69,7 @@ export default { drawingPoints: [], drawingStartPoint: null, isDrawing: false, + activeCursorPosition: null, // 实时鼠标位置 // 实体管理 allEntities: [], // 所有绘制的实体 @@ -349,6 +350,7 @@ export default { this.drawingPoints = []; this.drawingStartPoint = null; this.isDrawing = false; + this.activeCursorPosition = null; this.viewer.scene.canvas.style.cursor = 'default'; }, @@ -368,8 +370,6 @@ export default { // 绘制线 startLineDrawing() { this.drawingPoints = []; - // 记录当前鼠标的实时位置 - let activeCursorPosition = null; // 清除可能存在的旧实体 if (this.tempEntity) this.viewer.entities.remove(this.tempEntity); @@ -381,7 +381,7 @@ export default { this.drawingHandler.setInputAction((movement) => { const newPosition = this.getClickPosition(movement.endPosition); if (newPosition) { - activeCursorPosition = newPosition; + this.activeCursorPosition = newPosition; } }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); @@ -393,7 +393,7 @@ export default { // === 第一步:点击第一个点后,立即创建“动态虚线” === if (this.drawingPoints.length === 1) { - activeCursorPosition = position; // 初始化鼠标位置 + this.activeCursorPosition = position; // 初始化鼠标位置 // 创建预览虚线(只创建这一次,之后它会自动随数据更新) this.tempPreviewEntity = this.viewer.entities.add({ @@ -401,11 +401,11 @@ export default { // 关键:使用 CallbackProperty 动态获取位置 positions: new Cesium.CallbackProperty(() => { // 只有当有点且鼠标位置存在时才渲染 - if (this.drawingPoints.length > 0 && activeCursorPosition) { + if (this.drawingPoints.length > 0 && this.activeCursorPosition) { // 获取最后一个已确认的点 const lastPoint = this.drawingPoints[this.drawingPoints.length - 1]; // 返回 [最后一个点, 当前鼠标位置] - return [lastPoint, activeCursorPosition]; + return [lastPoint, this.activeCursorPosition]; } return []; }, false), @@ -451,8 +451,8 @@ export default { this.cancelDrawing(); } - // 重置局部变量 - activeCursorPosition = null; + // 重置鼠标位置 + this.activeCursorPosition = null; }, Cesium.ScreenSpaceEventType.RIGHT_CLICK); }, @@ -475,7 +475,9 @@ export default { type: 'line' }; - this.stopDrawing(); + // 重置绘制点数组,保持绘制状态以继续绘制 + this.drawingPoints = []; + this.tempEntity = null; return entity; } else { this.cancelDrawing(); @@ -486,7 +488,6 @@ export default { // 绘制多边形 startPolygonDrawing() { this.drawingPoints = []; - let activeCursorPosition = null; // 存储鼠标实时位置 // 1. 清理旧实体 // 移除之前可能遗留的实体,确保干净的画布 @@ -499,7 +500,7 @@ export default { this.drawingHandler.setInputAction((movement) => { const newPosition = this.getClickPosition(movement.endPosition); if (newPosition) { - activeCursorPosition = newPosition; + this.activeCursorPosition = newPosition; } }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); @@ -511,7 +512,7 @@ export default { // === 关键逻辑:点击第一个点时,创建唯一的“动态多边形” === if (this.drawingPoints.length === 1) { - activeCursorPosition = position; // 初始化鼠标位置 + this.activeCursorPosition = position; // 初始化鼠标位置 this.tempEntity = this.viewer.entities.add({ // --- 填充面配置 --- @@ -519,8 +520,8 @@ export default { // hierarchy 使用 CallbackProperty 实现动态填充 hierarchy: new Cesium.CallbackProperty(() => { // 组合:已确定的点 + 当前鼠标位置 - if (activeCursorPosition) { - return new Cesium.PolygonHierarchy([...this.drawingPoints, activeCursorPosition]); + if (this.activeCursorPosition) { + return new Cesium.PolygonHierarchy([...this.drawingPoints, this.activeCursorPosition]); } return new Cesium.PolygonHierarchy(this.drawingPoints); }, false), @@ -533,9 +534,9 @@ export default { polyline: { // positions 使用 CallbackProperty 实现动态闭合线 positions: new Cesium.CallbackProperty(() => { - if (activeCursorPosition) { + if (this.activeCursorPosition) { // 闭合回路:[所有点, 鼠标位置, 回到起点] - return [...this.drawingPoints, activeCursorPosition, this.drawingPoints[0]]; + return [...this.drawingPoints, this.activeCursorPosition, this.drawingPoints[0]]; } return this.drawingPoints; }, false), @@ -561,7 +562,7 @@ export default { } // 重置状态 - activeCursorPosition = null; + this.activeCursorPosition = null; }, Cesium.ScreenSpaceEventType.RIGHT_CLICK); }, @@ -576,15 +577,19 @@ export default { type: 'polygon' } - this.stopDrawing() + // 重置绘制点数组,保持绘制状态以继续绘制 + this.drawingPoints = [] + if (this.tempEntity) { + this.viewer.entities.remove(this.tempEntity) + this.tempEntity = null + } return entity }, // 绘制矩形(优化版:两点定矩形,实时预览) startRectangleDrawing() { + // 重置绘制状态 this.drawingPoints = []; // 存储起点和终点 - let activeCursorPosition = null; // 实时鼠标位置 - let startPoint = null; // 记录起点 // 1. 清理旧实体 if (this.tempEntity) this.viewer.entities.remove(this.tempEntity); @@ -594,7 +599,7 @@ export default { this.drawingHandler.setInputAction((movement) => { const newPosition = this.getClickPosition(movement.endPosition); if (newPosition) { - activeCursorPosition = newPosition; + this.activeCursorPosition = newPosition; } }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); @@ -603,19 +608,18 @@ export default { const position = this.getClickPosition(click.position); if (position) { // --- 情况A:第一次点击(确定起点) --- - if (!startPoint) { - startPoint = position; - this.drawingPoints.push(startPoint); - activeCursorPosition = startPoint; // 初始化鼠标位置 + if (this.drawingPoints.length === 0) { + this.drawingPoints.push(position); + this.activeCursorPosition = position; // 初始化鼠标位置 // 创建动态预览矩形 this.tempEntity = this.viewer.entities.add({ rectangle: { // 关键:使用 CallbackProperty 动态计算矩形范围 coordinates: new Cesium.CallbackProperty(() => { - if (startPoint && activeCursorPosition) { + if (this.drawingPoints.length > 0 && this.activeCursorPosition) { // 使用 Cesium 内置工具,根据两个点(对角)自动计算矩形范围 - return Cesium.Rectangle.fromCartesianArray([startPoint, activeCursorPosition]); + return Cesium.Rectangle.fromCartesianArray([this.drawingPoints[0], this.activeCursorPosition]); } return Cesium.Rectangle.fromDegrees(0, 0, 0, 0); }, false), @@ -629,10 +633,10 @@ export default { }); } // --- 情况B:第二次点击(确定终点) --- - else { + else if (this.drawingPoints.length === 1) { this.drawingPoints.push(position); // 停止监听鼠标移动,因为形状已确定 - activeCursorPosition = null; + this.activeCursorPosition = null; // 调用完成逻辑 this.finishRectangleDrawing(); @@ -679,8 +683,8 @@ export default { type: 'rectangle' }; - // 6. 重置状态 - this.stopDrawing(); + // 6. 重置状态,保持绘制状态以继续绘制 + this.drawingPoints = []; }, // 计算矩形面积(辅助方法) @@ -718,73 +722,136 @@ export default { }, // 绘制圆形 startCircleDrawing() { + // 重置绘制状态 this.drawingPoints = []; // 存储圆心 - let activeCursorPosition = null; // 实时鼠标位置 - let centerPoint = null; // 圆心坐标 + this.activeCursorPosition = null; // 1. 清理旧实体 - if (this.tempEntity) this.viewer.entities.remove(this.tempEntity); - this.tempEntity = null; + if (this.tempEntity) { + try { + this.viewer.entities.remove(this.tempEntity); + } catch (e) { + console.warn('Failed to remove temp entity:', e); + } + this.tempEntity = null; + } + if (this.tempPreviewEntity) { + try { + this.viewer.entities.remove(this.tempPreviewEntity); + } catch (e) { + console.warn('Failed to remove temp preview entity:', e); + } + this.tempPreviewEntity = null; + } - // 2. 鼠标移动事件 + // 2. 重置事件处理器 + this.drawingHandler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE); + this.drawingHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK); + this.drawingHandler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK); + + // 3. 鼠标移动事件 this.drawingHandler.setInputAction((movement) => { - const newPosition = this.getClickPosition(movement.endPosition); - if (newPosition) { - activeCursorPosition = newPosition; + try { + const newPosition = this.getClickPosition(movement.endPosition); + if (newPosition) { + this.activeCursorPosition = newPosition; + } + } catch (e) { + console.warn('Mouse move error:', e); } }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); - // 3. 鼠标点击事件 + // 4. 鼠标点击事件 this.drawingHandler.setInputAction((click) => { - const position = this.getClickPosition(click.position); - if (position) { - // --- 情况A:第一次点击(确定圆心) --- - if (!centerPoint) { - centerPoint = position; - this.drawingPoints.push(centerPoint); - activeCursorPosition = centerPoint; + try { + const position = this.getClickPosition(click.position); + if (position) { + // --- 情况A:第一次点击(确定圆心) --- + if (this.drawingPoints.length === 0) { + this.drawingPoints.push(position); + this.activeCursorPosition = position; + + // 创建动态预览圆形 + if (this.tempEntity) { + try { + this.viewer.entities.remove(this.tempEntity); + } catch (e) { + console.warn('Failed to remove existing temp entity:', e); + } + this.tempEntity = null; + } - // 创建动态预览圆形 - this.tempEntity = this.viewer.entities.add({ - position: centerPoint, // 圆心固定 - ellipse: { - // 关键:使用 CallbackProperty 动态计算半径(半长轴和半短轴) - semiMajorAxis: new Cesium.CallbackProperty(() => { - if (centerPoint && activeCursorPosition) { - return Cesium.Cartesian3.distance(centerPoint, activeCursorPosition); - } - return 0; - }, false), - semiMinorAxis: new Cesium.CallbackProperty(() => { - if (centerPoint && activeCursorPosition) { - return Cesium.Cartesian3.distance(centerPoint, activeCursorPosition); + // 确保有有效的圆心位置 + if (position) { + // 先创建一个固定半径的临时圆,避免半径为0的情况 + const initialRadius = 100; // 初始半径设为100米 + + this.tempEntity = this.viewer.entities.add({ + position: position, // 直接使用确定的圆心位置 + ellipse: { + // 关键:使用 CallbackProperty 动态计算半径(半长轴和半短轴) + semiMajorAxis: 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 distance = Cesium.Cartesian3.distance(center, edge); + return isFinite(distance) && distance > 0 ? distance : initialRadius; + } + } + return initialRadius; + } catch (e) { + return initialRadius; + } + }, false), + semiMinorAxis: 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 distance = Cesium.Cartesian3.distance(center, edge); + return isFinite(distance) && distance > 0 ? distance : initialRadius; + } + } + return initialRadius; + } catch (e) { + 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 } - return 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, - // height: 0, // 如果需要贴地可开启或使用 heightReference + }); } - }); - } - // --- 情况B:第二次点击(确定边缘/半径) --- - else { - // 记录边缘点(虽然圆只需要圆心和半径,但记录下来方便后续处理) - this.drawingPoints.push(position); - activeCursorPosition = null; // 停止动态更新 - - // 传递边缘点位置去结束绘制 - this.finishCircleDrawing(position); + } + // --- 情况B:第二次点击(确定边缘/半径) --- + else if (this.drawingPoints.length === 1) { + // 记录边缘点(虽然圆只需要圆心和半径,但记录下来方便后续处理) + this.drawingPoints.push(position); + this.activeCursorPosition = null; // 停止动态更新 + + // 传递边缘点位置去结束绘制 + this.finishCircleDrawing(position); + } } + } catch (e) { + console.warn('Mouse click error:', e); } }, Cesium.ScreenSpaceEventType.LEFT_CLICK); - // 4. 右键取消 + // 5. 右键取消 this.drawingHandler.setInputAction(() => { - this.cancelDrawing(); + try { + this.cancelDrawing(); + } catch (e) { + console.warn('Right click error:', e); + } }, Cesium.ScreenSpaceEventType.RIGHT_CLICK); }, @@ -827,17 +894,15 @@ export default { type: 'circle' }; - // 6. 结束绘制状态 - this.stopDrawing(); + // 6. 重置状态,保持绘制状态以继续绘制 + this.drawingPoints = []; + this.activeCursorPosition = null; }, // 绘制扇形 startSectorDrawing() { + // 重置绘制状态 this.drawingPoints = []; // 存储圆心、半径端点、角度端点 - let activeCursorPosition = null; // 实时鼠标位置 - let centerPoint = null; // 圆心坐标 - let radiusPoint = null; // 半径端点 - let radius = 0; // 半径长度 // 1. 清理旧实体 if (this.tempEntity) this.viewer.entities.remove(this.tempEntity); @@ -849,7 +914,7 @@ export default { this.drawingHandler.setInputAction((movement) => { const newPosition = this.getClickPosition(movement.endPosition); if (newPosition) { - activeCursorPosition = newPosition; + this.activeCursorPosition = newPosition; } }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); @@ -858,17 +923,16 @@ export default { const position = this.getClickPosition(click.position); if (position) { // --- 情况A:第一次点击(确定圆心) --- - if (!centerPoint) { - centerPoint = position; - this.drawingPoints.push(centerPoint); - activeCursorPosition = centerPoint; + if (this.drawingPoints.length === 0) { + this.drawingPoints.push(position); + this.activeCursorPosition = position; // 创建动态预览半径线 this.tempPreviewEntity = this.viewer.entities.add({ polyline: { positions: new Cesium.CallbackProperty(() => { - if (centerPoint && activeCursorPosition) { - return [centerPoint, activeCursorPosition]; + if (this.drawingPoints.length > 0 && this.activeCursorPosition) { + return [this.drawingPoints[0], this.activeCursorPosition]; } return []; }, false), @@ -882,10 +946,12 @@ export default { }); } // --- 情况B:第二次点击(确定半径) --- - else if (!radiusPoint) { - radiusPoint = position; - this.drawingPoints.push(radiusPoint); - radius = Cesium.Cartesian3.distance(centerPoint, radiusPoint); + else if (this.drawingPoints.length === 1) { + this.drawingPoints.push(position); + this.activeCursorPosition = position; // 更新 activeCursorPosition 为实际点击位置 + const centerPoint = this.drawingPoints[0]; + const radiusPoint = this.drawingPoints[1]; + const fixedRadius = Cesium.Cartesian3.distance(centerPoint, radiusPoint); // 移除半径预览线 if (this.tempPreviewEntity) { @@ -897,11 +963,15 @@ export default { this.tempEntity = this.viewer.entities.add({ polygon: { hierarchy: new Cesium.CallbackProperty(() => { - if (centerPoint && activeCursorPosition) { - const currentRadius = Cesium.Cartesian3.distance(centerPoint, activeCursorPosition); + if (this.drawingPoints.length > 1 && this.activeCursorPosition) { + const centerPoint = this.drawingPoints[0]; + const radiusPoint = this.drawingPoints[1]; + if (!isFinite(fixedRadius) || fixedRadius === 0) { + return new Cesium.PolygonHierarchy([]); + } const startAngle = this.calculatePointAngle(centerPoint, radiusPoint); - const endAngle = this.calculatePointAngle(centerPoint, activeCursorPosition); - const positions = this.generateSectorPositions(centerPoint, currentRadius, startAngle, endAngle); + const endAngle = this.calculatePointAngle(centerPoint, this.activeCursorPosition); + const positions = this.generateSectorPositions(centerPoint, fixedRadius, startAngle, endAngle); return new Cesium.PolygonHierarchy(positions); } return new Cesium.PolygonHierarchy([]); @@ -914,13 +984,12 @@ export default { }); } // --- 情况C:第三次点击(确定角度) --- - else { - const anglePoint = position; - this.drawingPoints.push(anglePoint); - activeCursorPosition = null; // 停止动态更新 + else if (this.drawingPoints.length === 2) { + this.drawingPoints.push(position); + this.activeCursorPosition = null; // 停止动态更新 // 传递角度点位置去结束绘制 - this.finishSectorDrawing(centerPoint, radiusPoint, anglePoint); + this.finishSectorDrawing(this.drawingPoints[0], this.drawingPoints[1], this.drawingPoints[2]); } } }, Cesium.ScreenSpaceEventType.LEFT_CLICK); @@ -933,7 +1002,7 @@ export default { // 完成扇形绘制 finishSectorDrawing(centerPoint, radiusPoint, anglePoint) { - const radius = Cesium.Cartesian3.distance(centerPoint, anglePoint); + const radius = Cesium.Cartesian3.distance(centerPoint, radiusPoint); const startAngle = this.calculatePointAngle(centerPoint, radiusPoint); const endAngle = this.calculatePointAngle(centerPoint, anglePoint); @@ -978,8 +1047,8 @@ export default { }; this.allEntities.push(entityData); - // 5. 结束绘制状态 - this.stopDrawing(); + // 5. 重置状态,保持绘制状态以继续绘制 + this.drawingPoints = []; }, // 计算角度 @@ -989,8 +1058,8 @@ export default { const centerLL = Cesium.Cartographic.fromCartesian(center); // 计算两点相对于圆心的角度 - const startAngle = Math.atan2(startLL.longitude - centerLL.longitude, startLL.latitude - centerLL.latitude); - const endAngle = Math.atan2(endLL.longitude - centerLL.longitude, endLL.latitude - centerLL.latitude); + const startAngle = Math.atan2(startLL.latitude - centerLL.latitude, startLL.longitude - centerLL.longitude); + const endAngle = Math.atan2(endLL.latitude - centerLL.latitude, endLL.longitude - centerLL.longitude); // 返回角度差 return endAngle - startAngle; @@ -1003,8 +1072,8 @@ export default { const centerLL = Cesium.Cartographic.fromCartesian(center); // 计算两点相对于圆心的角度 - const startAngle = Math.atan2(startLL.longitude - centerLL.longitude, startLL.latitude - centerLL.latitude); - const endAngle = Math.atan2(endLL.longitude - centerLL.longitude, endLL.latitude - centerLL.latitude); + const startAngle = Math.atan2(startLL.latitude - centerLL.latitude, startLL.longitude - centerLL.longitude); + const endAngle = Math.atan2(endLL.latitude - centerLL.latitude, endLL.longitude - centerLL.longitude); // 计算角度差(确保为正值) let angleDiff = endAngle - startAngle; @@ -1022,7 +1091,7 @@ export default { const centerLL = Cesium.Cartographic.fromCartesian(center); // 计算点相对于圆心的角度 - const angle = Math.atan2(pointLL.longitude - centerLL.longitude, pointLL.latitude - centerLL.latitude); + const angle = Math.atan2(pointLL.latitude - centerLL.latitude, pointLL.longitude - centerLL.longitude); return angle; }, @@ -1034,8 +1103,8 @@ export default { // 添加圆心 positions.push(center); - // 计算角度差 - let angleDiff = endAngle - startAngle; + // 计算角度差(顺时针方向) + let angleDiff = startAngle - endAngle; if (angleDiff < 0) { angleDiff += 2 * Math.PI; } @@ -1047,13 +1116,13 @@ export default { const numPoints = Math.max(5, Math.ceil(angleDiff * 180 / Math.PI / 10)); const angleStep = angleDiff / (numPoints - 1); - // 生成扇形的顶点 + // 生成扇形的顶点(顺时针方向) for (let i = 0; i < numPoints; i++) { - const currentAngle = startAngle + i * angleStep; + const currentAngle = startAngle - i * angleStep; const distance = radius / 6378137; // 转换为弧度 - const lat = centerLL.latitude + Math.cos(currentAngle) * distance; - const lng = centerLL.longitude + Math.sin(currentAngle) * distance / Math.cos(centerLL.latitude); + const lat = centerLL.latitude + Math.sin(currentAngle) * distance; + const lng = centerLL.longitude + Math.cos(currentAngle) * distance / Math.cos(centerLL.latitude); const position = Cesium.Cartesian3.fromRadians(lng, lat); positions.push(position); @@ -1065,6 +1134,8 @@ export default { return positions; }, + + // 计算两点之间的距离(米) calculateDistance(point1, point2) { return Cesium.Cartesian3.distance(point1, point2); @@ -1073,7 +1144,6 @@ export default { // 绘制箭头 startArrowDrawing() { this.drawingPoints = []; // 存储起点和终点 - let activeCursorPosition = null; // 实时鼠标位置 // 1. 清理旧实体 if (this.tempEntity) this.viewer.entities.remove(this.tempEntity); @@ -1085,7 +1155,7 @@ export default { this.drawingHandler.setInputAction((movement) => { const newPosition = this.getClickPosition(movement.endPosition); if (newPosition) { - activeCursorPosition = newPosition; + this.activeCursorPosition = newPosition; } }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); @@ -1097,7 +1167,7 @@ export default { // --- 情况A:第一次点击(确定起点) --- if (this.drawingPoints.length === 1) { - activeCursorPosition = position; // 初始化鼠标位置 + this.activeCursorPosition = position; // 初始化鼠标位置 // 创建动态预览箭头 this.tempPreviewEntity = this.viewer.entities.add({ @@ -1105,11 +1175,11 @@ export default { // 使用 CallbackProperty 动态获取位置 positions: new Cesium.CallbackProperty(() => { // 只有当有点且鼠标位置存在时才渲染 - if (this.drawingPoints.length > 0 && activeCursorPosition) { + if (this.drawingPoints.length > 0 && this.activeCursorPosition) { // 获取最后一个已确认的点 const lastPoint = this.drawingPoints[this.drawingPoints.length - 1]; // 返回 [最后一个点, 当前鼠标位置] - return [lastPoint, activeCursorPosition]; + return [lastPoint, this.activeCursorPosition]; } return []; }, false), @@ -1126,7 +1196,7 @@ export default { // --- 情况B:第二次点击(确定终点) --- else { // 停止监听鼠标移动,因为形状已确定 - activeCursorPosition = null; + this.activeCursorPosition = null; // 调用完成逻辑 this.finishArrowDrawing(); @@ -1153,7 +1223,8 @@ export default { // 创建最终的箭头实体 const entity = this.addArrowEntity([...this.drawingPoints]); - this.stopDrawing(); + // 重置绘制点数组,保持绘制状态以继续绘制 + this.drawingPoints = []; return entity; } else { this.cancelDrawing(); From 84cf5fd996e23fb46255016a27510d3546f03ff3 Mon Sep 17 00:00:00 2001 From: ctw <1051735452@qq.com> Date: Fri, 23 Jan 2026 13:07:55 +0800 Subject: [PATCH 2/6] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=8D=95=E4=B8=AA?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=8A=9F=E8=83=BD=EF=BC=8C=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E7=BA=BF=E7=9A=84=E7=BB=98=E5=88=B6=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-ui/src/views/cesiumMap/index.vue | 338 +++++++++++++++++++++++++++++---- 1 file changed, 301 insertions(+), 37 deletions(-) diff --git a/ruoyi-ui/src/views/cesiumMap/index.vue b/ruoyi-ui/src/views/cesiumMap/index.vue index 0f69877..6087fa6 100644 --- a/ruoyi-ui/src/views/cesiumMap/index.vue +++ b/ruoyi-ui/src/views/cesiumMap/index.vue @@ -67,6 +67,7 @@ export default { tempEntity: null, // 最终实体 tempPreviewEntity: null, // 预览实体(新增) drawingPoints: [], + drawingPointEntities: [], // 存储线绘制时的点实体 drawingStartPoint: null, isDrawing: false, activeCursorPosition: null, // 实时鼠标位置 @@ -162,6 +163,8 @@ export default { }) this.initScaleBar() + this.initPointMovement() + this.initRightClickHandler() console.log('Cesium离线二维地图已加载') } catch (error) { @@ -170,6 +173,52 @@ export default { this.showErrorMessage(); } }, + + initRightClickHandler() { + // 创建屏幕空间事件处理器 + this.rightClickHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas) + + // 右键点击事件:删除单个实体 + this.rightClickHandler.setInputAction((click) => { + // 如果正在绘制,不处理删除操作 + if (this.isDrawing) { + return; + } + + const pickedObject = this.viewer.scene.pick(click.position) + + if (Cesium.defined(pickedObject) && pickedObject.id) { + const pickedEntity = pickedObject.id + + // 查找对应的实体数据 + let entityData = this.allEntities.find(e => e.entity === pickedEntity || e === pickedEntity) + + // 特殊处理:如果点击的是线段上的点,找到对应的线实体 + if (!entityData) { + // 检查是否是线段上的点 + for (const lineEntity of this.allEntities) { + if (lineEntity.type === 'line' && lineEntity.pointEntities) { + if (lineEntity.pointEntities.includes(pickedEntity)) { + entityData = lineEntity + break + } + } + } + } + + if (entityData) { + // 显示确认对话框 + if (confirm('确定要删除这个对象吗?')) { + if (entityData.id) { + this.removeEntity(entityData.id) + } else if (entityData.entity && entityData.entity.id) { + this.removeEntity(entityData.entity.id) + } + } + } + } + }, Cesium.ScreenSpaceEventType.RIGHT_CLICK) + }, showErrorMessage() { const container = document.getElementById('cesiumViewer'); if (container) { @@ -347,13 +396,49 @@ export default { this.tempPreviewEntity = null; } + // 清理点实体 + if (this.drawingPointEntities) { + this.drawingPointEntities.forEach(pointEntity => { + this.viewer.entities.remove(pointEntity); + }); + this.drawingPointEntities = []; + } + this.drawingPoints = []; this.drawingStartPoint = null; this.isDrawing = false; this.activeCursorPosition = null; + // 重新初始化右键点击删除处理器 + if (!this.rightClickHandler) { + this.initRightClickHandler(); + } + this.viewer.scene.canvas.style.cursor = 'default'; }, + + cancelDrawing() { + // 取消绘制,清理临时实体和状态 + if (this.tempEntity) { + this.viewer.entities.remove(this.tempEntity); + this.tempEntity = null; + } + + if (this.tempPreviewEntity) { + this.viewer.entities.remove(this.tempPreviewEntity); + this.tempPreviewEntity = null; + } + + if (this.drawingPointEntities) { + this.drawingPointEntities.forEach(pointEntity => { + this.viewer.entities.remove(pointEntity); + }); + this.drawingPointEntities = []; + } + + this.drawingPoints = []; + this.activeCursorPosition = null; + }, // ******************************************************************** // 绘制点 startPointDrawing() { @@ -367,9 +452,9 @@ export default { }, // 绘制线 - // 绘制线 startLineDrawing() { this.drawingPoints = []; + this.drawingPointEntities = []; // 存储点实体 // 清除可能存在的旧实体 if (this.tempEntity) this.viewer.entities.remove(this.tempEntity); @@ -377,7 +462,7 @@ export default { this.tempEntity = null; this.tempPreviewEntity = null; - // 1. 鼠标移动事件:仅更新坐标变量,不操作实体 + // 1. 鼠标移动事件:更新坐标变量 this.drawingHandler.setInputAction((movement) => { const newPosition = this.getClickPosition(movement.endPosition); if (newPosition) { @@ -391,37 +476,29 @@ export default { if (position) { this.drawingPoints.push(position); - // === 第一步:点击第一个点后,立即创建“动态虚线” === - if (this.drawingPoints.length === 1) { - this.activeCursorPosition = position; // 初始化鼠标位置 + // 创建点实体并添加到场景中 + this.entityCounter++; + const pointId = `point_${this.entityCounter}`; + const pointEntity = this.viewer.entities.add({ + id: pointId, + position: position, + point: { + pixelSize: this.defaultStyles.point.size, + color: Cesium.Color.fromCssColorString(this.defaultStyles.point.color), + outlineColor: Cesium.Color.WHITE, + outlineWidth: 2 + } + }); + this.drawingPointEntities.push(pointEntity); - // 创建预览虚线(只创建这一次,之后它会自动随数据更新) - this.tempPreviewEntity = this.viewer.entities.add({ - polyline: { - // 关键:使用 CallbackProperty 动态获取位置 - positions: new Cesium.CallbackProperty(() => { - // 只有当有点且鼠标位置存在时才渲染 - if (this.drawingPoints.length > 0 && this.activeCursorPosition) { - // 获取最后一个已确认的点 - const lastPoint = this.drawingPoints[this.drawingPoints.length - 1]; - // 返回 [最后一个点, 当前鼠标位置] - return [lastPoint, this.activeCursorPosition]; - } - return []; - }, false), - width: this.defaultStyles.line.width, - // 虚线材质 - material: new Cesium.PolylineDashMaterialProperty({ - color: Cesium.Color.fromCssColorString(this.defaultStyles.line.color), - dashLength: 16 - }), - clampToGround: true // 贴地 - } - }); + // 移除旧的预览虚线 + if (this.tempPreviewEntity) { + this.viewer.entities.remove(this.tempPreviewEntity); + this.tempPreviewEntity = null; } - // === 第二步:点击后续点时,绘制/延长“固定实线” === - else { - // 移除旧的实线,重新画包含新点的实线 + + // 创建或更新实线 + if (this.drawingPoints.length > 1) { if (this.tempEntity) { this.viewer.entities.remove(this.tempEntity); } @@ -434,20 +511,47 @@ export default { } }); } + + // 创建新的预览虚线(使用 CallbackProperty 实现实时更新) + this.tempPreviewEntity = this.viewer.entities.add({ + polyline: { + positions: new Cesium.CallbackProperty(() => { + if (this.activeCursorPosition) { + return [this.drawingPoints[this.drawingPoints.length - 1], this.activeCursorPosition]; + } + return [this.drawingPoints[this.drawingPoints.length - 1]]; + }, false), + width: this.defaultStyles.line.width, + material: new Cesium.PolylineDashMaterialProperty({ + color: Cesium.Color.fromCssColorString(this.defaultStyles.line.color), + dashLength: 16 + }), + clampToGround: true + } + }); } }, Cesium.ScreenSpaceEventType.LEFT_CLICK); // 3. 右键完成绘制 this.drawingHandler.setInputAction(() => { - // 完成绘制前,移除那条动态虚线 + // 移除临时实体 if (this.tempPreviewEntity) { this.viewer.entities.remove(this.tempPreviewEntity); this.tempPreviewEntity = null; } + if (this.tempEntity) { + this.viewer.entities.remove(this.tempEntity); + this.tempEntity = null; + } if (this.drawingPoints.length > 1) { this.finishLineDrawing(); } else { + // 取消绘制时,移除所有点实体 + this.drawingPointEntities.forEach(pointEntity => { + this.viewer.entities.remove(pointEntity); + }); + this.drawingPointEntities = []; this.cancelDrawing(); } @@ -466,7 +570,7 @@ export default { } // 创建最终的实线实体 - const entity = this.addLineEntity([...this.drawingPoints]); + const entity = this.addLineEntity([...this.drawingPoints], [...this.drawingPointEntities]); // 计算长度 const length = this.calculateLineLength([...this.drawingPoints]); @@ -475,11 +579,19 @@ export default { type: 'line' }; + + // 重置绘制点数组,保持绘制状态以继续绘制 this.drawingPoints = []; + this.drawingPointEntities = []; this.tempEntity = null; return entity; } else { + // 取消绘制时,移除所有点实体 + this.drawingPointEntities.forEach(pointEntity => { + this.viewer.entities.remove(pointEntity); + }); + this.drawingPointEntities = []; this.cancelDrawing(); return null; } @@ -1548,7 +1660,7 @@ export default { return entityData }, - addLineEntity(positions) { + addLineEntity(positions, pointEntities = []) { this.entityCounter++ const id = `line_${this.entityCounter}` @@ -1569,6 +1681,7 @@ export default { points: positions.map(p => this.cartesianToLatLng(p)), positions: positions, entity: entity, + pointEntities: pointEntities, // 存储点实体 color: this.defaultStyles.line.color, width: this.defaultStyles.line.width, label: `线 ${this.entityCounter}` @@ -1823,20 +1936,39 @@ export default { }, removeEntity(id) { - const index = this.allEntities.findIndex(e => e.id === id) + // 查找对应的实体数据 + const index = this.allEntities.findIndex(e => + e.id === id || + (e.entity && e.entity.id === id) || + (e.type === 'line' && e.pointEntities && e.pointEntities.some(p => p.id === id)) + ) + if (index > -1) { const entity = this.allEntities[index] // 从地图中移除 - if (entity.entity) { + if (entity instanceof Cesium.Entity) { + // 情况 A: 直接是 Cesium Entity 对象 + this.viewer.entities.remove(entity) + } else if (entity.entity) { + // 情况 B: 包装对象,包含 entity 属性 this.viewer.entities.remove(entity.entity) } + // 移除线实体相关的点实体 + if (entity.type === 'line' && entity.pointEntities) { + entity.pointEntities.forEach(pointEntity => { + this.viewer.entities.remove(pointEntity) + }) + } + + + // 从数组中移除 this.allEntities.splice(index, 1) // 如果删除的是选中的实体,清空选中状态 - if (this.selectedEntity && this.selectedEntity.id === id) { + if (this.selectedEntity && (this.selectedEntity.id === id || (this.selectedEntity.entity && this.selectedEntity.entity.id === id))) { this.selectedEntity = null } } @@ -1861,6 +1993,13 @@ export default { 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); + }); + } } catch (e) { console.warn('删除实体失败:', e); } @@ -2179,6 +2318,121 @@ export default { // ... 原有的比例尺代码保持不变 }, + initPointMovement() { + // 创建屏幕空间事件处理器 + this.pointMovementHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas) + + let selectedPoint = null + let selectedLineEntity = null + let pointIndex = -1 + let originalCameraController = null + let isMoving = false + + // 鼠标按下事件:选择点 + this.pointMovementHandler.setInputAction((click) => { + const pickedObject = this.viewer.scene.pick(click.position) + + if (Cesium.defined(pickedObject) && pickedObject.id) { + const pickedEntity = pickedObject.id + + // 检查是否点击了点实体 + if (pickedEntity.point) { + // 查找包含该点的线实体 + for (const lineEntity of this.allEntities) { + if (lineEntity.type === 'line' && lineEntity.pointEntities) { + const index = lineEntity.pointEntities.indexOf(pickedEntity) + if (index !== -1) { + selectedPoint = pickedEntity + selectedLineEntity = lineEntity + pointIndex = index + isMoving = true + + // 禁用相机控制器,使地图固定 + originalCameraController = this.viewer.scene.screenSpaceCameraController.enableInputs + this.viewer.scene.screenSpaceCameraController.enableInputs = false + break + } + } + } + } + } + }, Cesium.ScreenSpaceEventType.LEFT_DOWN) + + // 鼠标移动事件:移动点 + this.pointMovementHandler.setInputAction((movement) => { + if (isMoving && selectedPoint && selectedLineEntity) { + const newPosition = this.getClickPosition(movement.endPosition) + if (newPosition) { + // 更新点的位置 + selectedPoint.position = newPosition + + // 创建新的位置数组,确保 Cesium 能够检测到变化 + const newPositions = [...selectedLineEntity.positions] + newPositions[pointIndex] = newPosition + + // 移除旧的线段实体 + this.viewer.entities.remove(selectedLineEntity.entity) + + // 清除所有可能存在的重复线段 + const entitiesToRemove = [] + this.viewer.entities.values.forEach(e => { + if (e.id && e.id === selectedLineEntity.id) { + entitiesToRemove.push(e) + } + }) + entitiesToRemove.forEach(e => { + this.viewer.entities.remove(e) + }) + + // 创建新的线段实体 + const newEntity = this.viewer.entities.add({ + id: selectedLineEntity.id, + name: selectedLineEntity.label, + polyline: { + positions: newPositions, + width: selectedLineEntity.width, + material: Cesium.Color.fromCssColorString(selectedLineEntity.color), + clampToGround: true + } + }) + + // 更新线实体的引用和位置数组 + selectedLineEntity.entity = newEntity + selectedLineEntity.positions = newPositions + + // 更新点数据 + selectedLineEntity.points[pointIndex] = this.cartesianToLatLng(newPosition) + + // 重新计算距离 + const length = this.calculateLineLength(selectedLineEntity.positions) + this.measurementResult = { + distance: length, + type: 'line' + } + + // 强制刷新地图渲染 + this.viewer.scene.requestRender() + } + } + }, Cesium.ScreenSpaceEventType.MOUSE_MOVE) + + // 鼠标释放事件:结束移动 + this.pointMovementHandler.setInputAction(() => { + // 恢复相机控制器 + if (originalCameraController !== null) { + this.viewer.scene.screenSpaceCameraController.enableInputs = originalCameraController + originalCameraController = null + } + + + + isMoving = false + selectedPoint = null + selectedLineEntity = null + pointIndex = -1 + }, Cesium.ScreenSpaceEventType.LEFT_UP) + }, + updateScaleBar() { // ... 原有的比例尺更新代码保持不变 }, @@ -2187,6 +2441,16 @@ export default { this.stopDrawing() this.clearAll() + if (this.pointMovementHandler) { + this.pointMovementHandler.destroy() + this.pointMovementHandler = null + } + + if (this.rightClickHandler) { + this.rightClickHandler.destroy() + this.rightClickHandler = null + } + if (this.viewer) { this.viewer.destroy() this.viewer = null From d40be59b6f597b570d55d69b34b5c350fe371270 Mon Sep 17 00:00:00 2001 From: ctw <1051735452@qq.com> Date: Fri, 23 Jan 2026 13:21:16 +0800 Subject: [PATCH 3/6] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=BA=BF=E7=9A=84?= =?UTF-8?q?=E6=82=AC=E5=81=9C=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-ui/src/views/cesiumMap/index.vue | 81 ++++++++++++++++++++++++++++++++-- 1 file changed, 77 insertions(+), 4 deletions(-) diff --git a/ruoyi-ui/src/views/cesiumMap/index.vue b/ruoyi-ui/src/views/cesiumMap/index.vue index 6087fa6..887b4d7 100644 --- a/ruoyi-ui/src/views/cesiumMap/index.vue +++ b/ruoyi-ui/src/views/cesiumMap/index.vue @@ -105,6 +105,11 @@ export default { }, beforeDestroy() { + // 销毁鼠标悬停事件处理器 + if (this.hoverHandler) { + this.hoverHandler.destroy(); + this.hoverHandler = null; + } this.destroyViewer() }, @@ -163,9 +168,10 @@ export default { }) this.initScaleBar() - this.initPointMovement() - this.initRightClickHandler() - console.log('Cesium离线二维地图已加载') + this.initPointMovement() + this.initRightClickHandler() + this.initHoverHandler() + console.log('Cesium离线二维地图已加载') } catch (error) { console.error('地图错误:', error) @@ -219,6 +225,57 @@ export default { } }, Cesium.ScreenSpaceEventType.RIGHT_CLICK) }, + + // 初始化鼠标悬停事件处理器 + initHoverHandler() { + // 创建屏幕空间事件处理器 + this.hoverHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas) + + // 鼠标移动事件:检测是否悬停在线上 + this.hoverHandler.setInputAction((movement) => { + // 如果正在绘制,不处理悬停操作 + if (this.isDrawing) { + return; + } + + const pickedObject = this.viewer.scene.pick(movement.endPosition) + + if (Cesium.defined(pickedObject) && pickedObject.id) { + const pickedEntity = pickedObject.id + + // 查找对应的实体数据 + let entityData = this.allEntities.find(e => e.entity === pickedEntity || e === pickedEntity) + + // 特殊处理:如果悬停的是线段上的点,找到对应的线实体 + if (!entityData) { + // 检查是否是线段上的点 + for (const lineEntity of this.allEntities) { + if (lineEntity.type === 'line' && lineEntity.pointEntities) { + if (lineEntity.pointEntities.includes(pickedEntity)) { + entityData = lineEntity + break + } + } + } + } + + // 如果是线实体,显示长度信息 + if (entityData && entityData.type === 'line') { + const length = this.calculateLineLength(entityData.positions) + this.measurementResult = { + distance: length, + type: 'line' + }; + } else { + // 如果不是线实体,隐藏信息 + this.measurementResult = null; + } + } else { + // 如果没有悬停在任何实体上,隐藏信息 + this.measurementResult = null; + } + }, Cesium.ScreenSpaceEventType.MOUSE_MOVE) + }, showErrorMessage() { const container = document.getElementById('cesiumViewer'); if (container) { @@ -414,6 +471,9 @@ export default { this.initRightClickHandler(); } + // 隐藏测量结果 + this.measurementResult = null; + this.viewer.scene.canvas.style.cursor = 'default'; }, @@ -462,11 +522,24 @@ export default { this.tempEntity = null; this.tempPreviewEntity = null; - // 1. 鼠标移动事件:更新坐标变量 + // 1. 鼠标移动事件:更新坐标变量并实时计算线段长度 this.drawingHandler.setInputAction((movement) => { const newPosition = this.getClickPosition(movement.endPosition); if (newPosition) { this.activeCursorPosition = newPosition; + + // 当已经有至少一个点时,实时计算线段长度 + if (this.drawingPoints.length > 0) { + // 计算从最后一个点到当前鼠标位置的线段长度 + const tempPositions = [...this.drawingPoints, newPosition]; + const length = this.calculateLineLength(tempPositions); + + // 更新测量结果,显示实时长度 + this.measurementResult = { + distance: length, + type: 'line' + }; + } } }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); From 1838c436f3e8a7b8309a4800ea4f9c5e4a14710d Mon Sep 17 00:00:00 2001 From: ctw <1051735452@qq.com> Date: Fri, 23 Jan 2026 15:47:09 +0800 Subject: [PATCH 4/6] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=B7=A6=E5=8F=B3?= =?UTF-8?q?=E8=8F=9C=E5=8D=95=E6=A0=8F=E6=98=BE=E7=A4=BA=E9=9A=90=E8=97=8F?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/application-druid.yml | 2 +- ruoyi-ui/src/store/getters.js | 1 + ruoyi-ui/src/store/modules/user.js | 7 ++- ruoyi-ui/src/views/childRoom/RightPanel.vue | 2 - ruoyi-ui/src/views/childRoom/index.vue | 26 ++++++++--- ruoyi-ui/src/views/dialogs/PlatformEditDialog.vue | 50 +++++++++++----------- ruoyi-ui/src/views/selectRoom/index.vue | 6 --- ruoyi-ui/vue.config.js | 2 +- 8 files changed, 54 insertions(+), 42 deletions(-) diff --git a/ruoyi-admin/src/main/resources/application-druid.yml b/ruoyi-admin/src/main/resources/application-druid.yml index c40f2aa..037db5c 100644 --- a/ruoyi-admin/src/main/resources/application-druid.yml +++ b/ruoyi-admin/src/main/resources/application-druid.yml @@ -8,7 +8,7 @@ spring: master: url: jdbc:mysql://localhost:3306/ry?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 username: root - password: A20040303ctw! + password: 123456 # 从库数据源 slave: # 从数据源开关/默认关闭 diff --git a/ruoyi-ui/src/store/getters.js b/ruoyi-ui/src/store/getters.js index 3680f95..a3906cf 100644 --- a/ruoyi-ui/src/store/getters.js +++ b/ruoyi-ui/src/store/getters.js @@ -13,6 +13,7 @@ const getters = { introduction: state => state.user.introduction, roles: state => state.user.roles, permissions: state => state.user.permissions, + userLevel: state => state.user.userLevel, permission_routes: state => state.permission.routes, topbarRouters: state => state.permission.topbarRouters, defaultRoutes: state => state.permission.defaultRoutes, diff --git a/ruoyi-ui/src/store/modules/user.js b/ruoyi-ui/src/store/modules/user.js index 6a7b710..5ea90a2 100644 --- a/ruoyi-ui/src/store/modules/user.js +++ b/ruoyi-ui/src/store/modules/user.js @@ -13,7 +13,8 @@ const user = { nickName: '', avatar: '', roles: [], - permissions: [] + permissions: [], + userLevel: '' }, mutations: { @@ -37,6 +38,9 @@ const user = { }, SET_PERMISSIONS: (state, permissions) => { state.permissions = permissions + }, + SET_USER_LEVEL: (state, userLevel) => { + state.userLevel = userLevel } }, @@ -77,6 +81,7 @@ const user = { commit('SET_NAME', user.userName) commit('SET_NICK_NAME', user.nickName) commit('SET_AVATAR', avatar) + commit('SET_USER_LEVEL', user.userLevel || '') /* 初始密码提示 */ if(res.isDefaultModifyPwd) { MessageBox.confirm('您的密码还是初始密码,请修改密码!', '安全提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => { diff --git a/ruoyi-ui/src/views/childRoom/RightPanel.vue b/ruoyi-ui/src/views/childRoom/RightPanel.vue index c199ccb..01ac0fe 100644 --- a/ruoyi-ui/src/views/childRoom/RightPanel.vue +++ b/ruoyi-ui/src/views/childRoom/RightPanel.vue @@ -27,7 +27,6 @@ 新建 -