123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563 |
- <template>
- <view class="jnpf-location-map">
- <u-top-tips ref="uTips" />
- <view class="content">
- <view class="user-select u-flex-col">
- <view class="user-select-search">
- <u-search :placeholder="$t('common.searchText')" v-model="keyword" height="72" :show-action="false" bg-color="#f0f2f6"
- shape="square" @change='search'>
- </u-search>
- </view>
- </view>
- </view>
- <view class="header">
- <view class="map-container">
- <map class='map' id="maps" :latitude="location.latitude" :longitude="location.longitude"
- :circles="circles" :polygons="polygons" :scale='15' @regionchange="regionChange">
- <!-- #ifdef H5 -->
- <cover-image class="map-marker h5-map-marker" src="/static/image/mark.png" />
- <!-- #endif -->
- <!-- #ifndef H5-->
- <cover-image class="map-marker" src="/static/image/mark.png" />
- <!-- #endif -->
- <cover-view class="map-locate" @click="handleLocate">
- <cover-image v-if="!locateLoading" src="/static/image/locate.png" />
- <cover-image v-else class="map-locate-img" src="/static/image/waite.png" />
- </cover-view>
- </map>
- </view>
- </view>
- <view class="around-contain">
- <scroll-view style="height:100%" id="scroll-view-h" class="scroll-view2" :refresher-enabled="false"
- :refresher-threshold="50" :scroll-with-animation='true' @scrolltolower="handleScrollToLower"
- :scroll-y="true">
- <radio-group class="around-contain-item" v-for="(item,index) in list" :key="index" v-if="list.length"
- @change="onSelectValueChange(item,index)">
- <label class="u-radio-label">
- <radio class="u-radio" :value="item.id" :checked="item.id === selectId" />
- <view class="around-item-title-box">
- <view class="around-item-title u-line-1"> {{ item.name }}</view>
- <view class="around-item-sub-title u-line-1"> {{ item.address }}</view>
- </view>
- </label>
- </radio-group>
- <u-loading class="loading" mode="circle" size="44" v-if="loading" />
- <view v-if="!loading&&!list.length" class="nodata u-flex-col">
- <image :src="noDataIcon" mode="widthFix" class="noDataIcon" />
- {{$t('common.noData')}}
- </view>
- </scroll-view>
- </view>
- <view class="jnpf-bottom-actions">
- <u-button class="buttom-btn" @click="close()">{{$t('common.cancelText')}}</u-button>
- <u-button class="buttom-btn" type="primary" @click.stop="handleConfirm()">{{$t('common.okText')}}</u-button>
- </view>
- </view>
- </template>
- <script>
- import resources from '@/libs/resources.js'
- import {
- getAroundList,
- getTextList
- } from '@/api/common.js'
- export default {
- data() {
- return {
- loading: false,
- noDataIcon: resources.message.nodata,
- tabWidth: 150,
- tabIndex: 0,
- keyword: '',
- location: {
- longitude: 116.404, // 经度
- latitude: 39.915, // 纬度
- },
- circles: [],
- list: [],
- pagination: {
- currentPage: 1,
- pageSize: 50
- },
- total: 0,
- currentLocation: {},
- selectId: '',
- selectItem: {},
- enableLocation: '',
- showPopup: false,
- locateLoading: false,
- polygons: [],
- enableLocationScope: false,
- adjustmentScope: 500,
- enableDesktopLocation: false,
- locationScope: [],
- emitKey: '',
- // #ifdef APP
- dragLoading: false
- // #endif
- };
- },
- onLoad(e) {
- const data = e.data ? JSON.parse(e.data) : {}
- this.enableLocationScope = data.enableLocationScope || false
- this.adjustmentScope = data.adjustmentScope || 500
- this.enableDesktopLocation = data.enableDesktopLocation || false
- this.locationScope = data.locationScope || []
- this.emitKey = data.emitKey
- this.init()
- },
- methods: {
- init() {
- this.circles = []
- this.polygons = []
- this.selectId = ''
- this.list = []
- this.locateLoading = false
- // #ifdef APP
- this.dragLoading = false
- // #endif
- this.getLocation()
- },
- getLocation() {
- this.loading = true;
- uni.getLocation({
- type: 'gcj02',
- isHighAccuracy: true,
- success: (res) => {
- this.location.longitude = res.longitude // 经度
- this.location.latitude = res.latitude // 纬度
- //查询附近位置
- this.getList()
- //添加可选区域圆形
- this.handelCircle();
- //添加微调区域圆形
- this.handleScopeCircle();
- },
- fail: (err) => {
- //查询附近位置
- this.getList()
- //添加可选区域圆形
- this.handelCircle();
- //添加微调区域圆形
- this.handleScopeCircle();
- }
- });
- },
- handleGetCenter() {
- this.mapContext = uni.createMapContext("maps", this);
- this.mapContext.getCenterLocation({
- type: 'gcj02',
- geocode: true,
- isHighAccuracy: true,
- altitude: true,
- success: (res) => {
- this.location.longitude = res.longitude
- this.location.latitude = res.latitude
- if (this.enableLocationScope) {
- const discount = this.jnpf.getDistance(this.currentLocation.latitude, this
- .currentLocation.longitude, this.location.latitude, this.location.longitude
- ) || 0;
- if (discount > (this.adjustmentScope || 500)) return this.$refs.uTips.show({
- title: '超出微调范围',
- type: 'warning',
- });
- }
- this.getList()
- }
- })
- },
- handelCircle() {
- if (!this.enableDesktopLocation || !this.locationScope.length) return;
- for (let i = 0; i < this.locationScope.length; i++) {
- const o = this.locationScope[i];
- if (!o.lng || !o.lat || !o.radius) continue;
- o.longitude = o.lng
- o.latitude = o.lat
- this.addCircle({
- ...o,
- color: '#54d65e99',
- fillColor: '#54d65e66',
- });
- }
- },
- handleScopeCircle() {
- if (!this.enableLocationScope) return;
- this.currentLocation = this.$u.deepClone(this.location);
- this.addCircle({
- ...this.location,
- radius: this.adjustmentScope || 500,
- color: '#1890ff99',
- fillColor: '#1890ff66'
- });
- },
- addCircle(o) {
- // #ifdef H5
- this.polygons.push({
- points: this.CreateSimpleCircle(o.latitude, o.longitude, o.radius, 100),
- strokeColor: o.color,
- fillColor: o.fillColor,
- strokeWidth: 1
- })
- // #endif
- // #ifndef H5
- this.circles.push({
- ...o,
- strokeWidth: 1,
- })
- // #endif
- },
- // #ifdef H5
- CreateSimpleCircle(lat, lng, radius, pointCount) {
- var km = radius / 1000;
- var a = km < 5 ? 0.01 : km < 50 ? 0.1 : km < 500 ? 1 : 10;
- var b = this.getCircleDistance(lng, lat, lng + a, lat);
- var c = this.getCircleDistance(lng, lat, lng, lat + a);
- var rb = radius / b * a;
- var rc = radius / c * a;
- var arr = [];
- var n = 0,
- step = 360.0 / pointCount,
- N = 360 - step / 2; //注意浮点数±0.000000001的差异
- for (var i = 0; n < N; i++, n += step) {
- var x = lng + rb * Math.cos(n * Math.PI / 180);
- var y = lat + rc * Math.sin(n * Math.PI / 180);
- arr[i] = {
- latitude: y,
- longitude: x
- }
- }
- arr.push({
- latitude: arr[0].latitude,
- longitude: arr[0].longitude
- });
- return arr;
- },
- getCircleDistance(lng1, lat1, lng2, lat2) {
- var d = Math.PI / 180;
- var f = lat1 * d,
- h = lat2 * d;
- var i = lng2 * d - lng1 * d;
- var e = (1 - Math.cos(h - f) + (1 - Math.cos(i)) * Math.cos(f) * Math.cos(h)) / 2;
- return 2 * 6378137 * Math.asin(Math.sqrt(e));
- },
- // #endif
- regionChange(e) {
- // #ifdef APP
- if (this.dragLoading) return (this.dragLoading = false);
- this.list = [];
- this.handleGetCenter()
- // #endif
- // #ifndef APP
- if (e.detail.causedBy == 'drag' && e.type == 'end') {
- this.list = [];
- this.handleGetCenter()
- }
- // #endif
- },
- handleScrollToLower() {
- if (this.pagination.pageSize * this.pagination.currentPage < this.total) {
- this.pagination.currentPage = this.pagination.currentPage + 1;
- this.getList()
- } else {
- this.$u.toast('没有更多信息啦!')
- }
- },
- getList() {
- this.loading = true;
- const query = {
- key: this.define.aMapWebKey,
- location: this.location.longitude + ',' + this.location.latitude,
- radius: -1,
- offset: this.pagination.pageSize,
- page: this.pagination.currentPage,
- };
- getAroundList(query).then(res => {
- this.handleResult(res)
- }).catch(() => {
- this.loading = false;
- })
- },
- handleResult(res) {
- this.loading = false;
- if (res.data.status == '1') {
- this.list = [...this.list, ...res.data.pois || []];
- this.total = Number(res.data.count || 0)
- } else {
- this.$u.toast(res.data.info)
- }
- },
- onSelectValueChange(item, index) {
- // #ifdef APP
- this.dragLoading = true
- // #endif
- this.selectStatus = true
- this.selectId = item.id
- this.selectItem = item
- const [longitude, latitude] = (item.location || '').split(',');
- this.location = {
- longitude,
- latitude
- };
- // #ifdef APP
- setTimeout(() => {
- this.dragLoading = false
- }, 800)
- // #endif
- },
- handleConfirm() {
- if (!this.selectId) return this.$u.toast('请选择地址')
- const data = this.selectItem
- const [lng, lat] = data.location.split(',');
- if (this.enableLocationScope) {
- const discount = this.jnpf.getDistance(this.currentLocation.latitude, this.currentLocation
- .longitude, lat,
- lng) || 0;
- if (discount > (this.adjustmentScope || 500)) return this.$refs.uTips.show({
- title: '超出微调范围',
- type: 'warning',
- });
- }
- //判断可选范围
- if (this.enableDesktopLocation && this.locationScope.length) {
- let list = [];
- for (let i = 0; i < this.locationScope.length; i++) {
- const o = this.locationScope[i];
- const discount = this.jnpf.getDistance(o.lat, o.lng, lat, lng) || 0;
- list.push(discount > o.radius);
- }
- if (list.every(o => o === true)) return this.$refs.uTips.show({
- title: '超出规定范围',
- type: 'warning',
- });
- }
- const address = data.address && data.address.length ? data.address : '';
- //台湾、北京、上海、重庆、深圳地址特殊处理
- let fullAddress = data.pname + data.cityname + data.adname + address + data.name;
- if (data.pname == data.cityname) fullAddress = data.pname + data.adname + address + data.name;
- if (data.pname == data.cityname && data.pname == data.adname) fullAddress = data.pname + address +
- data.name;
- this.innerValue = {
- pName: data.pname,
- cName: data.cityname,
- adName: data.adname,
- address,
- name: data.name,
- lng,
- lat,
- fullAddress,
- };
- uni.$emit(this.emitKey, JSON.stringify(this.innerValue))
- this.close();
- },
- close() {
- uni.navigateBack({
- delta: 1
- });
- },
- getDistance(lat1, lon1, lat2, lon2) {
- const toRadians = (degrees) => {
- return degrees * (Math.PI / 180);
- }
- const R = 6371;
- const dLat = toRadians(lat2 - lat1);
- const dLon = toRadians(lon2 - lon1);
- const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
- Math.cos(toRadians(lat1)) * Math.cos(toRadians(lat2)) *
- Math.sin(dLon / 2) * Math.sin(dLon / 2);
- const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
- const distance = R * c;
- return distance * 1000;
- },
- search() {
- // 节流,避免输入过快多次请求
- this.searchTimer && clearTimeout(this.searchTimer)
- this.searchTimer = setTimeout(() => {
- this.list = [];
- this.pagination.currentPage = 1
- this.keyword ? this.handleSearch() : this.getList();
- }, 300)
- },
- handleSearch() {
- this.loading = true;
- const query = {
- key: this.define.aMapWebKey,
- keywords: this.keyword,
- radius: this.enableLocationScope ? this.adjustmentScope || 500 : -1,
- offset: this.pagination.pageSize,
- page: this.pagination.currentPage,
- };
- getTextList(query).then(res => {
- this.handleResult(res);
- });
- },
- handleLocate() {
- if (this.locateLoading) return
- this.locateLoading = true
- uni.getLocation({
- type: 'gcj02',
- isHighAccuracy: true,
- success: (res) => {
- this.locateLoading = false
- if (!res.longitude || !res.latitude) return
- this.mapContext = uni.createMapContext("maps", this);
- this.mapContext.moveToLocation({
- longitude: res.longitude,
- latitude: res.latitude,
- })
- },
- fail: (res) => {
- this.locateLoading = false
- this.$u.toast('获取定位失败')
- }
- })
- },
- }
- };
- </script>
- <style scoped lang="scss">
- .jnpf-location-map {
- /* #ifdef H5 */
- height: calc(100vh - 44px);
- /* #endif */
- /* #ifndef H5 */
- height: 100vh;
- /* #endif */
- display: flex;
- flex-direction: column;
- .header {
- .map-container {
- position: relative;
- padding: 0rpx 20rpx;
- .map {
- width: 100%;
- height: 600rpx;
- }
- .map-marker {
- width: 38rpx;
- height: 64rpx;
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translate(-50%, calc(-50% - 20rpx));
- z-index: 9999;
- }
- .h5-map-marker {
- transform: translate(-50%, calc(-50% - 30rpx));
- }
- .map-locate {
- position: absolute;
- bottom: 10px;
- right: 10px;
- height: 24px;
- width: 24px;
- padding: 4px;
- background-color: #fff;
- border-radius: 50%;
- box-shadow: 0 0 5px silver;
- z-index: 999;
- .map-locate-img {
- -webkit-animation: rotate 2s linear infinite;
- }
- @keyframes rotate {
- 0% {
- -webkit-transform: rotate(0deg);
- }
- 25% {
- -webkit-transform: rotate(90deg);
- }
- 50% {
- -webkit-transform: rotate(180deg);
- }
- 75% {
- -webkit-transform: rotate(270deg);
- }
- 100% {
- -webkit-transform: rotate(1turn);
- }
- }
- }
- }
- }
- .content {
- width: 100%;
- .user-select {
- .user-select-search {
- padding: 0rpx 20rpx;
- margin: 20rpx 0;
- }
- }
- }
- .around-contain {
- flex: 1;
- width: 100%;
- overflow: hidden;
- .loading {
- display: flex;
- justify-content: center;
- margin: 250rpx auto 0;
- }
- .around-contain-item {
- display: flex;
- align-items: center;
- padding: 10rpx 0;
- height: 60px;
- line-height: 22px;
- border-bottom: 1px solid #f2f2f6;
- .u-radio-label {
- width: 100%;
- display: flex;
- align-items: center;
- // #ifdef MP
- :deep(.u-radio) {
- margin: 0 16rpx 0 20rpx;
- }
- // #endif
- // #ifndef MP
- :deep(.uni-radio-input) {
- margin: 0 16rpx 0 20rpx;
- }
- // #endif
- .around-item-title-box {
- flex: 1;
- min-width: 0;
- padding-right: 16rpx;
- .around-item-title {
- font-size: 30rpx;
- color: #171a1d;
- }
- .around-item-sub-title {
- font-size: 28rpx;
- color: #b9babb;
- padding-top: 8rpx;
- }
- }
- }
- }
- }
- }
- </style>
|