BUG 25647
This commit is contained in:
@@ -3,31 +3,34 @@
|
|||||||
<div class="grid-select">
|
<div class="grid-select">
|
||||||
<span class="label">网格选择</span>
|
<span class="label">网格选择</span>
|
||||||
<div class="value">
|
<div class="value">
|
||||||
<AiTreePicker :ops="treeList" v-model="form.id" @select="handerSelect">
|
<AiTreePicker :ops="treeList" v-model="form.id" @select="handleSelect">
|
||||||
<div class="grid-name" :style="{ color: form.girdName ? '' : '#c0c4cc' }">{{form.girdName || '请选择社区居委会'}} <u-icon name="arrow-right" color="#cccccc" size="14"></u-icon></div>
|
<div class="grid-name" :style="{ color: form.girdName ? '' : '#c0c4cc' }">{{ form.girdName || '请选择社区居委会' }}
|
||||||
</AiTreePicker>
|
<u-icon name="arrow-right" color="#cccccc" size="14"></u-icon>
|
||||||
|
</div>
|
||||||
|
</AiTreePicker>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="map-content">
|
<div class="map-content">
|
||||||
<AiTMap v-if="areaId" :areaId="areaId" :map.sync="map" :lib.sync="lib" :ops="ops" :libraries="['service', 'tools']"></AiTMap>
|
<AiTMap ref="AiTMap" :map.sync="map" :lib.sync="lib" :libraries="['service', 'tools']"/>
|
||||||
</div>
|
</div>
|
||||||
<u-popup v-model="show" mode="bottom" border-radius="14">
|
<u-popup v-model="show" mode="bottom" border-radius="14">
|
||||||
<div class="popup">
|
<div class="popup">
|
||||||
<div class="bg"></div>
|
<div class="bg"></div>
|
||||||
<div class="title">{{form.girdName}}</div>
|
<div class="title">{{ form.girdName }}</div>
|
||||||
<div class="info-flex">
|
<div class="info-flex">
|
||||||
<span class="label">网格类型</span>
|
<span class="label">网格类型</span>
|
||||||
<span class="value">{{$dict.getLabel('girdType', form.girdType)}}</span>
|
<span class="value">{{ $dict.getLabel('girdType', form.girdType) }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="info-flex">
|
<div class="info-flex">
|
||||||
<span class="label">网格层级</span>
|
<span class="label">网格层级</span>
|
||||||
<span class="value">{{$dict.getLabel('girdLevel', form.girdLevel)}}</span>
|
<span class="value">{{ $dict.getLabel('girdLevel', form.girdLevel) }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="form.girdMemberList && form.girdMemberList.length">
|
<div v-if="form.girdMemberList && form.girdMemberList.length">
|
||||||
<div class="info-flex" v-for="(item, index) in form.girdMemberList" :key="index">
|
<div class="info-flex" v-for="(item, index) in form.girdMemberList" :key="index">
|
||||||
<span class="label">网格管理员</span>
|
<span class="label">网格管理员</span>
|
||||||
<span class="value">{{item.name}} {{item.phone}}
|
<span class="value">{{ item.name }} {{ item.phone }}
|
||||||
<img :src="$cdn + 'common/phone.png'" alt="" @click="callPhone(item.phone)" class="phone-icon" v-if="item.phone">
|
<img :src="$cdn + 'common/phone.png'" alt="" @click="callPhone(item.phone)" class="phone-icon"
|
||||||
|
v-if="item.phone">
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -35,120 +38,123 @@
|
|||||||
</div>
|
</div>
|
||||||
</u-popup>
|
</u-popup>
|
||||||
|
|
||||||
<div class="footer" @click="view" v-if="form.id && !show">
|
<div class="footer" @click="show=true" v-if="form.id && !show">
|
||||||
<div class="btn">查看网格信息</div>
|
<div class="btn">查看网格信息</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapState } from 'vuex'
|
import {mapState} from 'vuex'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
areaId: '',
|
areaId: '',
|
||||||
ops: {},
|
lib: null,
|
||||||
lib: '',
|
|
||||||
map: null,
|
map: null,
|
||||||
show: false,
|
show: false,
|
||||||
form: {girdName: '', id: ''},
|
form: {girdName: '', id: ''},
|
||||||
treeList: [],
|
treeList: [],
|
||||||
showSelect: false,
|
showSelect: false,
|
||||||
editor: null,
|
editor: null,
|
||||||
|
polygons: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: { ...mapState(['user']) },
|
computed: {...mapState(['user'])},
|
||||||
created() {
|
created() {
|
||||||
this.$dict.load('girdType', 'girdLevel')
|
this.$dict.load('girdType', 'girdLevel')
|
||||||
this.areaId = this.user.areaId
|
this.areaId = this.user.areaId
|
||||||
this.getTreeList()
|
this.getLeafNodes()
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
callPhone(phone) {
|
getLeafNodes() {
|
||||||
uni.makePhoneCall({ phoneNumber: phone })
|
this.$http.post(`/app/appgirdinfo/queryGirdMemberGirdsById`).then((res) => {
|
||||||
},
|
if (res?.data) {
|
||||||
handerSelect(e) {
|
let arr = []
|
||||||
console.log(e)
|
|
||||||
this.form = e
|
|
||||||
this.initMap(e.points)
|
|
||||||
},
|
|
||||||
initMap(points) {
|
|
||||||
if(points && points.length) {
|
|
||||||
//初始化地图
|
|
||||||
this.$nextTick(() =>{
|
|
||||||
let {lib: TMap, map} = this
|
|
||||||
var center = new TMap.LatLng(points[0].lat, points[0].lng)
|
|
||||||
map.setCenter(center)
|
|
||||||
map.setZoom(15)
|
|
||||||
|
|
||||||
console.log(points)
|
|
||||||
var simplePath = []
|
|
||||||
|
|
||||||
points.map((item) => {
|
|
||||||
var info = new TMap.LatLng(item.lat, item.lng)
|
|
||||||
simplePath.push(info)
|
|
||||||
})
|
|
||||||
|
|
||||||
// 初始化几何图形及编辑器
|
|
||||||
this.editor = new TMap.tools.GeometryEditor({
|
|
||||||
map, // 编辑器绑定的地图对象
|
|
||||||
overlayList: [ // 可编辑图层
|
|
||||||
{
|
|
||||||
overlay: new TMap.MultiPolygon({
|
|
||||||
map,
|
|
||||||
styles: {
|
|
||||||
highlight: new TMap.PolygonStyle({
|
|
||||||
color: 'rgba(255, 255, 0, 0.6)'
|
|
||||||
})
|
|
||||||
},
|
|
||||||
geometries: [
|
|
||||||
{
|
|
||||||
paths: simplePath
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}),
|
|
||||||
id: 'polygon',
|
|
||||||
selectedStyleId: 'highlight'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
actionMode: TMap.tools.constants.EDITOR_ACTION.INTERACT, // 编辑器的工作模式
|
|
||||||
activeOverlayId: 'polygon', // 激活图层
|
|
||||||
selectable: true, // 开启点选功能
|
|
||||||
snappable: true // 开启吸附
|
|
||||||
});
|
|
||||||
|
|
||||||
})
|
|
||||||
}else {
|
|
||||||
return this.$u.toast('该网格未绘制')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getTreeList() {
|
|
||||||
this.$http.post(`/app/appgirdinfo/listAll`).then((res) => {
|
|
||||||
if (res.code == 0) {
|
|
||||||
this.treeList = res.data
|
this.treeList = res.data
|
||||||
|
res.data.forEach(e => {
|
||||||
|
if (e.points?.length > 0) {
|
||||||
|
arr.push(e.points.map(p => [p.lng, p.lat]))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.renderGridMap(arr)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
view() {
|
renderGridMap(paths, count = 0) {
|
||||||
this.show = true
|
let {map, lib: TMap, $refs: {AiTMap: {fitBounds}}} = this
|
||||||
}
|
if (TMap) {
|
||||||
|
const colors = ["#A194F4", "#7CBDF3", "#F3A57D", "#62D063", "#58DBDA", "#F7D151"]
|
||||||
|
if (this.polygons.length > 0) {
|
||||||
|
this.polygons.forEach(e => e.destroy())
|
||||||
|
this.polygons = []
|
||||||
|
}
|
||||||
|
let bounds = []
|
||||||
|
paths.forEach((path, i) => {
|
||||||
|
let color = colors[i % colors.length]
|
||||||
|
let polygon = new TMap.MultiPolygon({
|
||||||
|
map, styles: {
|
||||||
|
default: new TMap.PolygonStyle({
|
||||||
|
showBorder: true,
|
||||||
|
borderColor: color,
|
||||||
|
borderWidth: 2,
|
||||||
|
color: this.$colorUtils.Hex2RGBA(color, 0.1),
|
||||||
|
borderDashArray: [10, 10]
|
||||||
|
})
|
||||||
|
},
|
||||||
|
geometries: [{paths: path.map(e => new TMap.LatLng(e[1], e[0]))}]
|
||||||
|
})
|
||||||
|
this.polygons.push(polygon)
|
||||||
|
bounds.push(fitBounds(path.map(e => new TMap.LatLng(e[1], e[0]))))
|
||||||
|
})
|
||||||
|
bounds = bounds.reduce((a, b) => {
|
||||||
|
return fitBounds([
|
||||||
|
a.getNorthEast(),
|
||||||
|
a.getSouthWest(),
|
||||||
|
b.getNorthEast(),
|
||||||
|
b.getSouthWest(),
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
map.fitBounds(bounds, {padding: 100})
|
||||||
|
} else {
|
||||||
|
if (count < 5) {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.renderGridMap(paths, ++count)
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
callPhone(phone) {
|
||||||
|
uni.makePhoneCall({phoneNumber: phone})
|
||||||
|
},
|
||||||
|
handleSelect(e) {
|
||||||
|
if (e?.points?.length > 0) {
|
||||||
|
this.form = e
|
||||||
|
let path = e.points?.map(p => [p.lng, p.lat]) || []
|
||||||
|
this.renderGridMap([path])
|
||||||
|
} else {
|
||||||
|
this.$u.toast("所选网格没有标绘!")
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
::v-deep uni-page-body{
|
::v-deep uni-page-body {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
ai-tree-picker{
|
|
||||||
|
ai-tree-picker {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.detail {
|
.detail {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
.grid-select{
|
|
||||||
|
.grid-select {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 34px 32px;
|
padding: 34px 32px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@@ -157,32 +163,39 @@ ai-tree-picker{
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
line-height: 44px;
|
line-height: 44px;
|
||||||
color: #333;
|
color: #333;
|
||||||
.label{
|
|
||||||
|
.label {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 140px;
|
width: 140px;
|
||||||
font-size: 32px;
|
font-size: 32px;
|
||||||
}
|
}
|
||||||
.value{
|
|
||||||
|
.value {
|
||||||
font-size: 28px;
|
font-size: 28px;
|
||||||
.u-icon{
|
|
||||||
|
.u-icon {
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.map-content{
|
|
||||||
|
.map-content {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: calc(100% - 112px);
|
height: calc(100% - 112px);
|
||||||
}
|
}
|
||||||
.popup{
|
|
||||||
|
.popup {
|
||||||
padding: 0 32px 16px;
|
padding: 0 32px 16px;
|
||||||
.bg{
|
|
||||||
|
.bg {
|
||||||
width: 64px;
|
width: 64px;
|
||||||
height: 10px;
|
height: 10px;
|
||||||
background: #CCC;
|
background: #CCC;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
margin: 32px 0 32px 344px;
|
margin: 32px 0 32px 344px;
|
||||||
}
|
}
|
||||||
.title{
|
|
||||||
|
.title {
|
||||||
font-size: 36px;
|
font-size: 36px;
|
||||||
font-family: PingFang-SC-Heavy, PingFang-SC;
|
font-family: PingFang-SC-Heavy, PingFang-SC;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
@@ -190,22 +203,26 @@ ai-tree-picker{
|
|||||||
line-height: 50px;
|
line-height: 50px;
|
||||||
margin-bottom: 24px;
|
margin-bottom: 24px;
|
||||||
}
|
}
|
||||||
.info-flex{
|
|
||||||
|
.info-flex {
|
||||||
padding: 26px 0 30px 0;
|
padding: 26px 0 30px 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-bottom: 1px solid #D8DDE6;
|
border-bottom: 1px solid #D8DDE6;
|
||||||
line-height: 40px;
|
line-height: 40px;
|
||||||
font-size: 28px;
|
font-size: 28px;
|
||||||
.label{
|
|
||||||
|
.label {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 160px;
|
width: 160px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
color: #333;
|
color: #333;
|
||||||
}
|
}
|
||||||
.value{
|
|
||||||
|
.value {
|
||||||
color: #666;
|
color: #666;
|
||||||
font-size: 26px;
|
font-size: 26px;
|
||||||
.phone-icon{
|
|
||||||
|
.phone-icon {
|
||||||
width: 40px;
|
width: 40px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
vertical-align: sub;
|
vertical-align: sub;
|
||||||
@@ -215,10 +232,12 @@ ai-tree-picker{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.grid-name{
|
|
||||||
|
.grid-name {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
.footer{
|
|
||||||
|
.footer {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
@@ -231,7 +250,8 @@ ai-tree-picker{
|
|||||||
height: 112px;
|
height: 112px;
|
||||||
line-height: 112px;
|
line-height: 112px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
.btn{
|
|
||||||
|
.btn {
|
||||||
flex: 2;
|
flex: 2;
|
||||||
background: #1365DD;
|
background: #1365DD;
|
||||||
color: #FFF;
|
color: #FFF;
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ const calcAge = (code) => {
|
|||||||
return Math.ceil($moment().year() - $moment(birthday).year())
|
return Math.ceil($moment().year() - $moment(birthday).year())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
dict,
|
dict,
|
||||||
confirm,
|
confirm,
|
||||||
@@ -52,5 +51,27 @@ export default {
|
|||||||
},
|
},
|
||||||
hideLoading: () => {
|
hideLoading: () => {
|
||||||
uni.hideLoading()
|
uni.hideLoading()
|
||||||
|
},
|
||||||
|
colorUtils: {
|
||||||
|
Hex2RGBA(color, alpha = 1) {
|
||||||
|
let hex = 0;
|
||||||
|
if (color.charAt(0) == "#") {
|
||||||
|
if (color.length == 4) {
|
||||||
|
//检测诸如#FFF简写格式
|
||||||
|
color = "#" + color.charAt(1).repeat(2) +
|
||||||
|
color.charAt(2).repeat(2) +
|
||||||
|
color.charAt(3).repeat(2);
|
||||||
|
}
|
||||||
|
hex = parseInt(color.slice(1), 16);
|
||||||
|
}
|
||||||
|
let r = hex >> 16 & 0xFF;
|
||||||
|
let g = hex >> 8 & 0xFF;
|
||||||
|
let b = hex & 0xFF;
|
||||||
|
return `rgba(${r},${g},${b},${alpha})`;
|
||||||
|
},
|
||||||
|
RGBtoHex(r, g, b) {
|
||||||
|
let hex = r << 16 | g << 8 | b;
|
||||||
|
return "#" + hex.toString(16);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,10 +59,10 @@ export default {
|
|||||||
this.$emit('update:map', this.tmap)
|
this.$emit('update:map', this.tmap)
|
||||||
this.areaId && this.getMapArea()
|
this.areaId && this.getMapArea()
|
||||||
},
|
},
|
||||||
getMapArea() {
|
fitBounds(latLngList, count = 0) {
|
||||||
let {mapLib, areaId, tmap: map} = this, keyword = areaId.substring(0, 6)
|
// 由多边形顶点坐标数组计算能完整呈现该多边形的最小矩形范围
|
||||||
const fitBounds = (latLngList) => {
|
let {mapLib: TMap} = this
|
||||||
// 由多边形顶点坐标数组计算能完整呈现该多边形的最小矩形范围
|
if (TMap) {
|
||||||
if (latLngList.length === 0) {
|
if (latLngList.length === 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -80,7 +80,14 @@ export default {
|
|||||||
new TMap.LatLng(boundsS, boundsW),
|
new TMap.LatLng(boundsS, boundsW),
|
||||||
new TMap.LatLng(boundsN, boundsE)
|
new TMap.LatLng(boundsN, boundsE)
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
if (count < 5) {
|
||||||
|
this.fitBounds(latLngList, ++count)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
getMapArea() {
|
||||||
|
let {mapLib, areaId, tmap: map} = this, keyword = areaId.substring(0, 6)
|
||||||
let polygons = new TMap.MultiPolygon({map, geometries: []});
|
let polygons = new TMap.MultiPolygon({map, geometries: []});
|
||||||
new mapLib.service.District({
|
new mapLib.service.District({
|
||||||
polygon: 2,
|
polygon: 2,
|
||||||
@@ -93,14 +100,14 @@ export default {
|
|||||||
level.forEach((place) => {
|
level.forEach((place) => {
|
||||||
let bounds = [];
|
let bounds = [];
|
||||||
let newGeometries = place.polygon.map((polygon, index) => {
|
let newGeometries = place.polygon.map((polygon, index) => {
|
||||||
bounds.push(fitBounds(polygon)); // 计算能完整呈现行政区边界的最小矩形范围
|
bounds.push(this.fitBounds(polygon)); // 计算能完整呈现行政区边界的最小矩形范围
|
||||||
return {
|
return {
|
||||||
id: `${place.id}_${index}`,
|
id: `${place.id}_${index}`,
|
||||||
paths: polygon, // 将得到的行政区划边界用多边形标注在地图上
|
paths: polygon, // 将得到的行政区划边界用多边形标注在地图上
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
bounds = bounds.reduce((a, b) => {
|
bounds = bounds.reduce((a, b) => {
|
||||||
return fitBounds([
|
return this.fitBounds([
|
||||||
a.getNorthEast(),
|
a.getNorthEast(),
|
||||||
a.getSouthWest(),
|
a.getSouthWest(),
|
||||||
b.getNorthEast(),
|
b.getNorthEast(),
|
||||||
|
|||||||
Reference in New Issue
Block a user