123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504 |
- <template>
- <div class="panel-sjwg flex flex-col aside-left-inner">
- <div class="title-main shrink-0">数据网格可视化</div>
- <div class="title-sub my-4 shrink-0">
- 底板数据
- <i @click="toggleContentShow('b1')" class="drop-down" :class="{ 'reverse': contentShow.b1 }"></i>
- </div>
- <Transition>
- <ul class="list-base flex flex-wrap shrink-0" v-if="contentShow.b1" v-collapse>
- <li v-for="item in basicList" class="text-center w-1/4 mb-4 cursor-pointer" @click="handleBaseClick(item)">
- <img :src="getAssetsFile(`page/${item.active ? item.icon + '-h' : item.icon}.png`)" alt="" class="ml-2 mb-1">
- <span class="block text-base ml-2">{{ item.label }}</span>
- </li>
- </ul>
- </Transition>
- <div class="title-sub mb-4 shrink-0">
- 低空要素数据
- <i @click="toggleContentShow('b2')" class="drop-down" :class="{ 'reverse': contentShow.b2 }"></i>
- </div>
- <Transition>
- <div v-if="contentShow.b2" v-collapse="'scroll'" class="flex-1 pr-1">
- <div class="title-shade">
- <span>空域</span>
- <i class="btn-selectall" :class="{ 'active': checkAll.area }" @click="handleCheckAll('area')"></i>
- <i class="drop-down" @click="toggleContentShow('b2r1')" :class="{ 'reverse': contentShow.b2r1 }"></i>
- </div>
- <Transition>
- <ul v-if="contentShow.b2r1" v-collapse>
- <li v-for="item in areaList" class="list-item">
- <img src="../../../assets/images/page/icon-location.png" alt="">
- <span>{{ item.name }}</span>
- <i title="查看" @click="handleCheck(item, 'area')" :class="{ 'active': item.check }"></i>
- <i title="网格" @click="handleMesh(item, 'area')" :class="{ 'active': item.mesh }"></i>
- <i title="删除" @click="handleDelete(item, 'area')"></i>
- </li>
- </ul>
- </Transition>
- <div class="title-shade">
- <span>航线</span>
- <i class="btn-selectall" :class="{ 'active': checkAll.route }" @click="handleCheckAll('route')"></i>
- <i class="drop-down" @click="toggleContentShow('b2r2')" :class="{ 'reverse': contentShow.b2r2 }"></i>
- </div>
- <Transition>
- <ul v-if="contentShow.b2r2" v-collapse>
- <li v-for="item in routeList" class="list-item">
- <img src="../../../assets/images/page/icon-route.png" alt="">
- <span>{{ item.name }}</span>
- <i title="查看" @click="handleCheck(item, 'route')" :class="{ 'active': item.check }"></i>
- <i title="网格" @click="handleMesh(item, 'route')" :class="{ 'active': item.mesh }"></i>
- <i title="删除" @click="handleDelete(item, 'route')"></i>
- </li>
- </ul>
- </Transition>
- <div class="title-shade">
- <span>起降场</span>
- <i class="btn-selectall" :class="{ 'active': checkAll.plot }" @click="handleCheckAll('plot')"></i>
- <i class="drop-down" @click="toggleContentShow('b2r3')" :class="{ 'reverse': contentShow.b2r3 }"></i>
- </div>
- <Transition>
- <ul v-if="contentShow.b2r3" v-collapse>
- <li v-for="item in plotList" class="list-item">
- <img src="../../../assets/images/page/icon-plot.png" alt="">
- <span>{{ item.name }}</span>
- <i title="查看" @click="handleCheck(item, 'plot')" :class="{ 'active': item.check }"></i>
- <i title="网格" @click="handleMesh(item, 'plot')" :class="{ 'active': item.mesh }"></i>
- <i title="删除" @click="handleDelete(item, 'plot')"></i>
- </li>
- </ul>
- </Transition>
- </div>
- </Transition>
- </div>
- </template>
- <script setup>
- import { getAssetsFile, getData } from '@/utils/require';
- import { onBeforeMount, onBeforeUnmount, reactive, ref } from 'vue';
- import { showShapes, heatMap, AddSingleLayer, InspectCube } from '@/utils/map/addLayer'
- import { DeleteArea, DeletePlot, DeleteRoute, GetAreaList, GetPlotList, GetRouteList } from '@/service/http'
- import { airSpaceTypes } from '@/utils/options';
- import { hexToRgb } from '@/utils/tools';
- import usePanelStore from '@/store/panel';
- const panelStore = usePanelStore()
- onBeforeMount(() => {
- getLists()
- })
- function showWarning(message) {
- ElMessage({ offset: 90, type: 'warning', message })
- }
- function getLists() {
- Promise.all([
- GetAreaList().then(res => {
- if (!Array.isArray(res.data.data)) {
- showWarning('空域列表查询失败')
- return
- }
- areaList.value = res.data.data.map(row => ({
- ...row,
- check: false,
- mesh: false
- }))
- contentShow.b2r1 = true
- }).catch(() => {
- showWarning('空域列表查询失败')
- }),
- GetPlotList().then(res => {
- if (!Array.isArray(res.data.data)) {
- showWarning('起降场列表查询失败')
- return
- }
- plotList.value = res.data.data.map(row => ({
- ...row,
- check: false,
- mesh: false
- }))
- }).catch(() => {
- showWarning('起降场列表查询失败')
- }),
- GetRouteList().then(res => {
- if (!Array.isArray(res.data.data)) {
- showWarning('航线列表查询失败')
- return
- }
- routeList.value = res.data.data.map(row => ({
- ...row,
- check: false,
- mesh: false
- }))
- }).catch(() => {
- showWarning('航线列表查询失败')
- })
- ]).finally(() => {
- // 恢复选中状态
- handleRestoreChecked()
- })
- }
- const basicList = ref([
- { label: '白模', alias: '全市白模', icon: 'icon-layer-bm', active: false },
- { label: '精模', alias: '五角场精模', icon: 'icon-layer-jm', active: false },
- { label: '道路', alias: ['快速路', '高速公路', '地面道路'], icon: 'icon-layer-dl', active: false },
- { label: '河流', alias: '全市河流', icon: 'icon-layer-hl', active: false },
- { label: '人口', alias: '人口', icon: 'icon-layer-rk', active: false },
- ])
- async function handleBaseClick(layer) {
- layer.active = !layer.active
- const aliasArr = Array.isArray(layer.alias) ? layer.alias : [layer.alias]
- const resources = await getData('resources.json')
- const targetServices = resources.filter(r => aliasArr.some(i => i === r.title))
- if (targetServices.length === 0) return
- targetServices.forEach(service => {
- if (service.type == "feature") {
- heatMap({
- ...service,
- visible: layer.active,
- })
- } else {
- AddSingleLayer({
- ...service,
- visible: layer.active,
- opacity: 1
- })
- }
- })
- }
- const areaList = ref([])
- function handleCheck(item, type) {
- // console.log(item)
- item.check = !item.check
- let color
- switch (type) {
- case 'area':
- color = hexToRgb(airSpaceTypes.find(i => i.value === item.spaceType).color, 0.5)
- break;
- case 'plot':
- color = [0, 0, 255, 0.5]
- break;
- case 'route':
- color = [255, 255, 0, 0.5]
- }
- const data = [{
- type: type === 'route' ? item.type : item.geoType,
- shape: {
- ...JSON.parse(item.shape),
- color
- }
- }]
- showShapes({
- id: item.id,
- data: item.check ? data : null
- })
- }
- function handleDelete(item, type) {
- switch (type) {
- case 'area':
- DeleteArea(item.id).then(res => {
- if (res.data.code === 200) {
- ElMessage.success('删除成功')
- getLists()
- }
- })
- break;
- case 'plot':
- DeletePlot(item.id).then(res => {
- if (res.data.code === 200) {
- ElMessage.success('删除成功')
- getLists()
- }
- })
- break;
- case 'route':
- DeleteRoute(item.id).then(res => {
- if (res.data.code === 200) {
- ElMessage.success('删除成功')
- getLists()
- }
- })
- }
- }
- function handleMesh(item) {
- item.mesh = !item.mesh
- InspectCube({
- id: item.id,
- show: item.mesh,
- type: item.geoType || item.type,
- shape: JSON.parse(item.shape)
- })
- }
- const routeList = ref([])
- const plotList = ref([])
- const contentShow = reactive({
- b1: true,
- b2: true,
- b2r1: false,
- b2r2: false,
- b2r3: false,
- })
- function toggleContentShow(id) {
- contentShow[id] = !contentShow[id]
- const subs = ['b2r1', 'b2r2', 'b2r3']
- subs.forEach(i => {
- if (contentShow[id] && subs.includes(id) && id !== i) {
- contentShow[i] = false
- }
- })
- }
- function clearAllFeatures() {
- [...areaList.value, ...plotList.value, ...routeList.value].forEach(row => {
- if (row.check) {
- showShapes({
- id: row.id,
- data: null
- })
- }
- if (row.mesh) {
- InspectCube({
- id: row.id,
- show: false,
- type: row.geoType || row.type,
- })
- }
- })
- }
- const checkAll = reactive({
- area: false,
- route: false,
- plot: false
- })
- function handleCheckAll(type) {
- checkAll[type] = !checkAll[type]
- const targetList = type === 'area' ? areaList.value : type === 'route' ? routeList.value : plotList.value
- targetList.forEach(row => {
- if (checkAll[type] && !row.check) {
- handleCheck(row, type)
- } else if (!checkAll[type] && row.check) {
- handleCheck(row, type)
- }
- })
- }
- function handleStoreChecked() {
- panelStore.setSjwg({
- basicList: basicList.value.map(({ label, active }) => ({ label, active })),
- checkAll,
- areaList: areaList.value.map(({ id, check, mesh }) => ({ id, check, mesh })),
- routeList: routeList.value.map(({ id, check, mesh }) => ({ id, check, mesh })),
- plotList: plotList.value.map(({ id, check, mesh }) => ({ id, check, mesh })),
- })
- }
- function handleRestoreChecked() {
- if (!Object.keys(panelStore.sjwg).length) return
- const temp = panelStore.sjwg
- basicList.value.forEach(i => {
- i.active = temp.basicList.find(t => t.label === i.label).active
- })
- Object.keys(checkAll).forEach(k => {
- checkAll[k] = temp.checkAll[k]
- })
- areaList.value.forEach(i => {
- const target = temp.areaList.find(t => t.id === i.id)
- if (target) {
- i.check = target.check
- i.mesh = target.mesh
- }
- })
- routeList.value.forEach(i => {
- const target = temp.routeList.find(t => t.id === i.id)
- if (target) {
- i.check = target.check
- i.mesh = target.mesh
- }
- })
- plotList.value.forEach(i => {
- const target = temp.plotList.find(t => t.id === i.id)
- if (target) {
- i.check = target.check
- i.mesh = target.mesh
- }
- })
- }
- onBeforeUnmount(() => {
- // clearAllFeatures()
- handleStoreChecked()
- })
- const vCollapse = {
- beforeMount(el, binding) {
- el.style.height = '0';
- el.style.overflow = binding.value === 'scroll' ? 'auto' : 'hidden';
- el.style.transition = 'height 0.5s ease';
- },
- mounted(el) {
- const naturalHeight = el.scrollHeight;
- el.style.height = `${naturalHeight}px`;
- },
- beforeUnmount(el) {
- el.style.height = '0';
- }
- }
- </script>
- <style lang="scss" scoped>
- .list-base {
- li {
- span {
- width: 75px;
- }
- img {
- width: 75px;
- height: 77px;
- }
- }
- }
- .drop-down {
- display: block;
- width: 20px;
- height: 20px;
- margin-left: 10px;
- background: url('../../../assets/images/page/dropdown.png') no-repeat;
- background-size: 10px 7px;
- background-position: center;
- transition: transform 0.3s ease;
- cursor: pointer;
- &.reverse {
- transform: rotateZ(180deg);
- }
- }
- .title-shade {
- position: relative;
- height: 32px;
- background: linear-gradient(to right, rgba(101, 131, 190, 1) 0%, rgba(101, 131, 190, 0) 100%);
- display: flex;
- align-items: center;
- padding: 0 16px;
- margin-bottom: 10px;
- &::before {
- content: '';
- position: absolute;
- left: 0;
- top: 0;
- width: 4px;
- height: 32px;
- background: #C0D5FF;
- }
- span {
- text-shadow: 0px 4px 4px rgba(21, 41, 91, 0.45);
- margin-right: 10px;
- }
- .btn-selectall {
- display: block;
- width: 26px;
- height: 26px;
- background: url('../../../assets/images/page/btn-selectall.png');
- background-size: 100%;
- background-position: center 1px;
- cursor: pointer;
- filter: opacity(0.6);
- &.active {
- filter: opacity(1) drop-shadow(0 0 5px #379bff);
- transform: scale(1.1);
- }
- }
- .drop-down {
- margin-left: auto;
- }
- }
- .list-item {
- position: relative;
- height: 40px;
- padding: 0 15px;
- margin: 9px 0;
- display: flex;
- align-items: center;
- background: #4352704d;
- &::before {
- content: '';
- position: absolute;
- left: 0;
- top: 0;
- width: 1px;
- height: 40px;
- background: #808DC9;
- }
- &:last-child {
- margin-bottom: 15px;
- }
- img {
- width: 24px;
- height: 24px;
- margin-right: 10px;
- }
- span {
- flex: 1;
- }
- i {
- display: block;
- width: 34px;
- height: 34px;
- margin-left: 5px;
- cursor: pointer;
- filter: grayscale(1);
- &.active {
- filter: grayscale(0);
- }
- }
- i:nth-child(3) {
- background: url('../../../assets/images/page/btn-check.png');
- background-size: cover;
- }
- i:nth-child(4) {
- background: url('../../../assets/images/page/btn-mesh.png');
- background-size: cover;
- }
- i:nth-child(5) {
- background: url('../../../assets/images/page/btn-delete.png');
- background-size: 40px 40px;
- background-position: center;
- }
- }
- </style>
|