|
@@ -0,0 +1,317 @@
|
|
|
+<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)"
|
|
|
+ >
|
|
|
+ <el-tooltip
|
|
|
+ class="box-item"
|
|
|
+ effect="dark"
|
|
|
+ :content="item.name ? item.name : '本体边界'"
|
|
|
+ placement="top"
|
|
|
+ >
|
|
|
+ <div class="left">
|
|
|
+ <span>{{ item.name ? item.name : "本体边界" }}</span>
|
|
|
+ </div>
|
|
|
+ </el-tooltip>
|
|
|
+ <div
|
|
|
+ class="right"
|
|
|
+ @click.stop
|
|
|
+ v-if="!boardStatus.editPolygonId && !queryMode"
|
|
|
+ >
|
|
|
+ <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" v-if="!queryMode">
|
|
|
+ <div class="draw-global-icon" @click="cleanupEdit ? cleanupEdit() : enterEdit()">
|
|
|
+ <el-icon size="36">
|
|
|
+ <Check v-if="cleanupEdit" />
|
|
|
+ <picpenIcon v-else-if="!selectId" />
|
|
|
+ <piceditIcon v-else></piceditIcon>
|
|
|
+ </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="矢量图名称"
|
|
|
+ name="矢量图"
|
|
|
+ />
|
|
|
+ </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, Check } 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, queryMode } from "./install";
|
|
|
+import { confirm } from "@/helper/message";
|
|
|
+import picpenIcon from "@/assets/pic_pen.svg";
|
|
|
+import piceditIcon from "@/assets/pic_edit.svg";
|
|
|
+import { ElMessage } from "element-plus";
|
|
|
+
|
|
|
+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]);
|
|
|
+ const view = mapManage.map.getView();
|
|
|
+ // view.setZoom(20);
|
|
|
+ setTimeout(() => {
|
|
|
+ view.setCenter([total[0] / points.length, total[1] / points.length]);
|
|
|
+ }, 100);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+board.polygon.bus.on("activePolygonId", selectChange);
|
|
|
+
|
|
|
+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);
|
|
|
+ const id = board.polygon.status.editPolygonId;
|
|
|
+ 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();
|
|
|
+ const points = getWholeLinePolygonPoints(board.polygon.attrib, id);
|
|
|
+ if (points.length <= 2) {
|
|
|
+ board.polygon.removePolygon(id);
|
|
|
+ ElMessage.error("请至少绘制3个点");
|
|
|
+ }
|
|
|
+ needUpdate && boardDataChange();
|
|
|
+ cleanupEdit.value = null;
|
|
|
+ };
|
|
|
+ board.polygon.bus.on("penEndHandler", cleanupEdit.value);
|
|
|
+};
|
|
|
+
|
|
|
+onBeforeUnmount(() => {
|
|
|
+ cleanupEdit.value && cleanupEdit.value();
|
|
|
+ board.polygon.status.lightPointId = null;
|
|
|
+});
|
|
|
+
|
|
|
+const isShowPolyEditName = ref(false);
|
|
|
+const handleShowEditModel = (item: PolyDataType) => {
|
|
|
+ selectChange(item.id);
|
|
|
+ isShowPolyEditName.value = true;
|
|
|
+};
|
|
|
+
|
|
|
+const del = async (id: string) => {
|
|
|
+ if ((await confirm("确定要删除吗")) && !currentItem.value) {
|
|
|
+ if (selectId.value === id) {
|
|
|
+ selectChange(null);
|
|
|
+ }
|
|
|
+ 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.title || p.id,
|
|
|
+ desc: p.title || p.id,
|
|
|
+ }));
|
|
|
+ await downloadPointsXLSL1(points, dists, `${item.name || "本体边界"}-绘制矢量数据`);
|
|
|
+};
|
|
|
+</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;
|
|
|
+ }
|
|
|
+
|
|
|
+ .left {
|
|
|
+ flex: 0 0 220px;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ white-space: nowrap;
|
|
|
+ }
|
|
|
+
|
|
|
+ .icon {
|
|
|
+ margin-left: 8px;
|
|
|
+ font-size: 16px;
|
|
|
+ color: #409eff;
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
+
|
|
|
+ .right {
|
|
|
+ flex: none;
|
|
|
+ width: 80px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .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>
|