WQQ 1 тиждень тому
батько
коміт
39165864f0
100 змінених файлів з 1218 додано та 51 видалено
  1. BIN
      RuoYi-Vue3/public/img/componentsImg/draw-solid-figuree.png
  2. 2 0
      RuoYi-Vue3/src/supermap-cesium-module/components/components.js
  3. 81 46
      RuoYi-Vue3/src/supermap-cesium-module/components/draw/add-point-symbol/add-point-symbol.js
  4. 8 2
      RuoYi-Vue3/src/supermap-cesium-module/components/draw/add-point-symbol/add-point-symbol.vue
  5. 128 0
      RuoYi-Vue3/src/supermap-cesium-module/components/draw/draw-solid-figure/draw-solid-figure.js
  6. 826 0
      RuoYi-Vue3/src/supermap-cesium-module/components/draw/draw-solid-figure/draw-solid-figure.vue
  7. 6 0
      RuoYi-Vue3/src/supermap-cesium-module/components/draw/draw-solid-figure/index.js
  8. 141 0
      RuoYi-Vue3/src/supermap-cesium-module/components/scale-bar/scale-bar.vue
  9. 4 1
      RuoYi-Vue3/src/supermap-cesium-module/components/viewer/viewer.js
  10. 4 1
      RuoYi-Vue3/src/supermap-cesium-module/components/viewer/viewer.vue
  11. 5 0
      RuoYi-Vue3/src/supermap-cesium-module/config/views_config.js
  12. 13 1
      RuoYi-Vue3/src/supermap-cesium-module/js/local/resourceCN.js
  13. BIN
      ruoyi-admin/target/classes/com/ruoyi/RuoYiApplication.class
  14. BIN
      ruoyi-admin/target/classes/com/ruoyi/RuoYiServletInitializer.class
  15. BIN
      ruoyi-admin/target/classes/com/ruoyi/web/controller/cesium/CesiumMapConfigController.class
  16. BIN
      ruoyi-admin/target/classes/com/ruoyi/web/controller/common/CaptchaController.class
  17. BIN
      ruoyi-admin/target/classes/com/ruoyi/web/controller/common/CommonController.class
  18. BIN
      ruoyi-admin/target/classes/com/ruoyi/web/controller/monitor/CacheController.class
  19. BIN
      ruoyi-admin/target/classes/com/ruoyi/web/controller/monitor/ServerController.class
  20. BIN
      ruoyi-admin/target/classes/com/ruoyi/web/controller/monitor/SysLogininforController.class
  21. BIN
      ruoyi-admin/target/classes/com/ruoyi/web/controller/monitor/SysOperlogController.class
  22. BIN
      ruoyi-admin/target/classes/com/ruoyi/web/controller/monitor/SysUserOnlineController.class
  23. BIN
      ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysConfigController.class
  24. BIN
      ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysDeptController.class
  25. BIN
      ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysDictDataController.class
  26. BIN
      ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysDictTypeController.class
  27. BIN
      ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysIndexController.class
  28. BIN
      ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysLoginController.class
  29. BIN
      ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysMenuController.class
  30. BIN
      ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysNoticeController.class
  31. BIN
      ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysPostController.class
  32. BIN
      ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysProfileController.class
  33. BIN
      ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysRegisterController.class
  34. BIN
      ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysRoleController.class
  35. BIN
      ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysUserController.class
  36. BIN
      ruoyi-admin/target/classes/com/ruoyi/web/controller/tool/TestController.class
  37. BIN
      ruoyi-admin/target/classes/com/ruoyi/web/controller/tool/UserEntity.class
  38. BIN
      ruoyi-admin/target/classes/com/ruoyi/web/controller/watershed/WatershedModelController.class
  39. BIN
      ruoyi-admin/target/classes/com/ruoyi/web/controller/watershed/WatershedServiceController.class
  40. BIN
      ruoyi-admin/target/classes/com/ruoyi/web/core/config/SwaggerConfig.class
  41. BIN
      ruoyi-common/target/classes/com/ruoyi/common/annotation/Excel$ColumnType.class
  42. BIN
      ruoyi-common/target/classes/com/ruoyi/common/annotation/Excel$Type.class
  43. BIN
      ruoyi-common/target/classes/com/ruoyi/common/annotation/Excel.class
  44. BIN
      ruoyi-common/target/classes/com/ruoyi/common/config/RuoYiConfig.class
  45. BIN
      ruoyi-common/target/classes/com/ruoyi/common/config/serializer/SensitiveJsonSerializer.class
  46. BIN
      ruoyi-common/target/classes/com/ruoyi/common/constant/CacheConstants.class
  47. BIN
      ruoyi-common/target/classes/com/ruoyi/common/constant/Constants.class
  48. BIN
      ruoyi-common/target/classes/com/ruoyi/common/constant/GenConstants.class
  49. BIN
      ruoyi-common/target/classes/com/ruoyi/common/constant/HttpStatus.class
  50. BIN
      ruoyi-common/target/classes/com/ruoyi/common/constant/ScheduleConstants$Status.class
  51. BIN
      ruoyi-common/target/classes/com/ruoyi/common/constant/ScheduleConstants.class
  52. BIN
      ruoyi-common/target/classes/com/ruoyi/common/constant/UserConstants.class
  53. BIN
      ruoyi-common/target/classes/com/ruoyi/common/core/controller/BaseController$1.class
  54. BIN
      ruoyi-common/target/classes/com/ruoyi/common/core/controller/BaseController.class
  55. BIN
      ruoyi-common/target/classes/com/ruoyi/common/core/domain/AjaxResult.class
  56. BIN
      ruoyi-common/target/classes/com/ruoyi/common/core/domain/BaseEntity.class
  57. BIN
      ruoyi-common/target/classes/com/ruoyi/common/core/domain/R.class
  58. BIN
      ruoyi-common/target/classes/com/ruoyi/common/core/domain/TreeEntity.class
  59. BIN
      ruoyi-common/target/classes/com/ruoyi/common/core/domain/TreeSelect.class
  60. BIN
      ruoyi-common/target/classes/com/ruoyi/common/core/domain/entity/SysDept.class
  61. BIN
      ruoyi-common/target/classes/com/ruoyi/common/core/domain/entity/SysDictData.class
  62. BIN
      ruoyi-common/target/classes/com/ruoyi/common/core/domain/entity/SysDictType.class
  63. BIN
      ruoyi-common/target/classes/com/ruoyi/common/core/domain/entity/SysMenu.class
  64. BIN
      ruoyi-common/target/classes/com/ruoyi/common/core/domain/entity/SysRole.class
  65. BIN
      ruoyi-common/target/classes/com/ruoyi/common/core/domain/entity/SysUser.class
  66. BIN
      ruoyi-common/target/classes/com/ruoyi/common/core/domain/model/LoginBody.class
  67. BIN
      ruoyi-common/target/classes/com/ruoyi/common/core/domain/model/LoginUser.class
  68. BIN
      ruoyi-common/target/classes/com/ruoyi/common/core/domain/model/RegisterBody.class
  69. BIN
      ruoyi-common/target/classes/com/ruoyi/common/core/page/PageDomain.class
  70. BIN
      ruoyi-common/target/classes/com/ruoyi/common/core/page/TableDataInfo.class
  71. BIN
      ruoyi-common/target/classes/com/ruoyi/common/core/page/TableSupport.class
  72. BIN
      ruoyi-common/target/classes/com/ruoyi/common/core/redis/RedisCache.class
  73. BIN
      ruoyi-common/target/classes/com/ruoyi/common/core/text/CharsetKit.class
  74. BIN
      ruoyi-common/target/classes/com/ruoyi/common/core/text/Convert.class
  75. BIN
      ruoyi-common/target/classes/com/ruoyi/common/core/text/StrFormatter.class
  76. BIN
      ruoyi-common/target/classes/com/ruoyi/common/enums/BusinessStatus.class
  77. BIN
      ruoyi-common/target/classes/com/ruoyi/common/enums/BusinessType.class
  78. BIN
      ruoyi-common/target/classes/com/ruoyi/common/enums/DataSourceType.class
  79. BIN
      ruoyi-common/target/classes/com/ruoyi/common/enums/DesensitizedType.class
  80. BIN
      ruoyi-common/target/classes/com/ruoyi/common/enums/HttpMethod.class
  81. BIN
      ruoyi-common/target/classes/com/ruoyi/common/enums/LimitType.class
  82. BIN
      ruoyi-common/target/classes/com/ruoyi/common/enums/OperatorType.class
  83. BIN
      ruoyi-common/target/classes/com/ruoyi/common/enums/UserStatus.class
  84. BIN
      ruoyi-common/target/classes/com/ruoyi/common/exception/DemoModeException.class
  85. BIN
      ruoyi-common/target/classes/com/ruoyi/common/exception/GlobalException.class
  86. BIN
      ruoyi-common/target/classes/com/ruoyi/common/exception/ServiceException.class
  87. BIN
      ruoyi-common/target/classes/com/ruoyi/common/exception/UtilException.class
  88. BIN
      ruoyi-common/target/classes/com/ruoyi/common/exception/base/BaseException.class
  89. BIN
      ruoyi-common/target/classes/com/ruoyi/common/exception/file/FileException.class
  90. BIN
      ruoyi-common/target/classes/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.class
  91. BIN
      ruoyi-common/target/classes/com/ruoyi/common/exception/file/FileSizeLimitExceededException.class
  92. BIN
      ruoyi-common/target/classes/com/ruoyi/common/exception/file/FileUploadException.class
  93. BIN
      ruoyi-common/target/classes/com/ruoyi/common/exception/file/InvalidExtensionException$InvalidFlashExtensionException.class
  94. BIN
      ruoyi-common/target/classes/com/ruoyi/common/exception/file/InvalidExtensionException$InvalidImageExtensionException.class
  95. BIN
      ruoyi-common/target/classes/com/ruoyi/common/exception/file/InvalidExtensionException$InvalidMediaExtensionException.class
  96. BIN
      ruoyi-common/target/classes/com/ruoyi/common/exception/file/InvalidExtensionException$InvalidVideoExtensionException.class
  97. BIN
      ruoyi-common/target/classes/com/ruoyi/common/exception/file/InvalidExtensionException.class
  98. BIN
      ruoyi-common/target/classes/com/ruoyi/common/exception/job/TaskException$Code.class
  99. BIN
      ruoyi-common/target/classes/com/ruoyi/common/exception/job/TaskException.class
  100. BIN
      ruoyi-common/target/classes/com/ruoyi/common/exception/user/BlackListException.class

BIN
RuoYi-Vue3/public/img/componentsImg/draw-solid-figuree.png


+ 2 - 0
RuoYi-Vue3/src/supermap-cesium-module/components/components.js

@@ -47,6 +47,7 @@ import addPbr from "./layer/pbr-material/index.js"
 
 import draw from "./draw/draw-line-surface/index.js"
 import symbol from "./draw/add-point-symbol/index.js"
+import drawSolidFigure from "./draw/draw-solid-figure/index.js"
 import light from "./scene/light/index.js"
 import projection from "./scene/projection-image/index.js"
 import pickCoordinate from "./scene/pick-coordinate/index.js"
@@ -94,6 +95,7 @@ const components = [
     flyRoute,
     draw,
     symbol,
+    drawSolidFigure,
     light,
     projection,
     pickCoordinate,

+ 81 - 46
RuoYi-Vue3/src/supermap-cesium-module/components/draw/add-point-symbol/add-point-symbol.js

@@ -23,8 +23,10 @@ function addPointSymbol(props) {
     // 传入props改变默认值
     if (props) {
         for (let key in props) {
-            if (state.hasOwnProperty(key)) {
+            if (state.hasOwnProperty(key) && props[key] !== undefined) {
                 state[key] = props[key]
+            } else if (state.hasOwnProperty(key) && props[key] === undefined) {
+                // 保持默认值
             } else {
                 tool.Message.errorMsg(resource.AttributeError + key);
             }
@@ -32,7 +34,7 @@ function addPointSymbol(props) {
     }
 
     // 初始化数据
-    let currentData = s3mModels[state.selectedTypeId].data;
+    let currentData = s3mModels[state.selectedTypeId] ? s3mModels[state.selectedTypeId].data : [];
     let s3mInstanceColc;
     let currentSelectedSymbol = null;
     let modelEditor, emitter;
@@ -74,14 +76,16 @@ function addPointSymbol(props) {
             document.body.classList.remove("measureCur");
             let position = scene.pickPosition(e.message.position);
             let color = Cesium.Color.fromCssColorString(state.symbolColor);
-            let id = 'symbol-' + s3mModels[state.selectedTypeId].id + '-' + currentData[state.selectedSymbolId].id + '-' + new Date().getTime()
-            let path = currentData[state.selectedSymbolId].path;
-            s3mInstanceColc.add(path, {
-                id: id,
-                position: position,
-                color: color
-            });
-            if (!currentUrls.includes(path)) currentUrls.push(path);
+            if (s3mModels[state.selectedTypeId] && currentData[state.selectedSymbolId]) {
+                let id = 'symbol-' + s3mModels[state.selectedTypeId].id + '-' + currentData[state.selectedSymbolId].id + '-' + new Date().getTime()
+                let path = currentData[state.selectedSymbolId].path;
+                s3mInstanceColc.add(path, {
+                    id: id,
+                    position: position,
+                    color: color
+                });
+                if (!currentUrls.includes(path)) currentUrls.push(path);
+            }
             isAddSingle = false;
             // currentSelectedSymbol = s3mInstanceColc.getInstance(currentData[state.selectedSymbolId].path, id)
             return;
@@ -163,38 +167,67 @@ function addPointSymbol(props) {
     }
 
     function DrawPolylineUpdate(position, line) {
+        if (!line || !line.positions || line.positions.length < 2) {
+            console.error('Invalid line object or positions array');
+            isAddLIneFace = false;
+            return;
+        }
+        
         let positions = [];
-        for (let i = 1, j = line._positions.length; i < j; i++) {
-            let startPoint = line._positions[i - 1];
-            let endPoint = line._positions[i];
-            let d = Cesium.Cartesian3.distance(startPoint, endPoint)
-            let count = getCount(parseInt(d));
-            for (let i = 1, j = count; i <= j; i++) {
-                positions.push(
-                    Cesium.Cartesian3.lerp(
-                        startPoint,
-                        endPoint,
-                        i / count,
-                        new Cesium.Cartesian3()
-                    )
-                );
+        for (let i = 1, j = line.positions.length; i < j; i++) {
+            let startPoint = line.positions[i - 1];
+            let endPoint = line.positions[i];
+            if (startPoint && endPoint) {
+                let d = Cesium.Cartesian3.distance(startPoint, endPoint);
+                let count = getCount(parseInt(d));
+                for (let k = 1, l = count; k <= l; k++) {
+                    positions.push(
+                        Cesium.Cartesian3.lerp(
+                            startPoint,
+                            endPoint,
+                            k / l,
+                            new Cesium.Cartesian3()
+                        )
+                    );
+                }
             }
         }
+        
+        if (positions.length === 0) {
+            console.error('No positions generated');
+            isAddLIneFace = false;
+            return;
+        }
+        
         viewer.scene.clampToHeightMostDetailed(positions)
             .then((Cartesians) => {
                 isAddLIneFace = false;
+                if (!Cartesians || Cartesians.length === 0) {
+                    console.error('No clamped positions returned');
+                    return;
+                }
+                
                 let color = Cesium.Color.fromCssColorString(state.symbolColor);
-                let id = 'symbol-' + s3mModels[state.selectedTypeId].id + '-' + currentData[state.selectedSymbolId].id + '-';
-                let path = currentData[state.selectedSymbolId].path;
-                if (!currentUrls.includes(path)) currentUrls.push(path);
-                for (let i = 0, j = Cartesians.length; i <= j; i++) {
-                    s3mInstanceColc.add(path, {
-                        id: id + new Date().getTime() + i,
-                        position: Cartesians[i],
-                        color: color
-                    });
+                if (s3mModels[state.selectedTypeId] && currentData[state.selectedSymbolId] && s3mInstanceColc) {
+                    let id = 'symbol-' + s3mModels[state.selectedTypeId].id + '-' + currentData[state.selectedSymbolId].id + '-';
+                    let path = currentData[state.selectedSymbolId].path;
+                    if (path) {
+                        if (!currentUrls.includes(path)) currentUrls.push(path);
+                        for (let i = 0, j = Cartesians.length; i < j; i++) {
+                            if (Cartesians[i]) {
+                                s3mInstanceColc.add(path, {
+                                    id: id + new Date().getTime() + i,
+                                    position: Cartesians[i],
+                                    color: color
+                                });
+                            }
+                        }
+                    }
                 }
-
+            })
+            .catch((error) => {
+                console.error('Error clamping positions to height:', error);
+                isAddLIneFace = false;
             });
     }
     //精度计算count插值
@@ -218,17 +251,19 @@ function addPointSymbol(props) {
                 handlerPolygon.deactivate();
                 emitter.initPolygonEmitter(res.result.object.positions)
                 let color = Cesium.Color.fromCssColorString(state.symbolColor);
-                let id = 'symbol-' + s3mModels[state.selectedTypeId].id + '-' + currentData[state.selectedSymbolId].id + '-';
-                let path = currentData[state.selectedSymbolId].path;
-                if (!currentUrls.includes(path)) currentUrls.push(path);
-                let density = Number(state.density);
-                for (let i = 0; i < density; i++) {
-                    let p = emitter.getOneRandomPosition()
-                    s3mInstanceColc.add(path, {
-                        id: id + new Date().getTime() + i,
-                        position: p,
-                        color: color
-                    });
+                if (s3mModels[state.selectedTypeId] && currentData[state.selectedSymbolId]) {
+                    let id = 'symbol-' + s3mModels[state.selectedTypeId].id + '-' + currentData[state.selectedSymbolId].id + '-';
+                    let path = currentData[state.selectedSymbolId].path;
+                    if (!currentUrls.includes(path)) currentUrls.push(path);
+                    let density = Number(state.density);
+                    for (let i = 0; i < density; i++) {
+                        let p = emitter.getOneRandomPosition()
+                        s3mInstanceColc.add(path, {
+                            id: id + new Date().getTime() + i,
+                            position: p,
+                            color: color
+                        });
+                    }
                 }
                 isAddLIneFace = false;
             },
@@ -276,7 +311,7 @@ function addPointSymbol(props) {
 
 
     watch(() => state.selectedTypeId, val => {
-        currentData = s3mModels[state.selectedTypeId].data;
+        currentData = s3mModels[val] ? s3mModels[val].data : [];
     })
     watch(() => state.symbolColor, val => {
         let color = Cesium.Color.fromCssColorString(val);

+ 8 - 2
RuoYi-Vue3/src/supermap-cesium-module/components/draw/add-point-symbol/add-point-symbol.vue

@@ -9,7 +9,7 @@
       </div>
       <div class="sm-half-L symbolic">
         <div
-          v-for="(model,index) in s3mModels[selectedTypeId].data"
+          v-for="(model,index) in (s3mModels[selectedTypeId] ? s3mModels[selectedTypeId].data : [])"
           :key="model.id"
           class="symbolic-box"
           style="width: 40px;"
@@ -50,6 +50,7 @@
 
 <script>
 import addPointSymbol from "./add-point-symbol.js";
+import Resource from '../../../js/local/lang.js';
 
 export default {
   name: "Sm3dPointSymbol",
@@ -69,6 +70,10 @@ export default {
     // 区域种树总数
     density: {
       type: Number
+    },
+    // 添加类型
+    addType: {
+      type: String
     }
   },
   setup(props) {
@@ -94,7 +99,8 @@ export default {
       density,
       clear,
       statrtAdd,
-      addType
+      addType,
+      Resource
     };
   }
 };

+ 128 - 0
RuoYi-Vue3/src/supermap-cesium-module/components/draw/draw-solid-figure/draw-solid-figure.js

@@ -0,0 +1,128 @@
+// 绘制体功能逻辑
+
+class DrawSolidFigure {
+  constructor(viewer) {
+    this.viewer = viewer;
+    this.handler = null;
+    this.currentEntity = null;
+  }
+
+  /**
+   * 初始化绘制处理器
+   */
+  initHandler() {
+    if (!this.handler) {
+      this.handler = new Cesium.DrawHandler(this.viewer, Cesium.DrawMode.Point);
+    }
+  }
+
+  /**
+   * 开始绘制几何体
+   * @param {string} type - 几何体类型:box, cylinder, sphere, cone
+   * @param {string} color - 颜色,十六进制字符串
+   * @param {number} opacity - 透明度,0-1
+   * @param {function} callback - 绘制完成后的回调函数
+   */
+  startDrawing(type, color, opacity, callback) {
+    this.initHandler();
+    this.clear();
+
+    const self = this;
+
+    this.handler.activate();
+
+    // 绘制完成事件
+    this.handler.drawEvt.addEventListener((result) => {
+      if (result.object) {
+        const position = result.object.position;
+        self.createSolid(position, type, color, opacity);
+        self.handler.deactivate();
+        if (callback) {
+          callback(self.currentEntity);
+        }
+      }
+    });
+  }
+
+  /**
+   * 创建几何体
+   * @param {Cesium.Cartesian3} position - 几何体位置
+   * @param {string} type - 几何体类型
+   * @param {string} color - 颜色
+   * @param {number} opacity - 透明度
+   */
+  createSolid(position, type, color, opacity) {
+    const cesiumColor = Cesium.Color.fromCssColorString(color).withAlpha(opacity);
+
+    switch (type) {
+      case 'box':
+        this.currentEntity = this.viewer.entities.add({
+          position: position,
+          box: {
+            dimensions: new Cesium.Cartesian3(100, 100, 100),
+            material: cesiumColor
+          }
+        });
+        break;
+      case 'cylinder':
+        this.currentEntity = this.viewer.entities.add({
+          position: position,
+          cylinder: {
+            length: 200,
+            topRadius: 50,
+            bottomRadius: 50,
+            material: cesiumColor
+          }
+        });
+        break;
+      case 'sphere':
+        this.currentEntity = this.viewer.entities.add({
+          position: position,
+          ellipsoid: {
+            radii: new Cesium.Cartesian3(100, 100, 100),
+            material: cesiumColor
+          }
+        });
+        break;
+      case 'cone':
+        this.currentEntity = this.viewer.entities.add({
+          position: position,
+          cylinder: {
+            length: 200,
+            topRadius: 0,
+            bottomRadius: 100,
+            material: cesiumColor
+          }
+        });
+        break;
+      default:
+        break;
+    }
+
+    return this.currentEntity;
+  }
+
+  /**
+   * 清除绘制
+   */
+  clear() {
+    if (this.handler) {
+      this.handler.deactivate();
+      this.handler.clear();
+    }
+    if (this.currentEntity) {
+      this.viewer.entities.remove(this.currentEntity);
+      this.currentEntity = null;
+    }
+  }
+
+  /**
+   * 销毁
+   */
+  destroy() {
+    this.clear();
+    this.handler = null;
+  }
+}
+
+export default DrawSolidFigure;

+ 826 - 0
RuoYi-Vue3/src/supermap-cesium-module/components/draw/draw-solid-figure/draw-solid-figure.vue

@@ -0,0 +1,826 @@
+<template>
+  <div id="draw-panel" class="sm-panel" v-drag>
+    <div class="sm-function-module-sub-section" style="margin:0" v-stopdrag>
+      <div class="sm-half-L">
+        <label style="width:auto">
+          <input type="radio" value="single" v-model="drawMode" />
+          单个
+        </label>
+        <label style="width:auto">
+          <input type="radio" value="continuous" v-model="drawMode" />
+          连续
+        </label>
+      </div>
+      <div class="sm-half-L symbolic">
+        <div
+          v-for="model in basicGeometries"
+          :key="model.type"
+          class="symbolic-box"
+          style="width: 40px;"
+          :class="{ 'theme-border-color': selectedModel && selectedModel.type === model.type }"
+          @click="selectModel(model)"
+        >
+          <img :src="model.thumbnail" alt="" class="model-thumbnail" />
+          <label style="width:100%">{{ model.name }}</label>
+        </div>
+      </div>
+      <div class="sm-half-L">
+        <label style="width: 35%;">颜色</label>
+        <el-color-picker v-model="selectedColor" size="mini" style="width:63%"></el-color-picker>
+      </div>
+      <div class="sm-half-L">
+        <label style="width: 35%;">透明度</label>
+        <el-slider v-model="selectedOpacity" :min="0" :max="1" :step="0.1" style="width:63%"></el-slider>
+      </div>
+      <div class="sm-half-L" v-if="selectedEntity">
+        <label style="width: 35%;">位置 X</label>
+        <input type="number" class="sm-input" style="width:63%" step="0.1" v-model="position.x" />
+      </div>
+      <div class="sm-half-L" v-if="selectedEntity">
+        <label style="width: 35%;">位置 Y</label>
+        <input type="number" class="sm-input" style="width:63%" step="0.1" v-model="position.y" />
+      </div>
+      <div class="sm-half-L" v-if="selectedEntity">
+        <label style="width: 35%;">位置 Z</label>
+        <input type="number" class="sm-input" style="width:63%" step="0.1" v-model="position.z" />
+      </div>
+      <div class="sm-half-L" v-if="selectedEntity" style="display: flex; align-items: center;">
+        <label style="width: 35%;">旋转</label>
+        <div style="width:63%; display: flex; gap: 4px;">
+          <input type="number" class="sm-input" style="flex: 1; width: 45px;" step="1" v-model="rotation.x" />
+          <input type="number" class="sm-input" style="flex: 1; width: 45px;" step="1" v-model="rotation.y" />
+          <input type="number" class="sm-input" style="flex: 1; width: 45px;" step="1" v-model="rotation.z" />
+        </div>
+      </div>
+      <div class="sm-half-L" v-if="selectedEntity" style="display: flex; align-items: center;">
+        <label style="width: 35%;">缩放</label>
+        <div style="width:63%; display: flex; gap: 4px;">
+          <input type="number" class="sm-input" style="flex: 1; width: 45px;" step="0.1" min="0.1" v-model="scale.x" />
+          <input type="number" class="sm-input" style="flex: 1; width: 45px;" step="0.1" min="0.1" v-model="scale.y" />
+          <input type="number" class="sm-input" style="flex: 1; width: 45px;" step="0.1" min="0.1" v-model="scale.z" />
+        </div>
+      </div>
+      <div class="boxchild">
+        <button class="tbtn" type="button" v-on:click="startDraw">{{ isDrawing ? '停止绘制' : '绘制' }}</button>
+        <button class="tbtn tbtn-margin-left" type="button" v-on:click="clear">清除</button>
+        <button class="tbtn tbtn-margin-left" type="button" v-on:click="close">关闭</button>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { ref, onMounted, onUnmounted, reactive, watch } from 'vue';
+import { ElMessage } from 'element-plus';
+
+export default {
+  name: 'Sm3dDrawSolidFigure',
+  emits: ['close'],
+  setup(props, { emit }) {
+    // 基础几何体模型
+    const basicGeometries = ref([
+      {
+        type: 'box',
+        name: '立方体',
+        thumbnail: '/img/componentsImg/draw-solid-figuree.png',
+        dimensions: { x: 1, y: 1, z: 1 }
+      },
+      {
+        type: 'cylinder',
+        name: '圆柱体',
+        thumbnail: '/img/componentsImg/draw-solid-figuree.png',
+        dimensions: { length: 1, radius: 0.5 }
+      },
+      {
+        type: 'sphere',
+        name: '球体',
+        thumbnail: '/img/componentsImg/draw-solid-figuree.png',
+        dimensions: { radius: 0.5 }
+      },
+      {
+        type: 'cone',
+        name: '圆锥体',
+        thumbnail: '/img/componentsImg/draw-solid-figuree.png',
+        dimensions: { length: 1, radius: 0.5 }
+      }
+    ]);
+
+    // 选中的实体
+    const selectedEntity = ref(null);
+    // 选中实体的属性
+    const selectedColor = ref('#409eff');
+    const selectedOpacity = ref(0.8);
+    const position = reactive({ x: 0, y: 0, z: 0 });
+    const rotation = reactive({ x: 0, y: 0, z: 0 });
+    const scale = reactive({ x: 1, y: 1, z: 1 });
+    // 绘制模式
+    const drawMode = ref('single');
+    // 选中的模型类型
+    const selectedModel = ref(null);
+    // 绘制状态
+    const isDrawing = ref(false);
+    // 绘制激活标志,用于区分是否正在进行绘制(避免与选中实体冲突)
+    let isDrawHandlerActive = false;
+    // 防止循环更新的标志
+    let isUpdatingProperties = false;
+
+    let viewer = null;
+    let currentEditor = null;
+
+    const close = () => {
+      // 通知父组件关闭此组件
+      emit('close', 'Sm3dDrawSolidFigure');
+    };
+
+    // 选择模型类型
+    const selectModel = (model) => {
+      selectedModel.value = model;
+      ElMessage.success(`已选择 ${model.name}`);
+    };
+
+    // 开始绘制
+    const startDraw = () => {
+      console.log('startDraw called, isDrawing:', isDrawing.value, 'selectedModel:', selectedModel.value);
+      if (!selectedModel.value) {
+        ElMessage.warning('请先选择模型类型');
+        return;
+      }
+      isDrawing.value = !isDrawing.value;
+      console.log('After toggle, isDrawing:', isDrawing.value);
+      if (isDrawing.value) {
+        // 清除之前选中的实体的高亮
+        if (selectedEntity.value) {
+          removeHighlight(selectedEntity.value);
+          if (currentEditor) {
+            currentEditor.deactivate();
+            currentEditor = null;
+          }
+          selectedEntity.value = null;
+        }
+        isDrawHandlerActive = true;
+        viewer.enableCursorStyle = false;
+        viewer._element.style.cursor = 'crosshair';
+        ElMessage.success(`开始${drawMode.value === 'single' ? '单个' : '连续'}绘制模式`);
+      } else {
+        ElMessage.info('已停止绘制');
+        selectedModel.value = null;
+        isDrawHandlerActive = false;
+        viewer.enableCursorStyle = true;
+        viewer._element.style.cursor = 'default';
+      }
+    };
+
+    // 清除所有模型
+    const clear = () => {
+      if (viewer) {
+        viewer.entities.removeAll();
+        selectedEntity.value = null;
+        selectedModel.value = null;
+        isDrawing.value = false;
+        if (currentEditor) {
+          currentEditor.deactivate();
+          currentEditor = null;
+        }
+        ElMessage.success('已清除所有模型');
+      }
+    };
+
+    // 左键点击处理
+    const onLeftClick = (movement) => {
+      console.log('=== Left click ===');
+      console.log('isDrawing:', isDrawing.value);
+      console.log('selectedModel:', selectedModel.value);
+      console.log('drawMode:', drawMode.value);
+
+      // 绘制模式
+      if (isDrawing.value === true && selectedModel.value !== null) {
+        console.log('Entering DRAW mode');
+
+        let position = viewer.scene.pickPosition(movement.position);
+        console.log('Position:', position, 'defined:', Cesium.defined(position));
+
+        if (!Cesium.defined(position)) {
+          console.warn('Cannot get position');
+          return;
+        }
+
+        createGeometry(position, selectedModel.value);
+        console.log('Geometry created, drawMode:', drawMode.value);
+
+        if (drawMode.value === 'single') {
+          console.log('Single mode - stopping draw');
+          isDrawing.value = false;
+          isDrawHandlerActive = false;
+          selectedModel.value = null;
+          viewer.enableCursorStyle = true;
+          viewer._element.style.cursor = 'default';
+          ElMessage.info('已完成单个绘制');
+        } else {
+          console.log('Continuous mode - continuing');
+        }
+        return;
+      }
+
+      console.log('Entering SELECT mode');
+
+      // 非绘制模式:选择实体
+      let pickedObject = viewer.scene.pick(movement.position);
+      console.log('Picked object:', pickedObject);
+
+      if (Cesium.defined(pickedObject) && pickedObject.id) {
+        selectEntity(pickedObject.id);
+      } else if (isDrawing.value === false) {
+        clearSelection();
+      }
+    };
+
+    // 右键点击处理
+    const onRightClick = (movement) => {
+      console.log('=== Right click ===');
+      console.log('isDrawing:', isDrawing.value);
+      console.log('drawMode:', drawMode.value);
+      console.log('Condition result:', isDrawing.value === true && drawMode.value === 'continuous');
+
+      if (isDrawing.value === true && drawMode.value === 'continuous') {
+        console.log('Stopping continuous draw');
+        isDrawing.value = false;
+        isDrawHandlerActive = false;
+        selectedModel.value = null;
+        viewer.enableCursorStyle = true;
+        viewer._element.style.cursor = 'default';
+        ElMessage.info('已结束连续绘制');
+      }
+    };
+
+    // 阻止右键默认菜单
+    const onContextMenu = (event) => {
+      if (isDrawing.value) {
+        event.preventDefault();
+      }
+    };
+
+    // 键盘事件处理函数
+    const handleKeyDown = (event) => {
+      if (event.key === 'Enter') {
+        event.preventDefault();
+      }
+    };
+
+    // 初始化场景事件
+    const initSceneEvents = () => {
+      if (!viewer) return;
+
+      // 左键点击 - 绘制或选择
+      viewer.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
+      viewer.screenSpaceEventHandler.setInputAction(onLeftClick, Cesium.ScreenSpaceEventType.LEFT_CLICK);
+
+      // 右键点击 - 结束连续绘制
+      viewer.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK);
+      viewer.screenSpaceEventHandler.setInputAction(onRightClick, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
+
+      // 阻止右键默认菜单
+      viewer._element.addEventListener('contextmenu', onContextMenu);
+
+      // 键盘事件
+      document.addEventListener('keydown', handleKeyDown);
+    };
+
+    // 清理事件
+    const cleanupEvents = () => {
+      if (viewer) {
+        viewer.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
+        viewer.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK);
+        viewer._element.removeEventListener('contextmenu', onContextMenu);
+        viewer.enableCursorStyle = true;
+        viewer._element.style.cursor = 'default';
+      }
+      document.removeEventListener('keydown', handleKeyDown);
+      if (currentEditor) {
+        currentEditor.deactivate();
+        currentEditor = null;
+      }
+      isDrawing.value = false;
+      isDrawHandlerActive = false;
+    };
+
+    // 选择实体
+    const selectEntity = (entity) => {
+      if (selectedEntity.value) {
+        removeHighlight(selectedEntity.value);
+        if (currentEditor) {
+          currentEditor.deactivate();
+          currentEditor = null;
+        }
+      }
+      selectedEntity.value = entity;
+      updateSelectedEntityProperties();
+      addHighlight(entity);
+      addEditor(entity);
+    };
+
+    // 清除选择
+    const clearSelection = () => {
+      if (selectedEntity.value) {
+        removeHighlight(selectedEntity.value);
+        if (currentEditor) {
+          currentEditor.deactivate();
+          currentEditor = null;
+        }
+        selectedEntity.value = null;
+      }
+    };
+
+    // 添加模型高亮效果
+    const addHighlight = (entity) => {
+      if (!entity) return;
+
+      // 保存原始状态(只在第一次保存)
+      if (entity.box) {
+        if (entity.originalOutline === undefined) {
+          entity.originalOutline = entity.box.outline;
+          entity.originalOutlineColor = entity.box.outlineColor;
+        }
+        entity.box.outline = true;
+        entity.box.outlineColor = new Cesium.Color(1, 1, 0, 1);
+      } else if (entity.cylinder) {
+        if (entity.originalOutline === undefined) {
+          entity.originalOutline = entity.cylinder.outline;
+          entity.originalOutlineColor = entity.cylinder.outlineColor;
+        }
+        entity.cylinder.outline = true;
+        entity.cylinder.outlineColor = new Cesium.Color(1, 1, 0, 1);
+      } else if (entity.ellipsoid) {
+        if (entity.originalOutline === undefined) {
+          entity.originalOutline = entity.ellipsoid.outline;
+          entity.originalOutlineColor = entity.ellipsoid.outlineColor;
+        }
+        entity.ellipsoid.outline = true;
+        entity.ellipsoid.outlineColor = new Cesium.Color(1, 1, 0, 1);
+      }
+    };
+
+    // 移除模型高亮效果
+    const removeHighlight = (entity) => {
+      if (!entity) return;
+
+      if (entity.box) {
+        if (entity.originalOutline !== undefined) {
+          entity.box.outline = entity.originalOutline;
+          entity.box.outlineColor = entity.originalOutlineColor;
+        } else {
+          entity.box.outline = false;
+        }
+      } else if (entity.cylinder) {
+        if (entity.originalOutline !== undefined) {
+          entity.cylinder.outline = entity.originalOutline;
+          entity.cylinder.outlineColor = entity.originalOutlineColor;
+        } else {
+          entity.cylinder.outline = false;
+        }
+      } else if (entity.ellipsoid) {
+        if (entity.originalOutline !== undefined) {
+          entity.ellipsoid.outline = entity.originalOutline;
+          entity.ellipsoid.outlineColor = entity.originalOutlineColor;
+        } else {
+          entity.ellipsoid.outline = false;
+        }
+      }
+    };
+
+    // 添加操作轴编辑器
+    const addEditor = (entity) => {
+      if (!entity) return;
+
+      // 清除之前的编辑器
+      if (currentEditor) {
+        currentEditor.deactivate();
+        currentEditor = null;
+      }
+    };
+
+    // 创建几何体
+    const createGeometry = (position, model) => {
+      if (!viewer) return;
+
+      const color = Cesium.Color.fromCssColorString(selectedColor.value).withAlpha(selectedOpacity.value);
+      let entity;
+
+      switch (model.type) {
+        case 'box':
+          entity = viewer.entities.add({
+            position: position,
+            box: {
+              dimensions: new Cesium.Cartesian3(model.dimensions.x, model.dimensions.y, model.dimensions.z),
+              material: new Cesium.ColorMaterialProperty(color)
+            },
+            modelType: model.type,
+            modelName: model.name,
+            originalDimensions: new Cesium.Cartesian3(model.dimensions.x, model.dimensions.y, model.dimensions.z),
+            _rotation: { x: 0, y: 0, z: 0 },
+            _scale: { x: 1, y: 1, z: 1 }
+          });
+          break;
+        case 'sphere':
+          entity = viewer.entities.add({
+            position: position,
+            ellipsoid: {
+              radii: new Cesium.Cartesian3(model.dimensions.radius, model.dimensions.radius, model.dimensions.radius),
+              material: new Cesium.ColorMaterialProperty(color)
+            },
+            modelType: model.type,
+            modelName: model.name,
+            originalDimensions: new Cesium.Cartesian3(model.dimensions.radius, model.dimensions.radius, model.dimensions.radius),
+            _rotation: { x: 0, y: 0, z: 0 },
+            _scale: { x: 1, y: 1, z: 1 }
+          });
+          break;
+        case 'cylinder':
+          entity = viewer.entities.add({
+            position: position,
+            cylinder: {
+              length: model.dimensions.length,
+              topRadius: model.dimensions.radius,
+              bottomRadius: model.dimensions.radius,
+              material: new Cesium.ColorMaterialProperty(color)
+            },
+            modelType: model.type,
+            modelName: model.name,
+            originalDimensions: {
+              length: model.dimensions.length,
+              topRadius: model.dimensions.radius,
+              bottomRadius: model.dimensions.radius
+            },
+            _rotation: { x: 0, y: 0, z: 0 },
+            _scale: { x: 1, y: 1, z: 1 }
+          });
+          break;
+        case 'ellipsoid':
+          entity = viewer.entities.add({
+            position: position,
+            ellipsoid: {
+              radii: new Cesium.Cartesian3(model.dimensions.x, model.dimensions.y, model.dimensions.z),
+              material: new Cesium.ColorMaterialProperty(color)
+            },
+            modelType: model.type,
+            modelName: model.name,
+            originalDimensions: new Cesium.Cartesian3(model.dimensions.x, model.dimensions.y, model.dimensions.z),
+            _rotation: { x: 0, y: 0, z: 0 },
+            _scale: { x: 1, y: 1, z: 1 }
+          });
+          break;
+        case 'cone':
+          entity = viewer.entities.add({
+            position: position,
+            cylinder: {
+              length: model.dimensions.length,
+              topRadius: 0,
+              bottomRadius: model.dimensions.radius,
+              material: new Cesium.ColorMaterialProperty(color)
+            },
+            modelType: model.type,
+            modelName: model.name,
+            originalDimensions: {
+              length: model.dimensions.length,
+              topRadius: 0,
+              bottomRadius: model.dimensions.radius
+            },
+            _rotation: { x: 0, y: 0, z: 0 },
+            _scale: { x: 1, y: 1, z: 1 }
+          });
+          break;
+        default:
+          return;
+      }
+
+      if (entity) {
+        ElMessage.success(`${model.name} 创建成功`);
+        // 清除之前的高亮和编辑器
+        if (selectedEntity.value) {
+          removeHighlight(selectedEntity.value);
+          if (currentEditor) {
+            currentEditor.deactivate();
+            currentEditor = null;
+          }
+        }
+        selectedEntity.value = entity;
+        updateSelectedEntityProperties();
+        // 添加高亮效果
+        addHighlight(entity);
+        // 添加操作轴
+        addEditor(entity);
+        return entity;
+      }
+      return null;
+    };
+
+    // 更新选中实体的属性
+    const updateSelectedEntityProperties = () => {
+      if (!selectedEntity.value) return;
+
+      console.log('Updating properties for entity:', selectedEntity.value);
+
+      // 获取实体
+      const entity = selectedEntity.value;
+
+      // 设置标志,防止循环更新
+      isUpdatingProperties = true;
+
+      // 更新位置(经纬度保留6位小数,高度保留6位小数)
+      const cartesian = entity.position.getValue(viewer.clock.currentTime);
+      if (cartesian) {
+        const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
+        position.x = Number(Cesium.Math.toDegrees(cartographic.longitude).toFixed(6));
+        position.y = Number(Cesium.Math.toDegrees(cartographic.latitude).toFixed(6));
+        position.z = Number(cartographic.height.toFixed(6));
+      }
+
+      // 更新颜色和透明度
+      let material = null;
+      if (entity.box) {
+        material = entity.box.material;
+      } else if (entity.cylinder) {
+        material = entity.cylinder.material;
+      } else if (entity.ellipsoid) {
+        material = entity.ellipsoid.material;
+      }
+
+      if (material) {
+        let color = null;
+        if (material.color) {
+          if (typeof material.color.getValue === 'function') {
+            color = material.color.getValue(viewer.clock.currentTime);
+          } else {
+            color = material.color;
+          }
+        }
+        if (color instanceof Cesium.Color) {
+          selectedColor.value = color.toCssColorString();
+          selectedOpacity.value = Number(color.alpha.toFixed(2));
+        } else if (material instanceof Cesium.Color) {
+          selectedColor.value = material.toCssColorString();
+          selectedOpacity.value = Number(material.alpha.toFixed(2));
+        }
+      }
+
+      // 更新旋转(保留2位小数)
+      if (entity._rotation) {
+        // 优先使用保存的旋转值
+        rotation.x = Number(entity._rotation.x.toFixed(2));
+        rotation.y = Number(entity._rotation.y.toFixed(2));
+        rotation.z = Number(entity._rotation.z.toFixed(2));
+      } else if (entity.orientation) {
+        try {
+          const orientation = entity.orientation.getValue ? entity.orientation.getValue(viewer.clock.currentTime) : entity.orientation;
+          if (orientation) {
+            const hpr = Cesium.HeadingPitchRoll.fromQuaternion(orientation);
+            rotation.x = Number(Cesium.Math.toDegrees(hpr.pitch).toFixed(2));
+            rotation.y = Number(Cesium.Math.toDegrees(hpr.heading).toFixed(2));
+            rotation.z = Number(Cesium.Math.toDegrees(hpr.roll).toFixed(2));
+            // 保存初始旋转值
+            entity._rotation = { x: rotation.x, y: rotation.y, z: rotation.z };
+          }
+        } catch (error) {
+          console.error('Error updating rotation:', error);
+        }
+      } else {
+        rotation.x = 0;
+        rotation.y = 0;
+        rotation.z = 0;
+        // 保存初始旋转值
+        entity._rotation = { x: 0, y: 0, z: 0 };
+      }
+
+      // 更新缩放 - 从实体保存的原始尺寸计算(保留2位小数)
+      if (entity._scale) {
+        // 优先使用保存的缩放值
+        scale.x = Number(entity._scale.x.toFixed(2));
+        scale.y = Number(entity._scale.y.toFixed(2));
+        scale.z = Number(entity._scale.z.toFixed(2));
+      } else if (entity.box) {
+        if (entity.originalDimensions) {
+          const currentDimensions = entity.box.dimensions.getValue ? entity.box.dimensions.getValue(viewer.clock.currentTime) : entity.box.dimensions;
+          if (currentDimensions && entity.originalDimensions) {
+            scale.x = Number((currentDimensions.x / entity.originalDimensions.x).toFixed(2));
+            scale.y = Number((currentDimensions.y / entity.originalDimensions.y).toFixed(2));
+            scale.z = Number((currentDimensions.z / entity.originalDimensions.z).toFixed(2));
+            // 保存缩放值
+            entity._scale = { x: scale.x, y: scale.y, z: scale.z };
+          }
+        } else {
+          scale.x = 1;
+          scale.y = 1;
+          scale.z = 1;
+          // 保存缩放值
+          entity._scale = { x: 1, y: 1, z: 1 };
+        }
+      } else if (entity.cylinder) {
+        if (entity.originalDimensions) {
+          const currentLength = entity.cylinder.length.getValue ? entity.cylinder.length.getValue(viewer.clock.currentTime) : entity.cylinder.length;
+          const currentTopRadius = entity.cylinder.topRadius.getValue ? entity.cylinder.topRadius.getValue(viewer.clock.currentTime) : entity.cylinder.topRadius;
+          const currentBottomRadius = entity.cylinder.bottomRadius.getValue ? entity.cylinder.bottomRadius.getValue(viewer.clock.currentTime) : entity.cylinder.bottomRadius;
+          if (currentLength && entity.originalDimensions.length) {
+            // X轴向控制一个方向的半径,Y轴向控制另一个方向的半径,Z轴向控制高度
+            scale.x = Number((currentTopRadius / entity.originalDimensions.topRadius).toFixed(2));
+            scale.y = Number((currentBottomRadius / entity.originalDimensions.bottomRadius).toFixed(2));
+            scale.z = Number((currentLength / entity.originalDimensions.length).toFixed(2));
+            // 保存缩放值
+            entity._scale = { x: scale.x, y: scale.y, z: scale.z };
+          }
+        } else {
+          scale.x = 1;
+          scale.y = 1;
+          scale.z = 1;
+          // 保存缩放值
+          entity._scale = { x: 1, y: 1, z: 1 };
+        }
+      } else if (entity.ellipsoid) {
+        if (entity.originalDimensions) {
+          const currentRadii = entity.ellipsoid.radii.getValue ? entity.ellipsoid.radii.getValue(viewer.clock.currentTime) : entity.ellipsoid.radii;
+          if (currentRadii && entity.originalDimensions) {
+            scale.x = Number((currentRadii.x / entity.originalDimensions.x).toFixed(2));
+            scale.y = Number((currentRadii.y / entity.originalDimensions.y).toFixed(2));
+            scale.z = Number((currentRadii.z / entity.originalDimensions.z).toFixed(2));
+            // 保存缩放值
+            entity._scale = { x: scale.x, y: scale.y, z: scale.z };
+          }
+        } else {
+          scale.x = 1;
+          scale.y = 1;
+          scale.z = 1;
+          // 保存缩放值
+          entity._scale = { x: 1, y: 1, z: 1 };
+        }
+      }
+
+      // 重置标志
+      isUpdatingProperties = false;
+
+      console.log('Updated properties:', {
+        selectedColor: selectedColor.value,
+        selectedOpacity: selectedOpacity.value,
+        rotation: rotation,
+        scale: scale
+      });
+    };
+
+    // 监听属性变化,更新实体
+    watch(selectedColor, (newColor) => {
+      if (!selectedEntity.value) return;
+      const color = Cesium.Color.fromCssColorString(newColor).withAlpha(selectedOpacity.value);
+      const material = new Cesium.ColorMaterialProperty(color);
+      if (selectedEntity.value.box) {
+        selectedEntity.value.box.material = material;
+      } else if (selectedEntity.value.cylinder) {
+        selectedEntity.value.cylinder.material = material;
+      } else if (selectedEntity.value.ellipsoid) {
+        selectedEntity.value.ellipsoid.material = material;
+      }
+    });
+
+    watch(selectedOpacity, (newOpacity) => {
+      if (!selectedEntity.value) return;
+      const color = Cesium.Color.fromCssColorString(selectedColor.value).withAlpha(newOpacity);
+      const material = new Cesium.ColorMaterialProperty(color);
+      if (selectedEntity.value.box) {
+        selectedEntity.value.box.material = material;
+      } else if (selectedEntity.value.cylinder) {
+        selectedEntity.value.cylinder.material = material;
+      } else if (selectedEntity.value.ellipsoid) {
+        selectedEntity.value.ellipsoid.material = material;
+      }
+    });
+
+    watch(position, (newPosition) => {
+      if (!selectedEntity.value) return;
+      const cartesian = Cesium.Cartesian3.fromDegrees(newPosition.x, newPosition.y, newPosition.z);
+      selectedEntity.value.position = cartesian;
+    }, { deep: true });
+
+    watch(scale, (newScale) => {
+      if (!selectedEntity.value) return;
+      console.log('Scale changed:', newScale, 'Entity:', selectedEntity.value);
+      // 保存缩放值到实体对象中(使用对象字面量创建新对象,避免引用问题)
+      selectedEntity.value._scale = { x: newScale.x, y: newScale.y, z: newScale.z };
+      // 保存原始尺寸,避免累积缩放
+      if (selectedEntity.value.box) {
+        // 保存原始尺寸
+        if (!selectedEntity.value.originalDimensions) {
+          selectedEntity.value.originalDimensions = selectedEntity.value.box.dimensions.getValue(viewer.clock.currentTime);
+        }
+        const originalDimensions = selectedEntity.value.originalDimensions;
+        selectedEntity.value.box.dimensions = new Cesium.Cartesian3(originalDimensions.x * newScale.x, originalDimensions.y * newScale.y, originalDimensions.z * newScale.z);
+      } else if (selectedEntity.value.cylinder) {
+        // 保存原始尺寸
+        if (!selectedEntity.value.originalDimensions) {
+          selectedEntity.value.originalDimensions = {
+            length: selectedEntity.value.cylinder.length.getValue(viewer.clock.currentTime),
+            topRadius: selectedEntity.value.cylinder.topRadius.getValue(viewer.clock.currentTime),
+            bottomRadius: selectedEntity.value.cylinder.bottomRadius.getValue(viewer.clock.currentTime)
+          };
+        }
+        const originalDimensions = selectedEntity.value.originalDimensions;
+        // X轴向控制一个方向的半径,Y轴向控制另一个方向的半径,Z轴向控制高度
+        selectedEntity.value.cylinder.length = originalDimensions.length * newScale.z;
+        selectedEntity.value.cylinder.topRadius = originalDimensions.topRadius * newScale.x;
+        selectedEntity.value.cylinder.bottomRadius = originalDimensions.bottomRadius * newScale.y;
+      } else if (selectedEntity.value.ellipsoid) {
+        // 保存原始尺寸
+        if (!selectedEntity.value.originalDimensions) {
+          selectedEntity.value.originalDimensions = selectedEntity.value.ellipsoid.radii.getValue(viewer.clock.currentTime);
+        }
+        const originalDimensions = selectedEntity.value.originalDimensions;
+        selectedEntity.value.ellipsoid.radii = new Cesium.Cartesian3(originalDimensions.x * newScale.x, originalDimensions.y * newScale.y, originalDimensions.z * newScale.z);
+      }
+    }, { deep: true });
+
+    // 监听旋转变化,更新实体
+    watch(rotation, (newRotation) => {
+      if (!selectedEntity.value || isUpdatingProperties) return;
+      // 计算旋转矩阵
+      const heading = Cesium.Math.toRadians(newRotation.y);
+      const pitch = Cesium.Math.toRadians(newRotation.x);
+      const roll = Cesium.Math.toRadians(newRotation.z);
+      const hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);
+      const orientation = Cesium.Transforms.headingPitchRollQuaternion(
+        selectedEntity.value.position.getValue(viewer.clock.currentTime),
+        hpr
+      );
+      selectedEntity.value.orientation = orientation;
+      // 保存原始旋转值到实体
+      selectedEntity.value._rotation = { ...newRotation };
+    }, { deep: true });
+
+    onMounted(() => {
+      console.log('Sm3dDrawSolidFigure mounted, viewer:', window.viewer);
+      viewer = window.viewer;
+      if (viewer) {
+        console.log('Initializing scene events...');
+        initSceneEvents();
+      } else {
+        console.error('Viewer not found!');
+      }
+    });
+
+    onUnmounted(() => {
+      // 清理事件
+      cleanupEvents();
+    });
+
+    return {
+      basicGeometries,
+      selectedEntity,
+      selectedColor,
+      selectedOpacity,
+      position,
+      rotation,
+      scale,
+      drawMode,
+      selectedModel,
+      isDrawing,
+      close,
+      selectModel,
+      startDraw,
+      clear
+    };
+  }
+};
+</script>
+
+<style scoped>
+.model-thumbnail {
+  width: 30px;
+  height: 30px;
+  object-fit: cover;
+  margin-bottom: 5px;
+}
+
+.symbolic-box {
+  text-align: center;
+  cursor: pointer;
+  padding: 5px;
+  border-radius: 4px;
+  transition: all 0.3s;
+}
+
+.symbolic-box:hover {
+  background-color: #f0f0f0;
+}
+
+.symbolic-box.theme-border-color {
+  background-color: #ecf5ff;
+  border: 1px solid #409eff;
+  box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
+}
+
+.symbolic-box label {
+  font-size: 12px;
+  color: #606266;
+  display: block;
+  margin-top: 5px;
+}
+
+.symbolic-box.theme-border-color label {
+  color: #409eff;
+  font-weight: 500;
+}
+</style>

+ 6 - 0
RuoYi-Vue3/src/supermap-cesium-module/components/draw/draw-solid-figure/index.js

@@ -0,0 +1,6 @@
+import Sm3dDrawSolidFigure from './draw-solid-figure.vue';
+Sm3dDrawSolidFigure.install = function(app) {
+  app.component(Sm3dDrawSolidFigure.name, Sm3dDrawSolidFigure);
+};
+
+export default Sm3dDrawSolidFigure;

+ 141 - 0
RuoYi-Vue3/src/supermap-cesium-module/components/scale-bar/scale-bar.vue

@@ -0,0 +1,141 @@
+<template>
+  <div class="scale-bar" ref="scaleBarRef">
+    <div class="scale-bar-line" :style="{ width: barWidth + 'px' }"></div>
+    <div class="scale-bar-label">{{ label }}</div>
+  </div>
+</template>
+
+<script>
+import { ref, onMounted, onUnmounted } from 'vue';
+
+export default {
+  name: 'ScaleBar',
+  props: {
+    viewer: {
+      type: Object,
+      required: true
+    }
+  },
+  setup(props) {
+    const scaleBarRef = ref(null);
+    const barWidth = ref(100);
+    const label = ref('100m');
+    let updateInterval = null;
+
+    const updateScaleBar = () => {
+      if (!props.viewer || !props.viewer.camera || !props.viewer.scene) return;
+
+      try {
+        // 获取相机高度
+        const height = props.viewer.camera.positionCartographic.height;
+        
+        // 根据高度计算比例尺
+        let distance = 0;
+        let unit = 'm';
+
+        if (height < 1000) {
+          distance = 100;
+        } else if (height < 5000) {
+          distance = 500;
+        } else if (height < 10000) {
+          distance = 1000;
+        } else if (height < 50000) {
+          distance = 5000;
+        } else if (height < 100000) {
+          distance = 10000;
+        } else if (height < 500000) {
+          distance = 50000;
+        } else if (height < 1000000) {
+          distance = 100000;
+        } else {
+          distance = 500000;
+        }
+
+        // 格式化单位
+        if (distance >= 1000) {
+          distance = distance / 1000;
+          unit = 'km';
+        }
+
+        // 计算线段长度(固定比例)
+        barWidth.value = 100;
+        label.value = distance + unit;
+      } catch (error) {
+        console.error('Error updating scale bar:', error);
+      }
+    };
+
+    onMounted(() => {
+      // 初始更新
+      updateScaleBar();
+      
+      // 每500毫秒更新一次
+      updateInterval = setInterval(updateScaleBar, 500);
+      
+      // 监听相机变化事件
+      if (props.viewer.camera) {
+        props.viewer.camera.changed.addEventListener(updateScaleBar);
+      }
+    });
+
+    onUnmounted(() => {
+      if (updateInterval) {
+        clearInterval(updateInterval);
+      }
+    });
+
+    return {
+      scaleBarRef,
+      barWidth,
+      label
+    };
+  }
+};
+</script>
+
+<style scoped>
+.scale-bar {
+  position: absolute;
+  bottom: 20px;
+  left: 20px;
+  background: rgba(255, 255, 255, 0.8);
+  padding: 5px;
+  border-radius: 3px;
+  font-size: 12px;
+  font-family: Arial, sans-serif;
+  color: #333;
+  z-index: 100;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+}
+
+.scale-bar-line {
+  height: 2px;
+  background: #333;
+  position: relative;
+  margin-bottom: 2px;
+}
+
+.scale-bar-line::before,
+.scale-bar-line::after {
+  content: '';
+  position: absolute;
+  top: -3px;
+  width: 1px;
+  height: 8px;
+  background: #333;
+}
+
+.scale-bar-line::before {
+  left: 0;
+}
+
+.scale-bar-line::after {
+  right: 0;
+}
+
+.scale-bar-label {
+  text-align: center;
+}
+</style>

+ 4 - 1
RuoYi-Vue3/src/supermap-cesium-module/components/viewer/viewer.js

@@ -29,7 +29,8 @@ function initViewer(props, callback) {
       navigation: false,
       // contextOptions: {
       //   requestWebgl2: true
-      // }
+      // },
+      scale: true // 添加比例尺
     });
     // 太阳光默认打开
     // viewer.scene.globe.enableLighting = true;
@@ -134,6 +135,8 @@ function initViewer(props, callback) {
   viewer.imageryLayers.addImageryProvider(imageryProvider);
   viewer.imageryLayers.addImageryProvider(labelProvider);
 
+
+
   function openingAnimation() {
     const lon = 118.247854;
     const lat = 26.107280;

+ 4 - 1
RuoYi-Vue3/src/supermap-cesium-module/components/viewer/viewer.vue

@@ -1,6 +1,7 @@
 <template>
   <div id="cesiumContainer" ref="viewer">
     <SearchComponent v-if="viewerInstance" :viewer="viewerInstance" />
+    <ScaleBar v-if="viewerInstance" :viewer="viewerInstance" />
     <slot></slot>
   </div>
 </template>
@@ -9,12 +10,14 @@
 import { onMounted, ref, provide } from "vue";
 import initViewer from "./viewer.js";
 import SearchComponent from "../search/search.vue";
+import ScaleBar from "../scale-bar/scale-bar.vue";
 // import {initViewer} from "../../../dist/vue-webgl2.min";
 
 export default {
   name: "Sm3dViewer",
   components: {
-    SearchComponent
+    SearchComponent,
+    ScaleBar
   },
   props: {
     sceneUrl: {

+ 5 - 0
RuoYi-Vue3/src/supermap-cesium-module/config/views_config.js

@@ -220,6 +220,11 @@ export default [
                 imgSrc: "/img/componentsImg/draw-line-surface.png",  
                 name: "绘制线面"
             },
+            {
+                component: "Sm3dDrawSolidFigure",  //组件名称
+                imgSrc: "/img/componentsImg/draw-solid-figuree.png",  
+                name: "绘制体"
+            },
             {
                 component: "Sm3dPointSymbol",  //组件名称
                 imgSrc: "/img/componentsImg/add-sysmble.png",  

+ 13 - 1
RuoYi-Vue3/src/supermap-cesium-module/js/local/resourceCN.js

@@ -27,5 +27,17 @@ export default {
     daylightFilter: '日照过滤',
     analyze: '分析',
     clear: '清除',
-    shadowShow: '显示阴影'
+    shadowShow: '显示阴影',
+    
+    // 添加点符号相关
+    symbolType: '符号类型',
+    symbolColor: '符号颜色',
+    addType: '添加类型',
+    singleAdd: '单个添加',
+    lineAdd: '沿线添加',
+    faceAdd: '区域添加',
+    spacing: '间距',
+    number: '数量',
+    add: '添加',
+    clear: '清除'
 }

BIN
ruoyi-admin/target/classes/com/ruoyi/RuoYiApplication.class


BIN
ruoyi-admin/target/classes/com/ruoyi/RuoYiServletInitializer.class


BIN
ruoyi-admin/target/classes/com/ruoyi/web/controller/cesium/CesiumMapConfigController.class


BIN
ruoyi-admin/target/classes/com/ruoyi/web/controller/common/CaptchaController.class


BIN
ruoyi-admin/target/classes/com/ruoyi/web/controller/common/CommonController.class


BIN
ruoyi-admin/target/classes/com/ruoyi/web/controller/monitor/CacheController.class


BIN
ruoyi-admin/target/classes/com/ruoyi/web/controller/monitor/ServerController.class


BIN
ruoyi-admin/target/classes/com/ruoyi/web/controller/monitor/SysLogininforController.class


BIN
ruoyi-admin/target/classes/com/ruoyi/web/controller/monitor/SysOperlogController.class


BIN
ruoyi-admin/target/classes/com/ruoyi/web/controller/monitor/SysUserOnlineController.class


BIN
ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysConfigController.class


BIN
ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysDeptController.class


BIN
ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysDictDataController.class


BIN
ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysDictTypeController.class


BIN
ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysIndexController.class


BIN
ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysLoginController.class


BIN
ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysMenuController.class


BIN
ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysNoticeController.class


BIN
ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysPostController.class


BIN
ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysProfileController.class


BIN
ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysRegisterController.class


BIN
ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysRoleController.class


BIN
ruoyi-admin/target/classes/com/ruoyi/web/controller/system/SysUserController.class


BIN
ruoyi-admin/target/classes/com/ruoyi/web/controller/tool/TestController.class


BIN
ruoyi-admin/target/classes/com/ruoyi/web/controller/tool/UserEntity.class


BIN
ruoyi-admin/target/classes/com/ruoyi/web/controller/watershed/WatershedModelController.class


BIN
ruoyi-admin/target/classes/com/ruoyi/web/controller/watershed/WatershedServiceController.class


BIN
ruoyi-admin/target/classes/com/ruoyi/web/core/config/SwaggerConfig.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/annotation/Excel$ColumnType.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/annotation/Excel$Type.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/annotation/Excel.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/config/RuoYiConfig.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/config/serializer/SensitiveJsonSerializer.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/constant/CacheConstants.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/constant/Constants.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/constant/GenConstants.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/constant/HttpStatus.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/constant/ScheduleConstants$Status.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/constant/ScheduleConstants.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/constant/UserConstants.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/core/controller/BaseController$1.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/core/controller/BaseController.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/core/domain/AjaxResult.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/core/domain/BaseEntity.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/core/domain/R.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/core/domain/TreeEntity.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/core/domain/TreeSelect.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/core/domain/entity/SysDept.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/core/domain/entity/SysDictData.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/core/domain/entity/SysDictType.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/core/domain/entity/SysMenu.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/core/domain/entity/SysRole.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/core/domain/entity/SysUser.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/core/domain/model/LoginBody.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/core/domain/model/LoginUser.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/core/domain/model/RegisterBody.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/core/page/PageDomain.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/core/page/TableDataInfo.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/core/page/TableSupport.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/core/redis/RedisCache.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/core/text/CharsetKit.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/core/text/Convert.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/core/text/StrFormatter.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/enums/BusinessStatus.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/enums/BusinessType.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/enums/DataSourceType.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/enums/DesensitizedType.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/enums/HttpMethod.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/enums/LimitType.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/enums/OperatorType.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/enums/UserStatus.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/exception/DemoModeException.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/exception/GlobalException.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/exception/ServiceException.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/exception/UtilException.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/exception/base/BaseException.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/exception/file/FileException.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/exception/file/FileSizeLimitExceededException.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/exception/file/FileUploadException.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/exception/file/InvalidExtensionException$InvalidFlashExtensionException.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/exception/file/InvalidExtensionException$InvalidImageExtensionException.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/exception/file/InvalidExtensionException$InvalidMediaExtensionException.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/exception/file/InvalidExtensionException$InvalidVideoExtensionException.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/exception/file/InvalidExtensionException.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/exception/job/TaskException$Code.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/exception/job/TaskException.class


BIN
ruoyi-common/target/classes/com/ruoyi/common/exception/user/BlackListException.class


Деякі файли не було показано, через те що забагато файлів було змінено