Browse Source

3d模型操作

huangyan 8 months ago
parent
commit
821ec63268

+ 0 - 1
index.html

@@ -18,7 +18,6 @@
 
 <body>
   <div id="app">
-    
   </div>
   <script type="module" src="/src/main.ts"></script>
   <!-- 3D 1v -->

+ 20 - 0
package-lock.json

@@ -15,9 +15,11 @@
         "echarts": "^5.5.1",
         "element-plus": "^2.6.2",
         "mockjs": "^1.1.0",
+        "nprogress": "^0.2.0",
         "pinia": "^2.1.7",
         "vue": "^3.4.21",
         "vue-echarts": "^6.6.9",
+        "vue-loading-overlay": "^6.0.4",
         "vue-router": "^4.3.0"
       },
       "devDependencies": {
@@ -2727,6 +2729,12 @@
         "node": ">= 4"
       }
     },
+    "node_modules/nprogress": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmmirror.com/nprogress/-/nprogress-0.2.0.tgz",
+      "integrity": "sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==",
+      "license": "MIT"
+    },
     "node_modules/object-assign": {
       "version": "4.1.1",
       "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
@@ -4098,6 +4106,18 @@
         }
       }
     },
+    "node_modules/vue-loading-overlay": {
+      "version": "6.0.4",
+      "resolved": "https://registry.npmmirror.com/vue-loading-overlay/-/vue-loading-overlay-6.0.4.tgz",
+      "integrity": "sha512-DmMqLjQULk4bJ6C1IyDQzasgxb03KLrcj6nitlMIJkh6np0rQkWpgdu0upS3lJcrF9q+dmrhnU+A8I5pz41bqw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=12.13.0"
+      },
+      "peerDependencies": {
+        "vue": "^3.2.0"
+      }
+    },
     "node_modules/vue-router": {
       "version": "4.3.0",
       "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.3.0.tgz",

+ 2 - 0
package.json

@@ -18,9 +18,11 @@
     "echarts": "^5.5.1",
     "element-plus": "^2.6.2",
     "mockjs": "^1.1.0",
+    "nprogress": "^0.2.0",
     "pinia": "^2.1.7",
     "vue": "^3.4.21",
     "vue-echarts": "^6.6.9",
+    "vue-loading-overlay": "^6.0.4",
     "vue-router": "^4.3.0"
   },
   "devDependencies": {

+ 18 - 6
src/api/api.ts

@@ -1,13 +1,10 @@
-/*
- * @LastEditors: 刘嘉威 daidaibg@163.com
- * @LastEditTime: 2024-03-28 16:52:31
- */
 import axios from "axios";
 import type { AxiosRequestConfig, AxiosResponse } from "axios";
 import { StorageEnum, RequestEnum } from "@/enums";
 import { getLocalStorage } from "@/utils";
 
 import UtilVar from "../config/UtilVar";
+import { ElMessage } from "element-plus";
 let baseUrl = UtilVar.baseUrl;
 const CancelToken = axios.CancelToken;
 
@@ -16,6 +13,9 @@ export { baseUrl };
 // 添加请求拦截器
 axios.interceptors.request.use(
   function (config: AxiosRequestConfig): any {
+    if(config.noInterceptor){
+      return config;
+    }
     // 在发送请求之前做些什么 传token
     let token: any = getLocalStorage(StorageEnum.GB_TOKEN_STORE);
     if (token) {
@@ -30,6 +30,7 @@ axios.interceptors.request.use(
   function (error: any) {
     // 对请求错误做些什么
     console.log(error);
+    ElMessage.error(error);
     return Promise.reject(error);
   }
 );
@@ -104,10 +105,21 @@ export const GET = async (url: string, params: Params): Promise<any> => {
  * @param {any} params
  * @return {any}
  */
-export const POST = async (url: string, params: Params): Promise<any> => {
+// export const POST = async (url: string, params: Params): Promise<any> => {
+//   try {
+//     params = isEncryptionParam(params);
+//     const data = await axios.post(`${baseUrl}${url}`, params);
+//     return data.data;
+//   } catch (error) {
+//     return Promise.reject(error);
+//   }
+// };
+
+export const POST = async (url: string, params: any, config?: AxiosRequestConfig): Promise<any> => {
   try {
     params = isEncryptionParam(params);
-    const data = await axios.post(`${baseUrl}${url}`, params);
+    const finalConfig = { ...config, ...(config?.noInterceptor === undefined ? { noInterceptor: false } : {}) };
+    const data = await axios.post(`${baseUrl}${url}`, params, finalConfig);
     return data.data;
   } catch (error) {
     return Promise.reject(error);

+ 15 - 0
src/api/modules/login.ts

@@ -0,0 +1,15 @@
+import { POST } from "../api";
+
+// 定义登录URLs
+const loginUrl = {
+    'login': '/login', 
+};
+
+// 登录函数
+/** 登录 */
+export const Logins = (param: any = {}) => {
+    const config = { noInterceptor: true };
+    return POST(loginUrl.login, param,config);
+};
+
+export { loginUrl };

+ 19 - 12
src/assets/css/main.scss

@@ -21,26 +21,33 @@ body {
   margin: 0 auto;
   z-index: 1;
 }
-
+//3d模型
 #iot3d {
   position: absolute;
-  top: 0;
+  top: 3%;
   left: 0;
   transform: translate(0, 0);
-  // border: 5px solid rgba(0, 247, 132, 0.5);
-  margin-top: 5vh; 
-  width: 100%; 
-  height: 60vh; 
+  // border: 5px solid rgba(247, 0, 0, 0.5);
+  margin-top: 5vh;
+  width: 100%;
+  height: 80vh;
 }
 
-#iot3d > div,
-#iot3d > canvas {
+
+#iot3d>div,
+#iot3d>canvas {
   position: absolute;
   top: 0;
-  left: 25%;
-  width: 50% !important; /* 使用百分比宽度 */
-  height: 100% !important; /* 使用百分比高度 */
-  // border: 5px solid rgba(212, 0, 255, 0.5);
+  left: 0;
+  width: 100% !important;
+  height: 100% !important;
+  // border: #059465 solid 5px;
+}
+//加载动画样式
+#lot3d_loading_mask_html {
+  font-size: larger;
+  z-index: 9999;
+  background-color: rgba(255, 255, 255, 0.8);
 }
 
 html .el-message {

BIN
src/assets/img/geijkeji.gif


BIN
src/assets/img/geijkeji1.gif


+ 1 - 1
src/config/UtilVar.ts

@@ -19,7 +19,7 @@ const runtimeType:any = {
     },
     //开发环境
     development: () => {
-        UtilVar.baseUrl= `http://localhost:8080/api`
+        UtilVar.baseUrl= `http://116.204.6.184:8989/api`
 
     },
     hash:()=>{

+ 1 - 0
src/router/index.ts

@@ -7,6 +7,7 @@ import { isLoggedIn } from '@/utils/auth'
 // 登录页面组件
 const Login = () => import('@/views/LoginView.vue')
 
+
 const routes: Array<RouteRecordRaw> = [
   {
     path: '/',

+ 6 - 5
src/utils/auth.ts

@@ -1,9 +1,10 @@
 // '@/utils/auth.ts'
+import { StorageEnum, RequestEnum } from "@/enums";
+
 export function isLoggedIn(): boolean {
   // 登录状态检查逻辑
-  
-  // if (localStorage.getItem('token')) {
-  //   return true;
-  // }
-  return true;
+  if (localStorage.getItem(StorageEnum.GB_TOKEN_STORE)) {
+    return true;
+  }
+  return false;
 }

+ 1 - 1
src/views/HomeView.vue

@@ -40,7 +40,7 @@ const wrapperStyle = {};
   height: 100%;
   padding: 16px 16px 16px 16px;
   box-sizing: border-box;
-  // background-image: url("@/assets/img/pageBg.png");
+  background-image: url("@/assets/img/pageBg.png");
   // background-color: #0037ff;
   background-size: cover;
   background-position: center center;

+ 115 - 93
src/views/LoginView.vue

@@ -1,142 +1,162 @@
 <template>
-    <div class="login-container">
-        <el-form @submit.prevent="handleSubmit" :model="form" status-icon :rules="rules" ref="loginFormRef">
-            <!-- <h2>登录</h2> -->
-            <ItemWrap class="contetn_lr-item" title="登录">
-            <el-form-item prop="username">
-            <el-input v-model="form.username" placeholder="请输入用户名"></el-input>
-            </el-form-item>
-            <el-form-item prop="password">
-            <el-input v-model="form.password" type="password" placeholder="请输入密码"></el-input>
-            </el-form-item>
-
-            <el-form-item prop="captcha">
-                <div class="captcha-container">
-                    <canvas ref="captchaCanvas" width="150" height="40"></canvas>
-                    <el-button @click="refreshCaptcha" type="text">刷新验证码</el-button>
-                </div>
-                <el-input v-model="form.captchaAnswer" type="text" placeholder="请输入验证码"></el-input>
-            </el-form-item>
-
-            <el-form-item>
-                <el-button type="primary" :class="{ 'grayed-out': !isLoginFormValid }" :disabled="!isLoginFormValid" native-type="submit">登录</el-button>
-            </el-form-item>
-          </ItemWrap>
-
-        </el-form>
-    </div>
+  <div class="login-container">
+    <el-form @submit.prevent="handleSubmit" :model="form" status-icon :rules="rules" ref="loginFormRef">
+      <!-- <h2>登录</h2> -->
+      <ItemWrap class="contetn_lr-item" title="登录">
+        <el-form-item prop="username">
+          <el-input v-model="form.account" placeholder="请输入用户名"></el-input>
+        </el-form-item>
+        <el-form-item prop="password">
+          <el-input v-model="form.password" type="password" placeholder="请输入密码"></el-input>
+        </el-form-item>
+
+        <el-form-item prop="captcha">
+          <div class="captcha-container">
+            <canvas ref="captchaCanvas" width="150" height="40"></canvas>
+            <el-button @click="refreshCaptcha" type="text">刷新验证码</el-button>
+          </div>
+          <el-input v-model="form.captchaAnswer" type="text" placeholder="请输入验证码"></el-input>
+        </el-form-item>
+
+        <el-form-item>
+          <el-button type="primary" :class="{ 'grayed-out': !isLoginFormValid }" :disabled="!isLoginFormValid"
+            native-type="submit">登录</el-button>
+        </el-form-item>
+      </ItemWrap>
+
+    </el-form>
+  </div>
 </template>
 
 <script setup>
-import { reactive, onMounted, ref,computed  } from 'vue';
+import { reactive, onMounted, ref, computed } from 'vue';
 import { ElMessage } from 'element-plus';
 import router from '@/router';
+import { Logins } from '@/api/modules/login';
+import { StorageEnum, RequestEnum } from "@/enums";
+import { setLocalStorage } from "@/utils";
 
 const form = reactive({
-    username: '',
-    password: '',
-    captchaAnswer: '',
+  account: '',
+  password: '',
+  captchaAnswer: '',
 });
 
 const captchaAnswerFromServer = ref('');
 
 const isLoginFormValid = computed(() => {
-    return Boolean(form.username && form.password && form.captchaAnswer);
+  return Boolean(form.account && form.password && form.captchaAnswer);
 });
 
 const rules = reactive({
-    username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
-    password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
-    captchaAnswer: [{ required: true, message: '请输入验证码', trigger: 'blur' }],
+  account: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
+  password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
+  captchaAnswer: [{ required: true, message: '请输入验证码', trigger: 'blur' }],
 });
 
 const captchaCanvas = ref(null);
 
 function generateRandomString(length) {
-    const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
-    let result = '';
-    for (let i = 0; i < length; i++) {
-        result += characters.charAt(Math.floor(Math.random() * characters.length));
-    }
-    return result;
+  // const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
+  const characters = '0123456789';
+  let result = '';
+  for (let i = 0; i < length; i++) {
+    result += characters.charAt(Math.floor(Math.random() * characters.length));
+  }
+  return result;
 }
 
 function drawCaptcha(canvas) {
-    const ctx = canvas.getContext('2d');
-    const width = canvas.width;
-    const height = canvas.height;
-
-    // 清除画布
-    ctx.clearRect(0, 0, width, height);
-
-    // 绘制背景
-    ctx.fillStyle = '#eee';
-    ctx.fillRect(0, 0, width, height);
-
-    // 绘制验证码文本
-    const captchaText = generateRandomString(4);
-    captchaAnswerFromServer.value = captchaText;
-    ctx.font = 'bold 28px Arial';
-    ctx.textBaseline = 'middle';
-    ctx.fillStyle = '#333';
-    ctx.fillText(captchaText, width / 2 - 30, height / 2);
-
-    // 绘制干扰线
-    for (let i = 0; i < 5; i++) {
-        ctx.beginPath();
-        ctx.moveTo(Math.random() * width, Math.random() * height);
-        ctx.lineTo(Math.random() * width, Math.random() * height);
-        ctx.strokeStyle = '#aaa';
-        ctx.stroke();
-    }
+  const ctx = canvas.getContext('2d');
+  const width = canvas.width;
+  const height = canvas.height;
+
+  // 清除画布
+  ctx.clearRect(0, 0, width, height);
+
+  // 绘制背景
+  ctx.fillStyle = '#eee';
+  ctx.fillRect(0, 0, width, height);
+
+  // 绘制验证码文本
+  const captchaText = generateRandomString(4);
+  captchaAnswerFromServer.value = captchaText;
+  ctx.font = 'bold 28px Arial';
+  ctx.textBaseline = 'middle';
+  ctx.fillStyle = '#333';
+  ctx.fillText(captchaText, width / 2 - 30, height / 2);
+
+  // 绘制干扰线
+  for (let i = 0; i < 5; i++) {
+    ctx.beginPath();
+    ctx.moveTo(Math.random() * width, Math.random() * height);
+    ctx.lineTo(Math.random() * width, Math.random() * height);
+    ctx.strokeStyle = '#aaa';
+    ctx.stroke();
+  }
 }
 
 function refreshCaptcha() {
-    if (captchaCanvas.value) {
-        drawCaptcha(captchaCanvas.value);
-    }
+  if (captchaCanvas.value) {
+    drawCaptcha(captchaCanvas.value);
+  }
 }
 
 function handleSubmit() {
-    if (form.captchaAnswer.toLowerCase() !== captchaAnswerFromServer.value.toLowerCase()) {
-        ElMessage.error('验证码错误,请重新输入');
-        return;
+  if (form.captchaAnswer.toLowerCase() !== captchaAnswerFromServer.value.toLowerCase()) {
+    ElMessage.error('验证码错误,请重新输入');
+    return;
+  }
+
+  // 登录逻辑,例如跳转页面或调用API
+  Logins(form).then(res => {
+    if (res.code === 200) {
+      ElMessage.success('登录成功');
+      // console.log("登录", res.data.token);
+      // localStorage.setItem('token', res.data.token);
+      setLocalStorage(StorageEnum.GB_TOKEN_STORE, res.data.token);
+      router.push('/index');
+      form.account = '';
+      form.password = '';
+      form.captchaAnswer = '';
+      refreshCaptcha();
+    }
+    else {
+      ElMessage.error(res.message)
+      form.account = '';
+      form.password = '';
+      form.captchaAnswer = '';
     }
+  })
 
-    // 登录逻辑,例如跳转页面或调用API
-    ElMessage.success('登录成功');
-    localStorage.setItem('token', form.username);
-    router.push('/index');
-    form.username = '';
-    form.password = '';
-    form.captchaAnswer = '';
-    refreshCaptcha();
 }
 
 onMounted(() => {
-    if (captchaCanvas.value) {
-        drawCaptcha(captchaCanvas.value);
-    }
+  if (captchaCanvas.value) {
+    drawCaptcha(captchaCanvas.value);
+  }
 });
 </script>
 
 <style scoped>
 .captcha-container {
-    display: flex;
-    align-items: center;
-    gap: 10px;
-    margin-bottom: 10px;
+  display: flex;
+  align-items: center;
+  gap: 10px;
+  margin-bottom: 10px;
 }
 
 .captcha-container canvas {
-    border: 1px solid #ccc;
-    border-radius: 5px;
+  border: 1px solid #ccc;
+  border-radius: 5px;
 }
-.contetn_lr-item{
+
+.contetn_lr-item {
   font-size: 30px;
   width: 500px;
   height: auto;
 }
+
 .login-container {
   width: 500px;
   margin: 300px auto;
@@ -186,7 +206,7 @@ label {
   color: #61dafb;
   margin-right: 10px;
 }
- 
+
 #captcha span {
   color: #61dafb;
   margin-right: 10px;
@@ -196,10 +216,12 @@ label {
   width: 100px;
   margin-left: 10px;
 }
+
 .contetn_lr-item {
   height: 310px;
 }
+
 .grayed-out {
-    background-color: gray !important;
+  background-color: gray !important;
 }
 </style>

+ 1 - 1
src/views/header.vue

@@ -29,7 +29,7 @@ timeFn()
     <div class="guang"></div>
     <div class="d-flex jc-center">
       <div class="title">
-        <span class="title-text">智慧档案管理可视平台</span>
+        <span class="title-text">智慧档案管理一体化可视平台</span>
       </div>
     </div>
     <div class="timers">

+ 8 - 16
src/views/index/index.vue

@@ -15,8 +15,8 @@
         <LeftBottom />
       </ItemWrap>
     </div>
-    <div @mousedown="mousedownFn" @mouseup="mouseupFn" @mouseleave="mouseleaveFn" class="contetn_center" id="contetn_center">
-      <Iot3d v-if="shouldShowComponent" :style="{ 'z-index': ifIndex ? 200 : 1 }"  />
+    <div  class="contetn_center" id="contetn_center">
+      <Iot3d v-if="shouldShowComponent" style="z-index:200"  />
     </div>
     <div class="contetn_centerbottom">
       <ItemWrap class="contetn_center-bottom contetn_lr-item" title="视频监控">
@@ -160,26 +160,18 @@ import { NIcon } from "naive-ui";
 import Iot3d from "./iot3d.vue";
 import Monitoring from "./monitoring.vue";
 import { onBeforeRouteLeave } from 'vue-router';
+import loading from 'naive-ui/es/_internal/loading';
+import Loading from 'vue-loading-overlay'
 const shouldShowComponent = ref(true);
-const ifIndex = ref(false)
-const mousedownFn = () => {
-  console.log('1')
-  ifIndex.value = true
-}
-const mouseupFn = () => {
-  console.log('2')
-  ifIndex.value = false
-}
-const mouseleaveFn = () => {
-  console.log('3');
-  console.log(ifIndex.value);
-  // ifIndex.value = false;
-};
+
+
+
 onBeforeRouteLeave((to, from, next) => {
   shouldShowComponent.value = false;
   // 执行任何必要的清理工作
   next();
 });
+
 </script>
 
 

+ 60 - 12
src/views/index/iot3d.vue

@@ -5,22 +5,70 @@
 <script setup>
 import { ref,onMounted } from 'vue';
 import { IOT3D } from 'https://vdata.baozhida.cn/3d1v/static/js/version/IOT3Dv2.2.js';
-const canvasRef = ref()
 onMounted(()=>{
   const iot3d = new IOT3D('iot3d', false);
   iot3d.loadProject('W2N495VQH1UPGIFJKSZEMOY0C637AT8R', true, () => {
     iot3d.GetRenderer().setClearColor(0x000000, 0);
-    iot3d.GetRenderer().setSize(window.innerWidth, window.innerHeight);
-    iot3d.GetRenderer().setPixelRatio(window.devicePixelRatio);
+	// var route = [
+	// 		[2, 2, 2], // 第一个视角
+	// 		[2, 2 , 2], // 正对
+	// 		[2, 2 , 2], // 聚焦
+	// 	]
+	// 	// ------------- 路径移动
+	// 	iot3d.startMove(route,2)
+
+	// 	// 中心的
+	// 	iot3d.startFocusMotion([0, -2.815, 0],route,30);
+	iot3d.setSize(window.innerWidth, window.innerHeight)
+	
   });
-})
 
+	var Model_onDblclick_Model = null
+	// 鼠标在 模型内双击
+	iot3d.Model_onDblclick(function (Model) {
+		console.log("onDblclick_Model:",Model)
+		Model_onDblclick_Model = Model
+		iot3d.Model_Selected_Add(Model)  // 添加 选中
+		iot3d.orbitControls_target(Model.position)  //更新视角中心点
+	})
+	// 鼠标在 模型内单击
+	iot3d.Model_onClick(function (Model) {
+		console.log("Mouse_onClick:",Model)
+		if(Model == null) {
+			console.log("您点击了空处!")
+		} else {
+			console.log("您点击了模型!")
+		}
+	})
+	let lenght = 0
+	// 鼠标在 模型内按下
+	iot3d.Model_onMousedown(function (Model,event) {
+		console.log("Mouse_onMousedown:",Model,event)
+		var btnNum = event.button;
+		if(btnNum == 2) {
+			console.log("您点击了鼠标右键!")
+			if(Model == null) if(Model_onDblclick_Model != null) iot3d.Model_Selected_Del(Model_onDblclick_Model)  // 删除 选中
+		} else if(btnNum == 0) {
+			console.log("您点击了鼠标左键!")
+			console.log(Model.parent.children)
+			if (Model.parent.name==='总密集架'){
+				console.log("您点击了密集架!")
+				console.log("Model:",Model.parent.children.length)
+				
+			}
+			
+			// for (let i = 0; i < Model.parent.children.length; i++) {
+			// 	const element = Model.parent.children[i];
+			// 	if(element.type == "Object3D") {
+			// 		lenght++
+			// 	}
+			// }
+			// console.log("lenght:",lenght)
+		} else if(btnNum == 1) {
+			console.log("您点击了鼠标中键!");
 
-</script>
-<!-- <style lang="scss">
-  #iot3d{
-    display: flex;
-    justify-content: center;
-    align-items: center;
-  }
-</style> -->
+		}
+
+	})
+})
+</script>