suerprisePlus
2024-07-08 6f393bea8db5898684b573b8bebc64890fcc9183
three.js页面添加,obj模型添加
已添加1个文件
已修改4个文件
613 ■■■■ 文件已修改
package.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/iot/device.js 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/device/device-edit.vue 439 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/device/index.vue 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/threeJs/index.vue 143 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json
@@ -63,7 +63,7 @@
    "script-loader": "^0.7.2",
    "sortablejs": "1.10.2",
    "sql-formatter": "^4.0.2",
    "three": "^0.165.0",
    "three": "^0.157.0",
    "vue": "2.6.12",
    "vue-clipboard2": "^0.3.3",
    "vue-codemirror": "^4.0.6",
src/api/iot/device.js
@@ -144,3 +144,28 @@
    params: params,
  });
}
//mqtt连接参数查看
export function modelSelectPublishes(params) {
  return request({
    url: 'model/selectPublishes',
    method: 'get',
    params: params,
  });
}
// æ–°å¢žæ¨¡åž‹
export function setModelInsertModel(data) {
  return request({
    url: 'model/insertModel',
    method: 'post',
    data: data,
  });
}
//模型页面查询
export function setModelSelectModelByPage(params) {
  return request({
    url: 'model/selectModelByPage',
    method: 'get',
    params: params,
  });
}
src/views/iot/device/device-edit.vue
@@ -1,125 +1,154 @@
<template>
  <el-card style="margin: 6px; padding-bottom: 100px">
  <el-card style="margin: 6px;width:calc(100% - 12px); height: calc(100% - 12px);position:absolute; ">
    <el-tabs v-model="activeName" tab-position="left" @tab-click="tabChange" style="padding: 10px; min-height: 400px">
      <el-tab-pane name="basic">
        <span slot="label">* åŸºæœ¬ä¿¡æ¯</span>
        <el-form ref="form" :model="form" :rules="rules" label-width="100px">
          <el-row :gutter="100">
            <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="8">
              <el-form-item label="设备名称" prop="deviceName">
                <el-input v-model="form.deviceName" placeholder="请输入设备名称">
                  <el-button slot="append" @click="openSummaryDialog" v-if="form.deviceId != 0">摘要</el-button>
                </el-input>
              </el-form-item>
              <el-form-item label="" prop="productName">
                <template slot="label">
                  <span style="color: red">*</span>
                  æ‰€å±žäº§å“
                </template>
                <el-input readonly v-model="form.productName" placeholder="请选择产品" :disabled="form.status != 1">
                  <el-button slot="append" @click="selectProduct()" :disabled="form.status != 1">选择</el-button>
                </el-input>
              </el-form-item>
              <el-form-item label="" prop="serialNumber">
                <template slot="label">
                  <span style="color: red">*</span>
                  è®¾å¤‡ç¼–号
                </template>
                <el-input v-model="form.serialNumber" placeholder="请输入设备编号" :disabled="form.status !== 1" maxlength="32">
                  <el-button slot="append" @click="generateNum" :loading="genDisabled"
                    :disabled="form.status !== 1">生成</el-button>
                </el-input>
              </el-form-item>
              <el-form-item v-if="openServerTip">
                <template>
                  <el-alert type="info" show-icon description="当前选择TCP协议,设备编号生成为HEX格式"></el-alert>
                </template>
              </el-form-item>
              <el-form-item v-if="openTip">
                <template>
                  <el-alert type="success" show-icon description="当前选择的产品属于modbus协议,将在网关设备创建后根据采集点模板生成子设备"></el-alert>
                </template>
              </el-form-item>
              <el-form-item label="固件版本" prop="firmwareVersion">
                <el-input v-model="form.firmwareVersion" placeholder="请输入固件版本" type="number" step="0.1"
                  :disabled="form.status != 1 || form.deviceType === 3">
                  <template slot="prepend">Version</template>
                </el-input>
              </el-form-item>
              <el-form-item label="模拟设备" prop="isSimulate">
                <el-switch v-model="form.isSimulate" active-text="" inactive-text="" :active-value="1" :inactive-value="0"
                  :disabled="form.deviceType === 3"></el-switch>
              </el-form-item>
              <el-form-item label="设备影子" prop="isShadow">
                <el-switch v-model="form.isShadow" active-text="" inactive-text="" :active-value="1" :inactive-value="0"
                  :disabled="form.deviceType === 3"></el-switch>
              </el-form-item>
              <el-form-item label="禁用设备" prop="deviceStatus">
                <el-switch v-model="deviceStatus" active-text="" inactive-text=""
                           :disabled="form.status === 1 || form.deviceType === 3" :active-value="1" :inactive-value="0"
                           active-color="#F56C6C"></el-switch>
              </el-form-item>
              <el-form-item label="备注信息" prop="remark">
                <el-input v-model="form.remark" type="textarea" placeholder="请输入内容" rows="1" />
              </el-form-item>
            </el-col>
            <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="8">
              <el-form-item label="定位方式" prop="locationWay">
                <el-select v-model="form.locationWay" placeholder="请选择设备状态" clearable size="small" style="width: 100%"
                  :disabled="form.deviceType === 3">
                  <el-option v-for="dict in dict.type.iot_location_way" :key="dict.value" :label="dict.label"
                    :value="Number(dict.value)" />
                </el-select>
              </el-form-item>
              <el-form-item label="设备经度" prop="longitude">
                <el-input v-model="form.longitude" placeholder="请输入设备经度" type="number" :disabled="form.locationWay != 3">
                  <el-link slot="append" :underline="false" href="https://api.map.baidu.com/lbsapi/getpoint/index.html"
                    target="_blank" :disabled="form.locationWay != 3">坐标拾取</el-link>
                </el-input>
              </el-form-item>
              <el-form-item label="设备纬度" prop="latitude">
                <el-input v-model="form.latitude" placeholder="请输入设备纬度" type="number" :disabled="form.locationWay != 3">
                  <el-link slot="append" :underline="false" href="https://api.map.baidu.com/lbsapi/getpoint/index.html"
                    target="_blank" :disabled="form.locationWay != 3">坐标拾取</el-link>
                </el-input>
              </el-form-item>
              <el-form-item label="所在地址" prop="networkAddress">
                <el-input v-model="form.networkAddress" placeholder="请输入设备所在地址" :disabled="form.locationWay != 3" />
              </el-form-item>
              <el-form-item label="入网地址" prop="networkIp">
                <el-input v-model="form.networkIp" placeholder="设备入网IP" disabled />
              </el-form-item>
              <el-form-item label="激活时间" prop="activeTime">
                <el-date-picker clearable v-model="form.activeTime" type="date" value-format="yyyy-MM-dd"
                  placeholder="设备激活时间" disabled style="width: 100%"></el-date-picker>
              </el-form-item>
              <el-form-item label="设备信号" prop="rssi">
                <el-input v-model="form.rssi" placeholder="设备信号强度" disabled />
              </el-form-item>
              <el-form-item label="其他信息" prop="remark" v-if="form.deviceId != 0">
                <dict-tag :options="dict.type.iot_device_status" :value="form.status"
                  style="display: inline-block; margin-right: 8px" />
                <el-button size="small" @click="handleViewMqtt()">认证信息</el-button>
                <el-button size="small" @click="openCodeDialog()">二维码</el-button>
              </el-form-item>
            </el-col>
            <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="8" v-if="form.deviceId != 0">
              <div
                style="border: 1px solid #dfe4ed; border-radius: 5px; padding: 5px; text-align: center; line-height: 400px">
                <div id="map" style="height: 435px; width: 100%">地图展示区域,新增后显示</div>
              </div>
            </el-col>
          </el-row>
        </el-form>
        <el-form label-width="100px" style="margin-top: 50px">
          <el-form-item style="text-align: center; margin-left: -100px; margin-top: 10px">
            <el-button type="primary" @click="submitForm" v-hasPermi="['iot:device:edit']" v-show="form.deviceId != 0">ä¿®
              æ”¹</el-button>
            <el-button type="primary" @click="submitForm" v-hasPermi="['iot:device:add']" v-show="form.deviceId == 0">新
              å¢ž</el-button>
          </el-form-item>
        </el-form>
        <div style="width:100%;    display:flex">
          <div class="leftCount">
            <el-form ref="form" :model="form" :rules="rules" label-width="100px">
              <el-row :gutter="100">
                <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
                  <el-form-item label="设备名称" prop="deviceName">
                    <el-input v-model="form.deviceName" placeholder="请输入设备名称">
                      <el-button slot="append" @click="openSummaryDialog" v-if="form.deviceId != 0">摘要</el-button>
                    </el-input>
                  </el-form-item>
                  <el-form-item label="" prop="productName">
                    <template slot="label">
                      <span style="color: red">*</span>
                      æ‰€å±žäº§å“
                    </template>
                    <el-input readonly v-model="form.productName" placeholder="请选择产品" :disabled="form.status != 1">
                      <el-button slot="append" @click="selectProduct()" :disabled="form.status != 1">选择</el-button>
                    </el-input>
                  </el-form-item>
                  <el-form-item label="" prop="serialNumber">
                    <template slot="label">
                      <span style="color: red">*</span>
                      è®¾å¤‡ç¼–号
                    </template>
                    <el-input v-model="form.serialNumber" placeholder="请输入设备编号" :disabled="form.status !== 1"
                      maxlength="32">
                      <el-button slot="append" @click="generateNum" :loading="genDisabled"
                        :disabled="form.status !== 1">生成</el-button>
                    </el-input>
                  </el-form-item>
                  <el-form-item v-if="openServerTip">
                    <template>
                      <el-alert type="info" show-icon description="当前选择TCP协议,设备编号生成为HEX格式"></el-alert>
                    </template>
                  </el-form-item>
                  <el-form-item v-if="openTip">
                    <template>
                      <el-alert type="success" show-icon
                        description="当前选择的产品属于modbus协议,将在网关设备创建后根据采集点模板生成子设备"></el-alert>
                    </template>
                  </el-form-item>
                  <el-form-item label="固件版本" prop="firmwareVersion">
                    <el-input v-model="form.firmwareVersion" placeholder="请输入固件版本" type="number" step="0.1"
                      :disabled="form.status != 1 || form.deviceType === 3">
                      <template slot="prepend">Version</template>
                    </el-input>
                  </el-form-item>
                  <el-form-item label="模拟设备" prop="isSimulate">
                    <el-switch v-model="form.isSimulate" active-text="" inactive-text="" :active-value="1"
                      :inactive-value="0" :disabled="form.deviceType === 3"></el-switch>
                  </el-form-item>
                  <el-form-item label="设备影子" prop="isShadow">
                    <el-switch v-model="form.isShadow" active-text="" inactive-text="" :active-value="1"
                      :inactive-value="0" :disabled="form.deviceType === 3"></el-switch>
                  </el-form-item>
                  <el-form-item label="禁用设备" prop="deviceStatus">
                    <el-switch v-model="deviceStatus" active-text="" inactive-text=""
                      :disabled="form.status === 1 || form.deviceType === 3" :active-value="1" :inactive-value="0"
                      active-color="#F56C6C"></el-switch>
                  </el-form-item>
                  <el-form-item label="备注信息" prop="remark">
                    <el-input v-model="form.remark" type="textarea" placeholder="请输入内容" rows="1" />
                  </el-form-item>
                </el-col>
                <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
                  <el-form-item label="定位方式" prop="locationWay">
                    <el-select v-model="form.locationWay" placeholder="请选择设备状态" clearable size="small"
                      style="width: 100%" :disabled="form.deviceType === 3">
                      <el-option v-for="dict in dict.type.iot_location_way" :key="dict.value" :label="dict.label"
                        :value="Number(dict.value)" />
                    </el-select>
                  </el-form-item>
                  <el-form-item label="设备经度" prop="longitude">
                    <el-input v-model="form.longitude" placeholder="请输入设备经度" type="number"
                      :disabled="form.locationWay != 3">
                      <el-link slot="append" :underline="false"
                        href="https://api.map.baidu.com/lbsapi/getpoint/index.html" target="_blank"
                        :disabled="form.locationWay != 3">坐标拾取</el-link>
                    </el-input>
                  </el-form-item>
                  <el-form-item label="设备纬度" prop="latitude">
                    <el-input v-model="form.latitude" placeholder="请输入设备纬度" type="number"
                      :disabled="form.locationWay != 3">
                      <el-link slot="append" :underline="false"
                        href="https://api.map.baidu.com/lbsapi/getpoint/index.html" target="_blank"
                        :disabled="form.locationWay != 3">坐标拾取</el-link>
                    </el-input>
                  </el-form-item>
                  <el-form-item label="所在地址" prop="networkAddress">
                    <el-input v-model="form.networkAddress" placeholder="请输入设备所在地址" :disabled="form.locationWay != 3" />
                  </el-form-item>
                  <el-form-item label="入网地址" prop="networkIp">
                    <el-input v-model="form.networkIp" placeholder="设备入网IP" disabled />
                  </el-form-item>
                  <el-form-item label="激活时间" prop="activeTime">
                    <el-date-picker clearable v-model="form.activeTime" type="date" value-format="yyyy-MM-dd"
                      placeholder="设备激活时间" disabled
                      style="width: 100%"></el-date-picker>http://localhost:82/iot/template
                  </el-form-item>
                  <el-form-item label="设备信号" prop="rssi">
                    <el-input v-model="form.rssi" placeholder="设备信号强度" disabled />
                  </el-form-item>
                  <el-form-item label="设备模型" prop="modeUrl">
                    <el-select placeholder="请选择设备模型" v-model="modeUrl" @change="changeSelect" size="small"
                      style="width: 100%">
                      <el-option v-for="(item, index) in modelOption" :key="item.id" :label="item.name"
                        :value="item.id">
                      </el-option>
                    </el-select>
                  </el-form-item>
                  <el-form-item label="其他信息" prop="remark" v-if="form.deviceId != 0">
                    <dict-tag :options="dict.type.iot_device_status" :value="form.status"
                      style="display: inline-block; margin-right: 8px" />
                    <el-button size="small" @click="handleViewMqtt()">认证信息</el-button>
                    <el-button size="small" @click="openCodeDialog()">二维码</el-button>
                  </el-form-item>
                </el-col>
                <!-- <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="8" v-if="form.deviceId != 0">
            </el-col>   -->
              </el-row>
            </el-form>
            <el-form label-width="100px" style="margin-top: 50px">
              <el-form-item style="text-align: center; margin-left: -100px; margin-top: 10px">
                <el-button type="primary" @click="submitForm" v-hasPermi="['iot:device:edit']"
                  v-show="form.deviceId != 0">ä¿®
                  æ”¹</el-button>
                <el-button type="primary" @click="submitForm" v-hasPermi="['iot:device:add']"
                  v-show="form.deviceId == 0">新
                  å¢ž</el-button>
              </el-form-item>
            </el-form>
          </div>
          <div class="rightCount">
            <div class="contebtBoder">
              <div id="map" style="height:100%; width: 100%">地图展示区域,新增后显示</div>
            </div>
            <div   class="contebtBoder" style="margin-top: 20px;">
              <three-js :someData="someData"></three-js>
            </div>
          </div>
        </div>
        <!-- é€‰æ‹©äº§å“ -->
        <product-list ref="productList" :productId="form.productId" @productEvent="getProductData($event)" />
@@ -127,27 +156,27 @@
      <el-tab-pane name="runningStatus" v-if="form.deviceType !== 3 && !isSubDev">
        <span slot="label">运行状态</span>
        <running-status ref="runningStatus" :device="form" @statusEvent="getDeviceStatusData($event)"/>
        <running-status ref="runningStatus" :device="form" @statusEvent="getDeviceStatusData($event)" />
      </el-tab-pane>
      <el-tab-pane name="runningStatus" v-if="isSubDev">
        <span slot="label"><span style="color:red;">ï¿¥ </span>运行状态</span>
        <business ref="business"/>
        <business ref="business" />
      </el-tab-pane>
      <el-tab-pane name="sipChannel" :disabled="form.deviceId === 0" v-if="form.deviceType === 3">
        <span slot="label"><span style="color:red;">ï¿¥ </span>设备通道</span>
        <business ref="business"/>
        <business ref="business" />
      </el-tab-pane>
      <el-tab-pane :disabled="form.deviceId === 0" v-if="form.deviceType === 3" name="sipPlayer">
        <span slot="label"><span style="color:red;">ï¿¥ </span>设备直播</span>
        <business ref="business"/>
        <business ref="business" />
      </el-tab-pane>
      <el-tab-pane :disabled="form.deviceId === 0" v-if="form.deviceType === 3" name="sipVideo">
        <span slot="label"><span style="color:red;">ï¿¥ </span>直播录像</span>
        <business ref="business"/>
        <business ref="business" />
      </el-tab-pane>
      <el-tab-pane name="deviceTimer" :disabled="form.deviceId === 0"
@@ -172,7 +201,7 @@
        <device-func ref="deviceFuncLog" :device="form" />
      </el-tab-pane>
      <el-tab-pane name="deviceMonitor" :disabled="form.deviceId == 0 "
      <el-tab-pane name="deviceMonitor" :disabled="form.deviceId == 0"
        v-if="form.deviceType !== 3 && hasShrarePerm('monitor')">
        <span slot="label">实时监测</span>
        <device-monitor ref="deviceMonitor" :device="form" />
@@ -263,10 +292,15 @@
import business from "@/views/iot/business/index.vue";
import vueQr from 'vue-qr';
import { loadBMap } from '@/utils/map.js';
import { deviceSynchronization, getDevice, addDevice, updateDevice, generatorDeviceNum, listDevice, getMqttConnect } from '@/api/iot/device';
import {
  deviceSynchronization, getDevice, addDevice, updateDevice,
  generatorDeviceNum, listDevice, getMqttConnect, modelSelectPublishes,
  setModelInsertModel, setModelSelectModelByPage
} from '@/api/iot/device';
import { getDeviceRunningStatus } from '@/api/iot/device';
import { cacheJsonThingsModel } from '@/api/iot/model';
import { getDeviceTemp } from '@/api/iot/temp';
import threeJs from '../../threeJs/index.vue'
export default {
  name: 'DeviceEdit',
@@ -283,6 +317,7 @@
    deviceTimer,
    JsonViewer,
    vueQr,
    threeJs
  },
  watch: {
    activeName(val) {
@@ -343,7 +378,9 @@
        serialNumber: '',
        deviceType: 1,
        isSimulate: 0,
      },
      modeUrl: null,
      //mqtt参数查看
      listQuery: {
        clientId: 0,
@@ -389,9 +426,12 @@
        ],
      },
      isMediaDevice: false,
      modelOption: [],
      someData: null, showModelLayer: false,
    };
  },
  created() {
    this.getListSource();
    let activeName = this.$route.query.activeName;
    if (activeName != null && activeName != '') {
      this.activeName = activeName;
@@ -416,6 +456,28 @@
    this.mqttUnSubscribe(this.form);
  },
  methods: {
    // Js
    changeSelect() {
      this.$forceUpdate() // å¼ºåˆ¶åˆ·æ–°
    },
    getListSource() {
      modelSelectPublishes({
        name: '',
        type: ''
      }).then((response) => {
        if (response.code == 200) {
          if (response.data) {
            this.modelOption = response.data;
          } else {
            this.modelOption = [];
          }
        } else {
          this.$message('模型数据列表获取失败。');
        }
      })
    },
    /* è¿žæŽ¥Mqtt消息服务器 */
    async connectMqtt() {
      if (this.$mqttTool.client == null) {
@@ -522,7 +584,7 @@
        // èŽ·å–ç›‘æµ‹ç»Ÿè®¡æ•°æ®
        if (panel.name === 'deviceStastic' && !this.isSubDev) {
          this.$refs.deviceStatistic.getListHistory();
        } else if (panel.name === 'deviceTimer'&& !this.isSubDev) {
        } else if (panel.name === 'deviceTimer' && !this.isSubDev) {
          this.$refs.deviceTimer.getList();
        }
      });
@@ -545,6 +607,7 @@
    },
    /**获取设备详情*/
    getDevice(deviceId) {
      getDevice(deviceId).then(async (response) => {
        // åˆ†äº«è®¾å¤‡èŽ·å–ç”¨æˆ·æƒé™
        response.data.userPerms = [];
@@ -764,34 +827,58 @@
      this.$refs['form'].validate((valid) => {
        if (valid) {
          if (this.form.deviceId != 0) {
            updateDevice(this.form).then((response) => {
              if (response.data == 0) {
                this.$modal.alertError(response.msg);
              } else {
                this.$modal.alertSuccess('修改成功');
                this.form = JSON.parse(JSON.stringify(this.form));
                this.loadMap();
              }
            });
            this.setEditDevice();
          } else {
            addDevice(this.form).then(async (response) => {
              // èŽ·å–è®¾å¤‡çŠ¶æ€
              await this.getDeviceStatusWitchThingsModel(response);
              if (this.form.deviceId == null || this.form.deviceId == 0) {
                this.$modal.alertError('设备编号已经存在,添加设备失败');
              } else {
                if (this.form.status == 2) {
                  this.deviceStatus = 1;
                }
                this.$modal.alertSuccess('添加设备成功');
                this.loadMap();
              }
            });
            this.setAddDevice();
          }
        }
      });
    },
    setAddDevice() {
      const modeUrl = this.modeUrl;
      const modeName = this.form.deviceName;
      addDevice(this.form).then(async (response) => {
        // èŽ·å–è®¾å¤‡çŠ¶æ€
        await this.getDeviceStatusWitchThingsModel(response);
        if (this.form.deviceId == null || this.form.deviceId == 0) {
          this.$modal.alertError('设备编号已经存在,添加设备失败');
        } else {
          if (this.form.status == 2) {
            this.deviceStatus = 1;
          }
          if (modeUrl && response.data.deviceId) {
            this.setAddmodelToDevice(modeName, modeUrl, response.data.deviceId);
          }
          this.$modal.alertSuccess('添加设备成功');
          this.loadMap();
        }
      });
    },
    setEditDevice() {
      updateDevice(this.form).then((response) => {
        if (response.data == 0) {
          this.$modal.alertError(response.msg);
        } else {
          this.$modal.alertSuccess('修改成功');
          this.form = JSON.parse(JSON.stringify(this.form));
          this.loadMap();
        }
      });
    },
    setAddmodelToDevice(modeName, layerId, deviceId) {
      setModelInsertModel({
        "deviceid": deviceId,
        "layerid": layerId,
        "name": modeName
      }).then(response => {
      })
    },
    /** èŽ·å–è®¾å¤‡çŠ¶æ€å’Œç‰©æ¨¡åž‹ **/
    async getDeviceStatusWitchThingsModel(response) {
      // èŽ·å–ç¼“å­˜ç‰©æ¨¡åž‹
@@ -809,6 +896,9 @@
      // æ ¼å¼åŒ–物模型,拆分出监测值,数组添加前缀
      this.formatThingsModel(response.data);
      this.form = response.data;
      // è§£æžè®¾å¤‡æ‘˜è¦
      if (this.form.summary != null && this.form.summary != '') {
        this.summary = JSON.parse(this.form.summary);
@@ -819,6 +909,38 @@
      //Mqtt订阅
      this.connectMqtt();
      this.mqttSubscribe(this.form);
      this.$nextTick(() => {
        this.getModelURL(response.data.deviceId)
      })
    },
    getModelURL(res) {
      setModelSelectModelByPage({
        deviceid: res,
        pageIndex: 1,
        pageSize: 10
      }).then(response => {
        if (response.code != 200 || response.data.length <= 0) return
        const id = response.data[0].layerid;
        this.modeUrl = id
        if (this.modeUrl) {
          const obj = this.modelOption.filter(item => {
            if (item.id == id) {
              return item
            }
          })
          if (obj.length > 0) {
            this.showModelLayer = true;
            this.$nextTick(()=>{
              this.someData = obj[0].url
            })
          }
        }
      })
    },
    /**选择产品 */
    selectProduct() {
@@ -930,3 +1052,26 @@
  },
};
</script>
<style lang="scss" scoped>
.leftCount {
  flex: 1
}
.rightCount {
  width: 30%;
  height: 100%;
  padding-left: 20px;
  .contebtBoder {
    border: 1px solid #dfe4ed;
    border-radius: 5px;
    padding: 5px;
    text-align: center;
    line-height: 400px;
    height: 390px;
    position: relative;
  }
}
</style>
src/views/iot/device/index.vue
@@ -217,7 +217,8 @@
  name: 'Device',
  dicts: ['iot_device_status', 'iot_is_enable', 'iot_location_way', 'iot_transport_type'],
  components: {
    vueQr,
    vueQr
  },
  data() {
    return {
@@ -265,6 +266,7 @@
        isSimulate: 0,
      },
      isSubDev: false,
      threeModel:null,
    };
  },
  created() {
src/views/threeJs/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,143 @@
<template>
    <div id="threeBox" class="appBox"></div>
</template>
<script>
import * as THREE from "three";
import { OBJLoader } from "three/examples/jsm/loaders/OBJLoader.js";
import { MTLLoader } from "three/examples/jsm/loaders/MTLLoader.js";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { FBXLoader } from "three/examples/jsm/loaders/FBXLoader";
export default {
    props: {
        someData: {
            type: String,
            default: "",
        }
    },
    data() {
        return {
            scene: null,
            camera: null,
            mesh: null,
            renderer: null,
            object: null,
        }
    },
    mounted() {
    },
    methods: {
        setRender() {
            this.renderer.render(this.scene, this.camera);
        },
        setMapThreeStart() {
            const threeBox = document.getElementById("threeBox");
            const width = threeBox.offsetWidth;
            const height = threeBox.offsetHeight;
            // åˆ›å»ºåœºæ™¯
            this.scene = new THREE.Scene();
            // const axesHelper = new THREE.AxesHelper(200);
            // this.scene.add(axesHelper);
            // åˆ›å»ºç›¸æœº
            this.camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 10000);
            // æ ¹æ®éœ€è¦è®¾ç½®ç›¸æœºä½ç½®å…·ä½“值
            this.camera.position.set(0.5, 0.5, 0.5);
            this.camera.lookAt(0, 0, 0);
            this.scene.add(this.camera);
            // æ·»åŠ å…‰æº
            const ambientLight = new THREE.AmbientLight(0xffffff, 0.4);
            this.scene.add(ambientLight);
            const pointLight = new THREE.PointLight(0xffffff, 0.8);
            this.camera.add(pointLight);
            const ambientLight1 = new THREE.HemisphereLight("#Ffffff", "#000000", 1);
            this.scene.add(ambientLight1);
            // åˆ›å»ºæ¸²æŸ“器
            this.renderer = new THREE.WebGLRenderer({ antialias: false });
            this.renderer.setClearColor("rgb(248,248,255)", 1.0);
            this.renderer.setSize(width, height);
            threeBox.appendChild(this.renderer.domElement);
            this.setRender();
            this.clock = new THREE.Clock();
            this.addOrbitControls();
        },
        addOrbitControls() {
            // è®¾ç½®ç›¸æœºæŽ§ä»¶è½¨é“控制器OrbitControls
            const controls = new OrbitControls(this.camera, this.renderer.domElement);
            // å¦‚æžœOrbitControls改变了相机参数,重新调用渲染器渲染三维场景
            const that = this;
            controls.addEventListener("change", function () {
                that.setRender();
            }); //监听鼠标、键盘事件
        },
        replaceLast6Chars(res, replacement) {
            if (!res) return
            return res.slice(0, -3) + replacement.padEnd(3, '');
        },
        setMapThree(res) {
            var that = this;
            var mtlLoader = new MTLLoader();
            const objUrl = res;
            var mtlUrl = res;
            if (res.indexOf('.obj') > -1) {
                mtlUrl = this.replaceLast6Chars(res, 'mtl')
            }
            mtlLoader.load(mtlUrl, (material) => {
                console.log(material);
                material.preload();
                var objLoader = new OBJLoader();
                //设置当前加载的纹理
                objLoader
                    .setMaterials(material)
                    .load(objUrl, (item) => {
                        item.position.set(0, 0, 0);
                        //
                        //
                        item.traverse(function (obj) {
                            if (obj.isMesh) {
                                obj.castShadow = true; //阴影
                                obj.receiveShadow = true; //接受别人投的阴影
                            }
                        });
                        that.scene.add(item);
                        that.object = item;
                        that.setRender();
                    });
            });
        },
        setRender() {
            this.renderer.render(this.scene, this.camera);
        },
    },
    watch: {
        someData(n, o) {
            if (n) {
                if (!this.scene) {
                    this.setMapThreeStart();
                }
                this.$nextTick(() => {
                    this.setMapThree(n);
                })
                //
            }
        }
    }
}
</script>
<style scoped lang="scss">
.appBox {
    // width: 100%;
    // height: 100%;
    width: 616px;
    height: 379px;
    position: absolute;
}
</style>