实现效果如图所示
js
const app = getApp()
const api = require('../api')
Page({
/**
* 页面的初始数据
*/
data: {
successCode:0,
id:0,//正在编辑的地址的id,0表示新增
detail:{//当前正在添加/编辑的地址的信息
name: "",//收货人名 <string>
phone: "",//收货人电话 <string>
province: "",//省 <string>
provinceCode: "",//省编码 <string>
city: "",//市 <string>
cityCode: "",//市编码 <string>
area: "",//区 <string>
areaCode: "",//区编码 <string>
address: "",//详细地址 <string>
isDefault: 0,//0非默认,1默认 <number>
},
disabled:false,
provinceList:[],//从接口获取的省市区数据
cityList:[],
areaList:[],
provinceNameList:[],//地区组件中展示的省市区数据
cityNameList:[],
areaNameList:[],
provinceIndex:0,//被选中的省市区在数组中的index
cityIndex:0,
areaIndex:0,
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
if(options.id){
this.setData({
id:options.id
})
}
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
this.getInitRegion()
wx.setNavigationBarTitle({
title: '添加收货地址'
})
},
//获取初始化的省市区信息
/**
* 获取初始化的省市区信息
* 新增地址时,获取全部的省,第一个省下的市,第一个市下的区
* 编辑地址时,获取全部的省,已选中的省下的市,已选中的市下的区
*/
async getInitRegion(){
try{
const provinceList = await this.getRegionByCode('')
const provinceCode = this.data.detail.provinceCode?this.data.detail.provinceCode:provinceList[0].cityCode
const cityList = await this.getRegionByCode(provinceCode)
const cityCode = this.data.detail.cityCode?this.data.detail.cityCode:cityList[0].cityCode
const areaList = await this.getRegionByCode(cityCode)
const provinceNameList = []
const cityNameList = []
const areaNameList = []
provinceList.forEach((province,index)=>{
provinceNameList.push(province.cityName)
if(province.cityCode === this.data.detail.provinceCode){
this.setData({
provinceIndex:index
})
}
})
cityList.forEach((city,index)=>{
cityNameList.push(city.cityName)
if(city.cityCode === this.data.detail.cityCode){
this.setData({
cityIndex:index
})
}
})
areaList.forEach((area,index)=>{
areaNameList.push(area.cityName)
if(area.cityCode === this.data.detail.areaCode){
this.setData({
areaIndex:index
})
}
})
this.setData({
provinceList,
cityList,
areaList,
provinceNameList,
cityNameList,
areaNameList,
regionNameList:[provinceNameList,cityNameList,areaNameList]
})
return new Promise((resolve)=>{
resolve('success')
})
}catch(err){
console.log(err)
wx.showToast({
title: err,
icon:'none',
duration:2000
})
}
},
//切换省市区划
changeRangeColumn(e){
console.log('切换省市区划',e)
const index = e.detail.value
switch(e.detail.column){
case 0:
this.handleChangeProvince(index)
break;
case 1:
this.handleChangeCity(index)
break;
case 2:
this.handleChangeArea(index)
break;
default:
break
}
},
//地区弹框,切换省
async handleChangeProvince(provinceIndex){
this.setData({
provinceIndex:provinceIndex,
cityIndex:0,
areaIndex:0,
disabled:true
})
try{
const cityList = await this.getRegionByCode(this.data.provinceList[provinceIndex].cityCode)
const areaList = await this.getRegionByCode(cityList[0].cityCode)
const cityNameList = []
const areaNameList = []
cityList.forEach((city,index)=>{
cityNameList.push(city.cityName)
})
areaList.forEach((area,index)=>{
areaNameList.push(area.cityName)
})
console.log('省切换完毕')
this.setData({
cityList,
areaList,
cityNameList,
areaNameList,
regionNameList:[this.data.regionNameList[0],cityNameList,areaNameList],
disabled:false
})
}catch(err){
console.log(err)
wx.showToast({
title: err,
icon:'none',
duration:2000
})
}
},
//地区弹框,切换市
async handleChangeCity(cityIndex){
this.setData({
cityIndex:cityIndex,
areaIndex:0
})
try{
const areaNameList = []
const areaList = await this.getRegionByCode(this.data.cityList[cityIndex].cityCode)
areaList.forEach(area=>{
areaNameList.push(area.cityName)
})
this.setData({
areaList,
areaNameList,
regionNameList:[this.data.regionNameList[0],this.data.regionNameList[1],areaNameList],
})
}catch(err){
console.log(err)
wx.showToast({
title: err,
icon:'none',
duration:2000
})
}
},
//地区弹框,切换区
handleChangeArea(areaIndex){
this.setData({
areaIndex:areaIndex
})
},
bindRegionChange(e){
console.log('选择地址',e)
console.log('选定地址时,data为',this.data)
this.setData({
detail:{
...this.data.detail,
province:this.data.provinceList[this.data.provinceIndex].cityName,
city:this.data.cityList[this.data.cityIndex].cityName,
area:this.data.areaList[this.data.areaIndex].cityName,
provinceCode:this.data.provinceList[this.data.provinceIndex].cityCode,
cityCode:this.data.cityList[this.data.cityIndex].cityCode,
areaCode:this.data.areaList[this.data.areaIndex].cityCode,
}
})
},
//切换新增/编辑地址时的默认状态
changeDefault(e){
const newDetail = this.data.detail
newDetail.isDefault = e.detail.value?1:0
this.setData({
detail:newDetail
})
},
//根据行政code获取下级区域
getRegionByCode(code){
return new Promise((resolve,reject)=>{
wx.showLoading()
api.getRegionListByCode({
regionCode:code
}).then(res=>{
console.log('获取到省市区,code = '+code+',result = ',res)
wx.hideLoading()
if(res.code !== this.data.successCode){
reject(res.msg)
}
if(res.data.length === 0){
reject('未获取到省市区')
}
resolve(res.data)
})
})
},
bindInput(e){
const newDetail = this.data.detail
newDetail[e.currentTarget.dataset.name] = e.detail.value.trim()
this.setData({
detail:newDetail
})
console.log('detail',this.data.detail)
},
handleSubmit(e){
console.log(e)
const value = e.detail.value
if(this.checkEmpty(value.name)){
wx.showToast({
title: '请填写收货人',
icon: 'none',
duration: 2000
})
return false
}
if(this.checkEmpty(value.phone)){
wx.showToast({
title: '请填写手机号码',
icon: 'none',
duration: 2000
})
return false
}
if(this.checkEmpty(value.region.length === 0)){
wx.showToast({
title: '请选择地区',
icon: 'none',
duration: 2000
})
return false
}
if(this.checkEmpty(this.data.detail.province) || this.checkEmpty(this.data.detail.city) || this.checkEmpty(this.data.detail.area)){
wx.showToast({
title: '请选择完整的地区',
icon: 'none',
duration: 2000
})
return false
}
if(this.checkEmpty(value.address)){
wx.showToast({
title: '请填写详细地址',
icon: 'none',
duration: 2000
})
return false
}
if(!this.checkPhone(value.phone)){
wx.showToast({
title: '请填写正确的手机号',
icon: 'none',
duration: 2000
})
return false
}
if(!this.checkEmpty(this.data.detail.id)){
this.saveUpdateAddress(e.detail.value)
}else{
this.saveAddAddress(e.detail.value)
}
},
//保存新增的地址
saveAddAddress(value){
wx.showLoading()
api.addAddress({
...this.data.detail
}).then(res=>{
wx.hideLoading()
if(res.code !== this.data.successCode){
wx.showToast({
title: res.msg,
icon:'none',
duration:2000
})
return
}
wx.showToast({
title: '添加成功',
icon:'none',
duration:2000
})
})
},
//保存修改的地址
saveUpdateAddress(value){
wx.showLoading()
api.updateAddress({
...this.data.detail
}).then(res=>{
wx.hideLoading()
if(res.status !== this.data.successCode){
wx.showToast({
title: res.msg,
icon:'none',
duration:2000
})
return
}
wx.showToast({
title: '修改成功',
icon:'none',
duration:2000
})
})
},
//非空检查
checkEmpty(value){
if (value === '' || value === null || typeof (value) == 'undefined') {
return true
}
return false
}
})
wxml:
<view class="add-page">
<form catchsubmit="handleSubmit" >
<view class="address-block">
<view class="address-info">
<view class="address-title" >收货人</view>:
<view class="address-content">
<input
name="name"
value="{{detail.name}}"
placeholder="请输入名称"
placeholder-style="color:#999999;"
maxlength="20"
bindinput="bindInput"
data-name="name"
/>
</view>
</view>
<view class="address-info">
<view class="address-title">手机号码</view>:
<view class="address-content">
<input
name="phone"
value="{{detail.phone}}"
placeholder="请输入手机号"
placeholder-style="color:#999999;"
maxlength="11"
type="number"
bindinput="bindInput"
data-name="phone"
/>
</view>
</view>
<view class="address-info">
<view class="address-title">选择地区</view>:
<view class="address-content address-region">
<picker class=""
mode="multiSelector"
range="{{[provinceNameList,cityNameList,areaNameList]}}"
bindchange="bindRegionChange"
value="{{[provinceIndex,cityIndex,areaIndex]}}"
name="region"
bindcolumnchange="changeRangeColumn"
disabled="{{disabled}}"
>
<span class="address-region-name one-line" wx:if="{{detail.province}}">{{detail.province}} {{detail.city}} {{detail.area}}</span>
<span class="address-region-name one-line placeholder" wx:else>请选择</span>
<span class="arrow-right"></span>
</picker>
</view>
</view>
<view class="address-info address-detail">
<view class="address-title">详细地址</view>:
<view class="address-content">
<textarea class="address-detail-text" bindblur="bindTextAreaBlur" name="address" value="{{detail.address}}" placeholder="请输入详细地址" placeholder-style="color:#999999;" maxlength="150" bindinput="bindInput"
data-name="address"/>
</view>
</view>
<view class="address-info">
<span>设为默认地址</span>
<switch checked="{{detail.isDefault}}" bindchange="changeDefault" color="{{iconColor}}" />
</view>
</view>
<view class="bottom-btn">
<button class="btn-primary" type="primary" formType="submit">保存</button>
</view>
</form>
</view>
wxss:
page{
padding-bottom: 200rpx;
}
/*添加地址start*/
.add-page{
width: 100%;
font-size: 28rpx;
}
.address-block{
padding-left: 40rpx;
padding-right: 51rpx;
background-color: #ffffff;
}
.address-info{
width: 100%;
display: flex;
justify-content: space-between;
height: 98rpx;
line-height: 98rpx;
border-bottom: 1rpx solid #f1f1f1;
}
.address-info:last-child{
border-bottom:none;
}
.address-info input{
height: 100%;
}
.address-title{
flex: 0 0 130rpx;
text-align:justify;
}
.address-title:after{
display:inline-block;
content:'';
width:100%;
}
.address-content{
flex: 1 1 auto;
height: 100%;
padding-left: 35rpx;
}
.address-region{
display: inline-flex;
justify-content: space-between;
position: relative;
}
.address-region-name{
width: 450rpx;
}
.address-region .arrow-right{
display: inline-block;
position: absolute;
right: 0;
top: 40rpx;
}
.address-detail{
height: 226rpx;
padding-top: 40rpx;
line-height: 41rpx;
}
.address-detail-text{
width: 100%;
height: 100%;
}
/*添加地址end*/
测试数据:api.js
const provinceList =
[
{cityCode: "370000", cityName: "山东省"},
{cityCode: "140000", cityName: "山西省"},
{cityCode: "410000", cityName: "河南省"},
{cityCode: "130000", cityName: "河北省"},
]
const cityList = {
'370000':[
{cityCode: "370100", cityName: "济南市"},
{cityCode: "370200", cityName: "青岛市"}
],
'140000':[
{cityCode: "140100", cityName: "太原市"},
{cityCode: "140200", cityName: "大同市"},
{cityCode: "140300", cityName: "阳泉市"}
],
'130000':[
{cityCode: "130100", cityName: "石家庄市"}
],
'410000':[
{cityCode: "410100", cityName: "郑州市"},
{cityCode: "410200", cityName: "洛阳市"},
{cityCode: "410300", cityName: "开封市"},
{cityCode: "410300", cityName: "平顶山市"}
],
'370100':[
{cityCode: "370101", cityName: "济南区县-1"},
{cityCode: "370102", cityName: "济南区县-2"}
],
'370200':[
{cityCode: "370201", cityName: "青岛区县-1"},
{cityCode: "370202", cityName: "青岛区县-2"}
],
'140100':[
{cityCode: "140101", cityName: "太原区县-1"},
{cityCode: "140102", cityName: "太原区县-2"},
{cityCode: "140103", cityName: "太原区县-3"},
{cityCode: "140104", cityName: "太原区县-4"}
],
'140200':[
{cityCode: "140201", cityName: "大同区县-1"},
{cityCode: "140202", cityName: "大同区县-2"}
],
'140300':[
{cityCode: "140301", cityName: "阳泉区县-1"},
{cityCode: "140302", cityName: "阳泉区县-2"},
{cityCode: "140303", cityName: "阳泉区县-3"}
],
'130100':[
{cityCode: "130101", cityName: "石家庄区县-1"},
{cityCode: "130102", cityName: "石家庄区县-2"},
{cityCode: "130103", cityName: "石家庄区县-3"},
{cityCode: "130104", cityName: "石家庄区县-4"},
],
'410100':[
{cityCode: "410101", cityName: "郑州区县-1"},
{cityCode: "410102", cityName: "郑州区县-2"},
{cityCode: "410103", cityName: "郑州区县-3"},
],
'410200':[
{cityCode: "410201", cityName: "洛阳区县-1"},
{cityCode: "410202", cityName: "洛阳区县-2"}
],
'410300':[
{cityCode: "370100", cityName: "开封区县-1"}
],
'410400':[
{cityCode: "410401", cityName: "平顶山区县-1"},
{cityCode: "410402", cityName: "平顶山区县-2"},
{cityCode: "410403", cityName: "平顶山区县-3"},
{cityCode: "410404", cityName: "平顶山区县-4"},
],
}
module.exports = {
//新增地址
addAddress(params){
return new Promise(resolve=>{
resolve({
code:0,
msg:'success',
data:{}
})
})
},
//获取省市区联动
getRegionListByCode(params){
console.log('cityCode',params)
let result={
code:0,
msg:'success',
data:[]
}
if(params.regionCode == ''){
result={
...result,
data:provinceList
}
}else{
result={
...result,
data:cityList[params.regionCode]
}
}
return new Promise(resolve=>{
resolve(result)
})
}
}