<template> <view class=""> <view style="padding:30rpx"> <w-picker ref="Selector" mode="region" themeColor="#F76454" @confirm="onConfirm" /> <view class="nav"> <textarea v-model="message" type="text" :placeholder="placeholder" class="discern" placeholder-class="discern-placeholder" /> <view class="flex"> <view class="nav-clearbutton flexC" @click="message = ''">清空</view> <view class="nav-button flexC" @click="text">识别</view> </view> </view> <view class="box"> <view class="box-top"> <view class="title"> <text>收货人</text> <text class="star">*</text> </view> <input v-model="address.name" type="text" class="box-input" placeholder-class="input_placeholder" placeholder="请填写真实姓名" /> </view> <view class="box-top"> <navigator url="./phone-area" class="phone-area flexB"> <view class="flexS"> <view class="title"> <text class="text">国家/地区</text> <text class="star">*</text> </view> <text class="area">{{areaName}}({{address.areaCode}})</text> </view> <text class="icon cuIcon-right"></text> </navigator> </view> <view class="box-top"> <view class="title"> <text>手机号</text> <text class="star">*</text> </view> <input v-model="address.phone" type="number" class="box-input" placeholder-class="input_placeholder" placeholder="请填写手机号码" maxlength="11" /> </view> <view class="box-top"> <view class="title"> <text>省市区</text> <text class="star">*</text> </view> <view class="picker flexB" @tap="choosePicker"> <view :style="{ color: local ? '#333' : '#cbcbcb' }"> {{ local ? local : '请选择所在地区' }} </view> <text class="iconfont iconzhcc_xiangxiajiantou"></text> </view> </view> <view class="box-bottom"> <view class="title"> <text>详细地址</text> <text class="star">*</text> </view> <view class="textbox"> <textarea v-model="address.detail" type="text" placeholder="请填写详细地址" class="box-input" placeholder-class="input_placeholder" /> </view> </view> </view> <view class="remind">若自动识别的信息不准确,请手动修改</view> </view> <view class="bottom"> <view class="bottom-btn" @tap="save">保存地址</view> </view> </view> </template> <script> import WPicker from '@/components/w-picker/w-pickers.vue'; import cityPicker from '@/components/citypicker/city-pickers.vue'; import areaList from '@/common/util/phone-area.js' import AddressParse from 'address-parse'; import { discernAdress } from '@/api/Buy_soap_tape.js' import { _API_AddressAdd, _API_AddressUpdata, } from '@/api/address.js' export default { components: { WPicker, cityPicker }, data() { return { placeholder: '请粘贴或输入整段地址,点击“识别”自动拆分姓名、电话和地址。例如:张三,15100001111,河南省郑州市金水区某路和某路交叉口某小区某号楼', title: '新增地址', id: '', message: '', result: '', address: { name: '', phone: '', provice: '', city: '', area: '', detail: '', areaCode: '+86', // 手机号地区代码 }, requesting: false, local: '', pickerDefaultVal: ['河南省', '郑州市', '金水区'], areaName: '中国大陆', // 手机号地区名称 isMatch: /^[1][3-9]\d{9}$/, //手机号验证 codeList: areaList, //手机号区域选择 }; }, onLoad(opt) { if (opt.index) { // 如果传入 index 表示用户编辑地址 this.title = '编辑地址'; // 修改页面标题 const address = this.list[+opt.index]; if (!address) { return false; } this.id = address.id; // 获取地址 id this.address.name = address.con_name; this.address.phone = address.con_mobile; this.address.provice = address.provice; this.address.city = address.city; this.address.area = address.area; this.address.type = address.type ? 1 : 0; this.local = `${address.provice}-${address.city}-${address.area}`; this.address.detail = address.address; this.pickerDefaultVal = [address.provice, address.city, address.area]; this.address.areaCode = address.area_code ? address.area_code : '+86' if (this.address.areaCode) { let index = this.address.areaCode.indexOf('+') let code = this.address.areaCode.substring(index + 1) this.codeList[0].list.map(i => { if (i.code === Number(code)) { this.areaName = i.name this.isMatch = i.phoneReg } }) } } }, created() { uni.$on('CHOOSEPHONECODE', (name, code, reg, phoneReg) => { // 监听 chooseArea 事件更新 this.areaName = name; // 修改选择的手机号地区名称 this.address.areaCode = code // 修改选择的手机号地区代码 this.isMatch = phoneReg }) }, computed: { list() { return this.$store.state.list } }, methods: { checkCode(type, arr) { let t = '886' let a = '853' let x = '852' let msg = this.message.replace(/\s*/g, "") let index = '' let mobile = '' let code = '' if (msg.indexOf(t) != -1) { index = msg.indexOf(t) mobile = msg.substring(index + 3, index + 13) code = `+${t}` this.areaName = '中国台湾' this.isMatch = /^[0]{1}[9]{1}\d{8}$/ } else if (msg.indexOf(a) != -1) { index = msg.indexOf(a) mobile = msg.substring(index + 3, index + 11) code = `+${a}` this.areaName = '中国澳门' this.isMatch = /^[6]\d{7}$/ } else if (msg.indexOf(x) != -1) { index = msg.indexOf(x) mobile = msg.substring(index + 3, index + 11) code = `+${x}` this.areaName = '中国香港' this.isMatch = /^([6|9|5])\d{7}$/ } else { code = '+86' this.areaName = '中国大陆' mobile = arr.mobile this.isMatch = /^[1][3-9]\d{9}$/ } this.address = { name: arr.name.replace(/[0-9]/g, ''), phone: mobile, local: type === 0 ? `${arr.province}-${arr.city}-${arr.area}` : `${arr.province}-${arr.city}`, provice: arr.province, city: arr.city, area: arr.area, detail: arr.details, type: '', areaCode: code, }; }, text() { if (this.message.length < 1) { uni.toast('请输入需要识别的内容'); return; } this.result = AddressParse.parse(this.message); let arr = AddressParse.parse(this.message)[0]; if (arr.mobile === '') { this.checkCode(0, arr) } else if (arr.area === '') { const params = { city: arr.city, details: arr.details }; this.checkCode(1, arr) discernAdress(params).then(res => { if (res.code === 200) { if (!res.data.area) { uni.toast('有部分信息未能识别或错误,请核实或手动填写'); return; } // this.address.name = arr.name; // this.address.phone = arr.mobile; // this.address.detail = arr.details; // this.address.provice = arr.province; // this.address.city = arr.city; this.address.area = res.data.area; this.local = `${arr.province}-${arr.city}-${res.data.area}`; this.pickerDefaultVal = [this.address.provice, this.address.city, this.address.area]; } else { uni.toast('识别失败,请手动填写'); } }); } else { this.address.name = arr.name; this.address.phone = arr.mobile; this.address.detail = arr.details; this.address.provice = arr.province; this.address.city = arr.city; this.address.area = arr.area; this.local = `${arr.province}-${arr.city}-${arr.area}`; this.pickerDefaultVal = [this.address.provice, this.address.city, this.address.area]; this.address.areaCode = '+86' } }, save() { if (this.address.name) { this.address.name = this.address.name.replace(/\s*/g, ''); } // 保存/修改地址 if (!this.address.name.match(/^[\u4E00-\u9FA5\uf900-\ufa2d·s]{2,20}$/)) { // 校验姓名 uni.toast('真实姓名不符合要求'); return; } if (!this.address.phone) { uni.toast('手机号码不能为空'); return } if (this.isMatch && !this.address.phone.match(this.isMatch)) { uni.toast('手机号所属与区号不一致'); return } if (!this.address.area) { uni.toast('区域不能为空'); return; } if (!this.local.trim().length) { // 校验是否选择地区 uni.toast('请选择所在地区'); return; } if (!this.address.detail.trim().length) { // 校验是否填写详细地址 uni.toast('详细地址不能为空'); return; } const address = { con_name: this.address.name, con_mobile: this.address.phone, provice: this.address.provice, city: this.address.city, area: this.address.area, address: this.address.detail, type: this.address.type, areaCode: this.address.areaCode } uni.showLoading({ mask: true }) if (this.title === '新增地址') { _API_AddressAdd(address).then(res => { this.requesting = false; if (res.code === 200) { uni.navigateBack() uni.$emit('ADDRESS', '新增地址成功') } else { uni.showModal({ content: res.message || '新增地址失败', showCancel: false }) } }) } else if (this.title === '编辑地址') { address.id = this.id _API_AddressUpdata(address).then(res => { this.requesting = false; if (res.code === 200) { uni.navigateBack(); uni.$emit('ADDRESS', '修改地址成功'); } else { uni.showModal({ content: res.message || '修改地址失败', showCancel: false }) } }) } }, choosePicker() { // 显示地址选择器 this.$refs.Selector.show(); }, onConfirm(e) { // 选择地址选择器 this.local = `${e.checkArr[0]}-${e.checkArr[1]}-${e.checkArr[2]}`; this.address.provice = e.checkArr[0]; this.address.city = e.checkArr[1]; this.address.area = e.checkArr[2]; } }, } </script> <style lang="scss"> .discern-placeholder { font-size: 30rpx; font-family: PingFang SC-Regular, PingFang SC; font-weight: 400; color: #cbcbcb; line-height: 44rpx; } .input_placeholder { font-size: 30rpx; color: #cbcbcb; } </style> <style lang="scss" scoped> .nav { padding: 26rpx 20rpx 30rpx 30rpx; background-color: #fff; border-radius: 24rpx; display: flex; flex-direction: column; align-items: flex-end; .discern { width: 100%; height: 180rpx; font-size: 28rpx; } .flex { display: flex; view { width: 128rpx; height: 64rpx; font-size: 28rpx; border-radius: 32rpx; } } &-button { color: #ffffff; background: linear-gradient(90deg, #ff232c 0%, #ff571b 100%); } &-clearbutton { background: #fff4f3; border: 2rpx solid $base-color; color: $base-color; margin-right: 15rpx; } } .box { margin: 30rpx 0; background-color: #fff; border-radius: 24rpx; .phone-area { width: 100%; .area { color: #049E56; font-weight: bold; margin-left: 16rpx; } .icon { font-size: 40rpx; color: #999; } } &-input { font-size: 30rpx; min-height: 126rpx; width: 75%; margin-left: 20rpx; } &-top { min-height: 128rpx; margin: 0 30rpx; box-sizing: border-box; border-bottom: 2rpx solid #eeeeee; display: flex; justify-content: flex-start; align-items: center; .title { font-size: 34rpx; font-weight: bold; .star { color: $base-color; margin-left: 10rpx; font-size: 40rpx; } } .picker { width: 75%; min-height: 128rpx; margin-left: 20rpx; font-size: 30rpx; .iconfont { color: #cbcbcb; } } } &-bottom { height: 166rpx; padding: 20rpx 30rpx; box-sizing: border-box; border-bottom: 2rpx solid #eeeeee; display: flex; justify-content: flex-start; align-items: flex-start; .title { font-size: 34rpx; font-weight: bold; .star { color: $base-color; margin-left: 10rpx; font-size: 40rpx; } } .input_placeholder { font-size: 30rpx; color: #cbcbcb; } .textbox { height: 166rpx; .box-input { width: 440rpx; height: 120rpx; font-size: 30rpx; } } } &-changyong { height: 110rpx; padding: 26rpx 20rpx 30rpx 30rpx; display: flex; justify-content: space-between; align-items: center; .title { // width: 146rpx; font-size: 28rpx; font-weight: 400; line-height: 29rpx; color: #585858; } .input_placeholder { font-size: 28rpx; font-weight: 400; line-height: 29rpx; } .set-used { margin-right: auto; color: #ea4a41; font-size: 30rpx; } .set-control { width: 110rpx; height: 55rpx; line-height: 55rpx; border-radius: 50rpx; text-align: center; background: #f8f8f8; color: #333333; font-size: 30rpx; &:nth-last-of-type(1) { margin-left: 20rpx; } &.active { background: linear-gradient(to right, #f97c55, #f44545) !important; color: #ffffff !important; } } } } .remind { text-align: center; color: #fb231f; font-size: 28rpx; padding-bottom: 80rpx; } .bottom { position: fixed; bottom: 0; width: 100%; height: 100rpx; background-color: #fff; border-top: 1px solid #eeeeee; @include flex() &-btn { width: 702rpx; color: #fff; text-align: center; font-size: 32rpx; font-weight: bold; line-height: 88rpx; height: 88rpx; background: linear-gradient(93deg, #ff232c 0%, #ff571b 100%); opacity: 1; border-radius: 44px; } } </style>