2545307760@qq.com před 23 hodinami
rodič
revize
ca0a1fa12e

+ 7 - 0
web/src/router/index.js

@@ -22,6 +22,13 @@ const routes = [{
       closeTab: true,
     },
     component: () => import('@/view/admin/dataDashboard/dataDashboard.vue')
+  },
+  {
+    path: '/dataScreen',
+    meta: {
+      closeTab: true
+    },
+    component:() => import('@/view/screen/dataScreen.vue')
   }
 ]
 

+ 6 - 1
web/src/view/layout/index.vue

@@ -82,6 +82,7 @@
                           :key="item.path"
                         >{{ fmtTitle(item.meta.title,route) }}</el-breadcrumb-item>
                       </el-breadcrumb>
+                      <el-button :icon="Menu" text style="margin-left: 20px" @click="jumpScreen">数据大屏</el-button>
                     </el-col>
                     <el-col
                       :xs="12"
@@ -183,7 +184,6 @@
         <CommandMenu ref="command" />
       </el-main>
     </el-container>
-
   </el-container>
 </template>
 
@@ -201,6 +201,7 @@ import { useRouter, useRoute } from 'vue-router'
 import { useRouterStore } from '@/pinia/modules/router'
 import { fmtTitle } from '@/utils/fmtRouterTitle'
 import { useUserStore } from '@/pinia/modules/user'
+import { Menu } from "@element-plus/icons-vue";
 
 defineOptions({
   name: 'Layout',
@@ -255,6 +256,10 @@ const handleCommand = () => {
   command.value.open()
 }
 
+const jumpScreen = () => {
+  router.push('/dataScreen')
+}
+
 onMounted(() => {
   // 挂载一些通用的事件
   emitter.emit('collapse', isCollapse.value)

+ 296 - 0
web/src/view/screen/dataScreen.vue

@@ -0,0 +1,296 @@
+<template>
+  <div class="screen">
+    <div style="height: 10px"></div>
+    <div class="titleImage">
+      <el-image :src="titleUrl" />
+      <span class="Heading">龙弛智慧隧道系统</span>
+    </div>
+    <div class="coreBox">
+      <div ref="container" class="three-container"></div>
+      <div class="formBox">
+        <div class="panel">
+          <span class="panel-title">亮度调整</span>
+          <el-slider
+              v-model="transparency"
+              :step="50"
+              show-stops
+              :show-tooltip="false"
+              class="panel-slider"
+              @change="changeTransparency"
+          />
+          <div class="brightness" style="margin: 90px 0 0 25px;">
+            <span>低</span>
+            <span>中</span>
+            <span>高</span>
+          </div>
+          <el-slider
+              v-model="transparencyTwo"
+              :step="50"
+              show-stops
+              :show-tooltip="false"
+              class="panel-slider2"
+              @change="changeTransparencyTwo"
+          />
+          <div class="brightness" style="margin: 50px 0 0 25px;">
+            <span>低</span>
+            <span>中</span>
+            <span>高</span>
+          </div>
+          <div class="panel-bottom"></div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import * as THREE from 'three';
+import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
+import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
+import { onMounted, onUnmounted, reactive, ref } from 'vue';
+import { useScreenStore } from '@/pinia/modules/screen'
+// 单灯控制
+// import { updateTunnelLamp } from "@/api/tunnel";
+// 四路控制
+// import { deviceSwitch } from "@/api/device";
+// 标题图片
+import titleUrl from '@/assets/title_bg.png'
+// import {ElMessage} from "element-plus";
+
+const useScreen = useScreenStore()
+// 获取容器引用
+const container = ref(null);
+
+// 定义 Three.js 相关变量
+let scene, camera, renderer, controls;
+
+// 创建场景
+scene = new THREE.Scene();
+
+// 添加环境光
+const ambientLight = new THREE.AmbientLight(0xffffff, 1);
+
+// 初始化 Three.js 场景
+const initThree = () => {
+  scene.background = null;
+  // textureLoader.load('@/assets/OIP-C.jpg', (texture) => {
+  //   // 将图片设置为场景的背景
+  //   scene.background = texture;
+  // });
+  // 创建相机
+  camera = new THREE.PerspectiveCamera(
+      75,
+      container.value.clientWidth / container.value.clientHeight,
+      0.1,
+      1000
+  );
+  camera.position.set(30, 20, 30);
+
+  // 创建渲染器
+  renderer = new THREE.WebGLRenderer({ antialias: true });
+  renderer.setSize(container.value.clientWidth, container.value.clientHeight);
+  renderer.setClearAlpha(0);
+  // renderer.setClearColor(222842);
+  container.value.appendChild(renderer.domElement);
+
+  // 添加轨道控制器
+  controls = new OrbitControls(camera, renderer.domElement);
+  controls.enableDamping = true; // 启用阻尼效果
+  controls.dampingFactor = 0.05;
+
+  scene.add(ambientLight);
+
+  // 添加平行光
+  const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
+  directionalLight.position.set(5, 5, 5).normalize();
+  scene.add(directionalLight);
+};
+
+// 存储模型数据
+let materialOne = reactive({})
+let materialTwo = reactive({})
+
+
+// 加载 GLB 模型
+const loadModel = () => {
+  const loader = new GLTFLoader();
+  loader.load('../../public/隧道1.glb', function (gltf){
+        let object = gltf.scene
+        materialOne = object.children[0].children[3].material
+        materialTwo = object.children[19].children[3].material
+        //gltf.scene获取gltf文件包含的模型数据
+        scene.add(gltf.scene)
+      }, function (xhr) {
+        // 加载进度回调
+        console.log((xhr.loaded / xhr.total * 100) + '% loaded');
+      }, function (error) {
+        // 加载错误回调
+        // console.error('An error happened', error);
+      }
+  )
+};
+
+// 动画循环
+const animate = () => {
+  requestAnimationFrame(animate);
+  controls.update(); // 更新控制器
+  renderer.render(scene, camera);
+};
+
+// 亮度调整
+const transparency = ref(0)
+const changeTransparency = (e) => {
+  console.log(e)
+}
+
+const transparencyTwo = ref(0)
+const changeTransparencyTwo = (e) => {
+  console.log(e)
+}
+
+// 灯光数据
+const lampData = reactive({})
+
+// 组件挂载时初始化
+onMounted(() => {
+  Object.assign(lampData, useScreen.controllerData)
+  initThree();
+  loadModel();
+  animate();
+});
+
+// 组件卸载时清理资源
+onUnmounted(() => {
+  if (renderer) {
+    renderer.dispose();
+  }
+});
+</script>
+
+<style scoped lang="less">
+.horn {
+  position: absolute;
+  content: "";
+  width: 10px;
+  height: 10px;
+}
+.screen{
+  width: 100%;
+  height: 900px;
+  //background-image: url("@/assets/back.jpeg");
+  background-size:100% 100%;
+  background: #1d2b56 url("@/assets/line.png");
+
+  .titleImage {
+    width: 100%;
+    height: 70px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    position: relative;
+    .Heading{
+      position: absolute;
+      left: 42%;
+      top: 25%;
+      text-align: center;
+      font-size: 1.7vw;
+      font-weight: bold;
+      color: #0EFCFF;
+    }
+  }
+  .coreBox{
+    width: 100%;
+    height: 800px;
+    margin-top: 20px;
+    position: relative;
+    .three-container {
+      z-index: 1;
+      position: absolute;
+      height: 800px;
+      width: 100%;
+    }
+    .formBox{
+      position: absolute;
+      right: 20px;
+      z-index:2;
+    }
+    .panel{
+      position: relative;
+      width: 300px;
+      height: 200px;
+      border: 1px solid rgba(25,186,139,0.17);
+      padding: 0 0.1875rem 0.5rem;
+      margin-bottom: 0.1875rem;
+      background: url(@/assets/line.png) rgba(255,255,255,0.04);
+      &::before{
+        .horn;
+        top: 0;
+        left: 0;
+        border-left: 2px solid #02a6b5;
+        border-top: 2px solid #02a6b5;
+      }
+      &::after{
+        .horn;
+        top: 0;
+        right: 0;
+        border-right: 2px solid #02a6b5;
+        border-top: 2px solid #02a6b5;
+      }
+      .panel-bottom{
+        &::before{
+          .horn;
+          bottom: 0;
+          left: 0;
+          border-left: 2px solid #02a6b5;
+          border-bottom: 2px solid #02a6b5;
+        }
+        &::after{
+          .horn;
+          bottom: 0;
+          right: 0;
+          border-right: 2px solid #02a6b5;
+          border-bottom: 2px solid #02a6b5;
+        }
+      }
+      .panel-title{
+        position: absolute;
+        left: 110px;
+        top: 10px;
+        font-size: 20px;
+        font-weight: bold;
+        color: #0EFCFF;
+      }
+      .panel-slider{
+        width: 250px;
+        position: absolute;
+        top: 60px;
+        left: 25px;
+      }
+      .panel-slider2{
+        width: 250px;
+        position: absolute;
+        top: 120px;
+        left: 25px;
+      }
+      .brightness{
+        width: 250px;
+        display: flex;
+        justify-content: space-between;
+        color: #909399;
+        font-size: 14px;
+      }
+    }
+  }
+}
+
+/* ::v-deep是vue3提供的深度选择器,.el-form-item__label是element-plus官方定义的类 */
+/deep/ .el-form-item__label{
+  color: white;
+  font-size: 16px;
+}
+
+.el-slider__runway{ // 滑块的进度条颜色
+  background-color: #000000;
+}
+</style>
+