Browse Source

feat: 修改需求

bill 1 năm trước cách đây
mục cha
commit
3fc5add4db

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 53 - 9
src/lib/board/4dmap.d.ts


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1573 - 1569
src/lib/board/4dmap.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 4 - 4
src/lib/board/4dmap.umd.cjs


+ 13 - 15
src/request/type.ts

@@ -11,20 +11,18 @@ import {
   WholeLinePolygonAttrib,
 } from "drawing-board";
 
-
-
 type UserInfoRoles = {
-  roleId: number
-  roleKey: string
-  roleName: string
-}
+  roleId: number;
+  roleKey: string;
+  roleName: string;
+};
 export type UserInfo = {
   head: string;
   nickName: string;
   userName: string;
-  roles: UserInfoRoles[]
-  orgId: string
-  orgName?: string
+  roles: UserInfoRoles[];
+  orgId: string;
+  orgName?: string;
 };
 
 export type Relics = {
@@ -47,18 +45,18 @@ export type ResPage<T> = {
 };
 
 export type ResResult = {
-  code: number
-  data: any
-  message: any
-  success: boolean
-  timestamp: string
-
+  code: number;
+  data: any;
+  message: any;
+  success: boolean;
+  timestamp: string;
 };
 export type ScenePoint = {
   tbStatus: number;
   createTime: string;
   updateTime: string;
   cameraType: DeviceType;
+  index: number;
   id: number;
   uuid: number;
   name: string;

+ 29 - 9
src/router.ts

@@ -2,6 +2,9 @@ import { RouteRecordRaw, createRouter, createWebHashHistory } from "vue-router";
 import { UserStatus, logintAuth, userStatus } from "./store/user";
 import { watch, watchEffect } from "vue";
 
+export const COORD_NAME = "map-coord";
+export const POYS_NAME = "map-poy";
+
 const history = createWebHashHistory();
 const routes: RouteRecordRaw[] = [
   {
@@ -35,18 +38,32 @@ const routes: RouteRecordRaw[] = [
       {
         path: "relics/:relicsId",
         children: [
+          // {
+          //   path: "",
+          //   name: "map",
+          //   meta: { title: "文物", navClass: "map" },
+          //   component: () => import("@/view/map/map-board.vue"),
+          // },
           {
-            path: "",
+            path: "map",
             name: "map",
             meta: { title: "文物", navClass: "map" },
-            component: () => import("@/view/map/map-board.vue"),
+            component: () => import("@/view/map/layout.vue"),
+            children: [
+              {
+                path: "coord",
+                name: COORD_NAME,
+                meta: { title: "文物", navClass: "map" },
+                component: () => import("@/view/map/coord.vue"),
+              },
+              {
+                path: "polygons",
+                name: POYS_NAME,
+                meta: { title: "文物", navClass: "map" },
+                component: () => import("@/view/map/polygons.vue"),
+              },
+            ],
           },
-          // {
-          //   path: "test",
-          //   name: "map-test",
-          //   meta: { title: "文物", navClass: "map" },
-          //   component: () => import("@/view/map/test-board.vue"),
-          // },
           {
             path: "pano/:pid",
             name: "pano",
@@ -79,7 +96,6 @@ const routes: RouteRecordRaw[] = [
         meta: { title: "用户管理" },
         component: () => import("@/view/users.vue"),
       },
-  
     ],
   },
   {
@@ -169,6 +185,10 @@ router.beforeEach((to, _, next) => {
     }
     return;
   }
+  console.log(to.name);
+  if (to.name === "map") {
+    router.replace({ name: COORD_NAME, params: to.params });
+  }
 
   if (to.meta?.title) {
     setDocTitle(to.meta.title as string);

+ 96 - 21
src/store/scene.ts

@@ -1,11 +1,17 @@
 import { relicsScenesFetch, updateRelicsScenePosNameFetch } from "@/request";
-import { computed, ref } from "vue";
+import { computed, ref, watch, watchEffect } from "vue";
 import { Scene, ScenePoint } from "@/request/type";
 import { gHeaders } from "@/request/state";
 import { relics } from "./relics";
 import { DeviceType, DeviceType as SceneType } from "./device";
 import { conversionFactory } from "@/helper/coord-transform";
 import { getTokenFetch } from "@/request";
+import {
+  PolygonsPointAttrib,
+  getWholeLineLinesByPointId,
+  PolygonsAttrib,
+} from "drawing-board";
+import { getDrawingDetailFetch } from "@/request/drawing";
 
 export type { Scene, ScenePoint };
 
@@ -21,6 +27,7 @@ export const scenePoints = computed(() =>
     return t;
   }, [] as ScenePoint[])
 );
+
 export const relicsId = computed(() => relics.value!.relicsId);
 
 // https://4dkankan.oss-cn-shenzhen.aliyuncs.com/scene_view_data/KJ-t-OgSx9XIrvNQ/images/panoramas/22.jpg?x-oss-process=image/resize,m_fixed,w_6144&171342528615
@@ -38,6 +45,7 @@ export const getPointPano = (point: ScenePoint, tile = false) => {
     return `https://4dkk.4dage.com/scene_view_data/${point.sceneCode}/images/pan/high/${point.uuid}.jpg`;
   }
 };
+
 export const refreshScenes = async () => {
   const sscenes = await relicsScenesFetch(relicsId.value);
   scenes.value = sscenes.map((scene) => {
@@ -70,28 +78,32 @@ export const refreshScenes = async () => {
 
     return {
       ...scene,
-      scenePos: scene.scenePos.map((pos) => {
-        let coord =
-          scene.calcStatus !== SceneStatus.SUCCESS ? ([] as any) : pos.pos;
-        if (conversion && scene.calcStatus === SceneStatus.SUCCESS) {
-          let center = scenesTransform[pos.sceneCode]?.translate || [0, 0, 0];
-          let rotate = scenesTransform[pos.sceneCode]?.rotate || 0;
-          let [x, y, z] = pos.location;
-          console.log(pos.location);
-          const cos = Math.cos(rotate);
-          const sin = Math.sin(rotate);
-          x = x * cos - y * sin + center[0];
-          y = x * sin + y * cos + center[1];
-
-          coord = conversion.toWGS84([x, y, z]);
-        }
-        return {
-          ...pos,
-          pos: coord,
-        };
-      }),
+      scenePos: scene.scenePos
+        .sort((a, b) => a.index - b.index)
+        .map((pos) => {
+          let coord =
+            scene.calcStatus !== SceneStatus.SUCCESS ? ([] as any) : pos.pos;
+          if (conversion && scene.calcStatus === SceneStatus.SUCCESS) {
+            let center = scenesTransform[pos.sceneCode]?.translate || [0, 0, 0];
+            let rotate = scenesTransform[pos.sceneCode]?.rotate || 0;
+            let [x, y, z] = pos.location;
+            console.log(pos.location);
+            const cos = Math.cos(rotate);
+            const sin = Math.sin(rotate);
+            x = x * cos - y * sin + center[0];
+            y = x * sin + y * cos + center[1];
+
+            coord = conversion.toWGS84([x, y, z]);
+          }
+          return {
+            ...pos,
+            pos: coord,
+          };
+        }),
     };
   });
+
+  await refreshBoardData();
 };
 
 export const updateScenePointName = async (
@@ -145,3 +157,66 @@ export const SceneStatusDesc: { [key in SceneStatus]: string } = {
   [SceneStatus.ERR]: "计算失败",
   [SceneStatus.SUCCESS]: "计算成功",
 };
+
+export const boardData = ref<PolygonsAttrib & { id: string }>();
+export const refreshBoardData = async () => {
+  const data = (await getDrawingDetailFetch(String(relicsId.value)))
+    .data as PolygonsAttrib;
+
+  boardData.value = {
+    ...data,
+    id: relicsId.value.toString(),
+  };
+};
+
+const scenePosTransform = (scenes: Scene[]) => {
+  const points: PolygonsPointAttrib[] = [];
+  scenes.forEach((scene) => {
+    if (scene.calcStatus !== SceneStatus.SUCCESS) {
+      return;
+    }
+    scene.scenePos.forEach((pos) => {
+      if (!pos.pos || pos.pos.length === 0) {
+        return;
+      }
+      points.push({
+        x: pos.pos[0],
+        y: pos.pos[1],
+        title: pos.name,
+        id: pos.id.toString(),
+        rtk: true,
+      });
+    });
+  });
+  return points;
+};
+
+watch(
+  () => ({ scenes: scenes.value, poyData: boardData.value }),
+  ({ scenes, poyData }) => {
+    if (!poyData) return;
+
+    const points = scenePosTransform(scenes);
+    const canDelPoint = (id: string) =>
+      getWholeLineLinesByPointId(poyData, id).length === 0 &&
+      !points.some(({ id: rtkId }) => id === rtkId);
+
+    // 查看是否有多余的点,有则删除,出现原因是删除了场景
+    for (let i = 0; i < poyData.points.length; i++) {
+      if (canDelPoint(poyData.points[i].id)) {
+        poyData.points.splice(i--, 1);
+      }
+    }
+
+    // 将rtk点加入
+    for (let i = 0; i < points.length; i++) {
+      const ndx = poyData.points.findIndex(({ id }) => id === points[i].id);
+      if (!~ndx) {
+        poyData.points.push(points[i]);
+      } else {
+        poyData.points[ndx] = { ...points[i] };
+      }
+    }
+  },
+  { immediate: true, flush: "sync" }
+);

+ 411 - 0
src/view/map/coord.vue

@@ -0,0 +1,411 @@
+<template>
+  <div class="right-layout">
+    <div class="tile-select">
+      <el-select
+        v-model="tileType"
+        placeholder="选择底图"
+        style="width: 120px"
+        class="tile-type-select"
+      >
+        <el-option v-for="item in tileOptions" :key="item" :label="item" :value="item" />
+      </el-select>
+    </div>
+
+    <div class="right-content">
+      <el-form :inline="false" v-if="!queryMode">
+        <el-form-item>
+          <el-button type="primary" :icon="Plus" style="width: 100%" @click="addHandler">
+            添加场景
+          </el-button>
+        </el-form-item>
+      </el-form>
+      <div class="tree-layout">
+        <p class="sub-title">全部数据</p>
+        <el-tree
+          style="max-width: 600px"
+          :data="treeNode"
+          :props="{ disabled: 'run' }"
+          node-key="id"
+          ref="treeRef"
+          :show-checkbox="!queryMode"
+          default-expand-all
+          :expand-on-click-node="false"
+        >
+          <template #default="{ node, data }">
+            <div
+              class="tree-item"
+              @click="
+                !data.disable &&
+                  (data.type === 'scene' ? flyScene(data) : flyPos(data.raw))
+              "
+            >
+              <el-tooltip
+                v-if="data.type === 'scene'"
+                class="box-item"
+                effect="dark"
+                :content="data.raw.sceneName + ' ' + node.label"
+                placement="top"
+              >
+                <span :class="{ disable: data.disable }" class="title">
+                  <el-icon>
+                    <Grid />
+                  </el-icon>
+                  {{ data.raw.sceneName }}
+
+                  <span class="tree-scene-name">{{ node.label }}</span>
+                </span>
+              </el-tooltip>
+              <el-tooltip
+                v-else
+                class="box-item"
+                effect="dark"
+                :content="node.label"
+                placement="top"
+              >
+                <div class="title-box">
+                  <span :class="{ disable: data.disable }" class="title">
+                    <el-icon>
+                      <StateGpsIcon v-if="!data.disable" />
+                      <DeleteLocation v-else />
+                    </el-icon>
+                    {{ node.label }}
+                    <!-- uu -->
+                  </span>
+                  <span :class="{ disable: data.disable }" class="name">
+                    {{ data.raw.name }}
+                  </span>
+                </div>
+              </el-tooltip>
+              <span class="oper">
+                <template v-if="!queryMode">
+                  <template v-if="data.type === 'scene'">
+                    <el-icon color="#409efc" v-if="data.raw.creationMethod !== 2">
+                      <Delete @click.stop="delSceneHandler([data.raw])" />
+                    </el-icon>
+                  </template>
+                  <el-icon v-else color="#409efc">
+                    <Edit @click.stop="inputPoint = data.raw" />
+                  </el-icon>
+                </template>
+                <el-icon color="#409efc" style="margin-left: 8px">
+                  <!-- root -->
+                  <template v-if="data.raw.scenePos">
+                    <FrameIcon
+                      v-if="!data.run"
+                      @click.stop="
+                        data.type === 'scene'
+                          ? gotoScene(data.raw)
+                          : gotoPointPage(data.raw)
+                      "
+                    />
+                  </template>
+                  <template v-else>
+                    <PanoramaIcon
+                      v-if="!data.run"
+                      @click.stop="
+                        data.type === 'scene'
+                          ? gotoScene(data.raw)
+                          : gotoPointPage(data.raw)
+                      "
+                    />
+                  </template>
+                </el-icon>
+              </span>
+            </div>
+          </template>
+        </el-tree>
+      </div>
+    </div>
+
+    <template v-if="!queryMode">
+      <el-button
+        type="primary"
+        :icon="Download"
+        style="width: 100%"
+        @click="exportFile(getSelectPoints(), 2, relics?.name)"
+      >
+        导出本体边界坐标
+      </el-button>
+
+      <el-button
+        type="primary"
+        :icon="Download"
+        style="width: 100%; margin-top: 20px; margin-left: 0"
+        @click="exportImage(getSelectPoints(), relics?.name)"
+      >
+        下载全景图
+      </el-button>
+    </template>
+  </div>
+
+  <SingleInput
+    :visible="!!inputPoint"
+    @update:visible="inputPoint = null"
+    :value="inputPoint?.name || ''"
+    :update-value="updatePointName"
+    title="测点说明"
+    placeholder="请填写测点说明"
+  />
+</template>
+
+<script setup lang="ts">
+import { boardDataChange, queryMode } from "./install";
+import {
+  Plus,
+  Delete,
+  Grid,
+  Download,
+  DeleteLocation,
+  Edit,
+} from "@element-plus/icons-vue";
+import { computed, onBeforeUnmount, ref, watchEffect } from "vue";
+import {
+  Scene,
+  scenes,
+  ScenePoint,
+  updateScenePointName,
+  gotoScene,
+  relicsId,
+  refreshScenes,
+  boardData,
+  scenePoints,
+} from "@/store/scene";
+import { relics } from "@/store/relics";
+import SingleInput from "@/components/single-input.vue";
+import { selectScenes } from "../quisk";
+import { addRelicsScenesFetch, delRelicsScenesFetch } from "@/request";
+import { exportFile, exportImage } from "./pc4Helper";
+import { SceneStatus } from "@/store/scene";
+import StateGpsIcon from "@/assets/state_gps.svg";
+import PanoramaIcon from "@/assets/panorama.svg";
+import FrameIcon from "@/assets/frame.svg";
+import { alert } from "@/helper/message";
+import {
+  PolygonsPointAttrib,
+  getWholeLineLinesByPointId,
+  getWholeLinePoint,
+} from "drawing-board";
+import { flyScene, gotoPointPage, tileType, mapManage, tileOptions } from "./install";
+import { board } from "./install";
+
+const inputPoint = ref<ScenePoint | null>(null);
+const updatePointName = async (title: string) => {
+  const point = getWholeLinePoint(
+    boardData.value,
+    inputPoint.value.id.toString()
+  ) as PolygonsPointAttrib;
+  await Promise.all([
+    boardDataChange(() => (point.title = title)),
+    updateScenePointName(inputPoint.value!, title),
+  ]);
+};
+
+const flyPos = (point: ScenePoint) => {
+  mapManage.map.getView().setCenter(point.pos);
+  board.polygon.status.activePointId = point.id.toString();
+};
+
+const relicsName = ref("");
+watchEffect(() => (relicsName.value = relics.value?.name || ""));
+
+const treeRef = ref<any>();
+const treeNode = computed(() =>
+  scenes.value.map((scene) => ({
+    label: scene.sceneCode,
+    id: scene.id,
+    type: "scene",
+    run: scene.calcStatus !== SceneStatus.SUCCESS,
+    disable: scene.scenePos.every((pos) => !pos.pos || pos.pos.length === 0),
+    raw: scene,
+    children: scene.scenePos.map((pos) => ({
+      label: pos.uuid,
+      run: scene.calcStatus !== SceneStatus.SUCCESS,
+      disable: !pos.pos || pos.pos.length === 0,
+      id: pos.id,
+      type: "point",
+      raw: { ...pos, name: pos.name, cameraType: scene.cameraType },
+    })),
+  }))
+);
+
+const getSelectPoints = () =>
+  treeRef
+    .value!.getCheckedNodes(false, false)
+    .filter((option: any) => option.type === "point")
+    .map((option: any) => option.raw) as ScenePoint[];
+
+watchEffect(() => {
+  if (treeRef.value) {
+    board.polygon.status.selectPoiIds = getSelectPoints().map((point) =>
+      point.id.toString()
+    );
+  }
+});
+
+const delScenesBeforeCheck = async (scenes: Scene[]) => {
+  if (scenes.length === 0) return true;
+  for (const scene of scenes) {
+    const que = scene.scenePos.some((pos) => {
+      const id = pos.id.toString();
+      return getWholeLineLinesByPointId(boardData.value, id).length !== 0;
+    });
+    if (que) {
+      await alert("已存在矢量图数据,不可删除。");
+      return false;
+    }
+    return true;
+  }
+};
+
+const addHandler = async () => {
+  const sceneCodes = scenes.value.map((scene) => scene.sceneCode);
+  await selectScenes({
+    scenes: scenes.value,
+    selfScenes: scenes.value.filter((scene) => scene.creationMethod === 2),
+    submit: async (nScene) => {
+      const requests: Promise<any>[] = [];
+      const delScenes = sceneCodes
+        .filter((sceneCode) => !nScene.some((scene) => scene.sceneCode === sceneCode))
+        .map((sceneCode) => scenes.value.find((scene) => scene.sceneCode === sceneCode)!);
+
+      if (!(await delScenesBeforeCheck(delScenes))) {
+        throw "不可删除";
+      }
+
+      delScenes.length &&
+        requests.push(
+          delRelicsScenesFetch(
+            relicsId.value,
+            delScenes.map((item) => ({ sceneCode: item.sceneCode, id: item.sceneId }))
+          )
+        );
+      const addScenes = nScene.filter(({ sceneCode }) => !sceneCodes.includes(sceneCode));
+      addScenes.length &&
+        requests.push(
+          addRelicsScenesFetch(
+            relicsId.value!,
+            addScenes.map((item) => ({ sceneCode: item.sceneCode, id: item.sceneId }))
+          )
+        );
+
+      await Promise.all(requests);
+      requests.length && (await refreshScenes());
+    },
+  });
+};
+
+const delSceneHandler = async (scenes: Scene[]) => {
+  if (!(await delScenesBeforeCheck(scenes))) {
+    return;
+  }
+  await delRelicsScenesFetch(
+    relicsId.value,
+    scenes.map((item) => ({ sceneCode: item.sceneCode, id: item.sceneId }))
+  );
+  await refreshScenes();
+};
+
+const pointClickHandler = ({ id }: { id: any }) => {
+  const point = scenePoints.value.find((point) => point.id.toString() === id);
+  point && gotoPointPage(point);
+};
+
+board.polygon.bus.on("clickPoint", pointClickHandler);
+onBeforeUnmount(() => {
+  board.polygon.bus.off("clickPoint", pointClickHandler);
+});
+</script>
+
+<style lang="scss" scoped>
+:deep(.el-tree-node__content) {
+  --el-tree-node-content-height: 26px;
+  line-height: 26px;
+  user-select: none;
+  margin-bottom: 8px;
+}
+
+:deep(.el-tree-node__children .el-tree-node__content) {
+  --el-tree-node-content-height: 52px;
+
+  & > label.el-checkbox {
+    padding-top: 6px;
+    align-items: flex-start;
+  }
+}
+
+.tree-item {
+  display: flex;
+  width: calc(100% - 50px);
+  align-items: flex-start;
+  justify-content: space-between;
+  font-size: var(--font14);
+
+  .title {
+    flex: 1;
+    overflow: hidden;
+    display: inline-flex;
+    align-items: center;
+    text-overflow: ellipsis; //文本溢出显示省略号
+    white-space: nowrap; //文本不会换行
+    line-height: 26px;
+  }
+
+  .title-box {
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    width: 100%;
+    flex-wrap: nowrap;
+
+    .name {
+      padding-left: 15px;
+      color: #999;
+    }
+  }
+
+  .oper {
+    flex: none;
+    line-height: 26px;
+    vertical-align: middle;
+  }
+}
+
+.disable {
+  pointer-events: all;
+}
+
+.tree-layout {
+  p {
+    color: #303133;
+  }
+
+  .sub-title {
+    font-size: 14px;
+    font-weight: bolder;
+  }
+}
+
+.right-layout {
+  display: flex;
+  height: 100%;
+  flex-direction: column;
+
+  .right-content {
+    flex: 1;
+    overflow-y: auto;
+  }
+}
+
+.tree-layout .tree-scene-name {
+  font-size: 10px;
+  margin: 0;
+  color: #999;
+}
+
+.tile-select {
+  position: absolute;
+  right: 100%;
+  top: 10px;
+  margin-right: 10px;
+}
+</style>

+ 125 - 0
src/view/map/install.ts

@@ -0,0 +1,125 @@
+import { TileType, createMap, Manage } from "./openlayer";
+import { computed, ref, watch, watchEffect } from "vue";
+import ScaleLine from "ol/control/ScaleLine";
+import { createBoard, PoPoint, changeEnv } from "drawing-board";
+import { Scene, ScenePoint, boardData, relicsId, scenes } from "@/store/scene";
+import { router, COORD_NAME } from "@/router";
+import { addOrUpdateDrawingFetch } from "@/request/drawing";
+
+// ---------map---------
+
+export const tileOptions: TileType[] = ["影像底图", "矢量底图"];
+export const tileType = ref<TileType>(tileOptions[0]);
+export const defaultCenter = [116.412611, 39.908866];
+
+const addScale = (mapManage: Manage) => {
+  const scaleLine = new ScaleLine({
+    className: "scale-view",
+    maxWidth: 150,
+    minWidth: 100,
+    units: "metric",
+  });
+  // 加载比例尺
+  mapManage.map.addControl(scaleLine);
+
+  watch(
+    tileType,
+    (type) => {
+      const el = (scaleLine as any).element as HTMLDivElement;
+      el.classList.add(type === "影像底图" ? "light" : "dark");
+      el.classList.remove(type === "影像底图" ? "dark" : "light");
+    },
+    { flush: "post", immediate: true }
+  );
+};
+
+export const mapManage = createMap();
+mapManage.setCenter(defaultCenter);
+watchEffect(() => mapManage.setTileType(tileType.value));
+addScale(mapManage);
+
+const noValidPoint = (pos: ScenePoint) => !pos.pos || pos.pos.length === 0;
+const validScene = (scene: Scene) => !scene.scenePos.every(noValidPoint);
+
+export const autoInitPos = () => {
+  const scene = scenes.value.find(validScene);
+  if (scene) {
+    flyScene(scene);
+    return true;
+  } else {
+    return false;
+  }
+};
+
+watch(
+  () => scenes.value.find(validScene)?.sceneCode,
+  (code) => {
+    code && autoInitPos();
+  },
+  { immediate: true }
+);
+
+export const flyScene = (scene: Scene) => {
+  console.log("flyScene", scene);
+  const totalPos = [0, 0];
+  let numCalc = 0;
+  for (let i = 0; i < scene.scenePos.length; i++) {
+    const coord = scene.scenePos[i].pos as number[];
+    if (coord && coord.length > 0) {
+      totalPos[0] += coord[0];
+      totalPos[1] += coord[1];
+      numCalc++;
+    }
+  }
+
+  totalPos[0] /= numCalc;
+  totalPos[1] /= numCalc;
+  mapManage.map.getView().setCenter(totalPos);
+};
+
+export const gotoPointPage = (point: ScenePoint) => {
+  router.push({
+    name: queryMode.value ? "query-pano" : "pano",
+    params: { pid: point.id },
+  });
+};
+
+// -------board------
+export const board = createBoard({ map: mapManage.map });
+watch(
+  boardData,
+  (data) => {
+    data && board.setData(data);
+    console.log("set board data", data);
+  },
+  {
+    immediate: true,
+    flush: "pre",
+  }
+);
+watch(
+  () => [router.currentRoute.value.name, boardData.value],
+  ([name]) => {
+    const showOther = name !== COORD_NAME;
+    board.polygon &&
+      board.polygon.children.filter((entity) => {
+        if (!(entity instanceof PoPoint && entity.attrib.rtk)) {
+          entity.visible(showOther);
+        }
+      });
+  },
+  { immediate: true, flush: "post" }
+);
+export const boardDataChange = (dataChange?: () => void) => {
+  dataChange && dataChange();
+  return addOrUpdateDrawingFetch({
+    relicsId: relicsId.value.toString(),
+    data: boardData.value,
+  });
+};
+
+// -----------status----------
+
+export const queryMode = computed(() =>
+  router.currentRoute.value.name.toString().includes("query")
+);

+ 220 - 0
src/view/map/layout.vue

@@ -0,0 +1,220 @@
+<template>
+  <div class="map-layout">
+    <div class="custom_bar">
+      <div class="back_container">
+        <el-button :icon="Back" circle type="primary" @click="router.back()" />
+      </div>
+      <div class="nav_container">
+        <div
+          v-for="menu in menus"
+          :key="menu.router"
+          class="nav_item"
+          :class="{ active: router.currentRoute.value.name === menu.router }"
+          @click="router.push({ name: menu.router })"
+        >
+          <el-icon size="20">
+            <component :is="menu.icon" />
+          </el-icon>
+          <span>{{ menu.name }}</span>
+        </div>
+      </div>
+    </div>
+
+    <div class="map-oper-layout">
+      <div class="map-container" :ref="setMapContainer">
+        <div class="board" :ref="setBoardContainer"></div>
+      </div>
+
+      <div class="data-panel">
+        <RouterView v-slot="{ Component }" v-if="loaded">
+          <component :is="Component" />
+        </RouterView>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { router } from "@/router";
+import { Back } from "@element-plus/icons-vue";
+import vectorIcon from "@/assets/vector.svg";
+import locationIcon from "@/assets/location.svg";
+import { COORD_NAME, POYS_NAME } from "@/router";
+import { mapManage, board, autoInitPos, defaultCenter } from "./install";
+import { ref, watch } from "vue";
+import { initRelics, relics } from "@/store/relics";
+
+const menus = [
+  {
+    icon: locationIcon,
+    name: "坐标",
+    router: COORD_NAME,
+  },
+  {
+    icon: vectorIcon,
+    name: "矢量图",
+    router: POYS_NAME,
+  },
+];
+
+const setMapContainer = (dom: HTMLDivElement) => setTimeout(() => mapManage.mount(dom));
+const setBoardContainer = (dom: HTMLDivElement) =>
+  setTimeout(() => board.setProps({ dom }));
+
+const loaded = ref(false);
+watch(
+  () => router.currentRoute.value.params?.relicsId,
+  (rid) => {
+    if (!rid) return;
+    loaded.value = false;
+    initRelics(Number(rid)).finally(() => {
+      if (!relics.value) {
+        return router.replace({ name: "relics" });
+      }
+      if (mapManage && !autoInitPos()) {
+        mapManage.flyUserCenter(defaultCenter);
+      }
+      loaded.value = true;
+    });
+  },
+  { immediate: true }
+);
+</script>
+
+<style lang="scss" scoped>
+.map-layout {
+  display: flex;
+  flex-direction: row;
+  height: 100%;
+}
+
+.custom_bar {
+  width: 60px;
+  height: 100%;
+  background-color: white;
+
+  // padding-top: 76px;
+  .back_container {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    color: #606266;
+    height: 76px;
+  }
+
+  .nav_container {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    color: #606266;
+
+    .nav_item {
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+      justify-content: center;
+      padding: 10px 0;
+      cursor: pointer;
+      user-select: none;
+      width: 100%;
+      span {
+        line-height: 26px;
+        font-size: var(--font14);
+      }
+
+      &.active {
+        .icon {
+          color: #409eff;
+        }
+
+        color: #409eff;
+        background-color: #ecf5ff;
+        position: relative;
+
+        &::before {
+          content: "";
+          height: 100%;
+          width: 4px;
+          position: absolute;
+          top: 0;
+          left: 0;
+          background-color: #409eff;
+        }
+      }
+    }
+  }
+}
+
+.map-oper-layout {
+  display: flex;
+  flex-direction: row;
+  height: 100%;
+  flex: 1;
+}
+
+.map-container {
+  flex: 1;
+  position: relative;
+
+  .map-component {
+    pointer-events: none;
+    position: absolute;
+    width: 100%;
+    height: 100%;
+    left: 0;
+    top: 0;
+    z-index: 9;
+  }
+
+  .board {
+    position: absolute;
+    left: 0;
+    top: 0;
+    bottom: 0;
+    right: 0;
+    z-index: 1;
+  }
+}
+
+.data-panel {
+  width: 320px;
+  padding: 15px;
+  border-left: 1px solid var(--border-color);
+  position: relative;
+  z-index: 3;
+}
+</style>
+
+<style lang="scss">
+.scale-view {
+  --color: #fff;
+  position: absolute;
+  left: 20px;
+  bottom: 20px;
+  height: 8px;
+  color: var(--color);
+  text-align: center;
+  border: 1px solid var(--color);
+  border-top: none;
+  z-index: 1;
+  font-size: 14px;
+  display: flex;
+  align-items: end;
+
+  &.light {
+    --color: #fff;
+
+    > div {
+      text-shadow: 0 0 2px #000;
+    }
+  }
+
+  &.dark {
+    --color: #000;
+
+    > div {
+      text-shadow: 0 0 2px #fff;
+    }
+  }
+}
+</style>

+ 41 - 32
src/view/map/map-board.vue

@@ -29,6 +29,7 @@
         </div>
       </div>
     </Teleport>
+
     <div id="map" class="map-container" ref="mapContainer" @click.stop="unActiveId">
       <div class="map-component">
         <el-select
@@ -88,13 +89,21 @@
 import MapRight from "./map-right.vue";
 import { router, setDocTitle } from "@/router";
 import { Manage } from "./openlayer";
-import { ScenePoint, Scene, scenePoints, scenes, SceneStatus } from "@/store/scene";
+import {
+  ScenePoint,
+  Scene,
+  scenePoints,
+  scenes,
+  SceneStatus,
+  boardData,
+} from "@/store/scene";
 import { initRelics, initSelfRelics, relics } from "@/store/relics";
 import { onMounted, ref, watchEffect, watch, onUnmounted, computed } from "vue";
 import {
   createBoard,
   getWholeLineLinesByPointId,
   PolygonsPointAttrib,
+  PoPoint,
 } from "drawing-board";
 import MapRightPoly from "./map-right-poly.vue";
 import { Back } from "@element-plus/icons-vue";
@@ -113,6 +122,7 @@ import {
 
 import { mapManageInit, flyUserCenter, tileOptions, tileType } from "./map-flow";
 
+console.log(router.currentRoute.value);
 const scenePosTransform = (scenes: Scene[]) => {
   const points: PolygonsPointAttrib[] = [];
 
@@ -244,7 +254,24 @@ const boardContainer = ref<HTMLDivElement>();
 let mapManage: Manage;
 
 const board = createBoard();
-const boardData = ref<DrawingDataType | null>(null);
+watch(boardData, (data) => data && board.setData(data), {
+  immediate: true,
+  flush: "sync",
+});
+
+watch(
+  [currentTab, boardData],
+  ([tab]) => {
+    const showOther = tab !== 0;
+    board.polygon.children.filter((entity) => {
+      if (!(entity instanceof PoPoint && entity.attrib.rtk)) {
+        entity.visible(showOther);
+      }
+    });
+  },
+  { immediate: true, flush: "post" }
+);
+
 let endEdithandler;
 
 onMounted(async () => {
@@ -256,17 +283,6 @@ onMounted(async () => {
   isMounted.value = true;
 });
 
-const borardPolyData = computed(() => board.getData());
-watch(
-  borardPolyData,
-  (updater) => {
-    if (updater) {
-      boardData.value = (updater as any) as DrawingDataType;
-    }
-  },
-  { immediate: true, deep: true }
-);
-
 onUnmounted(() => {
   mapManage.map.dispose();
   board.destory();
@@ -280,7 +296,6 @@ const handleSyncDataToServer = () => {
   setTimeout(async () => {
     console.log("handleSyncDataToServer");
     const data = (board.getData() as any) as DrawingDataType;
-    console.log(data);
     boardData.value = data;
     const param: DrawingParamsType = {
       data: data,
@@ -322,18 +337,18 @@ watch(
       initPolyTabData();
       onCleanup(() => {});
     } else {
-      // 防止被vue组件收集,自己控制
-      let stop: () => void;
-      let timeout = setTimeout(() => {
-        stop = watch(() => scenes.value, initCroodTabdata, {
-          immediate: true,
-          deep: true,
-        });
-      });
-      onCleanup(() => {
-        stop && stop();
-        clearTimeout(timeout);
-      });
+      // // 防止被vue组件收集,自己控制
+      // let stop: () => void;
+      // let timeout = setTimeout(() => {
+      //   stop = watch(() => scenes.value, initCroodTabdata, {
+      //     immediate: true,
+      //     deep: true,
+      //   });
+      // });
+      // onCleanup(() => {
+      //   stop && stop();
+      //   clearTimeout(timeout);
+      // });
     }
   },
   { immediate: true }
@@ -429,12 +444,6 @@ const handlePolysEdit = (item: PolyDataType) => {
   border-left: 1px solid var(--border-color);
 }
 
-.map-component {
-  width: 100%;
-  height: 100%;
-  position: relative;
-}
-
 .active {
   cursor: pointer;
 }

+ 0 - 3
src/view/map/map-right.vue

@@ -263,9 +263,6 @@ const delSceneHandler = async (scenes: Scene[]) => {
       return;
     }
   }
-
-  console.log(res.data);
-  return;
   await delRelicsScenes(scenes);
   await refreshScenes();
 };

+ 1 - 1
src/view/map/openlayer/index.ts

@@ -1,7 +1,7 @@
 import { Manage } from "./manage";
 export type { TileType } from "./tile";
 
-export const createMap = (dom: HTMLDivElement) => {
+export const createMap = (dom?: HTMLDivElement) => {
   return new Manage(dom);
 };
 

+ 36 - 4
src/view/map/openlayer/manage.ts

@@ -11,7 +11,7 @@ import {
 import { Emitter } from "mitt";
 import { boundingExtent } from "ol/extent";
 
-const createMap = (container: HTMLDivElement) => {
+const createMap = (container?: HTMLDivElement) => {
   const view = new View({
     center: [113.59562585879772, 22.367660742553472],
     projection: "EPSG:4326",
@@ -33,9 +33,17 @@ export class Manage {
     click: any;
   }>;
 
-  constructor(container: HTMLDivElement) {
-    this.map = createMap(container);
+  moundDOM: HTMLDivElement;
+  constructor(container?: HTMLDivElement) {
+    this.moundDOM = document.createElement("div");
+    this.moundDOM.style.width = "300px";
+    this.moundDOM.style.height = "300px";
+
+    this.map = createMap(this.moundDOM);
     this.hotsBus = dynamicHots(this.map);
+    if (container) {
+      this.mount(container);
+    }
   }
 
   setTileType(type: TileType) {
@@ -55,6 +63,7 @@ export class Manage {
 
   setCenter(center: number[]) {
     this.map.getView().setCenter(center);
+    console.log(center);
   }
 
   delHots(ids: HotData["id"][]) {
@@ -73,11 +82,34 @@ export class Manage {
     this.map.getView().fit(extent, {
       size: this.map.getSize(),
       padding: [0, 0, 0, 0], // 根据需要调整边距
-      maxZoom: 19.5, // 防止过度放大
     });
   }
+  flyUserCenter(defaultCenter: number[]) {
+    this.setCenter(defaultCenter);
+    navigator.geolocation.getCurrentPosition(
+      (pos) => {
+        console.log("获取中心位置成功", pos);
+        this.setCenter([pos.coords.longitude, pos.coords.latitude]);
+      },
+      (e) => {
+        console.error(e);
+        console.error("获取中心位置失败");
+      },
+      {
+        enableHighAccuracy: false,
+        timeout: 50000,
+        maximumAge: 0,
+      }
+    );
+  }
 
   render() {
     this.map.render();
   }
+
+  mount(dom: HTMLDivElement) {
+    dom.appendChild(this.moundDOM);
+    this.moundDOM.style.width = "100%";
+    this.moundDOM.style.height = "100%";
+  }
 }

+ 288 - 0
src/view/map/polygons.vue

@@ -0,0 +1,288 @@
+<template>
+  <div class="right-layout" @click.stop="selectChange(null)">
+    <div class="right-content">
+      <div class="tree-layout">
+        <p class="sub-title">全部数据</p>
+        <div class="poly-list">
+          <template v-if="boardData.polygons.length > 0">
+            <div
+              v-for="item in boardData.polygons"
+              class="poly-list-item"
+              :class="{
+                active: [
+                  boardStatus.lightPolygonId,
+                  boardStatus.editPolygonId,
+                  selectId,
+                ].includes(item.id),
+              }"
+              @mouseenter="!selectId && (boardStatus.lightPolygonId = item.id)"
+              @mouseleave="!selectId && (boardStatus.lightPolygonId = null)"
+              @click.stop="!currentItem && selectChange(item.id)"
+            >
+              <div class="left">
+                <span>{{ item.name ? item.name : "本体边界" + item.id }}</span>
+              </div>
+              <div class="right" @click.stop v-if="!boardStatus.editPolygonId">
+                <el-icon class="icon">
+                  <Delete @click="del(item.id)" />
+                </el-icon>
+                <el-icon class="icon">
+                  <Edit @click="handleShowEditModel(item)" />
+                </el-icon>
+                <el-icon class="icon">
+                  <Download @click="handleDownload(item)" />
+                </el-icon>
+              </div>
+            </div>
+          </template>
+          <template v-else>
+            <div class="empty">暂没数据</div>
+          </template>
+        </div>
+      </div>
+    </div>
+  </div>
+
+  <Teleport to="body">
+    <div class="draw-global-icon" @click="cleanupEdit ? cleanupEdit() : enterEdit()">
+      <el-icon size="36">
+        <successIco v-if="cleanupEdit" />
+        <picpenIcon v-else />
+      </el-icon>
+    </div>
+    <SingleInput
+      v-if="selectItem"
+      :visible="isShowPolyEditName"
+      @update:visible="isShowPolyEditName = false"
+      :value="selectItem.name || ''"
+      :update-value="(name) => boardDataChange(() => (selectItem.name = name))"
+      placeholder="请输入"
+      title="修改边界名称"
+    />
+  </Teleport>
+</template>
+
+<script setup lang="ts">
+import { computed, onBeforeUnmount, ref, shallowRef, watch } from "vue";
+import type { PolyDataType } from "@/request/drawing.ts";
+import { Delete, Download, Edit } from "@element-plus/icons-vue";
+import SingleInput from "@/components/single-input.vue";
+import { downloadPointsXLSL1 } from "@/util/pc4xlsl";
+import { boardData, scenePoints } from "@/store/scene";
+import { getWholeLinePolygonPoints } from "drawing-board";
+import { board, boardDataChange, mapManage } from "./install";
+import { confirm } from "@/helper/message";
+import picpenIcon from "@/assets/pic_pen.svg";
+import successIco from "@/assets/panorama.svg";
+
+const boardStatus = board.polygon.status;
+const selectId = ref<string>();
+const selectChange = (id: string) => {
+  if (currentItem.value) return;
+  if (selectId.value === id) {
+    boardStatus.lightPolygonId = null;
+    selectId.value = null;
+  } else {
+    selectId.value = id;
+    if (!selectItem.value) {
+      selectChange(null);
+    } else {
+      boardStatus.lightPolygonId = selectItem.value.id;
+      const points = getWholeLinePolygonPoints(boardData.value, selectItem.value.id);
+      if (points.length) {
+        const total = points.reduce((t, p) => [t[0] + p.x, t[1] + p.y], [0, 0]);
+        mapManage.map
+          .getView()
+          .setCenter([total[0] / points.length, total[1] / points.length]);
+      }
+    }
+  }
+};
+board.polygon.bus.on("clickPolygon", (item) => selectChange(item.id));
+board.polygon.container.stage.on("click.checkSelect", (ev) => {
+  if (ev.target === board.polygon.container.stage) {
+    selectChange(null);
+  }
+});
+
+const selectItem = computed(() =>
+  boardData.value.polygons.find(({ id }) => id === selectId.value)
+);
+const currentItem = computed(() =>
+  boardData.value.polygons.find(({ id }) => id === boardStatus.editPolygonId)
+);
+
+const cleanupEdit = shallowRef<() => void>();
+const enterEdit = () => {
+  cleanupEdit.value && cleanupEdit.value();
+  const quitEdit = board.polygon.editPolygon(selectId.value);
+  let needUpdate = false;
+  const stopWatch = watch(
+    () => currentItem.value,
+    () => (needUpdate = true),
+    { deep: true }
+  );
+  cleanupEdit.value = () => {
+    board.polygon.bus.off("penEndHandler", cleanupEdit.value);
+    quitEdit();
+    selectChange(null);
+    stopWatch();
+    needUpdate && boardDataChange();
+    cleanupEdit.value = null;
+  };
+  board.polygon.bus.on("penEndHandler", cleanupEdit.value);
+};
+
+onBeforeUnmount(() => {
+  cleanupEdit.value && cleanupEdit.value();
+  board.polygon.bus.off("clickPolygon");
+  board.polygon.container.stage.off("click.checkSelect");
+});
+
+const isShowPolyEditName = ref(false);
+const handleShowEditModel = (item: PolyDataType) => {
+  selectChange(item.id);
+  isShowPolyEditName.value = true;
+};
+
+const del = async (id: string) => {
+  if ((await confirm("确定要删除吗")) && !currentItem.value) {
+    boardDataChange(() => board.polygon.removePolygon(id));
+  }
+};
+
+const handleDownload = async (item: any) => {
+  const polygonPoints: any[] = getWholeLinePolygonPoints(boardData.value, item.id);
+
+  const points = polygonPoints.map((p) => {
+    const pos = [p.x, p.y, 0];
+    if (p.rtk) {
+      const sPoint = scenePoints.value.find(({ id }) => id.toString() === p.title);
+      if (sPoint) {
+        pos[2] = sPoint.pos[2];
+      }
+    }
+    return pos;
+  });
+  const dists = polygonPoints.map((p) => ({
+    title: p.id,
+    desc: p.title || p.id,
+  }));
+  await downloadPointsXLSL1(
+    points,
+    dists,
+    `${item.name ? item.name : "本体边界" + item.id}`
+  );
+};
+</script>
+
+<style lang="scss" scoped>
+.tree-item {
+  display: flex;
+  width: calc(100% - 50px);
+  align-items: center;
+  justify-content: space-between;
+
+  .title {
+    flex: 1;
+    overflow: hidden;
+    text-overflow: ellipsis; //文本溢出显示省略号
+    white-space: nowrap; //文本不会换行
+  }
+
+  .oper {
+    flex: none;
+  }
+}
+
+.disable {
+  pointer-events: all;
+}
+
+.tree-layout {
+  p {
+    color: #303133;
+    font-size: 14px;
+  }
+
+  .sub-title {
+    font-size: 14px;
+    font-weight: bolder;
+    margin-bottom: 30px;
+  }
+}
+
+.right-layout {
+  display: flex;
+  height: 100%;
+  flex-direction: column;
+  font-size: 16px;
+
+  .right-content {
+    flex: 1;
+    overflow-y: auto;
+  }
+}
+
+.tree-layout .tree-scene-name {
+  font-size: 10px;
+  margin: 0;
+  color: #999;
+}
+
+.poly-list {
+  width: 100%;
+  display: flex;
+  flex-direction: column;
+  font-size: 14px;
+  user-select: none;
+
+  .poly-list-item {
+    cursor: pointer;
+    width: 100%;
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 10px;
+
+    &.active {
+      color: #409eff;
+    }
+
+    .icon {
+      margin-left: 8px;
+      font-size: 16px;
+      color: #409eff;
+      cursor: pointer;
+    }
+  }
+
+  .empty {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    font-size: 13px;
+    color: gray;
+    padding-top: 40px;
+  }
+}
+
+.draw-global-icon {
+  width: 64px;
+  height: 64px;
+  background: #ffffff;
+  border-radius: 50%;
+  position: fixed;
+  z-index: 1000;
+  transform: translateX(calc(-1 * calc(50% - 300px)));
+  left: calc(50% - 300px);
+  top: 90%;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  cursor: pointer;
+  color: #409eff;
+}
+</style>

+ 0 - 3
src/view/quisk.ts

@@ -7,7 +7,6 @@ import OrganizationEdit from "./organization-edit.vue";
 import UsersAdd from "./users-add.vue";
 import UsersEdit from "./users-edit.vue";
 import UsersPasswordEdit from "./users-password-edit.vue";
-console.log('RelicsEdit', RelicsEdit)
 
 export const relicsEdit = quiskMountFactory(RelicsEdit, {
   title: "创建文物",
@@ -45,5 +44,3 @@ export const usersPasswordEdit = quiskMountFactory(UsersPasswordEdit, {
   title: "修改密码",
   width: 520,
 });
-
-

+ 1 - 2
src/view/scene-select.vue

@@ -90,7 +90,6 @@ const tableProps = {
 
 let time: NodeJS.Timeout;
 const checkedTable = () => {
-  console.log('checkedTable', tableProps.tableRef.value)
   if (tableProps.tableRef.value) {
     tableProps.tableRef.value!.clearSelection();
     console.log("1");
@@ -104,7 +103,7 @@ const checkedTable = () => {
   }, 100);
 };
 
-watch(tableProps.tableRef, checkedTable);
+watch(() => tableProps.tableRef.value, checkedTable);
 
 defineExpose<QuiskExpose>({
   async submit() {

+ 60 - 24
src/view/scene.vue

@@ -4,23 +4,50 @@
       <div class="search">
         <el-form label-width="100px" inline>
           <el-form-item label="场景标题:">
-            <el-input clearable v-model="pageProps.sceneName" style="width: 250px" placeholder="请输入" />
+            <el-input
+              clearable
+              v-model="pageProps.sceneName"
+              style="width: 250px"
+              placeholder="请输入"
+            />
           </el-form-item>
           <el-form-item label="场景码:">
-            <el-input clearable v-model="pageProps.sceneCode" style="width: 250px" placeholder="请输入" />
+            <el-input
+              clearable
+              v-model="pageProps.sceneCode"
+              style="width: 250px"
+              placeholder="请输入"
+            />
           </el-form-item>
           <template v-if="!simple">
             <el-form-item label="SN码:">
-              <el-input clearable v-model="pageProps.snCode" style="width: 250px" placeholder="请输入" />
+              <el-input
+                clearable
+                v-model="pageProps.snCode"
+                style="width: 250px"
+                placeholder="请输入"
+              />
             </el-form-item>
             <el-form-item label="设备类型:">
               <el-select style="width: 250px" v-model="pageProps.cameraType" clearable>
-                <el-option :value="Number(key)" :label="type" v-for="(type, key) in DeviceTypeDesc" />
+                <el-option
+                  :value="Number(key)"
+                  :label="type"
+                  v-for="(type, key) in DeviceTypeDesc"
+                />
               </el-select>
             </el-form-item>
             <el-form-item label="拍摄时间:">
-              <el-date-picker clearable type="daterange" v-model="pageProps.shootTime" start-placeholder="请选择"
-                end-placeholder="请选择" range-separator="-" placeholder="请选择" style="width: 250px" />
+              <el-date-picker
+                clearable
+                type="daterange"
+                v-model="pageProps.shootTime"
+                start-placeholder="请选择"
+                end-placeholder="请选择"
+                range-separator="-"
+                placeholder="请选择"
+                style="width: 250px"
+              />
             </el-form-item>
             <!-- <el-form-item label="绑定账号:">
               <el-input
@@ -42,7 +69,13 @@
     </div>
 
     <div class="relics-content">
-      <el-table :data="sceneArray" border row-key="'sceneCode'" @selection-change="handleTableSelect" ref="tableRef">
+      <el-table
+        :data="sceneArray"
+        border
+        row-key="'sceneCode'"
+        @selection-change="handleTableSelect"
+        :ref="(d) => {tableProps && ((tableProps as any).tableRef.value = d)}"
+      >
         <slot name="table"></slot>
         <el-table-column label="场景标题" v-slot:default="{ row }">
           <a class="link" @click="gotoScene(row, false)">
@@ -90,8 +123,13 @@
             <el-button link type="primary" size="small" @click="gotoScene(row, true)">
               编辑
             </el-button>
-            <el-button link type="danger" @click="delHandler(row.sceneId)" size="small"
-              v-if="row.calcStatus !== SceneStatus.RUN">
+            <el-button
+              link
+              type="danger"
+              @click="delHandler(row.sceneId)"
+              size="small"
+              v-if="row.calcStatus !== SceneStatus.RUN"
+            >
               删除
             </el-button>
           </template>
@@ -99,15 +137,21 @@
       </el-table>
     </div>
     <div class="pag-layout">
-      <el-pagination background layout="total, prev, pager, next, sizes, jumper" v-model:page-size="pageProps.pageSize"
-        :page-sizes="[10, 20, 50, 100]" :total="total" @current-change="(data: number) => pageProps.pageNum = data"
-        :current-page="pageProps.pageNum" />
+      <el-pagination
+        background
+        layout="total, prev, pager, next, sizes, jumper"
+        v-model:page-size="pageProps.pageSize"
+        :page-sizes="[10, 20, 50, 100]"
+        :total="total"
+        @current-change="(data: number) => pageProps.pageNum = data"
+        :current-page="pageProps.pageNum"
+      />
     </div>
   </div>
 </template>
 
 <script lang="ts" setup>
-import { onActivated, ref, unref, watch, watchEffect } from "vue";
+import { onActivated, ref, watch } from "vue";
 import { scenePageFetch, ScenePageProps, delSceneFetch } from "@/request";
 import {
   SceneStatusDesc,
@@ -131,7 +175,6 @@ const initProps: ScenePageProps = {
 const pageProps = ref({ ...initProps });
 const total = ref<number>(0);
 const sceneArray = ref<Scene[]>([]);
-const tableRef = ref('');
 
 const refresh = debounce(async () => {
   const data = await scenePageFetch(pageProps.value);
@@ -155,19 +198,12 @@ const delHandler = async (relicsId: number) => {
 watch(pageProps, refresh, { deep: true, immediate: true });
 onActivated(refresh);
 
-watchEffect(() => {
-  if (unref(tableRef)) {
-    // props.tableProps.tableRef.value = unref(tableRef)
-  }
-})
-
-
 const handleTableSelect = (val: any) => {
   if (props.tableProps && "selectionChange" in props.tableProps) {
-    console.log('selectionChange')
-    props.tableProps.selectionChange(val)
+    console.log("selectionChange");
+    props.tableProps.selectionChange(val);
   }
-}
+};
 </script>
 
 <style scoped lang="scss">