2025-09-01 21:33:21 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<div class="app-container">
|
|
|
|
|
|
<div class="searchPanel">
|
|
|
|
|
|
<div class="more-search-pane">
|
|
|
|
|
|
<div class="search-where-container">
|
|
|
|
|
|
<el-form :model="queryParams" ref="queryRef" :inline="true" class="searchPanelForm">
|
|
|
|
|
|
<el-form-item label="媒体类型:">
|
2025-09-13 12:16:07 +08:00
|
|
|
|
<el-select v-model="queryParams.mediaType" placeholder="请选择" @change="getMediaTypeTwo"
|
2025-09-01 21:33:21 +08:00
|
|
|
|
clearable style="min-width: 30px">
|
|
|
|
|
|
<el-option v-for="item in mediaTypeOne" :key="item.id" :label="item.name"
|
|
|
|
|
|
:value="item.id" />
|
|
|
|
|
|
</el-select>
|
|
|
|
|
|
</el-form-item>
|
2025-09-01 23:00:15 +08:00
|
|
|
|
<el-form-item label="媒体大类:">
|
2025-09-13 12:16:07 +08:00
|
|
|
|
<el-select v-model="queryParams.mediaCategory" placeholder="请选择" @change="getMediaTypeThree"
|
2025-09-01 21:33:21 +08:00
|
|
|
|
clearable style="min-width: 30px">
|
|
|
|
|
|
<el-option v-for="item in mediaTypeTwo" :key="item.id" :label="item.name"
|
|
|
|
|
|
:value="item.id" />
|
|
|
|
|
|
</el-select>
|
|
|
|
|
|
</el-form-item>
|
2025-09-01 23:00:15 +08:00
|
|
|
|
<el-form-item label="展示形式:">
|
2025-09-13 12:16:07 +08:00
|
|
|
|
<el-select v-model="queryParams.displayForm" placeholder="请选择" clearable
|
2025-09-01 21:33:21 +08:00
|
|
|
|
style="min-width: 30px">
|
|
|
|
|
|
<el-option v-for="item in mediaTypeThree" :key="item.id" :label="item.name"
|
|
|
|
|
|
:value="item.id" />
|
|
|
|
|
|
</el-select>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-form>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="search-more-button">
|
|
|
|
|
|
<el-button v-if="!unfoldFlag" text class="foladText" @click="handleFlod">展开
|
|
|
|
|
|
<svg-icon icon-class="unfold" class="ml10" />
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
<el-button v-else text class="foladText" @click="handleFlod">收起
|
|
|
|
|
|
<svg-icon icon-class="packUp" class="ml10" />
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="searchSmallPanel" v-show="unfoldFlag">
|
|
|
|
|
|
<el-form :model="queryParams" ref="queryRef" :inline="true" class="searchSmallPanelForm">
|
|
|
|
|
|
<el-form-item label="城市:">
|
2025-09-13 12:16:07 +08:00
|
|
|
|
<el-select v-model="queryParams.provinceCode" placeholder="请选择" @change="getCityList" clearable
|
2025-09-01 21:33:21 +08:00
|
|
|
|
style="min-width: 30px">
|
|
|
|
|
|
<el-option v-for="item in province" :key="item.id" :label="item.name" :value="item.id" />
|
|
|
|
|
|
</el-select>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
<el-form-item label="">
|
2025-09-13 12:16:07 +08:00
|
|
|
|
<el-select v-model="queryParams.cityCode" placeholder="请选择" @change="getCountyList" clearable
|
2025-09-01 21:33:21 +08:00
|
|
|
|
style="min-width: 30px">
|
|
|
|
|
|
<el-option v-for="item in city" :key="item.id" :label="item.name" :value="item.id" />
|
|
|
|
|
|
</el-select>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
<el-form-item label="">
|
2025-09-13 12:16:07 +08:00
|
|
|
|
<el-select v-model="queryParams.areaCode" placeholder="请选择" @change="getTownList" clearable
|
2025-09-01 21:33:21 +08:00
|
|
|
|
style="min-width: 30px">
|
|
|
|
|
|
<el-option v-for="item in county" :key="item.id" :label="item.name" :value="item.id" />
|
|
|
|
|
|
</el-select>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
<el-form-item label="">
|
2025-09-13 12:16:07 +08:00
|
|
|
|
<el-select v-model="queryParams.townCode" placeholder="请选择" @change="getbusinessAreaList" clearable
|
|
|
|
|
|
style="min-width: 30px">
|
2025-09-01 21:33:21 +08:00
|
|
|
|
<el-option v-for="item in town" :key="item.id" :label="item.name" :value="item.id" />
|
|
|
|
|
|
</el-select>
|
|
|
|
|
|
</el-form-item>
|
2025-09-01 23:00:15 +08:00
|
|
|
|
<el-form-item label="商圈:">
|
2025-09-13 12:16:07 +08:00
|
|
|
|
<el-select v-model="queryParams.businessDistrictId" placeholder="请选择" clearable
|
2025-09-01 21:33:21 +08:00
|
|
|
|
style="min-width: 30px;">
|
2025-09-13 12:16:07 +08:00
|
|
|
|
<el-option v-for="item in businessAreaList" :key="item.id" :label="item.name"
|
|
|
|
|
|
:value="item.id" />
|
2025-09-01 21:33:21 +08:00
|
|
|
|
</el-select>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-form>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="choseResultPanel">
|
|
|
|
|
|
<el-form :inline="true" class="searchSmallPanelForm">
|
|
|
|
|
|
<el-form-item label="已选媒体:">
|
|
|
|
|
|
<div v-if="multipleChoseArr.length == 0" class="noChoseLabel">未选择媒体</div>
|
|
|
|
|
|
<template v-else>
|
|
|
|
|
|
<el-tag v-for="tag in multipleChoseArr" :key="tag.id" class="choseResultTag"
|
|
|
|
|
|
@close="handleCloseTag(tag)" closable>
|
|
|
|
|
|
{{ tag.mediaName }}
|
|
|
|
|
|
</el-tag>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-form>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<el-card class="mt10">
|
|
|
|
|
|
<el-row :gutter="10" class="my_row">
|
|
|
|
|
|
<el-col :span="8">
|
|
|
|
|
|
<el-form :model="queryParams" ref="queryRef" :inline="true" class="searchInputForm">
|
|
|
|
|
|
<el-form-item label="">
|
2025-09-13 12:16:07 +08:00
|
|
|
|
<el-input v-model="queryParams.keyword" placeholder="请输入媒体名称/媒体编号" :prefix-icon="Search"
|
2025-09-01 21:33:21 +08:00
|
|
|
|
style="width: 400px;" />
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-form>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
<el-col :span="16" style="text-align: right;">
|
|
|
|
|
|
<el-button type="primary" class="primaryBtn" @click="handleQuery">查询</el-button>
|
|
|
|
|
|
<el-button type="primary" class="primaryBtn" @click="resetQuery">重置</el-button>
|
|
|
|
|
|
<el-button type="primary" class="primaryBtn">PPT批量导出</el-button>
|
2025-09-13 12:16:07 +08:00
|
|
|
|
<el-button type="primary" class="primaryBtn" @click="handleClearChoseMedia">清空所选媒体</el-button>
|
2025-09-01 21:33:21 +08:00
|
|
|
|
</el-col>
|
|
|
|
|
|
</el-row>
|
2025-09-02 22:55:31 +08:00
|
|
|
|
<el-row :gutter="10" class="my_row" style="margin-bottom: 0;">
|
2025-09-01 21:33:21 +08:00
|
|
|
|
<el-col :span="12">
|
|
|
|
|
|
<el-table v-loading="loading" :data="outdoorMediaList" @selection-change="handleSelectionChange"
|
2025-09-02 22:55:31 +08:00
|
|
|
|
:height="unfoldFlag ? 'calc(100vh - 372px)' : 'calc(100vh - 338px)'">
|
2025-09-01 21:33:21 +08:00
|
|
|
|
<el-table-column type="selection" width="55" align="center" />
|
2025-09-13 12:16:07 +08:00
|
|
|
|
<el-table-column label="实景图片" align="left" prop="mediaFileList" width="170">
|
2025-09-01 21:33:21 +08:00
|
|
|
|
<template #default="scope">
|
2025-09-13 12:16:07 +08:00
|
|
|
|
<img v-if="scope.row.mediaFileList.length > 0"
|
|
|
|
|
|
:src="baseUrl + scope.row.mediaFileList[0].fileName" fit="fill"
|
|
|
|
|
|
style="width: 138px;height: 78px; border-radius: 4px" />
|
2025-09-01 21:33:21 +08:00
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
2025-09-10 20:52:06 +08:00
|
|
|
|
<el-table-column label="媒体名称" align="left" prop="mediaName" width="150" />
|
2025-09-13 12:16:07 +08:00
|
|
|
|
<el-table-column label="商圈" align="left" prop="businessDistrictName" width="150" />
|
|
|
|
|
|
<el-table-column label="媒体大类" align="left" prop="mediaCategoryStr" width="150" />
|
|
|
|
|
|
<el-table-column label="展示形式" align="left" prop="displayFormStr" width="150" />
|
2025-09-01 21:33:21 +08:00
|
|
|
|
<el-table-column label="操作" width="58" align="center" fixed="right">
|
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
|
<el-popover popper-class="my_popover" placement="left-start">
|
2025-09-14 00:06:28 +08:00
|
|
|
|
<div class="popBtns" @click="handleViewMedia(scope.row.id)"
|
2025-09-01 21:33:21 +08:00
|
|
|
|
v-hasPermi="['problemFeedback:edit']">查看
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="popBtns" @click="handleDownFiles(scope.row)"
|
2025-09-01 23:00:15 +08:00
|
|
|
|
v-hasPermi="['problemFeedback:edit']">下载PPT</div>
|
2025-09-01 21:33:21 +08:00
|
|
|
|
<template #reference>
|
|
|
|
|
|
<img style="cursor: pointer;" :src="scope.row.currentImageSrc"
|
|
|
|
|
|
@mouseenter="scope.row.currentImageSrc = hoverImageSrc"
|
|
|
|
|
|
@mouseleave="scope.row.currentImageSrc = defaultImageSrc" />
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-popover>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
</el-table>
|
|
|
|
|
|
|
|
|
|
|
|
<pagination :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize"
|
2025-09-13 12:16:07 +08:00
|
|
|
|
@pagination="getOutMediaPageList" />
|
2025-09-01 21:33:21 +08:00
|
|
|
|
</el-col>
|
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
|
<div id="mapContainer" class="mapContainer"></div>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
</el-row>
|
|
|
|
|
|
</el-card>
|
2025-09-14 00:06:28 +08:00
|
|
|
|
|
|
|
|
|
|
<detail ref="detailFormRef" />
|
2025-09-01 21:33:21 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
<script setup name="Post">
|
2025-09-03 20:21:01 +08:00
|
|
|
|
import { onMounted, onUnmounted, ref } from 'vue';
|
2025-09-01 21:33:21 +08:00
|
|
|
|
import { Search } from '@element-plus/icons-vue'
|
|
|
|
|
|
import { sysRegionListByPid } from "@/api/system/administrativeRegion"
|
|
|
|
|
|
import { sysMediaTypeListByPid } from "@/api/system/mediaType"
|
2025-09-13 12:16:07 +08:00
|
|
|
|
import { busTradingAreaPage } from "@/api/system/businessArea"
|
|
|
|
|
|
import { outMediaPageList } from "@/api/mediaLibrary"
|
2025-09-01 21:33:21 +08:00
|
|
|
|
import AMapLoader from "@amap/amap-jsapi-loader"; // 引入地图服务
|
|
|
|
|
|
import optionIcon from '@/assets/images/optionIcon.png'
|
|
|
|
|
|
import optionIconHover from '@/assets/images/optionIconHover.png'
|
|
|
|
|
|
import { useBackgroundStore } from '@/store/modules/background'
|
|
|
|
|
|
import otherbg from '@/assets/images/otherbg.png'
|
|
|
|
|
|
|
2025-09-14 00:06:28 +08:00
|
|
|
|
import detail from './detail.vue';
|
|
|
|
|
|
|
2025-09-01 21:33:21 +08:00
|
|
|
|
const bgStore = useBackgroundStore()
|
|
|
|
|
|
const { proxy } = getCurrentInstance()
|
2025-09-13 12:16:07 +08:00
|
|
|
|
const baseUrl = import.meta.env.VITE_APP_BASE_API
|
2025-09-09 14:52:18 +08:00
|
|
|
|
const { apiKey, secretKey } = window._CONFIG
|
2025-09-14 00:06:28 +08:00
|
|
|
|
const detailFormRef = ref(null)
|
2025-09-13 12:16:07 +08:00
|
|
|
|
// 操作图标
|
|
|
|
|
|
const defaultImageSrc = ref(optionIcon);
|
|
|
|
|
|
const hoverImageSrc = ref(optionIconHover);
|
2025-09-01 21:33:21 +08:00
|
|
|
|
// 省、市、县、镇数据
|
|
|
|
|
|
const province = ref([])
|
|
|
|
|
|
const city = ref([])
|
|
|
|
|
|
const county = ref([])
|
|
|
|
|
|
const town = ref([])
|
2025-09-13 12:16:07 +08:00
|
|
|
|
// 商圈信息列表
|
|
|
|
|
|
const businessAreaList = ref([])
|
2025-09-01 21:33:21 +08:00
|
|
|
|
// 媒体类型数据
|
|
|
|
|
|
const mediaTypeOne = ref([])
|
|
|
|
|
|
const mediaTypeTwo = ref([])
|
|
|
|
|
|
const mediaTypeThree = ref([])
|
2025-09-13 12:16:07 +08:00
|
|
|
|
// 媒体多选数据
|
2025-09-01 21:33:21 +08:00
|
|
|
|
const multipleChoseArr = ref([])
|
2025-09-13 12:16:07 +08:00
|
|
|
|
// 户外媒体数据
|
|
|
|
|
|
const outdoorMediaList = ref([])
|
|
|
|
|
|
// 是否折叠
|
|
|
|
|
|
const unfoldFlag = ref(false)
|
2025-09-01 21:33:21 +08:00
|
|
|
|
const loading = ref(true)
|
|
|
|
|
|
const total = ref(0)
|
|
|
|
|
|
const data = reactive({
|
|
|
|
|
|
queryParams: {
|
|
|
|
|
|
pageNum: 1,
|
|
|
|
|
|
pageSize: 10,
|
2025-09-13 12:16:07 +08:00
|
|
|
|
keyword: undefined,
|
|
|
|
|
|
mediaType: undefined,
|
|
|
|
|
|
mediaCategory: undefined,
|
|
|
|
|
|
displayForm: undefined,
|
|
|
|
|
|
provinceCode: undefined,
|
|
|
|
|
|
cityCode: undefined,
|
|
|
|
|
|
areaCode: undefined,
|
|
|
|
|
|
townCode: undefined,
|
|
|
|
|
|
businessDistrictId: undefined
|
2025-09-01 21:33:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
const { queryParams } = toRefs(data)
|
2025-09-13 12:16:07 +08:00
|
|
|
|
// map实例
|
|
|
|
|
|
const mapInstance = ref(null)
|
|
|
|
|
|
const massMarks = ref(null)
|
|
|
|
|
|
// 当前地图模式(2D/3D)
|
|
|
|
|
|
const mapMode = ref('2D')
|
|
|
|
|
|
// 是否全屏状态
|
|
|
|
|
|
const isFullscreen = ref(false)
|
|
|
|
|
|
// 地图数据点
|
|
|
|
|
|
const points = ref([])
|
2025-09-01 21:33:21 +08:00
|
|
|
|
|
|
|
|
|
|
// 获取一级媒体类型
|
|
|
|
|
|
const getMediaTypeOne = () => {
|
|
|
|
|
|
sysMediaTypeListByPid({ parentId: 0 }).then(res => {
|
|
|
|
|
|
mediaTypeOne.value = res.data
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
// 获取二级媒体类型
|
|
|
|
|
|
const getMediaTypeTwo = (value) => {
|
|
|
|
|
|
sysMediaTypeListByPid({ parentId: value }).then(res => {
|
|
|
|
|
|
queryParams.value.mediaTypeTwo = undefined
|
|
|
|
|
|
queryParams.value.mediaTypeThree = undefined
|
|
|
|
|
|
mediaTypeTwo.value = res.data
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
// 获取三级媒体类型
|
|
|
|
|
|
const getMediaTypeThree = (value) => {
|
|
|
|
|
|
sysMediaTypeListByPid({ parentId: value }).then(res => {
|
|
|
|
|
|
queryParams.value.mediaTypeThree = undefined
|
|
|
|
|
|
mediaTypeThree.value = res.data
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
// 获取省/直辖市数据
|
|
|
|
|
|
const getProvinceList = () => {
|
|
|
|
|
|
sysRegionListByPid({ parentId: '0' }).then(res => {
|
|
|
|
|
|
province.value = res.data
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
// 获取地级市/区数据
|
|
|
|
|
|
const getCityList = (value) => {
|
|
|
|
|
|
sysRegionListByPid({ parentId: value }).then(res => {
|
|
|
|
|
|
queryParams.value.cityId = undefined
|
|
|
|
|
|
queryParams.value.countyId = undefined
|
|
|
|
|
|
queryParams.value.townId = undefined
|
|
|
|
|
|
city.value = res.data
|
|
|
|
|
|
})
|
2025-09-13 12:16:07 +08:00
|
|
|
|
getbusinessAreaList()
|
2025-09-01 21:33:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
// 获取区/县数据
|
|
|
|
|
|
const getCountyList = (value) => {
|
|
|
|
|
|
sysRegionListByPid({ parentId: value }).then(res => {
|
|
|
|
|
|
queryParams.value.countyId = undefined
|
|
|
|
|
|
queryParams.value.townId = undefined
|
|
|
|
|
|
county.value = res.data
|
|
|
|
|
|
})
|
2025-09-13 12:16:07 +08:00
|
|
|
|
getbusinessAreaList()
|
2025-09-01 21:33:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
// 获取镇数据
|
|
|
|
|
|
const getTownList = (value) => {
|
|
|
|
|
|
sysRegionListByPid({ parentId: value }).then(res => {
|
|
|
|
|
|
queryParams.value.townId = undefined
|
|
|
|
|
|
town.value = res.data
|
|
|
|
|
|
})
|
2025-09-13 12:16:07 +08:00
|
|
|
|
getbusinessAreaList()
|
|
|
|
|
|
}
|
|
|
|
|
|
// 依据省市县镇查询商圈
|
|
|
|
|
|
const getbusinessAreaList = (val) => {
|
|
|
|
|
|
const _params = {
|
|
|
|
|
|
pageIndex: 1,
|
|
|
|
|
|
pageSize: 200,
|
|
|
|
|
|
provinceId: queryParams.value.provinceCode,
|
|
|
|
|
|
cityId: queryParams.value.cityCode,
|
|
|
|
|
|
countyId: queryParams.value.areaCode,
|
|
|
|
|
|
townId: queryParams.value.townCode,
|
|
|
|
|
|
}
|
|
|
|
|
|
busTradingAreaPage(_params).then(res => {
|
|
|
|
|
|
if (res.code == 200) {
|
|
|
|
|
|
businessAreaList.value = res.data.list
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
2025-09-01 21:33:21 +08:00
|
|
|
|
}
|
2025-09-13 12:16:07 +08:00
|
|
|
|
// 折叠展开
|
|
|
|
|
|
const handleFlod = () => {
|
|
|
|
|
|
unfoldFlag.value = !unfoldFlag.value
|
|
|
|
|
|
}
|
|
|
|
|
|
// 获取户外媒介列表数据
|
|
|
|
|
|
const getOutMediaPageList = () => {
|
|
|
|
|
|
loading.value = true
|
|
|
|
|
|
outMediaPageList(queryParams.value).then(res => {
|
|
|
|
|
|
res.data.rows.forEach(element => {
|
|
|
|
|
|
element.currentImageSrc = defaultImageSrc.value;
|
|
|
|
|
|
});
|
|
|
|
|
|
outdoorMediaList.value = res.data.rows
|
|
|
|
|
|
total.value = res.data.total
|
|
|
|
|
|
loading.value = false
|
2025-09-13 22:24:35 +08:00
|
|
|
|
|
|
|
|
|
|
// 在地图完全加载后执行点数据处理
|
|
|
|
|
|
renderMassMarks();
|
2025-09-13 12:16:07 +08:00
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
/** 搜索按钮操作 */
|
|
|
|
|
|
const handleQuery = () => {
|
|
|
|
|
|
queryParams.value.pageNum = 1
|
|
|
|
|
|
getOutMediaPageList()
|
|
|
|
|
|
}
|
|
|
|
|
|
/** 重置按钮操作 */
|
|
|
|
|
|
const resetQuery = () => {
|
|
|
|
|
|
queryParams.value = {
|
|
|
|
|
|
pageNum: 1,
|
|
|
|
|
|
pageSize: 10,
|
|
|
|
|
|
keyword: undefined,
|
|
|
|
|
|
mediaType: undefined,
|
|
|
|
|
|
mediaCategory: undefined,
|
|
|
|
|
|
displayForm: undefined,
|
|
|
|
|
|
provinceCode: undefined,
|
|
|
|
|
|
cityCode: undefined,
|
|
|
|
|
|
areaCode: undefined,
|
|
|
|
|
|
townCode: undefined,
|
|
|
|
|
|
businessDistrictId: undefined
|
|
|
|
|
|
}
|
|
|
|
|
|
handleQuery()
|
|
|
|
|
|
}
|
|
|
|
|
|
// 选择媒体事件
|
|
|
|
|
|
const handleSelectionChange = (selection) => {
|
|
|
|
|
|
multipleChoseArr.value = selection
|
|
|
|
|
|
}
|
|
|
|
|
|
// 移除选择项
|
|
|
|
|
|
const handleCloseTag = (tag) => {
|
|
|
|
|
|
const rowIndex = multipleChoseArr.value.findIndex(item => item.id == tag.id)
|
|
|
|
|
|
multipleChoseArr.value.splice(rowIndex, 1)
|
|
|
|
|
|
}
|
|
|
|
|
|
// 清空已选媒体
|
|
|
|
|
|
const handleClearChoseMedia = () => {
|
|
|
|
|
|
multipleChoseArr.value = []
|
|
|
|
|
|
}
|
2025-09-14 00:06:28 +08:00
|
|
|
|
// 查看媒体详情
|
|
|
|
|
|
const handleViewMedia = (_mediaId) => {
|
|
|
|
|
|
detailFormRef.value.initMediaDetail(_mediaId)
|
|
|
|
|
|
}
|
2025-09-13 12:16:07 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-09-01 21:33:21 +08:00
|
|
|
|
// 初始化地图
|
|
|
|
|
|
const loadMap = () => {
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
|
// 设置安全密钥
|
|
|
|
|
|
window._AMapSecurityConfig = {
|
2025-09-09 14:52:18 +08:00
|
|
|
|
securityJsCode: secretKey
|
2025-09-01 21:33:21 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
AMapLoader.load({
|
2025-09-09 14:52:18 +08:00
|
|
|
|
key: apiKey,
|
2025-09-13 12:16:07 +08:00
|
|
|
|
plugins: ["AMap.PlaceSearch"],
|
|
|
|
|
|
AMapUI: {
|
2025-09-01 21:33:21 +08:00
|
|
|
|
plugins: []
|
|
|
|
|
|
}
|
|
|
|
|
|
}).then(AMap => {
|
|
|
|
|
|
// 根据当前模式设置初始参数
|
|
|
|
|
|
const initialPitch = mapMode.value === '3D' ? 65 : 0;
|
|
|
|
|
|
const initialRotation = mapMode.value === '3D' ? -15 : 0;
|
|
|
|
|
|
|
|
|
|
|
|
mapInstance.value = new AMap.Map("mapContainer", {
|
|
|
|
|
|
resizeEnable: true,
|
|
|
|
|
|
pitch: initialPitch, // 倾斜角度决定2D/3D模式
|
|
|
|
|
|
rotation: initialRotation, // 旋转角度
|
2025-09-13 12:16:07 +08:00
|
|
|
|
zoom: 16,
|
|
|
|
|
|
zooms: [3, 16],
|
2025-09-01 21:33:21 +08:00
|
|
|
|
viewMode: mapMode.value // 启用3D视图
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2025-09-13 12:16:07 +08:00
|
|
|
|
// // 先添加基本控件
|
|
|
|
|
|
mapInstance.value.setZoom(16);
|
2025-09-01 21:33:21 +08:00
|
|
|
|
|
|
|
|
|
|
// 添加自定义控件容器
|
|
|
|
|
|
addCustomControls(AMap);
|
|
|
|
|
|
|
|
|
|
|
|
// 地图加载完成后隐藏Logo
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
hideAmapLogo();
|
|
|
|
|
|
}, 1000);
|
|
|
|
|
|
|
|
|
|
|
|
// 监听地图渲染完成事件
|
|
|
|
|
|
mapInstance.value.on('render', hideAmapLogo);
|
|
|
|
|
|
|
2025-09-13 12:16:07 +08:00
|
|
|
|
// 添加缩放变化监听
|
|
|
|
|
|
mapInstance.value.on('zoomchange', handleZoomChange);
|
|
|
|
|
|
|
2025-09-13 22:24:35 +08:00
|
|
|
|
//// 在地图完全加载后执行点数据处理
|
|
|
|
|
|
//renderMassMarks();
|
2025-09-01 21:33:21 +08:00
|
|
|
|
|
|
|
|
|
|
resolve();
|
|
|
|
|
|
}).catch(e => {
|
|
|
|
|
|
console.log(e, "高德地图加载失败");
|
|
|
|
|
|
reject(e);
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2025-09-13 12:16:07 +08:00
|
|
|
|
// 处理地图缩放事件
|
|
|
|
|
|
const handleZoomChange = () => {
|
|
|
|
|
|
const currentZoomLevel = mapInstance.value.getZoom();
|
|
|
|
|
|
// 如果缩放级别超过16,自动调整回16
|
|
|
|
|
|
if (currentZoomLevel > 16) {
|
|
|
|
|
|
mapInstance.value.setZoom(16);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-09-01 21:33:21 +08:00
|
|
|
|
// 添加自定义控件
|
|
|
|
|
|
const addCustomControls = (AMap) => {
|
|
|
|
|
|
// 创建控件容器
|
|
|
|
|
|
const controlContainer = document.createElement('div');
|
2025-09-13 12:16:07 +08:00
|
|
|
|
controlContainer.className = 'custom-map-controls';
|
2025-09-01 21:33:21 +08:00
|
|
|
|
|
|
|
|
|
|
// 2D/3D切换按钮
|
|
|
|
|
|
const toggle2D3DBtn = document.createElement('div');
|
|
|
|
|
|
toggle2D3DBtn.className = mapMode.value === '2D' ? 'map-control-btn map-control-3dbtn' : 'map-control-btn map-control-2dbtn';
|
|
|
|
|
|
toggle2D3DBtn.onclick = toggle2D3DMode;
|
|
|
|
|
|
|
|
|
|
|
|
// 全屏按钮
|
|
|
|
|
|
const fullscreenBtn = document.createElement('div');
|
|
|
|
|
|
fullscreenBtn.className = isFullscreen.value === true ? 'map-control-btn map-full-screen' : 'map-control-btn map-nofull-screen';
|
|
|
|
|
|
fullscreenBtn.onclick = toggleFullscreen;
|
|
|
|
|
|
|
|
|
|
|
|
controlContainer.appendChild(toggle2D3DBtn);
|
|
|
|
|
|
controlContainer.appendChild(fullscreenBtn);
|
|
|
|
|
|
|
|
|
|
|
|
// 添加到地图容器
|
|
|
|
|
|
document.getElementById('mapContainer').appendChild(controlContainer);
|
|
|
|
|
|
}
|
|
|
|
|
|
// 切换2D/3D模式
|
|
|
|
|
|
const toggle2D3DMode = () => {
|
|
|
|
|
|
if (!mapInstance.value) return;
|
|
|
|
|
|
|
|
|
|
|
|
const currentPitch = mapInstance.value.getPitch();
|
|
|
|
|
|
|
|
|
|
|
|
if (currentPitch === 0) {
|
|
|
|
|
|
// 切换到3D模式
|
|
|
|
|
|
mapInstance.value.setPitch(65);
|
|
|
|
|
|
mapInstance.value.setRotation(-15);
|
|
|
|
|
|
mapMode.value = '3D';
|
|
|
|
|
|
loadMap()
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 切换到2D模式
|
|
|
|
|
|
mapInstance.value.setPitch(0);
|
|
|
|
|
|
mapInstance.value.setRotation(0);
|
|
|
|
|
|
mapMode.value = '2D';
|
|
|
|
|
|
loadMap()
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-13 12:16:07 +08:00
|
|
|
|
}
|
2025-09-01 21:33:21 +08:00
|
|
|
|
// 切换全屏模式
|
|
|
|
|
|
const toggleFullscreen = () => {
|
|
|
|
|
|
const mapContainer = document.getElementById('mapContainer');
|
|
|
|
|
|
|
|
|
|
|
|
if (!document.fullscreenElement) {
|
|
|
|
|
|
// 进入全屏
|
|
|
|
|
|
if (mapContainer.requestFullscreen) {
|
|
|
|
|
|
mapContainer.requestFullscreen().then(() => {
|
|
|
|
|
|
isFullscreen.value = true;
|
|
|
|
|
|
const buttons = document.querySelectorAll('.map-control-btn');
|
|
|
|
|
|
buttons[1].className = 'map-control-btn map-full-screen';
|
|
|
|
|
|
}).catch(err => {
|
|
|
|
|
|
console.error('全屏模式错误:', err);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 退出全屏
|
|
|
|
|
|
if (document.exitFullscreen) {
|
|
|
|
|
|
document.exitFullscreen().then(() => {
|
|
|
|
|
|
isFullscreen.value = false;
|
|
|
|
|
|
const buttons = document.querySelectorAll('.map-control-btn');
|
|
|
|
|
|
buttons[1].className = 'map-control-btn map-nofull-screen';
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
// 监听全屏变化事件
|
|
|
|
|
|
document.addEventListener('fullscreenchange', () => {
|
|
|
|
|
|
if (!document.fullscreenElement) {
|
|
|
|
|
|
isFullscreen.value = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
// 创建自定义点样式
|
|
|
|
|
|
const createPointStyle = (color, size, styleType) => {
|
|
|
|
|
|
const canvas = document.createElement('canvas');
|
|
|
|
|
|
canvas.width = size * 2;
|
|
|
|
|
|
canvas.height = size * 2;
|
|
|
|
|
|
const ctx = canvas.getContext('2d');
|
|
|
|
|
|
|
|
|
|
|
|
// 根据样式类型绘制不同的图形
|
|
|
|
|
|
switch (styleType) {
|
|
|
|
|
|
case 'circle':
|
|
|
|
|
|
ctx.beginPath();
|
|
|
|
|
|
ctx.arc(size, size, size, 0, Math.PI * 2);
|
|
|
|
|
|
ctx.fillStyle = color;
|
|
|
|
|
|
ctx.fill();
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'ring':
|
|
|
|
|
|
ctx.beginPath();
|
|
|
|
|
|
ctx.arc(size, size, size, 0, Math.PI * 2);
|
|
|
|
|
|
ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
|
|
|
|
|
|
ctx.fill();
|
|
|
|
|
|
|
|
|
|
|
|
ctx.beginPath();
|
|
|
|
|
|
ctx.arc(size, size, size * 0.7, 0, Math.PI * 2);
|
|
|
|
|
|
ctx.fillStyle = color;
|
|
|
|
|
|
ctx.fill();
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'square':
|
|
|
|
|
|
ctx.fillStyle = color;
|
|
|
|
|
|
ctx.fillRect(0, 0, size * 2, size * 2);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'star':
|
|
|
|
|
|
ctx.fillStyle = color;
|
|
|
|
|
|
ctx.beginPath();
|
|
|
|
|
|
for (let i = 0; i < 5; i++) {
|
|
|
|
|
|
const angle = (i * 2 * Math.PI / 5) - Math.PI / 2;
|
|
|
|
|
|
const x = size + size * Math.cos(angle);
|
|
|
|
|
|
const y = size + size * Math.sin(angle);
|
|
|
|
|
|
if (i === 0) {
|
|
|
|
|
|
ctx.moveTo(x, y);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
ctx.lineTo(x, y);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const innerAngle = angle + Math.PI / 5;
|
|
|
|
|
|
const innerX = size + size * 0.4 * Math.cos(innerAngle);
|
|
|
|
|
|
const innerY = size + size * 0.4 * Math.sin(innerAngle);
|
|
|
|
|
|
ctx.lineTo(innerX, innerY);
|
|
|
|
|
|
}
|
|
|
|
|
|
ctx.closePath();
|
|
|
|
|
|
ctx.fill();
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return canvas;
|
|
|
|
|
|
}
|
|
|
|
|
|
// 渲染海量点
|
|
|
|
|
|
const renderMassMarks = () => {
|
|
|
|
|
|
// 清除现有的海量点
|
|
|
|
|
|
if (massMarks.value) {
|
|
|
|
|
|
massMarks.value.clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 创建三种不同大小的样式
|
|
|
|
|
|
const styles = [
|
2025-09-01 23:00:15 +08:00
|
|
|
|
// 优势媒体颜色-红色
|
2025-09-01 21:33:21 +08:00
|
|
|
|
{
|
|
|
|
|
|
url: createPointStyle('#EC1B60', 18, 'circle').toDataURL(),
|
|
|
|
|
|
anchor: new AMap.Pixel(18, 18),
|
|
|
|
|
|
size: new AMap.Size(18, 18)
|
|
|
|
|
|
},
|
2025-09-01 23:00:15 +08:00
|
|
|
|
// 网络媒体颜色-蓝色
|
2025-09-01 21:33:21 +08:00
|
|
|
|
{
|
|
|
|
|
|
url: createPointStyle('#058DED', 18, 'circle').toDataURL(),
|
|
|
|
|
|
anchor: new AMap.Pixel(18, 18),
|
|
|
|
|
|
size: new AMap.Size(18, 18)
|
|
|
|
|
|
},
|
|
|
|
|
|
];
|
2025-09-13 12:16:07 +08:00
|
|
|
|
// 调用接口,获取数据点
|
|
|
|
|
|
points.value = []
|
2025-09-13 22:24:35 +08:00
|
|
|
|
outdoorMediaList.value.forEach(itemPoint => {
|
|
|
|
|
|
console.log('itemPoint', itemPoint)
|
|
|
|
|
|
if (itemPoint.businessType == 1) points.value.push({ "lnglat": [itemPoint.mapX, itemPoint.mapY], "name": itemPoint.mediaName, "mediaId": itemPoint.id, "style": 0 })
|
|
|
|
|
|
if (itemPoint.businessType == 2) points.value.push({ "lnglat": [itemPoint.mapX, itemPoint.mapY], "name": itemPoint.mediaName, "mediaId": itemPoint.id, "style": 1 })
|
|
|
|
|
|
});
|
2025-09-13 12:16:07 +08:00
|
|
|
|
console.log('points', points.value)
|
2025-09-01 21:33:21 +08:00
|
|
|
|
// 创建MassMarks对象
|
2025-09-13 12:16:07 +08:00
|
|
|
|
massMarks.value = new AMap.MassMarks(points.value, {
|
2025-09-01 21:33:21 +08:00
|
|
|
|
opacity: 1,
|
|
|
|
|
|
zIndex: 111,
|
|
|
|
|
|
cursor: 'pointer',
|
|
|
|
|
|
style: styles
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 将海量点添加到地图
|
|
|
|
|
|
massMarks.value.setMap(mapInstance.value);
|
|
|
|
|
|
|
|
|
|
|
|
// 添加点击事件
|
|
|
|
|
|
massMarks.value.on('click', function (e) {
|
2025-09-13 12:16:07 +08:00
|
|
|
|
console.log('点击了节点', e.data)
|
2025-09-14 00:06:28 +08:00
|
|
|
|
handleViewMedia(e.data.mediaId)
|
2025-09-01 21:33:21 +08:00
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
// 隐藏Logo的函数
|
|
|
|
|
|
const hideAmapLogo = () => {
|
|
|
|
|
|
const logos = document.querySelectorAll('.amap-logo, .amap-copyright');
|
|
|
|
|
|
logos.forEach(logo => {
|
|
|
|
|
|
logo.style.display = 'none';
|
|
|
|
|
|
logo.style.visibility = 'hidden';
|
|
|
|
|
|
logo.style.opacity = '0';
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2025-09-03 20:21:01 +08:00
|
|
|
|
|
|
|
|
|
|
onUnmounted(() => {
|
2025-09-13 12:16:07 +08:00
|
|
|
|
if (mapInstance.value) {
|
|
|
|
|
|
mapInstance.value.destroy();
|
|
|
|
|
|
}
|
2025-09-03 20:21:01 +08:00
|
|
|
|
})
|
2025-09-01 21:33:21 +08:00
|
|
|
|
// 初始化
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
|
bgStore.setBgImage(otherbg)
|
2025-09-13 12:16:07 +08:00
|
|
|
|
getOutMediaPageList()
|
2025-09-01 21:33:21 +08:00
|
|
|
|
getMediaTypeOne()
|
|
|
|
|
|
getProvinceList()
|
|
|
|
|
|
loadMap()
|
|
|
|
|
|
});
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style lang="scss">
|
|
|
|
|
|
.noChoseLabel {
|
|
|
|
|
|
height: 24px;
|
|
|
|
|
|
line-height: 24px;
|
|
|
|
|
|
font-family: Microsoft YaHei;
|
|
|
|
|
|
font-weight: 400;
|
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
color: #ffffff90;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.mapContainer {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
background: #3f8bff;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.custom-map-controls {
|
|
|
|
|
|
position: absolute;
|
2025-09-01 23:00:15 +08:00
|
|
|
|
top: 5px;
|
|
|
|
|
|
right: 5px;
|
2025-09-01 21:33:21 +08:00
|
|
|
|
z-index: 1000;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
2025-09-01 23:00:15 +08:00
|
|
|
|
gap: 0px;
|
2025-09-01 21:33:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.map-control-btn {
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.map-control-2dbtn {
|
|
|
|
|
|
width: 40px;
|
|
|
|
|
|
height: 40px;
|
|
|
|
|
|
background: url('../../assets/images/icon-2D-btn.png');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.map-control-2dbtn:hover {
|
|
|
|
|
|
background: url('../../assets/images/icon-2D-active-btn.png');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.map-control-3dbtn {
|
|
|
|
|
|
width: 40px;
|
|
|
|
|
|
height: 40px;
|
|
|
|
|
|
background: url('../../assets/images/icon-3D-btn.png');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.map-control-3dbtn:hover {
|
|
|
|
|
|
background: url('../../assets/images/icon-3D-active-btn.png');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.map-nofull-screen {
|
|
|
|
|
|
width: 40px;
|
|
|
|
|
|
height: 40px;
|
|
|
|
|
|
background: url('../../assets/images/icon-full-screen.png');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.map-nofull-screen:hover {
|
|
|
|
|
|
background: url('../../assets/images/icon-full-screen-active.png');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.map-full-screen {
|
|
|
|
|
|
width: 40px;
|
|
|
|
|
|
height: 40px;
|
|
|
|
|
|
background: url('../../assets/images/icon-map-nofull-screen.png');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.map-full-screen:hover {
|
|
|
|
|
|
background: url('../../assets/images/icon-map-nofull-screen-active.png');
|
|
|
|
|
|
}
|
2025-09-13 12:16:07 +08:00
|
|
|
|
|
2025-09-01 21:33:21 +08:00
|
|
|
|
/* 全屏样式 */
|
|
|
|
|
|
.mapContainer:-webkit-full-screen {
|
|
|
|
|
|
width: 100% !important;
|
|
|
|
|
|
height: 100% !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.mapContainer:-moz-full-screen {
|
|
|
|
|
|
width: 100% !important;
|
|
|
|
|
|
height: 100% !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.mapContainer:-ms-fullscreen {
|
|
|
|
|
|
width: 100% !important;
|
|
|
|
|
|
height: 100% !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.mapContainer:fullscreen {
|
|
|
|
|
|
width: 100% !important;
|
|
|
|
|
|
height: 100% !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|