123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334 |
- <template>
- <div class="map-layout" v-loading="!loaded || captureing">
- <div class="custom_bar">
- <div class="back_container" v-if="!queryMode">
- <el-button :icon="Back" circle type="primary" @click="router.back()" />
- </div>
- <div class="nav_container">
- <div
- v-for="menu in menus"
- :key="menu.name"
- class="nav_item"
- :class="{
- active: menu.router.includes(router.currentRoute.value.name.toString()),
- }"
- @click="router.replace({ name: menu.router[Number(queryMode)] })"
- >
- <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 class="map-top-out-pano">
- <template v-if="!isCoordPage">
- <el-button @click="capture" v-if="loaded && !queryMode">
- 提取位置图
- </el-button>
- <el-button @click="showPoints = !showPoints">
- <el-checkbox :modelValue="showPoints" label="点位" size="large" />
- </el-button>
- </template>
- <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>
- <div class="map-bottom-out-pano">
- <div class="point-info">
- <div v-for="type in typeOptions">
- <el-icon size="20" :color="pointColorMap[type]">
- <locationIcon />
- </el-icon>
- <p>{{ type }}</p>
- </div>
- </div>
- </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, QUERY_COORD_NAME, QUERY_POYS_NAME } from "@/router";
- import {
- mapManage,
- board,
- autoInitPos,
- tileOptions,
- defaultCenter,
- tileType,
- } from "./install";
- import { computed, ref, watch } from "vue";
- import { initSelfRelics, relics } from "@/store/relics";
- import { queryMode } from "./install";
- import { PointTypeEnum, pointColorMap, PoPoint } from "drawing-board";
- import { boardData, scenePoints } from "@/store/scene";
- import saveAs from "@/util/file-serve";
- const typeOptions = computed(() => {
- const options = [
- PointTypeEnum.border,
- PointTypeEnum.center,
- PointTypeEnum.marker,
- PointTypeEnum.other,
- ];
- if (!isCoordPage.value) {
- options.push(PointTypeEnum.mapSelect);
- }
- return options;
- });
- const menus = [
- {
- icon: locationIcon,
- name: "坐标",
- router: [COORD_NAME, QUERY_COORD_NAME],
- },
- {
- icon: vectorIcon,
- name: "矢量图",
- router: [POYS_NAME, QUERY_POYS_NAME],
- },
- ];
- const setMapContainer = (dom: HTMLDivElement) => setTimeout(() => mapManage.mount(dom));
- const setBoardContainer = (dom: HTMLDivElement) =>
- setTimeout(() => board.setProps({ dom }));
- const loaded = ref(false);
- const isCoordPage = computed(() => {
- const name = router.currentRoute.value.name;
- return name && [COORD_NAME, QUERY_COORD_NAME].includes(name.toString());
- });
- watch(
- () => router.currentRoute.value.params?.relicsId,
- (rid) => {
- if (!rid) return;
- loaded.value = false;
- const isEditmode = [COORD_NAME, POYS_NAME].includes(
- router.currentRoute.value.name.toString()
- );
- initSelfRelics(Number(rid), isEditmode).finally(() => {
- if (!relics.value) {
- return router.replace({ name: "relics" });
- }
- if (mapManage && !autoInitPos()) {
- mapManage.flyUserCenter(defaultCenter);
- }
- loaded.value = true;
- });
- },
- { immediate: true }
- );
- const showPoints = ref(true);
- watch(
- () =>
- [
- isCoordPage.value,
- boardData.value,
- showPoints.value,
- board.polygon.attrib.points.length,
- ] as const,
- ([isCoordPage, _, showPoints]) => {
- if (!board.polygon) return;
- const ids = scenePoints.value.map(({ id }) => id.toString());
- board.polygon.children.forEach((entity) => {
- if (entity instanceof PoPoint) {
- if (isCoordPage) {
- entity.visible(entity.attrib.rtk && ids.includes(entity.attrib.id));
- } else {
- entity.visible(showPoints);
- }
- } else {
- entity.visible(!isCoordPage);
- }
- });
- },
- { immediate: true, flush: "post" }
- );
- const captureing = ref(false);
- const capture = async () => {
- captureing.value = true;
- await new Promise((resolve) => setTimeout(resolve, 300));
- try {
- const dataURL = await board.toDataURL(2);
- await saveAs(dataURL, `${relics.value.name}-位置图.jpg`);
- } finally {
- captureing.value = false;
- }
- };
- </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;
- }
- .map-top-out-pano {
- display: flex;
- position: absolute;
- right: 10px;
- top: 10px;
- z-index: 3;
- > * {
- margin-left: 10px;
- }
- }
- .map-bottom-out-pano {
- position: absolute;
- right: 10px;
- bottom: 10px;
- z-index: 3;
- }
- .point-info {
- background: #ffffff;
- border-radius: 4px 4px 4px 4px;
- padding: 10px;
- > div {
- display: flex;
- align-items: center;
- &:not(:last-child) {
- margin-bottom: 10px;
- }
- p {
- font-size: 16px;
- color: #606266;
- margin: 0;
- margin-left: 6px;
- }
- }
- }
- </style>
|