Files
dvcp_v2_webapp/packages/bigscreen/dv/AppHouseMapDv.vue
2022-12-01 09:35:20 +08:00

813 lines
18 KiB
Vue

<template>
<div style="height:100%;" class="AppHouseMapDv">
<div class="map">
<div id="map" ref="rootmap" @click="hidePopup"/>
<div class="community-info" v-show="isShowInfo">
<div class="community-info__close" title="关闭" @click="info = {}, isShowInfo = false,chooseBuildId=''">
<i class="iconClean iconfont"></i>
</div>
<div class="community-info__header">
<h2 v-if="!info.name">{{ info.createAddress }}</h2>
<h2 v-if="info.name">{{ info.homesteadAddress }}</h2>
<div>{{ info.lng }},{{ info.lat }}</div>
</div>
<div class="community-info__wrapper" v-if="info.name">
<h2>户主信息</h2>
<div class="community-info__item">
<label>所属村</label>
<span>{{ info.areaName }}</span>
</div>
<div class="community-info__item">
<label>姓名</label>
<span style="color:#2266FF;">{{ info.name }}</span>
</div>
<div class="community-info__item">
<label>联系电话</label>
<span style="color:#2266FF;">{{ info.phone }}</span>
</div>
<div class="community-info__item">
<label>性别</label>
<span>{{ info.sex == 1 ? '男' : '女' }}</span>
</div>
<div class="community-info__item">
<label>年龄</label>
<span>{{ info.age }}</span>
</div>
</div>
<div class="community-info__wrapper" v-if="info.name">
<h2>宅基地信息</h2>
<div class="community-info__item">
<label>住宅建筑面积</label>
<span>{{ info.liveBuildingArea }}</span>
</div>
<div class="community-info__item">
<label>建筑层数</label>
<span>{{ info.buildingFloorNumber }}</span>
</div>
<div class="community-info__item">
<label>建筑高度</label>
<span>{{ info.buildingHeight }}m</span>
</div>
</div>
<div class="community-info__wrapper" v-if="!info.name">
<h2>房屋信息</h2>
<div class="community-info__item">
<label>所属社区</label>
<span>{{ info.areaName }}</span>
</div>
<div class="community-info__item">
<label>所属小区</label>
<span>{{ info.communityName }}</span>
</div>
<div class="community-info__item">
<label>房屋类型</label>
<span>{{ dict.getLabel("communityBuildingType", info.buildingType) }}</span>
</div>
<div class="community-info__item">
<label>楼长姓名</label>
<span>{{ info.managerName }}</span>
</div>
<div class="community-info__item">
<label>楼长电话</label>
<span>{{ info.managerPhone }}</span>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import AMapLoader from '@amap/amap-jsapi-loader'
import {mapState} from 'vuex'
export default {
name: 'AppHouseMapDv',
label: '房屋地图',
provide() {
return {
root: this
}
},
props: {
instance: Function,
dict: Object
},
data() {
return {
map: null,
mapLib: null,
community: '',
areaData: {},
isShowInfo: false,
areaId: '',
areaName: '',
list: [],
info: {},
resident: null,
satellite: null,
zoom: 11,
chooseBuildId: '',
buildList: [],
searchList: [],
house: null,
center: [],
type: '',
showStatistics: false
}
},
computed: {
...mapState(['user'])
},
watch: {
community: {
deep: true,
handler() {
this.debounce(this.search, 500)
}
},
showStatistics: {
deep: true,
handler() {
this.debounce(this.getCorpLocation, 500)
}
},
},
created() {
this.dict.load('householdRelation', 'communityBuildingType')
},
mounted() {
this.areaId = this.user.info.areaId
this.areaName = this.user.info.areaName
this.getCorpLocation()
},
methods: {
getCorpLocation() {
if (this.showStatistics) {
return
}
this.instance.post("/app/appdvcpconfig/getCorpLocation").then(res => {
if (res.code == 0) {
this.initMap(res.data)
}
})
},
changeZoom(isAdd) {
const zoom = isAdd ? this.map.getZoom() + 1 : this.map.getZoom() - 1
this.map.setZoom(zoom, false, 600)
},
getBuildInfo(id, type) {
var url = `/app/apphomesteadinfo/queryDetailById?id=${id}`
if (type == 0) {
url = `/app/appcommunityhouseinfo/queryDetailByIdWithBuilding?buildId=${id}`
}
this.instance.post(url).then(res => {
if (res.code === 0) {
if (type == 1) {
this.info = res.data
} else {
this.info = res.data.build
this.resident = null;
}
this.$nextTick(() => {
this.isShowInfo = true
})
}
})
},
chooseCommunity(item) {
if (item.name) { //宅基地
if (!item.lng || !item.lat) {
return this.$message.error('未获取到该房屋坐标信息')
} else {
this.map.setZoomAndCenter(18, [item.lng, item.lat], false, 600)
this.info = item
this.$nextTick(() => {
this.isShowSearch = false
this.isShowInfo = true
})
}
} else { //楼栋
this.instance.post(`/app/appcommunityhouseinfo/queryDetailByIdWithBuilding`, null, {
params: {
buildId: item.buildingId,
houseId: item.id,
residentId: item.residentId
}
}).then(res => {
if (res.code === 0) {
if (!res.data.build?.lng || !res.data.build?.lat) {
this.isShowInfo = true
this.isShowSearch = false
this.info = res.data.build;
return this.$message.error('未获取到该房屋坐标信息')
} else {
this.chooseBuildId = res.data.build.id
this.house = res.data.house
this.resident = res.data.resident;
}
this.map.setZoomAndCenter(18, [res.data.build?.lng, res.data.build?.lat], false, 600)
this.info = res.data.build
this.$nextTick(() => {
this.isShowSearch = false
this.isShowInfo = true
})
}
})
}
},
toCenter() {
this.map.setZoomAndCenter(this.zoom, this.center, false, 600)
},
renderClusterMarker(context) {
let el = `<div class="polymeric">
<div class="polymeric-container">
<p>${context.count}</p>
</div>
</div>`
let {mapLib: AMap} = this
let offset = new AMap.Pixel(-9, -9)
context.marker.setContent(el)
context.marker.setOffset(offset)
context.marker.lnglat = context.clusterData[0].lnglat
context.marker.on('click', e => {
this.map.setZoomAndCenter(this.map.getZoom() + 2, e.target.lnglat, false, 500)
})
},
renderMarker(context) {
const buildId = context.data[0].id
let el = ''
var urlType = ''
if (context.data[0].communityName == context.data[0].buildingNumber) { //宅基地
urlType = 1
el = `<div id="buildId-${buildId}" class="mark ${buildId === this.chooseBuildId ? 'mark-active' : ''}">
<div class="mark-contaienr">
<span>${context.data[0].areaName}</span>&nbsp;&nbsp;
<span>${context.data[0].communityName}</span>
</div>
</div>`
} else {
urlType = 0
el = `<div id="buildId-${buildId}" class="mark ${buildId === this.chooseBuildId ? 'mark-active' : ''}">
<div class="mark-contaienr">
<span>${context.data[0].communityName}</span>&nbsp;&nbsp;
<span>${context.data[0].buildingNumber}栋</span>
</div>
</div>`
}
context.marker.setContent(el);
context.marker.setAnchor("center")
context.marker.id = `${buildId}`
context.marker.lnglat = context.data[0].lnglat
context.marker.urlType = urlType
context.marker.on('click', e => {
this.chooseBuildId = e.target.id
this.getBuildInfo(e.target.id, e.target.urlType)
context.marker.setContent(el);
document.querySelectorAll('.mark').forEach(el => {
el.classList.remove('mark-active')
})
document.querySelector(`#buildId-${e.target.id}`).classList.add('mark-active')
})
},
addMakert(points) {
let {mapLib: AMap} = this
new AMap.MarkerClusterer(this.map, points, {
gridSize: 60,
maxZoom: 15,
clusterByZoomChange: false,
renderClusterMarker: this.renderClusterMarker,
renderMarker: this.renderMarker
})
},
getCommunityList() {
this.instance.post('/app/appcommunitybuildinginfo/listByBuilding', null, {
params: {
current: 1,
size: 1000000
}
}).then(res => {
if (res.code === 0) {
this.buildList = res.data
const points = res.data.map(item => {
return {
lnglat: [item.lng, item.lat],
id: item.id,
corpId: item.corpId,
areaName: item.areaName,
buildingNumber: item.name || item.buildingNumber,
communityName: item.name || item.communityName,
}
})
this.addMakert(points)
}
})
},
hidePopup() {
this.isShowArea = false
this.isShowSearch = false
},
initMap({lng, lat}) {
this.center = [lng, lat];
AMapLoader.load({
key: '54a02a43d9828a8f9cd4f26fe281e74e',
version: '2.0',
plugins: ['AMap.ToolBar', 'AMap.Scale', 'AMap.MouseTool', 'AMap.MarkerClusterer'],
AMapUI: {
version: '1.1',
plugins: []
}
}).then((AMap) => {
this.mapLib = AMap
this.map = new AMap.Map('map', {
resizeEnable: true,
zooms: [6, 20],
center: [lng, lat],
zoom: this.zoom,
mapStyle: 'amap://styles/40f6fba77127e061a058f670433a67ec'
})
this.satellite = new AMap.TileLayer.Satellite()
this.getCommunityList()
})
}
}
}
</script>
<style lang="scss" scoped>
.map {
:deep( .amap-logo), :deep( .amap-copyright ){
display: none !important;
}
:deep( .amap-icon ){
width: 40px !important;
height: 40px !important;
img {
width: 100%;
height: 100%;
}
}
}
.community-info__star {
margin-top: 4px;
margin-bottom: 8px;
.community-info__star--content {
display: flex;
align-items: center;
height: 36px;
padding: 0 12px;
color: #666666;
font-size: 12px;
span {
flex: 1;
text-align: center;
&:first-child {
text-align: left;
}
&:last-child {
text-align: right;
}
}
&:nth-of-type(2n) {
background: #fff;
}
}
.community-info__star--tab {
display: flex;
align-items: center;
height: 36px;
padding: 0 12px;
user-select: none;
background: #fff;
span {
height: 100%;
line-height: 36px;
color: #999999;
font-size: 12px;
font-weight: 700;
cursor: pointer;
border-bottom: 2px solid transparent;
&:first-child {
margin-right: 16px;
}
&.star-active {
color: #2266FF;
border-bottom: 2px solid #2266FF;
}
}
}
}
.community-info__item--imgs {
display: block !important;
height: auto !important;
label {
height: 36px;
line-height: 36px;
}
.community-info__item--img {
display: flex;
align-items: center;
flex-wrap: wrap;
padding-bottom: 10px;
overflow: hidden;
img {
width: 69px;
height: 69px;
margin-right: 4px;
margin-bottom: 4px;
cursor: pointer;
&:nth-of-type(4n) {
margin-right: 0;
}
&:last-child {
margin-right: 0;
}
}
}
}
.map {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
:deep( .ol-zoom ){
display: none !important;
top: inherit !important;
bottom: 0.5em !important;
}
div {
box-sizing: border-box;
}
#map {
width: 100%;
height: 100%;
}
}
.community {
display: flex;
align-items: center;
position: relative;
height: 28px;
padding: 0 10px;
background: #0F8F64;
border-radius: 26px;
color: #fff;
font-size: 12px;
cursor: pointer;
&.color1 {
background: #2266FF;
em:after {
border-top-color: #2266FF !important;
}
}
&.color2 {
background: #F46159;
em:after {
border-top-color: #F46159 !important;
}
}
em {
position: absolute;
bottom: -6px;
left: 50%;
transform: translate(-50%, 0);
&::after {
position: absolute;
bottom: -6px;
left: 0;
width: 0;
height: 0;
border: 6px solid #0F8F64;
border-bottom-color: transparent;
border-left-color: transparent;
border-right-color: transparent;
transform: translate(-50%, 0);
overflow: hidden;
content: ' ';
}
}
i {
padding-right: 2px;
position: relative;
color: #ffc928;
font-size: 16px;
font-style: normal;
}
}
:deep( .polymeric ){
display: flex;
position: relative;
align-items: center;
justify-content: center;
width: 62px;
height: 62px;
border-radius: 50%;
cursor: pointer;
user-select: none;
&.polymeric-active {
.polymeric-container {
background: #F46159;
}
&::after {
background-color: #F46159;
}
}
&::after {
position: absolute;
z-index: -1;
width: 62px;
height: 62px;
border-radius: 50%;
-webkit-animation: warn 1s ease-out 0s infinite;
animation: warn 1s ease-out 0s infinite;
background-color: rgba(15, 143, 100, 1);
transform: translate(-50%, -50%);
content: " ";
}
.polymeric-container {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
width: 62px;
height: 62px;
border-radius: 50%;
background: rgba(15, 143, 100, 1);
p {
text-align: center;
width: 58px;
color: #fff;
font-size: 18px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
p:first-child {
font-size: 14px;
}
h2 {
color: #fff;
font-weight: normal;
font-size: 12px;
}
}
}
:deep( .mark ){
user-select: none;
cursor: pointer;
height: 32px;
border-radius: 26px;
position: relative;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
padding: 0 12px;
background: rgba(0,39,100,0.50);
border: 1px solid #36A5FF;
border-radius: 30px;
&.mark-active {
background: #004AC0;
border: 1px solid transparent;
box-shadow: inset 0 0 8px 2px #33BBFF;
}
.mark-contaienr {
color: white;
font-size: 14px;
position: relative;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
display: flex;
align-items: center;
justify-content: center;
}
.arrow {
position: absolute;
left: 50%;
transform: translateX(-50%);
bottom: -21px;
width: 0;
height: 0;
border: 12px solid transparent;
border-top: 12px solid #0F8F64;
}
}
@-webkit-keyframes warn {
0% {
transform: scale(.5);
opacity: 1
}
30% {
opacity: .5
}
to {
transform: scale(1.8);
opacity: 0
}
}
@keyframes warn {
0% {
transform: scale(.5);
opacity: 1
}
30% {
opacity: .5
}
to {
transform: scale(1.4);
opacity: 0
}
}
.community-info {
position: absolute;
top: 58px;
right: 10px;
width: 400px;
height: calc(100% - 117px);
overflow-y: auto;
overflow-x: hidden;
z-index: 111;
border-radius: 2px;
background: rgba(0,15,38,0.30);
border: 1px solid #103588;
// filter: blur(5px);
.community-info__close {
position: absolute;
right: 0;
top: 0;
padding: 16px 12px 0 12px;
font-size: 16px;
color: #fff;
cursor: pointer;
&:hover {
opacity: 0.6;
}
}
&::-webkit-scrollbar {
width: 6px;
height: 1px;
}
&::-webkit-scrollbar-thumb {
border-radius: 6px;
background: rgba(144, 147, 153, .5);
}
.community-info__header {
padding: 12px 20px;
background-image: linear-gradient(270deg, rgba(11, 158, 255, 0.2) 0%, rgba(2, 81, 227, 0.2) 100%);
h2 {
max-width: 360px;
line-height: 28px;
margin: 0;
color: #fff;
font-size: 20px;
font-weight: 600;
margin-bottom: 10px;
}
div {
display: flex;
align-items: center;
color: #D2E0FF;
font-size: 12px;
}
span {
display: block;
margin-top: 4px;
font-style: normal;
color: #82C5FF;
font-size: 14px;
}
}
.community-info__wrapper {
h2 {
margin: 20px 0 20px 20px;
padding: 0 20px;
font-size: 15px;
color: #fff;
font-weight: 600;
background: url(https://cdn.cunwuyun.cn/dvcp/ply/title-bg.png) no-repeat;
background-size: 169px 30px;
background-position-y: -5px;
background-position-x: -10px;
}
.community-info__item {
display: flex;
align-items: center;
justify-content: space-between;
margin: 0 20px;
padding: 12px 12px;
font-size: 14px;
color: #fff;
background: rgba(63, 136, 255, 0.15);
&:nth-of-type(2n) {
background: transparent;
}
span {
max-width: 70%;
text-align: right;
}
label {
flex-shrink: 1;
color: #82C5FF;
}
}
&.community-info__wrapper--last {
.community-info__item {
background: #fff;
&:nth-of-type(2n-1) {
background: #fff;
}
}
}
.bg-fff {
background-color: #fff !important;
}
}
}
</style>