pengwei
2025-03-24 f90fbbc76d23340e4568dd4dadbab5f7f02a030f
ÏîÄ¿´úÂë/client/src/views/tts/TheCurrentJob/Startjob.vue
@@ -126,6 +126,7 @@
                  "
                >
                  <el-table
                    empty-text="暂无数据"
                    :data="taskData"
                    width="100%"
                    :header-cell-style="{
@@ -172,6 +173,7 @@
          </div>
          <div style="position: absolute; width: 47rem; height: 2.5rem">
            <el-table
              empty-text="暂无数据"
              style="margin-top: 0.88rem"
              :data="gridData"
              width="100%"
@@ -229,6 +231,7 @@
            </el-table>
            <div class="consten" v-if="contentShow">
              <el-table
                empty-text="暂无数据"
                :data="gridData"
                width="100%"
                :header-cell-style="{
@@ -313,7 +316,10 @@
                v-model="torqueFrom.torqueSize"
                style="font-size: 0.75rem; height: 2rem"
                placeholder="请输入扭力值"
              />
                ><template #suffix>
                  <span style="font-size: 0.88rem; color: black">N*m</span>
                </template>
              </el-input>
              <!-- @blur="addTorque" -->
            </el-scrollbar>
          </div>
@@ -357,12 +363,17 @@
          justify-content: center;
          align-items: center;
          position: absolute;
          top: 33%;
          top: 35%;
          left: 50%;
          transform: translateX(-50%);
          z-index: 999;
        "
      >
        <div ref="container" style="width: 100%; height: 100%"></div>
        <div
          ref="container"
          class="my-three"
          style="width: 100%; height: 100%"
        ></div>
        <!-- <model-gltf
          :width="400"
          :height="400"
@@ -373,6 +384,11 @@
            enableZoom,
          }"
        /> -->
      </div>
      <div style="position: absolute; bottom: 5%; left: 2%">
        <span style="color: rgba(26, 201, 255, 1); font-size: 1.5em"
          >X:{{ xPos }}&nbsp;&nbsp;Y:{{ yPos }}&nbsp;&nbsp;Z:{{ zPos }}</span
        >
      </div>
      <div
        style="
@@ -471,10 +487,11 @@
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader"; //gltf
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
const container = ref(null);
let scene, camera, renderer, controls;
// let scene, camera, renderer, controls;
const router = useRouter();
const gridData = ref([]);
@@ -524,16 +541,38 @@
const innerRef = ref();
const scrollbarRef = ref();
const isJob = ref([]); //已经完成的步骤
//上一步
const Previous = (val) => {
  //上一个的值
  from.value.group = info.value.grouptype;
  from.value.takeid = info.value.njtakeid;
  from.value.setnum = obj.value.setpNum;
  flag.value = val;
  console.log(from.value, info.value);
  GetPre(from.value, flag.value).then((res) => {
    gridData.value = [res.data.nex];
    obj.value = res.data.nex;
    xPos.value =
      gridData.value[0].pointAxisXYZ != null &&
      gridData.value[0].pointAxisXYZ != 0
        ? gridData.value[0].pointAxisXYZ.split(",")[0]
        : -585;
    yPos.value =
      gridData.value[0].pointAxisXYZ != null &&
      gridData.value[0].pointAxisXYZ != 0
        ? gridData.value[0].pointAxisXYZ.split(",")[1]
        : 692;
    zPos.value =
      gridData.value[0].pointAxisXYZ != null &&
      gridData.value[0].pointAxisXYZ != 0
        ? gridData.value[0].pointAxisXYZ.split(",")[2]
        : 692;
    isJob.value = nodeList.slice(0, gridData.value[0].setpNum - 1); //已经完成的步骤
    cameraAnimate(
      [xPos.value, yPos.value, zPos.value],
      gridData.value[0].moduleName
    );
    queryData.value.setnum = obj.value.setpNum;
    GetTorque(queryData.value).then((res) => {
      Torque.value = res.data;
@@ -542,12 +581,10 @@
};
//下一步
const Next = (val) => {
  console.log(obj.value);
  from.value.group = info.value.grouptype;
  from.value.takeid = info.value.njtakeid;
  from.value.setnum = obj.value.setpNum;
  flag.value = val;
  GetNext(from.value, flag.value).then((res) => {
    if (res.message == "没有完成当前步骤") {
      gridData.value = res.data.nowdate;
@@ -560,8 +597,29 @@
    }
    centerDialogVisible.value = false;
    gridData.value = [res.data.nex];
    xPos.value =
      gridData.value[0].pointAxisXYZ != null &&
      gridData.value[0].pointAxisXYZ != 0
        ? gridData.value[0].pointAxisXYZ.split(",")[0]
        : -585;
    yPos.value =
      gridData.value[0].pointAxisXYZ != null &&
      gridData.value[0].pointAxisXYZ != 0
        ? gridData.value[0].pointAxisXYZ.split(",")[1]
        : 692;
    zPos.value =
      gridData.value[0].pointAxisXYZ != null &&
      gridData.value[0].pointAxisXYZ != 0
        ? gridData.value[0].pointAxisXYZ.split(",")[2]
        : 692;
    isJob.value = res.data.finish.map((item) => {
      return item.moduleName;
    });
    cameraAnimate(
      [xPos.value, yPos.value, zPos.value],
      gridData.value[0].moduleName
    );
    obj.value = res.data.nex;
    queryData.value.setnum = obj.value.setpNum;
    GetTorque(queryData.value).then((res) => {
      Torque.value = res.data;
@@ -611,138 +669,269 @@
  takeid: info.value.njtakeid,
  setnum: "",
});
const initData = () => {
  console.log(obj.value);
  GetScreenData({
const initData = async () => {
  await GetScreenData({
    group: info.value.grouptype,
    takeid: info.value.njtakeid,
  }).then((res) => {
    if (res.message == "返回工艺表中的第一条") {
      gridData.value = res.data.proNoe;
      obj.value = res.data.proNoe[0];
    // if (res.message == "返回工艺表中的第一条") {
    //   gridData.value = res.data.proNoe;
    //   obj.value = res.data.proNoe[0];
    //   sunNUm.value = res.data.maxproce;
    //   queryData.value.setnum = obj.value.setpNum;
    //   xPos.value =
    //     gridData.value[0].pointAxisXYZ != null &&
    //     gridData.value[0].pointAxisXYZ != 0
    //       ? gridData.value[0].pointAxisXYZ.split(",")[0]
    //       : -585;
    //   yPos.value =
    //     gridData.value[0].pointAxisXYZ != null &&
    //     gridData.value[0].pointAxisXYZ != 0
    //       ? gridData.value[0].pointAxisXYZ.split(",")[1]
    //       : 692;
    //   zPos.value =
    //     gridData.value[0].pointAxisXYZ != null &&
    //     gridData.value[0].pointAxisXYZ != 0
    //       ? gridData.value[0].pointAxisXYZ.split(",")[2]
    //       : 692;
    //   cameraAnimate(
    //     [xPos.value, yPos.value, zPos.value],
    //     nodeList[gridData.value[0].setpNum]
    //   );
    //   GetTorque(queryData.value).then((res) => {
    //     Torque.value = res.data;
    //   });
    //   return;
    // }
    gridData.value = [res.data.proNow];
      sunNUm.value = res.data.maxproce;
    obj.value = res.data.proNow;
      queryData.value.setnum = obj.value.setpNum;
      GetTorque(queryData.value).then((res) => {
        Torque.value = res.data;
      });
      return;
    }
    gridData.value = res.data.maxpro;
    sunNUm.value = res.data.maxproce;
    obj.value = res.data.maxpro[0];
    queryData.value.setnum = obj.value.setpNum;
    xPos.value =
      gridData.value[0].pointAxisXYZ != null &&
      gridData.value[0].pointAxisXYZ != 0
        ? gridData.value[0].pointAxisXYZ.split(",")[0]
        : -585;
    yPos.value =
      gridData.value[0].pointAxisXYZ != null &&
      gridData.value[0].pointAxisXYZ != 0
        ? gridData.value[0].pointAxisXYZ.split(",")[1]
        : 692;
    zPos.value =
      gridData.value[0].pointAxisXYZ != null &&
      gridData.value[0].pointAxisXYZ != 0
        ? gridData.value[0].pointAxisXYZ.split(",")[2]
        : 692;
    isJob.value = res.data.finish;
    cameraAnimate(
      [xPos.value, yPos.value, zPos.value],
      gridData.value[0].moduleName
    );
    GetTorque(queryData.value).then((res) => {
      Torque.value = res.data;
    });
  });
};
const showModel = () => {
  scene = new THREE.Scene();
  console.log("model", window.innerWidth, window.innerHeight);
  // åˆ›å»ºç›¸æœº (视角,宽高比,近裁剪面,远裁剪面)
  camera = new THREE.PerspectiveCamera(75, 1, 0.1, 1000);
  // åˆ›å»ºæ¸²æŸ“器
  renderer = new THREE.WebGLRenderer({
const CAMERA_POS = [100, 100, 150];
const BASE_COLOR = [0.2, 0.4, 0.6];
const RED_COLOR = [3.0, 0.2, 0.4];
const GREEN_COLOR = [0.0, 1.0, 0.0];
const xPos = ref("");
const yPos = ref("");
const zPos = ref("");
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  3000
);
const renderer = new THREE.WebGLRenderer({
    antialias: true,
    alpha: true,
  });
  renderer.setSize(400, 400); // è®¾ç½®æ¸²æŸ“器的大小
  container.value.appendChild(renderer.domElement);
  scene.background = null;
  // åŠ è½½GLTF模型
  const loader = new GLTFLoader();
  loader.load(
    "ThreeModel/test.gltf",
    (gltf) => {
      const model = gltf.scene;
      // è®¡ç®—模型的边界框并获取中心点
      const box = new THREE.Box3().setFromObject(model);
      const center = box.getCenter(new THREE.Vector3());
      // åˆ›å»ºä¸€ä¸ªç©ºå¯¹è±¡ä½œä¸ºçˆ¶èŠ‚ç‚¹ï¼Œå°†åæ ‡è½´å’Œæ¨¡åž‹æ·»åŠ åˆ°è¿™ä¸ªçˆ¶èŠ‚ç‚¹
      const parent = new THREE.Object3D();
      scene.add(parent);
      // å°†æ¨¡åž‹çš„位置设置为模型的边界框的中心,确保它居中
      model.position.sub(center); // è®©æ¨¡åž‹çš„中心与父节点对齐
      // å°†åæ ‡è½´åŠ©æ‰‹æ·»åŠ åˆ°çˆ¶èŠ‚ç‚¹
      // const axesHelper = new THREE.AxesHelper(100); // è½´çš„长度为100  x,y,z的颜色分别为(红色,绿色,蓝色)
      // parent.add(axesHelper); // å°†åæ ‡è½´æ·»åŠ åˆ°çˆ¶èŠ‚ç‚¹
      // å°†æ¨¡åž‹æ·»åŠ åˆ°çˆ¶èŠ‚ç‚¹
      parent.add(model);
      // ç¡®ä¿æ¨¡åž‹çš„大小适当,可以调整模型的大小
      model.scale.set(1, 1, 1); // å¦‚果需要的话可以缩放模型
    },
    undefined,
    (error) => {
      console.error("模型加载失败", error);
    }
  );
  const metalMaterial = new THREE.MeshStandardMaterial({
    color: 0xaaaaaa,
    metalness: 1,
    roughness: 0.2,
  precision: "highp",
  });
  const sphereGeometry = new THREE.SphereGeometry(1, 32, 32);
  const metalSphere = new THREE.Mesh(sphereGeometry, metalMaterial);
  scene.add(metalSphere);
  // åˆ›å»ºç¯å…‰
  const light = new THREE.AmbientLight(0xffffff); // çŽ¯å¢ƒå…‰æ˜¯ä¸€ç§å…¨å±€æ€§çš„å…‰æºï¼Œå‡åŒ€åœ°ç…§äº®æ•´ä¸ªåœºæ™¯ï¼Œå¹¶ä¸”ä¸ä¼šæœ‰é˜´å½±æ•ˆæžœ
  scene.add(light);
  const directionalLight = new THREE.DirectionalLight(0xffffff, 3); //这段代码创建了一个白色、强度为 1 çš„平行光源
  directionalLight.position.set(300, 300, 300).normalize(); //并将其位置设置在 (300, 300, 300)。然后,通过 normalize() æ–¹æ³•,确保平行光源的光线以一个标准的方向照射
  scene.add(directionalLight);
  // è®¾ç½®ç›¸æœºåˆå§‹ä½ç½®ï¼ˆx,y,z)
  camera.position.set(100, 100, 50); // è®¾ç½®ç›¸æœºä½ç½®ï¼Œç¡®ä¿å¯ä»¥çœ‹åˆ°æ¨¡åž‹
  // åˆ›å»º OrbitControls å®žä¾‹
  controls = new OrbitControls(camera, renderer.domElement);
  controls.enableZoom = false;
  controls.enablePan = false;
  controls.enableDamping = true; // å¯ç”¨é˜»å°¼æ•ˆæžœ
  controls.dampingFactor = 0.25; // é˜»å°¼ç³»æ•°
  controls.screenSpacePanning = false; // ç¦ç”¨å±å¹•空间平移
  controls.maxPolarAngle = Math.PI / 2; // é™åˆ¶ç›¸æœºåž‚直旋转的角度,防止翻转
  controls.target.set(0, 0, 0); // ç¡®ä¿ç›¸æœºå§‹ç»ˆå›´ç»•场景中心(模型位置)
  controls.minDistance = 2; // æœ€å°è·ç¦»ï¼Œé˜²æ­¢ç¼©å¾—太近
  controls.maxDistance = 500; // æœ€å¤§è·ç¦»ï¼Œé˜²æ­¢ç¼©å¾—太远
  // æ¸²æŸ“循环
  function animate() {
    requestAnimationFrame(animate);
    // æ›´æ–°æŽ§åˆ¶å™¨
    controls.update(); // åªæœ‰åœ¨å¯ç”¨é˜»å°¼çš„æ—¶å€™éœ€è¦è°ƒç”¨æ­¤å‡½æ•°
    // æ¸²æŸ“场景
    renderer.render(scene, camera);
const painting = (part) => {
  let newArr = [];
  // let newArr = flatten(isJob.value);
  scene.traverse(function (child) {
    // æ£€æŸ¥å¯¹è±¡æ˜¯å¦å…·æœ‰æè´¨å±žæ€§
    if (child.isMesh) {
      let materials = child.material;
      // å¦‚果材质是单个对象而不是数组,则将其放入数组中以便统一处理
      if (!Array.isArray(materials)) {
        materials = [materials];
      }
      let isString = []; // åˆ¤æ–­æ˜¯å¦æ˜¯å­—符串
      // éåŽ†æè´¨æ•°ç»„å¹¶è®¾ç½®é¢œè‰²
      //已经完成的节点
      isJob.value.forEach((item) => {
        if (
          item ==
            "抗蛇行减振器螺栓1,抗蛇行减振器螺栓2,抗蛇行减振器螺栓3,抗蛇行减振器螺栓4" &&
          item != part
        ) {
          isString = item.split(",");
          materials.forEach(function (material) {
            if (isString.includes(material.name)) {
              material.color.setRGB(...GREEN_COLOR);
            }
            material.needsUpdate = true; // å¼ºåˆ¶æ›´æ–°æè´¨
          });
        }
        materials.forEach(function (material) {
          if (material.name === item) {
            material.color.setRGB(...GREEN_COLOR);
          }
          material.needsUpdate = true; // å¼ºåˆ¶æ›´æ–°æè´¨
        });
      });
      console.log(part.split(","));
      if (
        part ==
        "抗蛇行减振器螺栓1,抗蛇行减振器螺栓2,抗蛇行减振器螺栓3,抗蛇行减振器螺栓4"
      ) {
        materials.forEach(function (material) {
          if (part.split(",").includes(material.name)) {
            material.color.setRGB(...RED_COLOR);
          }
          material.needsUpdate = true; // å¼ºåˆ¶æ›´æ–°æè´¨
        });
      } else {
        materials.forEach(function (material) {
          if (material.name == part) {
            material.color.setRGB(...RED_COLOR);
          }
          material.needsUpdate = true; // å¼ºåˆ¶æ›´æ–°æè´¨
        });
  }
  animate();
  // å“åº”窗口大小变化;
  window.addEventListener("resize", onWindowResize, false);
  function onWindowResize() {
    console.log(window.innerWidth, window.innerHeight);
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth / 2, window.innerHeight / 2);
      // if (
      //   typeof part ==
      //   "抗蛇行减振器螺栓1,抗蛇行减振器螺栓2,抗蛇行减振器螺栓3,抗蛇行减振器螺栓4"
      // ) {
      //   newArr = part.split(",");
      //   materials.forEach(function (material) {
      //     if (newArr.includes(material.name)) {
      //       material.color.setRGB(...GREEN_COLOR);
      //     }
      //     if (part.includes(material.name)) {
      //       material.color.setRGB(...RED_COLOR);
      //     } else {
      //       material.color.setRGB(...BASE_COLOR);
      //     }
      //     material.needsUpdate = true; // å¼ºåˆ¶æ›´æ–°æè´¨
      //   });
      // } else {
      //   materials.forEach(function (material) {
      //     if (newArr.includes(material.name)) {
      //       material.color.setRGB(...GREEN_COLOR);
      //     } else if (material.name === part) {
      //       material.color.setRGB(...RED_COLOR);
      //     } else {
      //       material.color.setRGB(...BASE_COLOR);
      //     }
      //     // if (newArr.includes(material.name)) {
      //     //   material.color.setRGB(...GREEN_COLOR);
      //     // }
      //     material.needsUpdate = true; // å¼ºåˆ¶æ›´æ–°æè´¨
      //   });
      // }
  }
  });
};
const cameraAnimate = (
  targetPosition = CAMERA_POS,
  part = null,
  duration = 500
) => {
  let startTime = null;
  const startPosition = {
    x: camera.position.x,
    y: camera.position.y,
    z: camera.position.z,
  };
  const distance = {
    x: targetPosition[0] - startPosition.x,
    y: targetPosition[1] - startPosition.y,
    z: targetPosition[2] - startPosition.z,
  };
  function animate(time) {
    if (!startTime) startTime = time;
    const elapsed = time - startTime;
    const progress = Math.min(elapsed / duration, 1);
    // ä½¿ç”¨çº¿æ€§æ’值计算新的位置
    camera.position.x = startPosition.x + distance.x * progress;
    camera.position.y = startPosition.y + distance.y * progress;
    camera.position.z = startPosition.z + distance.z * progress;
    xPos.value = Math.floor(camera.position.x);
    yPos.value = Math.floor(camera.position.y);
    zPos.value = Math.floor(camera.position.z);
    if (progress < 1) {
      requestAnimationFrame(animate);
    }
  }
  requestAnimationFrame(animate);
  painting(part);
  renderer.render(scene, camera); // å¼ºåˆ¶æ¸²æŸ“一次
};
const flatten = (arr) => {
  return arr.reduce(
    (acc, val) =>
      Array.isArray(val) ? acc.concat(flatten(val)) : acc.concat(val),
    []
  );
};
window.addEventListener("resize", () => {
  console.log("初始化场景", window.innerWidth, window.innerHeight);
  // camera.aspect = window.innerWidth / window.innerHeight;
  // camera.updateProjectionMatrix();
  // renderer.setSize(window.innerWidth, window.innerHeight);
});
const nodeList = [
  "转向架",
  "抗蛇行减振器螺栓1,抗蛇行减振器螺栓2,抗蛇行减振器螺栓3,抗蛇行减振器螺栓4",
  "抗蛇行减振器螺栓1,抗蛇行减振器螺栓2,抗蛇行减振器螺栓3,抗蛇行减振器螺栓4",
  "抗蛇行减振器螺栓2",
  "抗蛇行减振器螺栓3",
  "抗蛇行减振器螺栓4",
  "抗蛇行减振器螺栓1,抗蛇行减振器螺栓2,抗蛇行减振器螺栓3,抗蛇行减振器螺栓4",
  "抗蛇行减振器螺栓2",
  "抗蛇行减振器螺栓3",
  "抗蛇行减振器螺栓4",
  "高度调整杆",
  "高度调整杆",
  "高度调整杆",
  "转向架",
  "转向架",
  "转向架",
  "转向架",
  "转向架",
  "转向架",
  "转向架",
  "抗蛇行减振器螺栓1,抗蛇行减振器螺栓2,抗蛇行减振器螺栓3,抗蛇行减振器螺栓4",
  "抗蛇行减振器螺栓2",
  "抗蛇行减振器螺栓3",
  "抗蛇行减振器螺栓4",
  "抗蛇行减振器螺栓1,抗蛇行减振器螺栓2,抗蛇行减振器螺栓3,抗蛇行减振器螺栓4",
  "抗蛇行减振器螺栓1,抗蛇行减振器螺栓2,抗蛇行减振器螺栓3,抗蛇行减振器螺栓4",
  "高度调整杆",
  "高度调整杆",
  "高度调整杆",
  "转向架",
  "转向架",
  "转向架",
  "转向架",
  "转向架",
  "转向架",
  "转向架",
  "转向架",
];
const spanHide = ref();
const spanHide1 = ref();
const handleClickOutside = () => {
@@ -763,9 +952,9 @@
};
//添加扭力值
const addTorque = () => {
  torqueFrom.value.processSte = Torque.value[0].processSte;
  torqueFrom.value.takeId = Torque.value[0].takeId;
  torqueFrom.value.groupOp = Torque.value[0].groupOp;
  torqueFrom.value.processSte = queryData.value.setnum;
  torqueFrom.value.takeId = queryData.value.takeid;
  torqueFrom.value.groupOp = queryData.value.grop;
  if (
    torqueFrom.value.torqueSize == null ||
    torqueFrom.value.torqueSize == "" ||
@@ -798,10 +987,79 @@
      console.error("添加失败", error);
    });
};
onMounted(() => {
  document.addEventListener("click", handleClickOutside);
  // åˆå§‹åŒ–场景
  renderer.setSize(window.innerWidth / 1.5, window.innerHeight / 2);
  renderer.setClearColor(0xeeeeee); // è®¾ç½®èƒŒæ™¯è‰²
  // å¯ç”¨ç‰©ç†æ¸²æŸ“模式
  // renderer.physicallyCorrectLights = true;
  // renderer.toneMapping = THREE.ACESFilmicToneMapping;
  const mainTag = document.querySelector(".my-three");
  mainTag.appendChild(renderer.domElement);
  // æ·»åŠ äº¤äº’æŽ§åˆ¶å™¨ï¼ˆé¼ æ ‡æ‹–æ‹½ç¼©æ”¾ï¼‰
  const controls = new OrbitControls(camera, renderer.domElement);
  camera.position.set(...CAMERA_POS);
  controls.update();
  // æ·»åŠ å…‰æºï¼ˆé‡è¦ï¼å¦åˆ™æ¨¡åž‹å¯èƒ½æ˜¾ç¤ºä¸ºå…¨é»‘ï¼‰
  const light = new THREE.DirectionalLight(0xffffff, 3);
  light.position.set(5, 5, 5);
  scene.add(light);
  scene.add(new THREE.AmbientLight(0x404040));
  renderer.setClearAlpha(0);
  renderer.setPixelRatio(window.devicePixelRatio);
  scene.background = null;
  let dracoLoader = new DRACOLoader();
  dracoLoader.setDecoderPath("ThreeModel/draco/");
  dracoLoader.setDecoderConfig({ type: "js" });
  dracoLoader.preload();
  // åŠ è½½GLTF模型
  const loader = new GLTFLoader();
  loader.setDRACOLoader(dracoLoader);
  loader.load(
    "ThreeModel/modelDraco.glb", // æ›¿æ¢ä¸ºä½ çš„.gltf文件路径
    (gltf) => {
      const model = gltf.scene;
      model.scale.set(80, 80, 80);
      scene.add(model);
      // è‡ªåŠ¨å±…ä¸­æ¨¡åž‹ï¼ˆå¯é€‰ï¼‰
      const box = new THREE.Box3().setFromObject(model);
      const center = box.getCenter(new THREE.Vector3());
      model.position.sub(center);
    },
    (xhr) => {
      // åŠ è½½è¿›åº¦å›žè°ƒ
      // console.log(`${(xhr.loaded / xhr.total * 100).toFixed(1)}% loaded`);
    },
    (error) => {
      console.error("加载失败:", error);
    }
  );
  // åŠ¨ç”»å¾ªçŽ¯
  const animate = () => {
    requestAnimationFrame(animate);
    controls.update(); // å¯ç”¨æŽ§åˆ¶å™¨æ—¶éœ€è¦
    renderer.render(scene, camera);
  };
  initData();
  showModel();
  animate();
  mainTag.addEventListener("wheel", () => {
    xPos.value = Math.floor(camera.position.x);
    yPos.value = Math.floor(camera.position.y);
    zPos.value = Math.floor(camera.position.z);
  });
  mainTag.addEventListener("mousemove", () => {
    xPos.value = Math.floor(camera.position.x);
    yPos.value = Math.floor(camera.position.y);
    zPos.value = Math.floor(camera.position.z);
  });
  // };
  document.addEventListener("click", handleClickOutside);
  // showModel();
});
</script>
<style lang="scss" scoped>