Browse Source

* 主路光伏

chen.cheng 1 month ago
parent
commit
dee053e58d

BIN
ems-ui-cloud/public/models/textures/tri_pattern.jpg


+ 29 - 89
ems-ui-cloud/src/router/index.js

@@ -1,12 +1,12 @@
 import Vue from 'vue';
 import Router from 'vue-router';
-
-Vue.use(Router);
-
 /* Layout */
 import Layout from '@/layout';
 import LargeScreen from '@/views/largeScreen/index.vue'
 import PvRoad from "@/views/largeScreen/pv-road/index.vue";
+
+Vue.use(Router);
+
 /**
  * Note: 路由配置项
  *
@@ -21,12 +21,12 @@ import PvRoad from "@/views/largeScreen/pv-road/index.vue";
  * roles: ['admin', 'common']       // 访问路由的角色权限
  * permissions: ['a:a:a', 'b:b:b']  // 访问路由的菜单权限
  * meta : {
-    noCache: true                   // 如果设置为true,则不会被 <keep-alive> 缓存(默认 false)
-    title: 'title'                  // 设置该路由在侧边栏和面包屑中展示的名字
-    icon: 'svg-name'                // 设置该路由的图标,对应路径src/assets/icons/svg
-    breadcrumb: false               // 如果设置为false,则不会在breadcrumb面包屑中显示
-    activeMenu: '/system/user'      // 当路由设置了该属性,则会高亮相对应的侧边栏。
-  }
+ noCache: true                   // 如果设置为true,则不会被 <keep-alive> 缓存(默认 false)
+ title: 'title'                  // 设置该路由在侧边栏和面包屑中展示的名字
+ icon: 'svg-name'                // 设置该路由的图标,对应路径src/assets/icons/svg
+ breadcrumb: false               // 如果设置为false,则不会在breadcrumb面包屑中显示
+ activeMenu: '/system/user'      // 当路由设置了该属性,则会高亮相对应的侧边栏。
+ }
  */
 
 // 公共路由
@@ -67,7 +67,7 @@ export const constantRoutes = [
   {
     path: '/largeScreen',
     name: 'largeScreen',
-    redirect: { name: 'home' },
+    redirect: {name: 'home'},
     component: LargeScreen,
     hidden: true,
     children: [
@@ -78,7 +78,7 @@ export const constantRoutes = [
           title: '首页'
         },
         components: {
-          default:() => import('@/views/largeScreen/center.vue'),
+          default: () => import('@/views/largeScreen/center.vue'),
           left: () => import('@/views/largeScreen/home/left.vue'),
           right: () => import('@/views/largeScreen/home/right.vue')
         }
@@ -90,7 +90,7 @@ export const constantRoutes = [
           title: '源'
         },
         components: {
-          default:() => import('@/views/largeScreen/center.vue'),
+          default: () => import('@/views/largeScreen/center.vue'),
           left: () => import('@/views/largeScreen/source/left.vue'),
           right: () => import('@/views/largeScreen/source/right.vue')
         }
@@ -102,7 +102,7 @@ export const constantRoutes = [
           title: '储'
         },
         components: {
-          default:() => import('@/views/largeScreen/center.vue'),
+          default: () => import('@/views/largeScreen/center.vue'),
           left: () => import('@/views/largeScreen/storage/left.vue'),
           right: () => import('@/views/largeScreen/storage/right.vue')
         }
@@ -114,7 +114,7 @@ export const constantRoutes = [
           title: '荷'
         },
         components: {
-          default:() => import('@/views/largeScreen/center.vue'),
+          default: () => import('@/views/largeScreen/center.vue'),
           left: () => import('@/views/largeScreen/soc/left.vue'),
           right: () => import('@/views/largeScreen/soc/right.vue')
         }
@@ -126,7 +126,7 @@ export const constantRoutes = [
           title: '网'
         },
         components: {
-          default:() => import('@/views/largeScreen/center.vue'),
+          default: () => import('@/views/largeScreen/center.vue'),
           left: () => import('@/views/largeScreen/net/left.vue'),
           right: () => import('@/views/largeScreen/net/right.vue')
         }
@@ -138,7 +138,7 @@ export const constantRoutes = [
           title: '设备'
         },
         components: {
-          default:() => import('@/views/largeScreen/center.vue'),
+          default: () => import('@/views/largeScreen/center.vue'),
           left: () => import('@/views/largeScreen/device/left.vue'),
           right: () => import('@/views/largeScreen/device/right.vue')
         }
@@ -148,82 +148,22 @@ export const constantRoutes = [
   {
     path: '/PvRoad',
     name: 'PvRoad',
-    redirect: { name: 'home' },
+    redirect: {name: 'road-home'},
     component: PvRoad,
     hidden: true,
     children: [
       {
-        path: 'home',
-        name: 'home',
+        path: 'road-home',
+        name: 'road-home',
         meta: {
           title: '首页'
         },
         components: {
-          default:() => import('@/views/largeScreen/center.vue'),
-          left: () => import('@/views/largeScreen/home/left.vue'),
-          right: () => import('@/views/largeScreen/home/right.vue')
-        }
-      },
-      {
-        path: 'source',
-        name: 'source',
-        meta: {
-          title: '源'
-        },
-        components: {
-          default:() => import('@/views/largeScreen/center.vue'),
+          default: () => import('@/views/largeScreen/pv-road/center.vue'),
           left: () => import('@/views/largeScreen/source/left.vue'),
-          right: () => import('@/views/largeScreen/source/right.vue')
-        }
-      },
-      {
-        path: 'storage',
-        name: 'storage',
-        meta: {
-          title: '储'
-        },
-        components: {
-          default:() => import('@/views/largeScreen/center.vue'),
-          left: () => import('@/views/largeScreen/storage/left.vue'),
-          right: () => import('@/views/largeScreen/storage/right.vue')
+          right: () => import('@/views/largeScreen/source/pv-road-right.vue')
         }
       },
-      {
-        path: 'soc',
-        name: 'soc',
-        meta: {
-          title: '荷'
-        },
-        components: {
-          default:() => import('@/views/largeScreen/center.vue'),
-          left: () => import('@/views/largeScreen/soc/left.vue'),
-          right: () => import('@/views/largeScreen/soc/right.vue')
-        }
-      },
-      {
-        path: 'net',
-        name: 'net',
-        meta: {
-          title: '网'
-        },
-        components: {
-          default:() => import('@/views/largeScreen/center.vue'),
-          left: () => import('@/views/largeScreen/net/left.vue'),
-          right: () => import('@/views/largeScreen/net/right.vue')
-        }
-      },
-      {
-        path: 'device',
-        name: 'device',
-        meta: {
-          title: '设备'
-        },
-        components: {
-          default:() => import('@/views/largeScreen/center.vue'),
-          left: () => import('@/views/largeScreen/device/left.vue'),
-          right: () => import('@/views/largeScreen/device/right.vue')
-        }
-      }
     ]
   },
   {
@@ -235,7 +175,7 @@ export const constantRoutes = [
         path: 'index',
         component: () => import('@/views/index'),
         name: 'Index',
-        meta: { title: '首页', icon: 'dashboard', affix: true }
+        meta: {title: '首页', icon: 'dashboard', affix: true}
       }
     ]
   },
@@ -249,7 +189,7 @@ export const constantRoutes = [
         path: 'profile',
         component: () => import('@/views/system/user/profile/index'),
         name: 'Profile',
-        meta: { title: '个人中心', icon: 'user' }
+        meta: {title: '个人中心', icon: 'user'}
       }
     ]
   }
@@ -267,7 +207,7 @@ export const dynamicRoutes = [
         path: 'role/:userId(\\d+)',
         component: () => import('@/views/system/user/authRole'),
         name: 'AuthRole',
-        meta: { title: '分配角色', activeMenu: '/system/user' }
+        meta: {title: '分配角色', activeMenu: '/system/user'}
       }
     ]
   },
@@ -281,7 +221,7 @@ export const dynamicRoutes = [
         path: 'user/:roleId(\\d+)',
         component: () => import('@/views/system/role/authUser'),
         name: 'AuthUser',
-        meta: { title: '分配用户', activeMenu: '/system/role' }
+        meta: {title: '分配用户', activeMenu: '/system/role'}
       }
     ]
   },
@@ -295,7 +235,7 @@ export const dynamicRoutes = [
         path: 'index/:dictId(\\d+)',
         component: () => import('@/views/system/dict/data'),
         name: 'Data',
-        meta: { title: '字典数据', activeMenu: '/system/dict' }
+        meta: {title: '字典数据', activeMenu: '/system/dict'}
       }
     ]
   },
@@ -309,7 +249,7 @@ export const dynamicRoutes = [
         path: 'index/:jobId(\\d+)',
         component: () => import('@/views/monitor/job/log'),
         name: 'JobLog',
-        meta: { title: '调度日志', activeMenu: '/monitor/job' }
+        meta: {title: '调度日志', activeMenu: '/monitor/job'}
       }
     ]
   },
@@ -323,7 +263,7 @@ export const dynamicRoutes = [
         path: 'index/:tableId(\\d+)',
         component: () => import('@/views/tool/gen/editTable'),
         name: 'GenEdit',
-        meta: { title: '修改生成配置', activeMenu: '/tool/gen' }
+        meta: {title: '修改生成配置', activeMenu: '/tool/gen'}
       }
     ]
   }
@@ -343,6 +283,6 @@ Router.prototype.replace = function push(location) {
 
 export default new Router({
   mode: 'history', // 去掉url中的#
-  scrollBehavior: () => ({ y: 0 }),
+  scrollBehavior: () => ({y: 0}),
   routes: constantRoutes
 });

+ 77 - 0
ems-ui-cloud/src/views/largeScreen/pv-road/center.vue

@@ -0,0 +1,77 @@
+<template>
+  <div style="width: 100%;height: 100%">
+    <div class="center" id="model">
+
+    </div>
+  </div>
+
+</template>
+<script>
+import {mapMutations} from 'vuex';
+import renderModel from '../three/renderModel'
+import ComponentHandle from "@/utils/ComponentHandle";
+import pvReal from "@/views/largeScreen/dialog/pv-real.vue";
+
+export default {
+  name: 'Center',
+  data() {
+    return {
+      areaType: 'all',
+      modelApi: null,
+    };
+  },
+  components: {},
+  mounted() {
+    this.setAreaType("321283124S3003")
+    this.initThree();
+  },
+  methods: {
+    ...mapMutations('userState', ['setAreaType']),
+
+    initThree() {
+      setTimeout(() => {
+        this.modelApi = new renderModel('#model')
+        this.modelApi.initGltfModel()
+        this.modelApi.addDialog(ComponentHandle.createComponent({
+          component: pvReal,
+          props: {
+            areaCode: "321283124S3003"
+          }
+        }), "北区光伏", {
+          x: 0,
+          y: 20,
+          z: 20
+        })
+      }, 100)
+
+    }
+  }
+}
+</script>
+<style lang='scss' scoped>
+.tabs {
+  position: absolute;
+  top: 90px;
+  left: 425px;
+  z-index: 50;
+}
+
+.center {
+  // background: url("~@/assets/images/center.jpg") no-repeat;
+  // background-size:cover ;
+  // width: calc(100% - 806px);
+  width: 100%;
+  // margin: auto auto 0;
+  height: 100%;
+  position: relative;
+  z-index: 1;
+
+
+  ::v-deep .tag3d {
+    // color: #fff;
+    font-weight: 500;
+    font-size: 20px;
+  }
+
+}
+</style>

+ 3 - 7
ems-ui-cloud/src/views/largeScreen/pv-road/index.vue

@@ -25,10 +25,6 @@
       </div>
       <router-view class="sidebar-router-view" name="right"></router-view>
     </div>
-    <div class="footer-container">
-      <Footer></Footer>
-    </div>
-
   </div>
 </template>
 <script>
@@ -87,7 +83,7 @@ export default {
     this.timer = setInterval(() => {
       this.getDate();
     }, 1000);
-    this.getConfigKey("sys.info.title").then(response => {
+    this.getConfigKey("sys.info.pv-road-title").then(response => {
       this.sysTitle = response.msg;
     });
   },
@@ -143,8 +139,8 @@ export default {
     color: transparent;
     line-height: 70px;
     background-image: linear-gradient(to bottom,
-        white 30%,
-        #75bfe9 100%);
+      white 30%,
+      #75bfe9 100%);
   }
 
 }

+ 260 - 0
ems-ui-cloud/src/views/largeScreen/source/pv-road-right.vue

@@ -0,0 +1,260 @@
+<template>
+  <div>
+    <CusModule class="module-top" title="发电趋势预测">
+      <BaseChart height="350px" width="100%" :option="lineOptions"/>
+    </CusModule>
+    <CusModule title="告警信息">
+      <div class="seamless-header">
+        <div>告警内容</div>
+        <div>告警设备</div>
+        <div>告警时间</div>
+      </div>
+      <vue-seamless-scroll :data="listData" class="seamless-warp" :class-option="classOption">
+        <div class="seamless-item" v-for="(item, index) in listData" :key="index">
+          <div>{{ item.alarmMsg }}</div>
+          <div>{{ item.objName}}</div>
+          <div>{{ item.alarmTime }}</div>
+        </div>
+      </vue-seamless-scroll>
+    </CusModule>
+  </div>
+</template>
+<script>
+import CusModule from '../components/CusModule.vue';
+import BaseChart from '@/components/BaseChart/index.vue'
+import vueSeamlessScroll from 'vue-seamless-scroll'
+import {array2Map} from '@/utils';
+import * as echarts from 'echarts'
+import {mapState} from 'vuex';
+import {DateTool} from "@/utils/DateTool";
+import {ecoDateRange, predictionProdDateRange} from "@/api/screen";
+import {listAlarmInfo} from "@/api/alarm/alarm-info";
+import {ALARM_STATE} from "@/enums/alarm";
+import {ApiCode} from "@/api/apiEmums";
+
+export default {
+  name: 'SourceRight',
+  dicts: ['alarm_type'],
+  data() {
+    return {
+      lineData: [],
+      classOption: {
+        step: 0.3, // 数值越大速度滚动越快
+        limitMoveNum: 4, // 开始无缝滚动的数据量 this.dataList.length
+        hoverStop: true, // 是否开启鼠标悬停stop
+        direction: 1, // 0向下 1向上 2向左 3向右
+        openWatch: true, // 开启数据实时监控刷新dom
+        singleHeight: 0, // 单步运动停止的高度(默认值0是无缝不停止的滚动) direction => 0/1
+        singleWidth: 0, // 单步运动停止的宽度(默认值0是无缝不停止的滚动) direction => 2/3
+        waitTime: 1000 // 单步运动停止
+      },
+      listData: []
+    }
+  },
+  components: {
+    CusModule,
+    BaseChart,
+    vueSeamlessScroll
+  },
+  computed: {
+    ...mapState('userState', ['areaType', 'regionFactor', 'elec2CFactor']),
+    lineOptions() {
+      return {
+        legend: {
+          show: false,
+        },
+        tooltip: {
+          trigger: "axis",
+        },
+        grid: {
+          left: '5%',
+          right: '6%',
+          top: '15%',
+          bottom: '5%',
+          containLabel: true
+        },
+        yAxis: {
+          name: "kW·h",
+          splitLine: {
+            show: true,
+            lineStyle: {
+              color: '#334E5E'
+            }
+          },
+        },
+        xAxis: {
+          splitLine: {
+            show: false,
+          },
+          axisLabel: {
+            color: '#c1cadf',
+            fontSize: '10',
+          },
+          data: this.lineData.map(item => item.xData),
+        },
+        series: [
+          {
+            type: 'line',
+            name: "发电量",
+            smooth: true,
+            lineStyle: {
+              normal: {
+                color: "#80DBE1", // 线条颜色
+              },
+            },
+            itemStyle: {
+              color: "#80DBE1",
+              borderColor: "#fff",
+              borderWidth: 3
+            },
+            areaStyle: { //区域填充样式
+              normal: {
+                //线性渐变,前4个参数分别是x0,y0,x2,y2(范围0~1);相当于图形包围盒中的百分比。如果最后一个参数是‘true’,则该四个值是绝对像素位置。
+                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
+                  offset: 0,
+                  color: "rgba(81, 139, 152,0.8)"
+                },
+                  {
+                    offset: 1,
+                    color: "rgba(81, 139, 152, 0)"
+                  }
+                ], false),
+                shadowColor: 'rgba(81, 139, 152, 0.5)', //阴影颜色
+                shadowBlur: 20 //shadowBlur设图形阴影的模糊大小。配合shadowColor,shadowOffsetX/Y, 设置图形的阴影效果。
+              }
+            },
+            data: this.lineData.map(item => item.yData),
+          },
+        ],
+      }
+    }
+  },
+  watch: {
+    areaType() {
+      this.getDatas()
+    }
+  },
+  mounted() {
+    this.getDatas()
+  },
+  methods: {
+    getDatas() {
+      this.getDatesOfLastTenDays()
+      this.getRealTimeAlarm()
+    },
+    async getDatesOfLastTenDays() {
+      const next5Day = DateTool.addDays(DateTool.now(), 4);
+      const {data} = await predictionProdDateRange({
+        areaCode: this.areaType,
+        startRecTime: DateTool.now(),
+        endRecTime: next5Day,
+      })
+
+      const dates = DateTool.getDayOfRange(DateTool.now(), next5Day);
+      const mapIndex = array2Map(data, "date");
+      this.lineData = dates.map(item => ({
+        xData: item,
+        yData: mapIndex[item] ? mapIndex[item].elecProdQuantity : 0
+      }))
+    },
+
+    async getRealTimeAlarm() {
+      let result = [];
+      const {
+        code,
+        rows,
+      } = await listAlarmInfo({
+        pageNum: 1,
+        pageSize: 20,
+        areaCode: this.areaType,
+        alarmStateList: [
+          ALARM_STATE.new.value, ALARM_STATE.disposing.value,
+        ]
+      });
+      if (ApiCode.SUCCESS === code && rows && rows.length > 0) {
+        result = rows;
+      }
+      this.listData = result;
+    },
+  }
+}
+</script>
+<style lang='scss' scoped>
+@import url("../index.scss");
+
+.energy {
+  display: flex;
+
+  .energy-item {
+    position: relative;
+    flex: 0.5;
+    flex-shrink: 0;
+    height: 169px;
+    background: url('~@/assets/images/net/r1-item_bg.png') no-repeat;
+    background-size: cover;
+
+    .energy-item-value {
+      position: absolute;
+      width: 100%;
+      text-align: center;
+      bottom: 70px;
+      font-size: 14px;
+      font-weight: bold;
+    }
+
+    .energy-item-name {
+      position: absolute;
+      width: 100%;
+      text-align: center;
+      bottom: 20px;
+      font-size: 14px;
+    }
+  }
+}
+
+.seamless-header {
+  margin-top: 20px;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 5px 10px;
+  color: #7DBAFF;
+  background: #1B4A64;
+  font-size: 16px;
+
+  > div:first-of-type,
+  > div:last-of-type {
+    flex-basis: 35%;
+  }
+
+  > div {
+    text-align: center;
+  }
+}
+
+.seamless-warp {
+  overflow: hidden;
+  height: 400px;
+
+  .seamless-item {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 5px 0;
+
+    &:nth-child(odd) {
+      background: #000;
+    }
+
+    > div:first-of-type,
+    > div:last-of-type {
+      flex-basis: 38%;
+    }
+
+    > div {
+      text-align: center;
+      font-size: 13px;
+    }
+  }
+}
+</style>

+ 162 - 13
ems-ui-cloud/src/views/largeScreen/three/renderModel.js

@@ -2,6 +2,12 @@ import * as THREE from 'three'; //导入整个 three.js核心库
 import {FBXLoader} from 'three/examples/jsm/loaders/FBXLoader';
 import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls'; //导入控制器模块,轨道控制器
 import {CSS3DRenderer, CSS3DSprite} from 'three/examples/jsm/renderers/CSS3DRenderer.js';
+import {GLTFLoader} from 'three/examples/jsm/loaders/GLTFLoader.js'
+// 用于模型边缘高亮
+import {EffectComposer} from "three/examples/jsm/postprocessing/EffectComposer.js";
+import {RenderPass} from "three/examples/jsm/postprocessing/RenderPass.js";
+import {OutlinePass} from "three/examples/jsm/postprocessing/OutlinePass.js";
+import {UnrealBloomPass} from "three/examples/jsm/postprocessing/UnrealBloomPass.js";
 import * as TWEEN from '@tweenjs/tween.js';
 import {getBottomMaterial} from './material.js';
 
@@ -27,6 +33,57 @@ class renderModel {
     this.ambientLight;
     //模型平面
     this.planeGeometry;
+
+    this.outlineObjs = []
+  }
+
+  outlineObj(selectedObjects) {
+    // 创建一个EffectComposer(效果组合器)对象,然后在该对象上添加后期处理通道。
+    // 用于模型边缘高亮
+    let composer = new EffectComposer(this.renderer);
+    composer.renderTarget1.texture.outputColorSpace = THREE.sRGBEncoding;
+    composer.renderTarget2.texture.outputColorSpace = THREE.sRGBEncoding;
+    composer.renderTarget1.texture.encoding = THREE.sRGBEncoding;
+    composer.renderTarget2.texture.encoding = THREE.sRGBEncoding;
+
+    // 新建一个场景通道  为了覆盖到原来的场景上
+    composer.addPass(new RenderPass(this.scene, this.camera));
+    // 物体边缘发光通道
+    let outlinePass = new OutlinePass(
+      new THREE.Vector2(window.innerWidth, window.innerHeight),
+      this.scene,
+      this.camera,
+      selectedObjects
+    );
+    outlinePass.selectedObjects = selectedObjects;
+    outlinePass.edgeStrength = 10.0; // 边框的亮度
+    outlinePass.edgeGlow = 0.5; // 光晕[0,1]
+    outlinePass.usePatternTexture = false; // 是否使用父级的材质
+    outlinePass.edgeThickness = 1.0; // 边框宽度
+    outlinePass.downSampleRatio = 1; // 边框弯曲度
+    outlinePass.pulsePeriod = 5; // 呼吸闪烁的速度
+    outlinePass.visibleEdgeColor.set(parseInt(0x00ff00)); // 呼吸显示的颜色
+    outlinePass.hiddenEdgeColor = new THREE.Color(0, 0, 0); // 呼吸消失的颜色
+    outlinePass.clear = true;
+    composer.addPass(outlinePass);
+    // 自定义的着色器通道 作为参数
+    // effectFXAA = new ShaderPass(FXAAShader);
+    // effectFXAA.uniforms.resolution.value.set(
+    //   1 / window.innerWidth,
+    //   1 / window.innerHeight
+    // );
+    // effectFXAA.renderToScreen = true;
+    // composer.addPass(effectFXAA);
+
+    // // 发光效果
+    let unrealBloomPass = new UnrealBloomPass();
+    unrealBloomPass.strength = 0.1;
+    unrealBloomPass.radius = 0;
+    unrealBloomPass.threshold = 1;
+    composer.addPass(unrealBloomPass);
+    this.outlineObjs.push(composer)
+    console.log(">>>>>>>>>>>>>>>>>>>>>")
+
   }
 
   // 初始化加载模型方法
@@ -48,6 +105,25 @@ class renderModel {
     this.sceneAnimation();
   }
 
+  initGltfModel() {
+
+    //初始化场景
+    this.initScene();
+    //初始化相机
+    this.initCamera();
+    //初始化渲染器
+    this.initRender();
+    // 创建灯光
+    this.createLight();
+    //初始化控制器,控制摄像头,控制器一定要在渲染器后
+    this.initControls();
+    this.setGlbModel();
+    //监听场景大小改变,跳转渲染尺寸
+    window.addEventListener('resize', this.onWindowResizes);
+    //场景渲染
+    this.sceneAnimation();
+  }
+
   //创建场景
   initScene() {
     this.scene = new THREE.Scene();
@@ -140,9 +216,13 @@ class renderModel {
 
   animate() {
     this.renderer.render(this.scene, this.camera);
+    this.renderer.autoClear = true;
     this.controls.update();
     this.css3DRenderer.render(this.scene, this.camera);
     TWEEN.update();
+    // this.outlineObjs.forEach(item => {
+    //   item.render(this.scene, this.camera)
+    // })
     // // 检查模型位置是否发生变化
     // if (this.model) {
     //   console.log('Model Position:', this.model.position);
@@ -229,6 +309,61 @@ class renderModel {
     object.position.z = 0;
   }
 
+  setGlbModel() {
+    var fbxLoader = new GLTFLoader();
+    fbxLoader.load('/models/model-road-pv.glb', object => {
+      this.calcMeshCenter(object.scene);
+      this.model = object.scene;
+      object.scene.traverse(function (child) {
+        if (child.isMesh) {
+          child.material.emissive = child.material.color;
+          child.material.emissiveMap = child.material.map;
+        }
+      });
+      // 设置相机位置
+      this.camera.position.set(-20, -652, 500);
+      this.controls.target.set(-20, -20, 0);
+      this.model.scale.set(1, 1, 1);
+      // 设置相机坐标系
+      this.camera.lookAt(0, 0, 0);
+      // 将模型添加到场景中去
+      this.scene.add(this.model);
+      if (object.scene.type === 'Group') {
+        console.log('这是一个Group');
+        // 遍历Group中的子对象
+        object.scene.children.forEach(child => {
+          if (child.type === 'Mesh') {
+            console.log('这是一个Mesh', child.name); // 检查并记录Mesh的名称
+            if (["solar_cell097.001", "solar_cell097.002", "solar_cell097.003", "solar_cell097.004","Line007"].includes(child.name)) {
+              let selectedObjects = [child];
+              // this.outlineObj(selectedObjects);
+            }
+          }
+        });
+      } else if (object.scene.type === 'Mesh') {
+        console.log('这是一个单独的Mesh', object.scene.name); // 单独的Mesh对象
+      } else {
+        console.log('未知类型的对象', object.scene.type);
+      }
+      window.addEventListener('click', event => {
+
+        //   raycaster.setFromCamera(mouse, this.camera);
+
+        //   const intersects = raycaster.intersectObjects(this.scene.children);
+
+        const intersects = this.raycaster.intersectObjects(this.scene.children);
+
+        if (intersects.length > 0) {
+          const point = intersects[0].point;
+          console.log(`Clicked at: (${point.x}, ${point.y}, ${point.z})`);
+        }
+      });
+      console.log('load')
+      // this.initGUI();
+
+    });
+  }
+
   setFBXModel() {
     var fbxLoader = new FBXLoader();
     fbxLoader.load('/models/model2.FBX', object => {
@@ -248,22 +383,36 @@ class renderModel {
       this.camera.lookAt(0, 0, 0);
       // 将模型添加到场景中去
       this.scene.add(this.model);
-      // window.addEventListener('click', event => {
-      //   const raycaster = new THREE.Raycaster();
-      //   const mouse = new THREE.Vector2();
-      //   mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
-      //   mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
+      if (object.type === 'Group') {
+        console.log('这是一个Group');
+        // 遍历Group中的子对象
+        object.children.forEach(child => {
+          if (child.type === 'Mesh') {
+            console.log('这是一个Mesh', child.name); // 检查并记录Mesh的名称
+            if (child.name === 'Line007') {
+              let selectedObjects = [child];
+              this.outlineObj(selectedObjects);
+            }
+          }
+        });
+      } else if (object.type === 'Mesh') {
+        console.log('这是一个单独的Mesh', object.name); // 单独的Mesh对象
+      } else {
+        console.log('未知类型的对象', object.type);
+      }
+      window.addEventListener('click', event => {
 
-      //   raycaster.setFromCamera(mouse, this.camera);
+        //   raycaster.setFromCamera(mouse, this.camera);
 
-      //   const intersects = raycaster.intersectObjects(this.scene.children);
+        //   const intersects = raycaster.intersectObjects(this.scene.children);
 
-      //   if (intersects.length > 0) {
-      //     const point = intersects[0].point;
-      //     console.log(`Clicked at: (${point.x}, ${point.y}, ${point.z})`);
-      //   }
-      // });
-      // this.initGUI();
+        const intersects = this.raycaster.intersectObjects(this.scene.children);
+
+        if (intersects.length > 0) {
+          const point = intersects[0].point;
+          console.log(`Clicked at: (${point.x}, ${point.y}, ${point.z})`);
+        }
+      });
 
     });
   }