智慧园区前端大屏
shuishen
2024-11-06 4afab589ea612470d96642107cf0f210da814841
园区概况跳转企业详情处理
3 files modified
22 files added
2095 ■■■■■ changed files
src/router/index.js 17 ●●●●● patch | view | raw | blame | history
src/store/router.js 42 ●●●●● patch | view | raw | blame | history
src/views/a/components/box/dataContent.vue 25 ●●●●● patch | view | raw | blame | history
src/views/a/components/box/fireContent.vue 25 ●●●●● patch | view | raw | blame | history
src/views/a/components/box/fireSource.vue 25 ●●●●● patch | view | raw | blame | history
src/views/a/components/box/fireTrend.vue 25 ●●●●● patch | view | raw | blame | history
src/views/a/components/box/occurStatistics.vue 25 ●●●●● patch | view | raw | blame | history
src/views/a/components/box/publicContent.vue 26 ●●●●● patch | view | raw | blame | history
src/views/a/components/box/unitContent.vue 25 ●●●●● patch | view | raw | blame | history
src/views/a/components/leftContainer.vue 54 ●●●●● patch | view | raw | blame | history
src/views/a/components/rightContainer.vue 92 ●●●●● patch | view | raw | blame | history
src/views/a/index.vue 30 ●●●●● patch | view | raw | blame | history
src/views/layout/index.vue 54 ●●●●● patch | view | raw | blame | history
src/views/sub/components/mainMenu.vue 108 ●●●●● patch | view | raw | blame | history
src/views/sub/components/mainSearch.vue 100 ●●●●● patch | view | raw | blame | history
src/views/sub/components/mainTool.vue 109 ●●●●● patch | view | raw | blame | history
src/views/sub/components/scomponents/baseMap.vue 355 ●●●●● patch | view | raw | blame | history
src/views/sub/components/scomponents/cesium/AmapMercatorTilingScheme/CoordTransform.js 178 ●●●●● patch | view | raw | blame | history
src/views/sub/components/scomponents/cesium/AmapMercatorTilingScheme/index.js 53 ●●●●● patch | view | raw | blame | history
src/views/sub/components/scomponents/layersControl.vue 336 ●●●●● patch | view | raw | blame | history
src/views/sub/components/scomponents/tool/exportScene.vue 12 ●●●●● patch | view | raw | blame | history
src/views/sub/components/scomponents/tool/location.vue 92 ●●●●● patch | view | raw | blame | history
src/views/sub/components/scomponents/toolList.vue 132 ●●●●● patch | view | raw | blame | history
src/views/sub/index.vue 141 ●●●●● patch | view | raw | blame | history
src/views/survey/components/box/fireSource.vue 14 ●●●● patch | view | raw | blame | history
src/router/index.js
@@ -2,7 +2,7 @@
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2024-10-25 16:35:31
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-10-31 18:22:25
 * @LastEditTime: 2024-11-06 10:35:00
 * @FilePath: \bigScreen\src\router\index.js
 * @Description: 
 * 
@@ -72,6 +72,21 @@
          title: '救援队伍'
        },
        component: () => import('@/views/rt/index.vue')
      },
      {
        path: 'sub',
        name: 'sub',
        component: () => import('@/views/sub/index.vue'),
        redirect: '/layout/sub/a',
        children: [
          {
            path: 'a',
            meta: {
              title: 'a示例'
            },
            component: () => import('@/views/a/index.vue')
          },
        ]
      }
    ]
  },
src/store/router.js
New file
@@ -0,0 +1,42 @@
/*
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2024-11-06 10:46:45
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-11-06 10:56:14
 * @FilePath: \bigScreen\src\store\router.js
 * @Description:
 *
 * Copyright (c) 2024 by shuishen, All Rights Reserved.
 */
// src/stores/useUserStore.js
import { defineStore } from 'pinia'
export const useRouterStore = defineStore('useRouterStore', {
  // 存储状态的地方,相当于 Vuex 的 state
  state: () => ({
    loadSub: false
  }),
  // 相当于 Vuex 的 getters,用于计算状态
  getters: {
  },
  // 相当于 Vuex 的 mutations 和 actions,用于同步或异步地修改状态
  actions: {
    setLoadSub (flag) {
      this.loadSub = flag
    },
  },
  persist: {
    enabled: true,
    strategies: [
      {
        key: 'loadSub',
        paths: ['loadSub'],
        storage: localStorage,
      },
    ]
  }
})
src/views/a/components/box/dataContent.vue
New file
@@ -0,0 +1,25 @@
<!--
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2023-03-13 14:54:26
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2023-03-13 15:00:55
 * @FilePath: \forest-fire\src\views\statistics\components\box\dataContent.vue
 * @Description:
 *
 * Copyright (c) 2023 by ${git_name_email}, All Rights Reserved.
-->
<script setup>
import publicContent from './publicContent.vue'
</script>
<template>
    <public-content>
        <template #content>
            <div>
            </div>
        </template>
    </public-content>
</template>
<style lang="scss" scoped></style>
src/views/a/components/box/fireContent.vue
New file
@@ -0,0 +1,25 @@
<!--
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2023-03-13 14:54:26
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2023-03-13 15:00:55
 * @FilePath: \forest-fire\src\views\statistics\components\box\dataContent.vue
 * @Description:
 *
 * Copyright (c) 2023 by ${git_name_email}, All Rights Reserved.
-->
<script setup>
import publicContent from './publicContent.vue'
</script>
<template>
    <public-content>
        <template #content>
            <div>
            </div>
        </template>
    </public-content>
</template>
<style lang="scss" scoped></style>
src/views/a/components/box/fireSource.vue
New file
@@ -0,0 +1,25 @@
<!--
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2023-03-13 14:54:26
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2023-03-13 15:00:55
 * @FilePath: \forest-fire\src\views\statistics\components\box\dataContent.vue
 * @Description:
 *
 * Copyright (c) 2023 by ${git_name_email}, All Rights Reserved.
-->
<script setup>
import publicContent from './publicContent.vue'
</script>
<template>
    <public-content>
        <template #content>
            <div>
            </div>
        </template>
    </public-content>
</template>
<style lang="scss" scoped></style>
src/views/a/components/box/fireTrend.vue
New file
@@ -0,0 +1,25 @@
<!--
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2023-03-13 14:54:26
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2023-03-13 15:00:55
 * @FilePath: \forest-fire\src\views\statistics\components\box\dataContent.vue
 * @Description:
 *
 * Copyright (c) 2023 by ${git_name_email}, All Rights Reserved.
-->
<script setup>
import publicContent from './publicContent.vue'
</script>
<template>
    <public-content>
        <template #content>
            <div>
            </div>
        </template>
    </public-content>
</template>
<style lang="scss" scoped></style>
src/views/a/components/box/occurStatistics.vue
New file
@@ -0,0 +1,25 @@
<!--
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2023-03-13 14:54:26
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2023-03-13 15:00:55
 * @FilePath: \forest-fire\src\views\statistics\components\box\dataContent.vue
 * @Description:
 *
 * Copyright (c) 2023 by ${git_name_email}, All Rights Reserved.
-->
<script setup>
import publicContent from './publicContent.vue'
</script>
<template>
    <public-content>
        <template #content>
            <div>
            </div>
        </template>
    </public-content>
</template>
<style lang="scss" scoped></style>
src/views/a/components/box/publicContent.vue
New file
@@ -0,0 +1,26 @@
<!--
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2023-03-13 14:54:26
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-10-25 18:33:46
 * @FilePath: \bigScreen\src\views\statistics\components\box\publicContent.vue
 * @Description:
 *
 * Copyright (c) 2023 by ${git_name_email}, All Rights Reserved.
-->
<script setup>
</script>
<template>
  <div class="content">
    <slot></slot>
  </div>
</template>
<style lang="scss" scoped>
.content {
  padding: 20px 0;
  height: calc(100% - 32px);
}
</style>
src/views/a/components/box/unitContent.vue
New file
@@ -0,0 +1,25 @@
<!--
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2023-03-13 14:54:26
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2023-03-13 15:00:55
 * @FilePath: \forest-fire\src\views\statistics\components\box\dataContent.vue
 * @Description:
 *
 * Copyright (c) 2023 by ${git_name_email}, All Rights Reserved.
-->
<script setup>
import publicContent from './publicContent.vue'
</script>
<template>
    <public-content>
        <template #content>
            <div>
            </div>
        </template>
    </public-content>
</template>
<style lang="scss" scoped></style>
src/views/a/components/leftContainer.vue
New file
@@ -0,0 +1,54 @@
<!--
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2023-03-10 15:27:59
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-10-25 18:43:23
 * @FilePath: \bigScreen\src\views\statistics\components\leftContainer.vue
 * @Description:
 *
 * Copyright (c) 2023 by ${git_name_email}, All Rights Reserved.
-->
<script setup>
import dataContent from './box/dataContent.vue'
import unitContent from './box/unitContent.vue'
import fireContent from './box/fireContent.vue'
</script>
<template>
  <div class="left-container">
    <div class="data box">
      <title-box>
        <template #titleName>
          数据概览
        </template>
      </title-box>
      <div class="content-box">
        <data-content></data-content>
      </div>
    </div>
    <div class="unit box">
      <title-box>
        <template #titleName>
          入住单位统计
        </template>
      </title-box>
      <div class="content-box">
        <unit-content></unit-content>
      </div>
    </div>
    <div class="fire box">
      <title-box>
        <template #titleName>
          实时火警事件
        </template>
      </title-box>
      <div class="content-box">
        <fire-content></fire-content>
      </div>
    </div>
  </div>
</template>
<style lang="scss" scoped></style>
src/views/a/components/rightContainer.vue
New file
@@ -0,0 +1,92 @@
<!--
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2023-03-10 15:27:59
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-10-26 14:49:05
 * @FilePath: \bigScreen\src\views\survey\components\rightContainer.vue
 * @Description:
 *
 * Copyright (c) 2023 by ${git_name_email}, All Rights Reserved.
-->
<script setup>
import fireSource from './box/fireSource.vue'
import fireTrend from './box/fireTrend.vue'
import occurStatistics from './box/occurStatistics.vue'
import publicContent from './box/publicContent.vue'
</script>
<template>
  <div class="right-container">
    <div class="fire-source box">
      <title-box>
        <template #titleName>
          火警事件来源
        </template>
      </title-box>
      <div class="content-box">
      <fire-source></fire-source>
      </div>
    </div>
    <div class="occur-statistics box">
      <title-box>
        <template #titleName>
          易发区统计
        </template>
      </title-box>
      <div class="content-box">
      <fire-trend></fire-trend>
      </div>
    </div>
    <div class="fire-trend box">
      <title-box>
        <template #titleName>
          火警上报趋势
        </template>
      </title-box>
      <div class="content-box">
      <occur-statistics></occur-statistics>
      </div>
    </div>
  </div>
</template>
<style lang="scss" scoped>
.right-container {
  display: flex;
  flex-direction: column;
  padding: 20px;
  position: absolute;
  top: 0;
  right: 0;
  width: 440px;
  height: 100%;
  pointer-events: auto;
  .box {
    margin-top: 20px;
    .header {
      height: 32px;
      background: url(/img/bg/sub-title.png) no-repeat;
    }
  }
  .fire-source {
    flex: 3;
  }
  .occur-statistics {
    flex: 3;
  }
  .fire-trend {
    flex: 4;
  }
  .box:first-child {
    margin-top: 0;
  }
}
</style>
src/views/a/index.vue
New file
@@ -0,0 +1,30 @@
<!--
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2023-03-10 15:27:59
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2023-03-13 16:02:07
 * @FilePath: \forest-fire\src\views\statistics\index.vue
 * @Description: 综合设计
 *
 * Copyright (c) 2023 by ${git_name_email}, All Rights Reserved.
-->
<script setup>
import leftContainer from './components/leftContainer.vue'
import rightContainer from './components/rightContainer.vue'
</script>
<template>
    <div class="container page-container">
        <left-container></left-container>
        <right-container></right-container>
    </div>
</template>
<style lang="scss" scoped>
.container {
    position: absolute;
    width: 100%;
    height: 100%;
}
</style>
src/views/layout/index.vue
@@ -2,7 +2,7 @@
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2022-08-18 16:18:24
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-11-01 20:00:52
 * @LastEditTime: 2024-11-06 11:05:46
 * @FilePath: \bigScreen\src\views\layout\index.vue
 * @Description: 
 * 
@@ -13,23 +13,30 @@
    <map-container ref="MapContainer">
      <template #content>
        <div v-if="showContent" class="main-content" id="MainContent">
          <div class="main-header">
            <div class="title">吉水化工园区“一园一策一图”VR平台</div>
            <div class="login-out" @click="signOut">
              <img :src="loginOutBg" class="img" />
              <span>退出</span>
            </div>
          </div>
          <div class="main-container">
            <!-- 地图区域 -->
            <router-view ref="target-name"></router-view>
          </div>
          <main-search></main-search>
          <main-tool></main-tool>
          <main-menu></main-menu>
          <div v-if="!showSubLayout" class="w100 h100">
            <div class="main-header">
              <div class="title">吉水化工园区“一园一策一图”VR平台</div>
              <div class="login-out" @click="signOut">
                <img :src="loginOutBg" class="img" />
                <span>退出</span>
              </div>
            </div>
            <div class="main-container">
              <!-- 地图区域 -->
              <router-view></router-view>
            </div>
            <main-menu></main-menu>
          </div>
          <div v-if="showSubLayout" class="w100 h100">
            <router-view></router-view>
          </div>
        </div>
      </template>
    </map-container>
@@ -48,16 +55,25 @@
import { useLogin } from 'store/login'
const loginStore = useLogin()
import { useMap } from 'store/map'
import { useRouterStore } from 'store/router'
const store = useMap()
const storeRouter = useRouterStore()
const showContent = ref(false)
const showSubLayout = ref(false)
// 监听createB的变化  
watch(
  () => store.loadMap,
  (newValue) => {
    if (newValue) {
  [
    () => store.loadMap,
    () => storeRouter.loadSub,
  ],
  ([newLoadMap, newLoadSub]) => {
    if (newLoadMap) {
      showContent.value = true
    }
    console.log(newLoadSub, 5555)
    showSubLayout.value = newLoadSub
  },
  { immediate: true } // 设置immediate为true以便在组件挂载时立即检查createB的值  
)
src/views/sub/components/mainMenu.vue
New file
@@ -0,0 +1,108 @@
<template>
  <div class="page-mode">
    <div @mouseenter="item.childrenFlag = true" :class="{ active: currentUrl.indexOf(item.path) != -1 }"
      @mouseleave="item.childrenFlag = false" @click="goToPath(item)" v-for="(item, index) in menuList" :key="index">
      {{ item.menuName }}
    </div>
  </div>
</template>
<script setup>
import { ref, reactive, watch } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { Search } from '@element-plus/icons-vue'
import { getTime } from '@/utils/getTime.js'
let router = useRouter()
let currentUrl = ref('statistics')
const menuList = ref(
  [
    {
      menuName: '园区概况',
      path: '/layout/survey'
    },
    {
      menuName: '固定风险源',
      path: '/layout/rs'
    },
    {
      menuName: '应急空间',
      path: '/layout/space'
    },
    {
      menuName: '应急物资',
      path: '/layout/supplies'
    },
    {
      menuName: '三级防控',
      path: '/layout/pac'
    },
    {
      menuName: '救援队伍',
      path: '/layout/rt'
    },
  ]
)
const goToPath = (params) => {
  if (params.children && params.children.length > 0) return
  if (params.path) {
    if (router.currentRoute.value.path == params.path) return
    router.push(params.path)
  } else {
    params.childrenFlag = !params.childrenFlag
  }
}
watch(
  () => router.currentRoute.value,
  (newValue, oldValue) => {
    currentUrl.value = newValue.path
  },
  { immediate: true }
)
const userName = ref('管理员')
</script>
<style lang="scss" scoped>
.page-mode {
  position: absolute;
  top: auto;
  bottom: 55px;
  left: 50%;
  z-index: 99;
  transform: translateX(-50%);
  display: flex;
  pointer-events: auto;
  &>div {
    background-image: url(/images/mode-tab.png);
    background-size: cover;
    width: 150px;
    height: 50px;
    font-size: 16px;
    text-align: center;
    font-weight: bold;
    color: #BFD3E5;
    line-height: 32px;
    padding-top: 12px;
    margin-right: -20px;
    font-style: italic;
    cursor: pointer;
    box-sizing: border-box;
    &:last-child {
      margin-right: 0px;
    }
    &.active {
      color: #F6FCFF;
      background-image: url(/images/mode-tab-ac.png);
    }
  }
}
</style>
src/views/sub/components/mainSearch.vue
New file
@@ -0,0 +1,100 @@
<!--
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2024-10-26 16:09:35
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-10-28 11:04:58
 * @FilePath: \bigScreen\src\views\layout\components\mainSearch.vue
 * @Description:
 *
 * Copyright (c) 2024 by shuishen, All Rights Reserved.
-->
<template>
  <div class="page-search">
    <el-input size="medium" placeholder="请输入内容" :suffix-icon="Search" @input="onSearch()" v-model="searchVal"
      @focus="onFocus"></el-input>
    <div class="page-search-value-box" v-show="isShowSearchSKValBox">
      <ul>
        <li v-for="(item, index) in searchSKValList" :key="index" @click="sKValItemClick(item)">{{ item.name }}
        </li>
      </ul>
    </div>
  </div>
</template>
<script setup>
// 搜索栏相关
let isShowSearchSKValBox = false
let searchVal = ''
let searchSKValList = []
const onSearch = () => {
  if (searchVal == '') {
    isShowSearchSKValBox = false
  } else {
    isShowSearchSKValBox = true
  }
}
const onFocus = () => {
  onSearch()
}
const sKValItemClick = (item) => {
  isShowSearchSKValBox = false
}
</script>
<style lang="scss" scoped>
.page-search {
  position: absolute;
  left: 488px;
  z-index: 99;
  top: 110px;
  pointer-events: auto;
  ::v-deep(.el-input) {
    height: 38px;
    width: 280px;
    .el-input__wrapper {
      font-size: 16px;
      font-weight: 400;
      border: 1px solid #4081CB;
      border-radius: 4px;
      background: rgba(135, 158, 199, 0.3);
      box-shadow: inset 0px 3px 7px 0px rgba(42, 138, 236, 0.95);
      .el-input__inner {
        color: #BFD3E5;
      }
    }
  }
  .page-search-value-box {
    position: absolute;
    width: 100%;
    height: 200px;
    left: 0;
    top: 40px;
    background: rgba(135, 158, 199, 0.3);
    border-radius: 2px;
    overflow-y: scroll;
    ul>li {
      color: #ffffff;
      cursor: pointer;
      height: 20px;
      line-height: 20px;
      padding-left: 10px;
    }
    ul>li:hover {
      background-color: #0e1a35;
    }
  }
  .page-search-value-box::-webkit-scrollbar {
    display: none
  }
}
</style>
src/views/sub/components/mainTool.vue
New file
@@ -0,0 +1,109 @@
<template>
  <div class="toolBarRight animation-slide-top no-print-view">
    <el-button v-for="item, index in btnGroup" :key="index" @click="btnClick(item)"
      class="btn btn-link toolBarRight-btn">
      <i :class="item.icon"></i>{{ item.name }}
    </el-button>
  </div>
  <base-map v-show="currentComponent == 'map'" @close="closeBox"></base-map>
  <layers-control v-show="currentComponent == 'layers'" @close="closeBox"></layers-control>
  <tool-list :moreToolShow="moreToolShow" @close="closeBox"></tool-list>
</template>
<script setup>
import baseMap from './scomponents/baseMap.vue'
import layersControl from './scomponents/layersControl.vue'
import toolList from './scomponents/toolList.vue'
const currentComponent = ref('')
let moreToolShow = ref(false)
const btnGroup = [
  {
    name: '底图',
    icon: 'fa fa-map',
    key: 'map',
  },
  {
    name: '图层',
    icon: 'fa fa-tasks',
    key: 'layers',
  },
  {
    name: '工具',
    icon: 'fa fa-cubes',
    key: 'tool',
  },
]
const btnClick = (item) => {
  if (item.key == 'tool') {
    moreToolShow.value = !moreToolShow.value
  } else {
    currentComponent.value = item.key
  }
}
const closeBox = (type) => {
  if (type == 'tool') {
    moreToolShow.value = false
  } else {
    currentComponent.value = ''
  }
}
</script>
<style lang="scss" scoped>
.toolBarRight {
  display: flex;
  flex-wrap: nowrap;
  position: absolute;
  right: 540px;
  z-index: 99;
  top: 110px;
  border: 1px solid #4081CB;
  border-radius: 4px;
  background: rgba(135, 158, 199, 0.3);
  box-shadow: inset 0px 3px 7px 0px rgba(42, 138, 236, 0.95);
  pointer-events: auto;
  ::v-deep(.el-button) {
    margin-left: 0;
    border: none;
    border-radius: 0;
    background: transparent;
    &.btn {
      padding: 4px 12px;
      font-size: 14px;
      line-height: 1.6;
      -webkit-transition: border .2s linear, color .2s linear, width .2s linear, background-color .2s linear;
      -o-transition: border .2s linear, color .2s linear, width .2s linear, background-color .2s linear;
      transition: border .2s linear, color .2s linear, width .2s linear, background-color .2s linear;
    }
    &.btn-link {
      font-weight: 400;
      color: #007bff;
      text-decoration: none;
    }
    &.toolBarRight-btn {
      list-style-type: none;
      cursor: pointer;
      border-right: solid 1px #2b2c2f;
      color: #edffff;
    }
    &.toolBarRight-btn:last-child {
      border-right: none;
    }
    i {
      margin-right: 4px;
    }
  }
}
</style>
src/views/sub/components/scomponents/baseMap.vue
New file
@@ -0,0 +1,355 @@
<!--
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2024-10-28 11:44:45
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-11-05 18:39:20
 * @FilePath: \bigScreen\src\views\layout\components\scomponents\baseMap.vue
 * @Description:
 *
 * Copyright (c) 2024 by shuishen, All Rights Reserved.
-->
<template>
  <public-box>
    <template #name>
      <div class="name"><i class="fa fa-map"></i>&nbsp;底图</div>
    </template>
    <template #close>
      <div class="close" @click="$emit('close', 'map')"><i class="fa fa-close"></i></div>
    </template>
    <template #content>
      <div class="layers-box-content">
        <ul class="layers-box">
          <li :class="{ on: item.mode == curMode }" v-for="item, index in baseMaps" :key="index"
            @click="loadLAYER(item.mode, index)">
            <div><img :src="item.src"></div>
            <div>{{ item.name }}</div>
          </li>
        </ul>
      </div>
      <div class="show-terrain" style="margin-left:10px;color:#fff">
        <el-checkbox @change="terrainChange" v-model="showTerrainFlag" label="显示地形" size="large" />
      </div>
    </template>
  </public-box>
</template>
<script setup>
import { getAssetsFile } from 'utils/utils'
import AmapMercatorTilingScheme from './cesium/AmapMercatorTilingScheme/index'
const { appContext } = getCurrentInstance()
const global = appContext.config.globalProperties
const Cesium = DC.getLib('Cesium')
const cesiumToken =
  'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJkYTZlNGNlYS01NTU1LTQ1MGEtYmNlZS0yNTE2NDk5YWM2MjEiLCJpZCI6MTc5Njk2LCJpYXQiOjE3MDA1NDcwMjV9.qcl4AH2731cfFd0-I1ZLUINPXqvglLkDFD-UGR2zU5M'
Cesium.Ion.defaultAccessToken = cesiumToken
const TDT_Token = 'c6eea7dad4fa1e2d1e32ec0e7c9735db'
// 天地图Key
// 天地图地图
const TDT_IMG_C = 'https://{s}.tianditu.gov.cn/img_c/wmts?service=wmts&request=GetTile&version=1.0.0' +
  '&LAYER=img&tileMatrixSet=c&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}' +
  '&style=default&format=tiles&tk=' + TDT_Token
// 天地图注记
const TDT_ZJ = 'https://{s}.tianditu.gov.cn/cia_c/wmts?service=wmts&request=GetTile&version=1.0.0' +
  '&LAYER=cia&tileMatrixSet=c&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}' +
  '&style=default&format=tiles&tk=' + TDT_Token
// 标准地图注记
const TID_STAND = 'https://{s}.tianditu.gov.cn/vec_w/wmts?service=wmts&request=GetTile&version=1.0.0' +
  '&LAYER=img&tileMatrixSet=c&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}' +
  '&style=default&format=tiles&tk=' + TDT_Token
const imageryProvider_standZh = new Cesium.UrlTemplateImageryProvider({
  url: 'https://t{s}.tianditu.gov.cn/DataServer?T=cva_w&x={x}&y={y}&l={z}&tk=e45274b0235bb913eceb393aabbf9c9c',
  subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],
  maximumLevel: 18,
  credit: 'stand_zj',
})
const imageryProvider_stand = new Cesium.UrlTemplateImageryProvider({
  url: 'https://t{s}.tianditu.gov.cn/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=e45274b0235bb913eceb393aabbf9c9c',
  subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],
  // format: 'image/jpeg',
  // show: true,
  maximumLevel: 18,
  credit: 'stand_tc',
})
const annotation = new Cesium.WebMapTileServiceImageryProvider({
  url: TDT_ZJ,
  layer: 'tdtZwImg_c',
  style: 'default',
  format: 'tiles',
  tileMatrixSetID: 'c',
  subdomains: ['t0', 't1', 't2', 't3', 't4', 't5', 't6', 't7'],
  tilingScheme: new Cesium.GeographicTilingScheme(),
  tileMatrixLabels: [
    '1',
    '2',
    '3',
    '4',
    '5',
    '6',
    '7',
    '8',
    '9',
    '10',
    '11',
    '12',
    '13',
    '14',
    '15',
    '16',
    '17',
    '18',
    '19',
  ],
  maximumLevel: 50,
})
const imageryProvider_tdt = new Cesium.WebMapTileServiceImageryProvider({
  url: TDT_IMG_C,
  layer: 'tdtImg_c',
  style: 'default',
  format: 'tiles',
  tileMatrixSetID: 'c',
  subdomains: ['t0', 't1', 't2', 't3', 't4', 't5', 't6', 't7'],
  tilingScheme: new Cesium.GeographicTilingScheme(),
  tileMatrixLabels: [
    '1',
    '2',
    '3',
    '4',
    '5',
    '6',
    '7',
    '8',
    '9',
    '10',
    '11',
    '12',
    '13',
    '14',
    '15',
    '16',
    '17',
    '18',
    '19',
  ],
  maximumLevel: 17,
})
const imageryProvider_ammapSL = new Cesium.UrlTemplateImageryProvider({
  url: 'https://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}',
  layer: 'tdtVecBasicLayer',
  style: 'default',
  format: 'image/png',
  tileMatrixSetID: 'GoogleMapsCompatible',
  subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],
  maximumLevel: 18,
  tilingScheme: new AmapMercatorTilingScheme(),
  credit: 'amap_SL',
})
const imageryProvider_ammap = new Cesium.UrlTemplateImageryProvider({
  url: 'https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}',
  layer: 'tdtVecBasicLayer',
  style: 'default',
  format: 'image/png',
  tileMatrixSetID: 'GoogleMapsCompatible',
  subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],
  maximumLevel: 18,
  tilingScheme: new AmapMercatorTilingScheme(),
  credit: 'amap_stand',
})
const imageryProvider_ammapBz = new Cesium.UrlTemplateImageryProvider({
  url: 'https://webst02.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8',
  tilingScheme: new AmapMercatorTilingScheme(),
  minimumLevel: 3,
})
let mapLayers = [
  {
    src: getAssetsFile('stand.png'),
    mode: '0',
    name: '天地图矢量',
    layers: [
      { key: 'imageryProvider_standZh', layer: imageryProvider_standZh },
      { key: 'imageryProvider_stand', layer: imageryProvider_stand },
    ]
  },
  {
    src: getAssetsFile('satellite.png'),
    mode: '1',
    name: '天地图影像',
    layers: [
      { key: 'annotation', layer: annotation },
      {
        key: 'imageryProvider_tdt',
        layer: imageryProvider_tdt,
      }
    ]
  },
  {
    src: getAssetsFile('stand.png'),
    mode: '2',
    name: '高德矢量',
    layers: [
      {
        key: 'imageryProvider_ammapSL',
        layer: imageryProvider_ammapSL,
      }
    ]
  },
  {
    src: getAssetsFile('satellite.png'),
    mode: '3',
    name: '高德影像',
    layers: [
      { key: 'imageryProvider_ammap', layer: imageryProvider_ammap },
      { key: 'imageryProvider_ammapBz', layer: imageryProvider_ammapBz },
    ]
  }
]
let curMode = ref(null)
let baseMaps = reactive([])
baseMaps = mapLayers.map(item => {
  return {
    src: item.src,
    mode: item.mode,
    name: item.name,
  }
})
let globalBaseMapLayers = []
const loadLAYER = (mode, ind) => {
  if (mode == curMode.value) return
  let curmapLayers = []
  globalBaseMapLayers.length &&
    globalBaseMapLayers.forEach((item) => {
      item.mapLayer.show = false
    })
  curmapLayers.push(
    ...mapLayers[ind].layers,
  )
  // 创建一个Set来快速查找array2中的id
  let keyBaseMap = new Set(globalBaseMapLayers.map((item) => item.key))
  let keyMapLayers = new Set(curmapLayers.map((item) => item.key))
  let keyExistBaseMap = curmapLayers.filter((item) => !keyBaseMap.has(item.key))
  let keyNoExistBaseMap = globalBaseMapLayers.filter((item) =>
    keyMapLayers.has(item.key),
  )
  keyExistBaseMap.length &&
    keyExistBaseMap.forEach((item) => {
      let curLayer = {
        key: item.key,
        mapLayer: global.$viewer?.imageryLayers.addImageryProvider(item.layer),
      }
      curLayer.mapLayer.show = true
      global.$viewer?.imageryLayers.lowerToBottom(curLayer.mapLayer)
      globalBaseMapLayers.push(curLayer)
    })
  keyNoExistBaseMap.length &&
    keyNoExistBaseMap.forEach((item) => {
      item.mapLayer.show = true
      global.$viewer?.imageryLayers.lowerToBottom(item.mapLayer)
    })
  curMode.value = mode
}
loadLAYER(1, 1)
const showTerrainFlag = ref(false)
const terrainChange = (e) => {
  if (e) {
    let terrain = DC.TerrainFactory.createTerrain(DC.TerrainType.XYZ, {
      url: 'https://data.marsgis.cn/terrain'
    })
    global.$viewer.setTerrain(terrain)
  } else {
    global.$viewer.setTerrain()
  }
}
</script>
<style lang="scss" scoped>
.close {
  cursor: pointer;
}
.layers-box-content {
  .layers-box {
    display: flex;
    justify-content: space-between;
    flex-wrap: wrap;
    width: 354px;
    padding: 0 10px;
    box-sizing: border-box;
    li {
      margin-top: 10px;
      cursor: pointer;
      &.on,
      &:hover {
        div:first-child {
          border: solid 2px #337fe5;
        }
        div:last-child {
          color: #337fe5;
        }
      }
      div:first-child {
        width: 76px;
        height: 76px;
        background: red;
        border: 2px solid white;
        box-sizing: border-box;
        img {
          width: 100%;
          height: 100%;
        }
      }
      div:last-child {
        width: 76px;
        height: 20px;
        line-height: 20px;
        color: #fff;
        font-size: 12px;
        text-align: center;
      }
    }
  }
}
.show-terrain {
  ::v-deep(.el-checkbox) {
    .el-checkbox__label {
      color: #fff;
    }
  }
}
</style>
src/views/sub/components/scomponents/cesium/AmapMercatorTilingScheme/CoordTransform.js
New file
@@ -0,0 +1,178 @@
// 定义一些常量
const BD_FACTOR = (3.14159265358979324 * 3000.0) / 180.0;
const PI = 3.1415926535897932384626;
const RADIUS = 6378245.0;
const EE = 0.00669342162296594323;
class CoordTransform {
    /**
     * BD-09(百度坐标系) To GCJ-02(火星坐标系)
     * @param lng
     * @param lat
     * @returns {number[]}
     */
    static BD09ToGCJ02(lng, lat) {
        let x = +lng - 0.0065;
        let y = +lat - 0.006;
        let z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * BD_FACTOR);
        let theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * BD_FACTOR);
        let gg_lng = z * Math.cos(theta);
        let gg_lat = z * Math.sin(theta);
        return [gg_lng, gg_lat];
    }
    /**
     * GCJ-02(火星坐标系) To BD-09(百度坐标系)
     * @param lng
     * @param lat
     * @returns {number[]}
     * @constructor
     */
    static GCJ02ToBD09(lng, lat) {
        lat = +lat;
        lng = +lng;
        let z =
            Math.sqrt(lng * lng + lat * lat) +
            0.00002 * Math.sin(lat * BD_FACTOR);
        let theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * BD_FACTOR);
        let bd_lng = z * Math.cos(theta) + 0.0065;
        let bd_lat = z * Math.sin(theta) + 0.006;
        return [bd_lng, bd_lat];
    }
    /**
     * WGS-84(世界大地坐标系) To GCJ-02(火星坐标系)
     * @param lng
     * @param lat
     * @returns {number[]}
     */
    static WGS84ToGCJ02(lng, lat) {
        lat = +lat;
        lng = +lng;
        if (this.out_of_china(lng, lat)) {
            return [lng, lat];
        } else {
            let d = this.delta(lng, lat);
            return [lng + d[0], lat + d[1]];
        }
    }
    /**
     * GCJ-02(火星坐标系) To WGS-84(世界大地坐标系)
     * @param lng
     * @param lat
     * @returns {number[]}
     * @constructor
     */
    static GCJ02ToWGS84(lng, lat) {
        lat = +lat;
        lng = +lng;
        if (this.out_of_china(lng, lat)) {
            return [lng, lat];
        } else {
            let d = this.delta(lng, lat);
            let mgLng = lng + d[0];
            let mgLat = lat + d[1];
            return [lng * 2 - mgLng, lat * 2 - mgLat];
        }
    }
    /**
     *
     * @param lng
     * @param lat
     * @returns {number[]}
     */
    static delta(lng, lat) {
        let dLng = this.transformLng(lng - 105, lat - 35);
        let dLat = this.transformLat(lng - 105, lat - 35);
        const radLat = (lat / 180) * PI;
        let magic = Math.sin(radLat);
        magic = 1 - EE * magic * magic;
        const sqrtMagic = Math.sqrt(magic);
        dLng = (dLng * 180) / ((RADIUS / sqrtMagic) * Math.cos(radLat) * PI);
        dLat =
            (dLat * 180) / (((RADIUS * (1 - EE)) / (magic * sqrtMagic)) * PI);
        return [dLng, dLat];
    }
    /**
     *
     * @param lng
     * @param lat
     * @returns {number}
     */
    static transformLng(lng, lat) {
        lat = +lat;
        lng = +lng;
        let ret =
            300.0 +
            lng +
            2.0 * lat +
            0.1 * lng * lng +
            0.1 * lng * lat +
            0.1 * Math.sqrt(Math.abs(lng));
        ret +=
            ((20.0 * Math.sin(6.0 * lng * PI) +
                20.0 * Math.sin(2.0 * lng * PI)) *
                2.0) /
            3.0;
        ret +=
            ((20.0 * Math.sin(lng * PI) + 40.0 * Math.sin((lng / 3.0) * PI)) *
                2.0) /
            3.0;
        ret +=
            ((150.0 * Math.sin((lng / 12.0) * PI) +
                300.0 * Math.sin((lng / 30.0) * PI)) *
                2.0) /
            3.0;
        return ret;
    }
    /**
     *
     * @param lng
     * @param lat
     * @returns {number}
     */
    static transformLat(lng, lat) {
        lat = +lat;
        lng = +lng;
        let ret =
            -100.0 +
            2.0 * lng +
            3.0 * lat +
            0.2 * lat * lat +
            0.1 * lng * lat +
            0.2 * Math.sqrt(Math.abs(lng));
        ret +=
            ((20.0 * Math.sin(6.0 * lng * PI) +
                20.0 * Math.sin(2.0 * lng * PI)) *
                2.0) /
            3.0;
        ret +=
            ((20.0 * Math.sin(lat * PI) + 40.0 * Math.sin((lat / 3.0) * PI)) *
                2.0) /
            3.0;
        ret +=
            ((160.0 * Math.sin((lat / 12.0) * PI) +
                320 * Math.sin((lat * PI) / 30.0)) *
                2.0) /
            3.0;
        return ret;
    }
    /**
     * 判断是否在国内。不在国内不做偏移
     * @param lng
     * @param lat
     * @returns {boolean}
     */
    static out_of_china(lng, lat) {
        lat = +lat;
        lng = +lng;
        return !(lng > 73.66 && lng < 135.05 && lat > 3.86 && lat < 53.55);
    }
}
export default CoordTransform;
src/views/sub/components/scomponents/cesium/AmapMercatorTilingScheme/index.js
New file
@@ -0,0 +1,53 @@
/*
 * @Author: GuLiMmo 2820890765@qq.com
 * @Date: 2024-05-11 09:18:29
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-10-28 20:14:09
 * @FilePath: \bigScreen\src\views\layout\components\scomponents\cesium\AmapMercatorTilingScheme\index.js
 * @Description: 高德地图纠偏
 * Copyright (c) 2024 by GuLiMmo, All Rights Reserved.
 */
const {
  WebMercatorProjection,
  WebMercatorTilingScheme,
  Math,
  Cartographic,
  Cartesian2,
} = DC.__namespace.Cesium
import CoordTransform from './CoordTransform'
class AmapMercatorTilingScheme extends WebMercatorTilingScheme {
  constructor() {
    super()
    let projection = new WebMercatorProjection()
    this._projection.project = function (cartographic, result) {
      result = CoordTransform.WGS84ToGCJ02(
        Math.toDegrees(cartographic.longitude),
        Math.toDegrees(cartographic.latitude),
      )
      result = projection.project(
        new Cartographic(
          Math.toRadians(result[0]),
          Math.toRadians(result[1]),
        ),
      )
      return new Cartesian2(result.x, result.y)
    }
    this._projection.unproject = function (cartesian, result) {
      let cartographic = projection.unproject(cartesian)
      result = CoordTransform.GCJ02ToWGS84(
        Math.toDegrees(cartographic.longitude),
        Math.toDegrees(cartographic.latitude),
      )
      return new Cartographic(
        Math.toRadians(result[0]),
        Math.toRadians(result[1]),
      )
    }
  }
}
export default AmapMercatorTilingScheme
src/views/sub/components/scomponents/layersControl.vue
New file
@@ -0,0 +1,336 @@
<!--
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2024-10-31 10:47:29
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-11-05 18:36:54
 * @FilePath: \bigScreen\src\views\layout\components\scomponents\layersControl.vue
 * @Description:
 *
 * Copyright (c) 2024 by shuishen, All Rights Reserved.
-->
<template>
  <public-box>
    <template #name>
      <div class="name"><i class="fa fa-tasks"></i>&nbsp;图层</div>
    </template>
    <template #close>
      <div class="close" @click="$emit('close', 'layers')"><i class="fa fa-close"></i></div>
    </template>
    <template #content>
      <div class="tree-content">
        <el-tree ref="treeRef" :data="data" draggable="" show-checkbox node-key="id" default-expand-all
          :default-checked-keys="['1']" :props="defaultProps" :indent="treeProps['indent']" @check="handleCheckChange">
          <template v-slot:default="{ node }">
            <element-tree-line :node="node" :showLabelLine="treeProps['showLabelLine']" :indent="treeProps['indent']">
              <!-- 自定义label的slot -->
              <template v-slot:node-label>
                <span style="font-size: 12px">
                  {{ node.label }}
                  <i class="el-icon-eleme"></i></span>
              </template>
              <!-- 在右边追加内容的slot -->
              <!-- <template v-slot:after-node-label>
                <span style="padding-right: 10px">
                  <el-button type="primary" size="mini" @click.stop="openDrawer(node)">新增子节点</el-button>
                  <el-button type="primary" size="mini" @click.stop="openDrawer(node)">修改</el-button>
                  <el-button type="danger" size="mini" @click.stop="openDialog">删除</el-button></span>
              </template> -->
            </element-tree-line>
          </template>
        </el-tree>
      </div>
    </template>
  </public-box>
</template>
<script setup>
import { getPage } from '@/api/indParkInfo'
import { getList } from "@/api/space/space"
import { getList as getRiskList } from "@/api/riskSource/riskSource"
const { VITE_APP_BASE } = import.meta.env
import { getViewer } from 'utils/getViewer'
const globalViewer = getViewer()
const treeRef = ref(null)
const treeProps = {
  indent: 16,
  showLabelLine: true,
}
const data = [
  {
    id: '1',
    label: '化工园区',
    type: 'layer',
    subType: '3Dtile',
    url: VITE_APP_BASE + 'mx/tileset.json',
    layerName: 'hgyq'
  },
  {
    id: '2',
    label: '企业分布',
    type: 'layer',
    subType: 'labelPoint',
    method: getPage,
    params: {
      size: 1000
    },
    layerName: 'qyfb'
  },
  {
    id: '3',
    label: '应急空间',
    children: [
      {
        id: '3-1',
        label: '应急池',
        type: 'layer',
        subType: 'labelPoint',
        method: getList,
        params: {
          type: 1,
          size: 1000
        },
        layerName: 'yjc'
      },
      {
        id: '3-2',
        label: '阀门',
        type: 'layer',
        subType: 'labelPoint',
        method: getList,
        params: {
          type: 2,
          size: 1000
        },
        layerName: 'fm'
      },
      {
        id: '3-3',
        label: '公共管网',
        type: 'layer',
        subType: 'labelPoint',
        method: getList,
        params: {
          type: 3,
          size: 1000
        },
        layerName: 'gggw'
      },
      {
        id: '3-4',
        label: '污水提升泵站',
        type: 'layer',
        subType: 'labelPoint',
        method: getList,
        params: {
          type: 4,
          size: 1000
        },
        layerName: 'wstsbz'
      },
      {
        id: '3-5',
        label: '水库',
        type: 'layer',
        subType: 'labelPoint',
        method: getList,
        params: {
          type: 5,
          size: 1000
        },
        layerName: 'sk'
      },
      {
        id: '3-6',
        label: '应急泵',
        type: 'layer',
        subType: 'labelPoint',
        method: getList,
        params: {
          type: 6,
          size: 1000
        },
        layerName: 'yjb'
      },
      {
        id: '3-7',
        label: '消防沙',
        type: 'layer',
        subType: 'labelPoint',
        method: getList,
        params: {
          type: 7,
          size: 1000
        },
        layerName: 'xfs'
      }
    ]
  },
  {
    id: '4',
    label: '风险源',
    type: 'layer',
    subType: 'labelPoint',
    method: getRiskList,
    params: {
      size: 1000
    },
    showParams: 'category',
    layerName: 'fxy'
  },
]
const defaultProps = {
  children: 'children',
  label: 'label',
}
const checkType = (value) => {
  if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
    return 'obj'
  } else if (Array.isArray(value)) {
    return 'arr'
  }
}
// 用于存储收集到的节点的数组
const collectedNodes = reactive([])
// 递归函数,收集所有 flag 为 true 的子节点
const collectNodesWithFlag = (nodes) => {
  if (checkType(nodes) == 'obj') {
    if (nodes.type == 'layer') {
      collectedNodes.value.push(nodes)
    }
    if (nodes.children && nodes.children.length > 0) {
      collectNodesWithFlag(nodes.children)
      return
    }
  }
  if (checkType(nodes) == 'arr') {
    nodes.forEach(item => {
      if (item.type == 'layer') {
        collectedNodes.value.push(item)
      }
      if (item.children && item.children.length > 0) {
        collectNodesWithFlag(item.children)
      }
    })
  }
}
let addTileLayers = {}
let tileLayers = new DC.TilesetLayer('tileLayers')
globalViewer.addLayer(tileLayers)
const handleCheckChange = (data, options) => {
  collectedNodes.value = []
  collectNodesWithFlag(data)
  collectedNodes.value.forEach(item => {
    if (options.checkedKeys.some(i => i == item.id)) {
      if (item.subType == '3Dtile') {
        if (!addTileLayers[item.layerName]) {
          addTileLayers[item.layerName] = new DC.Tileset(
            item.url,
            {
              cullWithChildrenBounds: false,
              maximumScreenSpaceError: 256,
              maximumMemoryUsage: 1024,
              skipLevelOfDetail: true,
              preferLeaves: true
            })
          tileLayers.addOverlay(addTileLayers[item.layerName])
        } else {
          addTileLayers[item.layerName].show = true
        }
        console.log(addTileLayers[item.layerName], 11111111)
        globalViewer.flyTo(addTileLayers[item.layerName])
      } else if (item.subType == 'labelPoint') {
        if (!addTileLayers[item.layerName]) {
          addTileLayers[item.layerName] = new DC.HtmlLayer(addTileLayers[item.layerName])
          globalViewer.addLayer(addTileLayers[item.layerName])
        }
        item.method(item.params).then(res => {
          let data = res.data.data.records
          data.filter(i => i.lng && i.lng != '' && i.lat && i.lat != '').forEach(i => {
            let divIcon = new DC.DivIcon(
              new DC.Position(i.lng, i.lat, 0),
              `<div class="public-map-popup">
                <div class="marsBlueGradientPnl">
                  <div>${i[item.showParams] || i.name}</div>
                </div>
              </div>`
            )
            addTileLayers[item.layerName].addOverlay(divIcon)
          })
        })
      }
    } else {
      if (addTileLayers[item.layerName]) {
        if (item.subType == '3Dtile') {
          addTileLayers[item.layerName].show = false
        } else if (item.subType == 'labelPoint') {
          globalViewer.removeLayer(addTileLayers[item.layerName])
        }
        delete addTileLayers[item.layerName]
      }
    }
  })
}
onMounted(() => {
  handleCheckChange(data.filter(i => i.id == '1'), {
    checkedKeys: ['1']
  })
})
</script>
<style lang="scss" scoped>
.tree-content {
  min-width: 200px;
  padding: 10px;
  ::v-deep(.el-tree) {
    color: #fff;
    background: transparent;
    /* 鼠标浮动过的背景颜色 */
    .el-tree-node__content:hover {
      background: #0074b7;
    }
    /* 鼠标点击时节点的背景颜色 */
    .el-tree-node:focus>.el-tree-node__content {
      background-color: #0074b7 !important;
      color: rgb(255, 255, 255);
    }
    /* 鼠标失去焦点时节点背景的颜色 */
    .el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content {
      background: rgb(0, 129, 204);
    }
  }
}
</style>
src/views/sub/components/scomponents/tool/exportScene.vue
New file
@@ -0,0 +1,12 @@
<template>
</template>
<script setup>
import { getViewer } from 'utils/getViewer'
const globalViewer = getViewer()
globalViewer.exportScene()
const emit = defineEmits(['closeChild'])
emit('closeChild')
</script>
<style lang="scss" scoped></style>
src/views/sub/components/scomponents/tool/location.vue
New file
@@ -0,0 +1,92 @@
<!--
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2024-10-29 15:48:36
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-10-29 19:53:49
 * @FilePath: \bigScreen\src\views\layout\components\scomponents\tool\location.vue
 * @Description:
 *
 * Copyright (c) 2024 by shuishen, All Rights Reserved.
-->
<template>
  <public-box style="z-index: 100;">
    <template #name>
      <div class="name"><i class="fa fa-map-pin"></i>&nbsp;底图</div>
    </template>
    <template #close>
      <div class="close cursor-p" @click="$emit('closeChild')"><i class="fa fa-close"></i></div>
    </template>
    <template #content>
      <div class="cur-content">
        <div>
          <span>经度:</span>
          <el-input v-model="longitude" size="small" placeholder="请输入经度" />
        </div>
        <div>
          <span>纬度:</span>
          <el-input v-model="latitude" size="small" placeholder="请输入纬度" />
        </div>
        <div>
          <span>高度:</span>
          <el-input v-model="height" size="small" placeholder="请输入高度" />
        </div>
      </div>
      <div class="cur-btn">
        <el-button color="rgba(13,100,167,.8)" @click="flyTo" type="primary" size="small">坐标定位</el-button>
      </div>
    </template>
  </public-box>
</template>
<script setup>
const longitude = ref(0)
const latitude = ref(0)
const height = ref(0)
import { getViewer } from 'utils/getViewer'
const globalViewer = getViewer()
const flyTo = () => {
  globalViewer.flyToPosition(new DC.Position(longitude.value, latitude.value, height.value, 0, -90, 0), () => { }, 3)
}
</script>
<style lang="scss" scoped>
.cur-content {
  &>div {
    margin-top: 10px;
    padding: 0 10px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    span {
      width: 54px;
    }
    ::v-deep(.el-input) {
      border: none !important;
      .el-input__wrapper {
        background: rgba(63, 72, 84, .7) !important;
        border: none !important;
        box-shadow: none;
        input {
          color: #fff;
        }
      }
    }
  }
}
.cur-btn {
  margin: 10px 0;
  display: flex;
  justify-content: center;
  align-items: center;
}
</style>
src/views/sub/components/scomponents/toolList.vue
New file
@@ -0,0 +1,132 @@
<!--
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2024-10-29 14:20:49
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-10-29 17:21:51
 * @FilePath: \bigScreen\src\views\layout\components\scomponents\toolList.vue
 * @Description:
 *
 * Copyright (c) 2024 by shuishen, All Rights Reserved.
-->
<template>
  <ul v-show="moreToolShow" class="tool-list-box">
    <li @click="showComponent(item.component)" v-for="item, index in components" :key="index">
      <i :class="item.icon"></i> {{ item.title }}
    </li>
  </ul>
  <component :is="currentComponent" v-if="currentComponent" @closeChild="closeComponent" />
</template>
<script setup>
const { moreToolShow } = defineProps({
  moreToolShow: {
    type: Boolean, //参数类型
    default: false, //默认值
    required: true, //是否必须传递
  }
})
import location from './tool/location.vue'
import exportScene from './tool/exportScene.vue'
import { getViewer } from 'utils/getViewer'
import component from 'element-plus/es/components/tree-select/src/tree-select-option.mjs'
const emit = defineEmits(['close'])
const globalViewer = getViewer()
let currentComponent = shallowRef(null)
const components = [
  {
    icon: 'fa fa-calculator',
    title: '图上量算',
  },
  {
    icon: 'fa fa-bar-chart',
    title: '空间分析',
  },
  {
    name: 'location',
    icon: 'fa fa-map-pin',
    title: '坐标定位',
    component: location
  },
  {
    icon: 'fa fa-paper-plane',
    title: '地区导航',
  },
  {
    icon: 'fa fa-edit',
    title: '我的标记',
  },
  {
    icon: 'fa fa-tags',
    title: '视角书签',
  },
  {
    name: 'exportScene',
    icon: 'fa fa-download',
    title: '场景导出',
    component: exportScene
  },
  {
    icon: 'fa fa-object-group',
    title: '图上标绘',
  },
  {
    icon: 'fa fa-helicopter',
    title: '飞行漫游',
  },
  {
    icon: 'fa fa-level-up',
    title: '路线导航',
  },
  {
    icon: 'fa fa-columns',
    title: '卷帘对比',
  },
  {
    icon: 'fa fa-window-restore',
    title: '分屏对比',
  },
]
const showComponent = (component) => {
  currentComponent.value = component
  emit('close', 'tool')
}
const closeComponent = () => {
  currentComponent.value = null
}
</script>
<style lang="scss" scoped>
.tool-list-box {
  position: absolute;
  right: 540px;
  z-index: 101;
  top: 152px;
  background: rgba(63, 72, 84, .7);
  pointer-events: auto;
  li {
    padding: 6px 10px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    color: #fff;
    cursor: pointer;
    i {
      margin-right: 5px;
    }
  }
  li:hover {
    background: #4db3ff;
  }
  li:first-child {
    margin-top: 0;
  }
}
</style>
src/views/sub/index.vue
New file
@@ -0,0 +1,141 @@
<!--
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2022-08-18 16:18:24
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-11-06 11:07:43
 * @FilePath: \bigScreen\src\views\sub\index.vue
 * @Description:
 *
 * Copyright (c) 2022 by shuishen 1109946754@qq.com, All Rights Reserved.
-->
<template>
  <div>
    <div class="main-header">
      <div class="title">ssssssss</div>
    </div>
    <div class="main-container">
      <router-view ref="target-name"></router-view>
    </div>
    <div class="out">
      <el-button @click="goHome">退回</el-button>
    </div>
  </div>
</template>
<script setup>
import { useRouter, useRoute } from 'vue-router'
let router = useRouter()
import { useRouterStore } from 'store/router'
const store = useRouterStore()
const goHome = () => {
  store.setLoadSub(false)
  router.push('/layout')
}
</script>
<style scoped lang="scss">
$bg-blue: rgba(24, 33, 92, 0.9);
.out {
  position:fixed;
  top: 50%;
  left: 50%;
  pointer-events: all;
}
.wrapper {
  position: relative;
  width: 100%;
  height: 100%;
  #MainContent {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 99;
  }
  .main-content {
    height: 1080px;
    background: url(/images/header.png) no-repeat center / 100% 100%,
      url(/images/pro-bg.png) no-repeat center / 100% 100%;
    pointer-events: none;
    .main-header {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 40px;
      pointer-events: auto;
      .title {
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        margin: auto;
        width: 640px;
        height: 40px;
        font-size: 24px;
        font-family: YouSheBiaoTiHei;
        font-weight: 400;
        color: #eff8fc;
        line-height: 40px;
        text-align: center;
        letter-spacing: 8px;
        font-weight: bolder;
        background: linear-gradient(to bottom,
            #e2eaf0 0%,
            #aed1f1 100%);
        -webkit-background-clip: text;
        -webkit-text-fill-color: transparent;
        // opacity: 0.89;
        // text-shadow: 0px 4px 1px rgba(19, 80, 143, 0.66);
        // background: linear-gradient(0deg, rgba(119, 186, 255, 0.45) 0%, rgba(233, 248, 255, 0.45) 73.3154296875%, rgba(255, 255, 255, 0.45) 100%);
        // -webkit-background-clip: text;
        // -webkit-text-fill-color: transparent;
      }
      .login-out {
        position: absolute;
        top: 10px;
        right: 40px;
        height: 36px;
        color: #fff;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: space-between;
        cursor: pointer;
        .img {
          width: 16px;
          height: 16px;
        }
        span {
          font-size: 13px;
        }
      }
    }
    .main-container {
      position: absolute;
      top: 40px;
      left: 40px;
      right: 40px;
      bottom: 40px;
    }
  }
}
</style>
src/views/survey/components/box/fireSource.vue
@@ -1,9 +1,13 @@
<script setup>
import { Text } from 'vue'
import { useRouter, useRoute } from 'vue-router'
let router = useRouter()
import { inject, Text } from 'vue'
const { VITE_APP_BASE } = import.meta.env
import { getDetail } from '@/api/indParkInfo'
import { getAssetsFile } from 'utils/utils'
import { useRouterStore } from 'store/router'
const store = useRouterStore()
let state = reactive({
  parkInfo: {}
@@ -80,8 +84,10 @@
  })
}
const goSubLayout = () => {
  store.setLoadSub(true)
  router.push('/layout/sub')
}
</script>
<template>
@@ -111,6 +117,8 @@
        </div>
      </div>
    </div>
    <el-button @click="goSubLayout">跳转a</el-button>
  </div>
</template>