添加地址
效果:
JS代码
const app = getApp();
import Address from "../../api/address.js"
Page({
/**
* 页面的初始数据
*/
data: {
userName: '',
mobile: '',
address: '', // 详细地址
region: ["", "", ""], // 省市区选择器
region_id: [0, 0, 0], // 省市区选择器id
addressId: '',
location:{},
isCheck: false,
districtName:'',
district:[],
selectAddress:''//定位地址
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function(options) {
this.load(options);
if (this.data.addressId){ //页面标题控制
wx.setNavigationBarTitle({
title: '编辑地址'
})
}else{
wx.setNavigationBarTitle({
title: '新增地址'
})
}
},
load(options) {
const {
status,
id
} = options;
this.setData({
addressId: id || ''
})
if (this.data.addressId) this.getAddressDetail(status); //编辑地址调用
},
//保存地址事件
submit() {
const msg = this.checkMsg();
if (msg) {
app.commonTip(msg);
return false;
}
const data = {
//略
}
function cb(msg) {
app.successTip(msg);
setTimeout(() => { //返回页面
wx.navigateBack({
delta: 1
})
}, 200);
}
if (this.data.addressId) {
Address.addressupdate(data).then(res => {
cb('修改成功');
})
} else {
Address.addressadd(data).then(res => {
cb('保存成功');
})
}
},
//编辑地址状态调用事件
getAddressDetail(status) {
const data = {
status,
id: this.data.addressId
}
Address.getAddressInfo(data).then(res => {
const {
provinceId,
provinceName,
cityId,
cityName,
districtId,
districtName,
address,
latitude,
longitude,
selectAddress,
name,
phone,
defaultVal,
} = res.d[0];
this.setData({
address,
userName: name,
mobile: phone,
region: [provinceName, cityName, districtName],
['location.lat']:latitude,
['location.lng']: longitude,
selectAddress: selectAddress,
region_id: [provinceId, cityId, districtId],
isCheck: defaultVal == 1 ? true : false
})
}).catch(err => {
console.error(err);
})
},
//键盘输入事件:姓名
handleInputName(e) {
this.setData({
userName: e.detail.value
})
},
//数字键盘输入事件
handleInputMobile(e) {
this.setData({
mobile: e.detail.value
})
},
//键盘输入事件:地址
handleInputAddress(e) {
this.setData({
address: e.detail.value
})
},
//一键清空
handleClearInput(e) {
const attrName = e.currentTarget.dataset.name;
this.setData({
[`${attrName}`]: ''
})
},
// 处理鼠标移入显示一键清除
hadnleFocus(e) {
const type = e.type;
const value = e.detail.value;
const {
msg
} = e.currentTarget.dataset;
if (type == 'blur') {
if (!value) app.commonTip(msg);
}
},
hadnleCancel() {
this.handleIsShowCropper();
this.clearImageSrc();
},
//picker事件:点击触发弹起选择事件
bindRegionChange(e) {
const {
code,
value
} = e.detail
this.setData({
region: value,
region_id: code,
address: '',
selectAddress: ''
})
},
//校验
checkMsg() {
let msg = '';
//略
return msg;
},
// 默认地址选项
handleIsCheck(e) {
if (e.currentTarget.dataset.check == 0) {
this.setData({
isCheck: false
})
} else {
this.setData({
isCheck: true
})
}
},
//选择地址
chooseSite() {
const site = this.data.address;
const city = this.data.region_id[1];
const district = this.data.region_id[2];
if (city && district) {
wx.navigateTo({
url: `/pages/map/index?districtName=${district}`,
})
} else {
app.commonTip('请选择省市区')
}
},
// 删除地址
delSite(e) {
const id = e.currentTarget.dataset.id
wx.showModal({
title: '提示',
content: '是否删除',
success: (res) => {
if (res.confirm) {
Address.getDeleteAddress(id).then(res => {
if (res.success) {
app.successTip('删除成功');
setTimeout(() => {
wx.navigateBack({
delta: 1
})
}, 200)
}
}).catch(res => {
console.log(res)
})
} else if (res.cancel) {
console.log('用户点击取消')
}
}
})
}
})
WXML代码
<view class='mt20 site'>
<!-- 名字-->
<view class='site-v dflex'>
<input class='flex-1 site-input' placeholder-class='cc' value='{{userName}}' style="font-size:30rpx;font-weight:350;" placeholder='姓名' bindinput='handleInputName' bindfocus="hadnleFocus" bindblur="hadnleFocus"></input>
<icon class='iconshuruguanbi' data-name='userName' catchtap='handleClearInput' type='clear' size='16' wx:if='{{userName}}'></icon>
</view>
<!-- 电话 -->
<view class='site-v dflex'>
<input class='flex-1 site-input' placeholder-class='cc' maxlength="13" type='number' placeholder='手机号或固话' value='{{mobile}}' bindinput='handleInputMobile' style="font-size:30rpx;font-weight:350;"></input>
<icon class='iconshuruguanbi' data-name='mobile' catchtap='handleClearInput' type='clear' size='16' wx:if='{{mobile}}'></icon>
</view>
<!-- 省市区 -->
<view class='site-v dflex' style="padding:35rpx 0rpx;">
<picker class='flex-1 site-sex {{region[0]?"":"cc"}}' mode="region" bindchange="bindRegionChange" value="{{region}}">
<text wx:if="{{region[0]}}" style="font-size:30rpx;font-weight:350;"> {{region[0]}} {{region[1]}} {{region[2]}}</text>
<text wx:else style="font-size:30rpx;font-weight:350;">请选择省市区</text>
<icon class='iconfont iconenter site-icon'></icon>
</picker>
</view>
<!-- 定位 -->
<view class='site-v dflex' style="padding:25rpx 0rpx;">
<view class="detail">
<view class="detail-up">
<view class="detail-icon" bindtap='chooseSite'>
<image src="https://file.baimipay.cn/location.png"></image>
</view>
<view class="detail-textarea rel">
<view wx:if="{{!selectAddress}}" class='main-input cc' bindtap='chooseSite' style="font-size:30rpx;font-weight:350;">请选择定位</view>
<!-- <textarea wx:else bindtap='chooseSite' auto-height value='{{selectAddress}}' disabled="true" style="font-size:30rpx;margin-top:-20rpx;"></textarea> -->
<view wx:else bindtap='chooseSite' auto-height disabled="true" style="font-size:30rpx;">{{selectAddress}}</view>
</view>
</view>
</view>
</view>
<!-- 详细地址 -->
<view class='site-v dflex no-bot'>
<textarea bindinput="handleInputAddress" style="height:150rpx;" class='flex-1 site-input' placeholder-class='cc' value='{{address}}' placeholder='请填写详细地址、至少5个字' bindfocus="hadnleFocus" bindblur="hadnleFocus" maxlength="60" ></textarea>
<icon class='iconshuruguanbi' data-name='address' catchtap='handleClearInput' type='clear' size='16' wx:if='{{address}}'></icon>
<view class="textarea-length-tip">
<text style="color:red;" class='{{address.length?"col-f40":""}}'>{{address.length?address.length:"0"}}</text>/60
</view>
</view>
</view>
<view>
<text class="detail-tip">请确保定位与填写的地址为同一位置</text>
</view>
<!-- 默认选项 -->
<view class='check clearfix'>
<checkbox wx:if="{{!isCheck}}" color="#fff" class='left' bindtap='handleIsCheck' checked="{{isCheck}}" data-check='1'></checkbox>
<checkbox wx:else color="#fff" class='left' bindtap='handleIsCheck' checked="{{isCheck}}" data-check='0'></checkbox>
<view class='check-right left'>默认地址</view>
</view>
<!-- 按钮 -->
<view class="site-btn">
<button class='btn save' bindtap='submit'>保存</button>
<button class='btn del' wx:if="{{addressId}}" data-id="{{addressId}}" bindtap='delSite'>删除地址</button>
</view>
WXSS代码
.site {
/* padding: 0 32rpx; */
background: #fff;
}
.site-v {
position: relative;
padding: 29rpx 0;
border-bottom: 1rpx solid #e8e9ea;
}
.site-input {
margin-left: 30rpx;
width:80%;
text-align: left;
height: 52rpx;
line-height: 52rpx;
font-size: 30rpx;
box-sizing: border-box;
}
.no-bot {
border-bottom: none;
}
.site-l {
height: 52rpx;
font-size: 30rpx;
font-weight: 400;
line-height: 52rpx;
}
.site-sex {
padding-right: 30rpx;
/* display: flex; */
align-items: center;
justify-content: flex-end;
box-sizing: border-box;
font-size: 30rpx;
text-align: left;
font-weight: 400;
margin-left: 30rpx;
}
.site-tx {
padding-right: 70rpx;
box-sizing: border-box;
font-size: 28rpx;
line-height: 40rpx;
display: flex;
display: -webkit-flex;
align-items: center;
min-height: 40px;
max-height: 100rpx;
}
.site-icon {
position: absolute;
top: 50%;
right: 0;
transform: translateY(-50%) rotate(90deg);
line-height: 90rpx;
font-size: 24rpx;
color: #000;
margin-right: 32rpx;
}
.site-a {
position: relative;
min-height: 40rpx;
padding: 29rpx 0;
}
.font30 {
padding-right: 0;
padding-left: 129rpx;
font-size: 30rpx;
font-weight: 400;
}
.address-icon {
position: absolute;
right: 0rpx;
top: 50%;
transform: translateY(-71%);
color: #ccc;
}
.check {
padding: 20rpx 32rpx;
height: 40rpx;
line-height: 40rpx;
}
.check-right {
font-size: 26rpx;
margin-top: 2rpx;
color: #333;
}
.check checkbox {
margin-right: 4rpx;
}
.check checkbox .wx-checkbox-input {
width: 32rpx;
height: 32rpx;
overflow: hidden;
/* background-color: #F3CB3CFF */
}
checkbox .wx-checkbox-input.wx-checkbox-input-checked::before {
background-color: #f3cb3c;
border: 2rpx solid #f3cb3c;
width: 32rpx; /* 选中后对勾大小,不要超过背景的尺寸 */
height: 32rpx; /* 选中后对勾大小,不要超过背景的尺寸 */
line-height: 32rpx;
text-align: center;
font-size: 30rpx; /* 对勾大小 30rpx */
color: #fff; /* 对勾颜色 白色 */
transform: translate(-50%, -50%) scale(1);
}
.site-btn {
padding: 0 66rpx;
margin-top: 68rpx;
}
.site-btn .btn {
border-radius: 48rpx;
font-size: 32rpx;
height: 96rpx;
line-height: 96rpx;
}
.save {
background: #f3cb3c;
border: 1rpx solid #f3cb3c;
}
.del {
margin-top: 40rpx;
border: 1rpx solid #ccc;
background: #fff;
}
.icon-close {
position: absolute;
color: #ccc;
top: 50%;
transform: translateY(-62%);
right: 0rpx;
line-height: 40rpx;
}
.detail {
width: 100%;
padding: 10rpx 0;
box-sizing: border-box;
}
.detail-up {
width: 100%;
/* display: flex; */
align-items: center;
}
.detail-icon {
width: 30rpx;
height: 34rpx;
margin-left: 30rpx;
float: left;
}
.detail-textarea {
width: 88%;
margin-left:15rpx;
text-align: left;
float: left;
margin-top: -5rpx;
}
.detail-textarea textarea{
width: 100%;
}
.detail-textarea icon{
position: absolute;
color: #ccc;
top: 50%;
transform: translateY(-62%);
left: 30rpx;
line-height: 40rpx;
}
.detail image {
max-width: 100%;
max-height: 100%;
}
.detail-down{
/* width: 100%; */
font-size: 24rpx;
color: #ccc;
text-align: right;
margin-top: 10rpx;
}
.detail-tip{
word-spacing: 1px;
margin-left: 15px;
width: 100%;
font-size: 24rpx;
color: red;
margin-top: 10rpx;
}
.iconshuruguanbi{
margin-right: 30rpx;
margin-top: 10rpx;
}
.textarea-length-tip {
position: absolute;
right: 28rpx;
bottom: 20rpx;
z-index: 100;
color: #999;
}
选择地址页面代码
JS代码
const app = getApp();
import Serve from '../../api/address.js'
Page({
/**
* 页面的初始数据
*/
data: {
keyWords: '',
districtName: '',
timer: null,
items: [],
latitude: 31.080632,
longitude: 121.590618,
markers: [{
id: 1,
latitude: 31.080632,
longitude: 121.590618,
}],
isAuth: false,
initialized: false,
flag: false //刚进来的时候
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function(options) {
if (options.districtName) {
this.setData({
districtName: options.districtName
})
const community = wx.getStorageSync("siteInfo");
const defKeyWords = community.address || '小区';
this.getUserLocation(defKeyWords);
}
},
onReady: function() {
this.mapCtx = wx.createMapContext('myMap');
},
//查找附近地址
searchNearbyShop() {
this.setData({
flag: true
})
Serve.searchSite(this.data.keyWords, this.data.districtName).then(res => {
if (res.statusCode == 200) {
if (res.data.data && res.data.data.length > 0) {
const items = res.data.data;
const {
lat,
lng
} = items[0].location;
this.setData({
items,
[`markers[0].latitude`]: items[0].location.lat,
[`markers[0].longitude`]: items[0].location.lng,
latitude: lat,
longitude: lng,
})
this.translateMarker(lat, lng);
} else {
app.commonTip("抱歉没有搜到您想到的地址");
}
} else {
if (res.message) app.commonTip(res.message);
}
})
},
//输入地址
handleKeyWords(e) {
const keyWords = e.detail;
if (keyWords) {
this.setData({
keyWords,
})
} else {
var address = this.data.addressName
this.setData({
keyWords: address
})
}
clearTimeout(this.timer);
this.timer = setTimeout(() => {
this.searchNearbyShop();
}, 100)
},
//获取用户附近地区
getUserLocation(keywords) {
let that = this;
Serve.searchSite(keywords, that.data.districtName).then(res => {
const items = res.data.data;
if (res.data.data && res.data.data.length > 0) {
that.setData({
latitude: items[0].location.lat,
longitude: items[0].location.lng,
[`markers[0].latitude`]: items[0].location.lat,
[`markers[0].longitude`]: items[0].location.lng,
isAuth: true,
})
} else {
app.commonTip("未搜索到您选择的地区,请手动输入");
}
})
},
// 移动地图上的标注点
translateMarker: function(latitude, longitude) {
const self = this
this.mapCtx.translateMarker({
markerId: 1,
duration: 1000,
destination: {
latitude: latitude,
longitude: longitude,
},
animationEnd() {
console.log('animation end')
self.setData({
flag: false
})
}
})
},
clearKeyWords() {
this.setData({
keyWords: '',
items: []
})
},
//选择地址
selectAddress(e) {
const index = e.currentTarget.dataset.index;
const pages = getCurrentPages(); //获取当前页面js里面的pages里的所有信息。
const prevPage = pages[pages.length - 2]; //上一个页面
const address = this.siteAddress(this.data.items[index].address, this.data.items[index].title);
const location = this.data.items[index].location;
const districtName = this.data.items[index].ad_info.district;
const districtId = this.data.items[index].ad_info.adcode;
console.log(location);
prevPage.setData({
address,
location,
districtName,
selectAddress: address,
['region[2]']: districtName ? districtName : prevPage.data.region[2],
['region_id[2]']: districtId
})
wx.navigateBack({
delta: 1
})
},
// 处理用户移动地图
handleRegionChange(e) {
if (this.data.flag) {
return false
}
this.mapCtx.getCenterLocation({
success: res => {
// this.translateMarker(res.latitude, res.longitude)
clearTimeout(this.data.timer)
this.data.timer = setTimeout(() => {
this.searchCity(res.latitude, res.longitude)
}, 500)
}
});
},
//滑动查找地址
searchCity(latitude, longitude) {
Serve.cansearchSite(latitude, longitude).then(res => {
const items = res.data.result.pois;
this.setData({
items,
})
this.translateMarker(latitude, longitude)
console.log(res)
})
},
siteAddress(address, title) {
var index = address.indexOf("区")
console.log()
if (index == address.length - 1) {
return title
} else if (index > 0) {
return address.substr(index + 1)
} else {
return title
}
}
})
JSON代码
{
"usingComponents": {
"van-search": "../../components/dist/search/index"
},
"navigationBarTitleText": "选择地址"
}
WXML代码
<!--pages/buy/shop_address/index.wxml-->
<view class='page'>
<van-search class="search" placeholder="请输入搜索关键词" use-action-slot shape="round" bind:change="handleKeyWords" bind:clear="clearKeyWords" bind:confirm="searchNearbyShop" searchIcon="'iconfont iconsearch c9'">
</van-search>
<view class='map'>
<map id="myMap" style="width:100%;height:540rpx" longitude="{{longitude}}" latitude="{{latitude}}" markers="{{markers}}" scale='15' bindregionchange="handleRegionChange">
</map>
</view>
<scroll-view scroll-y class='list'>
<view class='list-item' wx:for="{{items}}" wx:key="index" data-index="{{index}}" bindtap='selectAddress'>
<view class='list-item_l'>
<view class='icon'>
<image src='/images/shop-address-location.png'></image>
</view>
<view class='text'>
<view class='f-16'>{{item.title}}</view>
<view class='f-13'>{{item.address}}</view>
</view>
</view>
</view>
</scroll-view>
</view>
WXSS代码
.page {
position: relative;
width: 100vw;
height: 100vh;
}
.search {
width: 100vw;
position: fixed;
left: 0;
top: 0;
z-index: 99;
}
.map {
width: 100vw;
position: fixed;
left: 0;
top: 108rpx;
}
.list {
width: 100%;
position: absolute;
top: 648rpx;
left: 0;
bottom: 0;
background-color: #fff;
padding: 0 32rpx;
box-sizing: border-box;
}
.list-item {
display: flex;
justify-content: space-between;
padding: 22rpx 0;
align-items: center;
box-sizing: border-box;
border-bottom: 1rpx solid #e8e9ea;
}
.list-item:last-child {
border: none;
}
.list-item .list-item_l {
display: flex;
align-items: center;
margin-right: 10rpx;
}
.list-item .list-item_l .icon {
width: 30rpx;
height: 34rpx;
margin-right: 24rpx;
}
image {
max-width: 100%;
max-height: 100%;
}