index.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  1. <template>
  2. <!-- 添加新地址 -->
  3. <view :style="colorStyle">
  4. <form @submit="formSubmit">
  5. <view class='addAddress'>
  6. <view class="pad30">
  7. <view class='default acea-row row-middle borderRadius15'>
  8. <input v-model="addressValue" type="text" placeholder="粘贴地址信息,自动拆分姓名、电话和地址"
  9. placeholder-class='placeholder' style="width:100%;"
  10. @blur="identify()">
  11. </view>
  12. </view>
  13. <view class="pad30 mt-22">
  14. <view class='list borderRadius15'>
  15. <view class='item acea-row row-between-wrapper'>
  16. <view class='name'>姓名</view>
  17. <input type='text' placeholder='请输入姓名' name='real_name' :value="userAddress.real_name"
  18. placeholder-class='placeholder'></input>
  19. </view>
  20. <view class='item acea-row row-between-wrapper'>
  21. <view class='name'>联系电话</view>
  22. <input type='number' maxlength="11" placeholder='请输入联系电话' name="phone" :value='userAddress.phone'
  23. placeholder-class='placeholder' pattern="\d*"></input>
  24. </view>
  25. <view class='item acea-row row-between-wrapper'>
  26. <view class='name'>所在地区</view>
  27. <view class="address acea-row row-between">
  28. <view class="addressCon acea-row" @click="changeRegion">
  29. <text class="picker color-add" v-if="!addressInfo.length">请选择地址</text>
  30. <view v-else>
  31. <text class="picker">{{addressText}}</text>
  32. <view class="font-num tip" v-if="isStreet">请补充县/区信息</view>
  33. </view>
  34. </view>
  35. <text class="iconfont icon-dizhi fontcolor" @click="chooseLocation"></text>
  36. </view>
  37. </view>
  38. <view class='item acea-row row-between-wrapper'>
  39. <view class='name'>详细地址</view>
  40. <view class="address">
  41. <input type='text' placeholder='请填写具体地址' name='detail' placeholder-class='placeholder'
  42. :value='userAddress.detail' class="detail"></input>
  43. </view>
  44. </view>
  45. </view>
  46. </view>
  47. <view class="pad30">
  48. <view class='default acea-row row-middle borderRadius15'>
  49. <checkbox-group @change='ChangeIsDefault'>
  50. <checkbox :checked="userAddress.is_default ? true : false" />设置为默认地址
  51. </checkbox-group>
  52. </view>
  53. </view>
  54. <button class='keepBnt bg-color' form-type="submit">立即保存</button>
  55. <!-- #ifdef MP -->
  56. <view class="wechatAddress" v-if="!id" @click="getWxAddress">导入微信地址</view>
  57. <!-- #endif -->
  58. <!-- #ifdef H5 -->
  59. <view class="wechatAddress" v-if="this.$wechat.isWeixin() && !id" @click="getAddress">导入微信地址</view>
  60. <!-- #endif -->
  61. </view>
  62. </form>
  63. <areaWindow ref="areaWindow" :display="display" :address="addressInfo"
  64. @submit="OnChangeAddress" @changeClose="changeClose"></areaWindow>
  65. <home v-if="navigation"></home>
  66. </view>
  67. </template>
  68. <script>
  69. import {
  70. editAddress,
  71. getAddressDetail,
  72. getGeocoder,
  73. getCityList
  74. } from '@/api/user.js';
  75. import {
  76. getCityData
  77. } from '@/api/api.js';
  78. import {
  79. toLogin
  80. } from '@/libs/login.js';
  81. import {
  82. mapGetters
  83. } from "vuex";
  84. import home from '@/components/home';
  85. import colors from '@/mixins/color.js';
  86. import areaWindow from '../components/areaWindow';
  87. import AddressParse from '../static/zh-address-parse.min.js'
  88. export default {
  89. components: {
  90. areaWindow,
  91. home
  92. },
  93. mixins:[colors],
  94. data() {
  95. return {
  96. cartId: '', //购物车id
  97. pinkId: 0, //拼团id
  98. couponId: 0, //优惠券id
  99. id: 0, //地址id
  100. userAddress: {
  101. is_default: false
  102. }, //地址详情
  103. isAuto: false, //没有授权的不会自动授权
  104. isShowAuth: false, //是否隐藏授权
  105. district: [],
  106. news: '',
  107. noCoupon: 0,
  108. display: false,
  109. addressInfo:[],
  110. addressVal:'',
  111. latitude:'',
  112. longitude:'',
  113. city_id:0,
  114. isStreet:0,
  115. addressValue:""
  116. };
  117. },
  118. computed: {...mapGetters(['isLogin']),
  119. addressText(){
  120. return this.addressInfo.map(v=>v.label).join('/');
  121. }
  122. },
  123. watch: {
  124. isLogin: {
  125. handler: function(newV, oldV) {
  126. if (newV) {
  127. this.getUserAddress();
  128. }
  129. },
  130. deep: true
  131. }
  132. },
  133. onLoad(options) {
  134. if (this.isLogin) {
  135. this.cartId = options.cartId || '';
  136. this.pinkId = options.pinkId || 0;
  137. this.couponId = options.couponId || 0;
  138. this.id = options.id || 0;
  139. this.noCoupon = options.noCoupon || 0;
  140. this.news = options.new || '';
  141. uni.setNavigationBarTitle({
  142. title: options.id ? '修改地址' : '添加地址'
  143. })
  144. this.getUserAddress();
  145. // this.getCityList();
  146. } else {
  147. toLogin();
  148. }
  149. },
  150. onShow() {
  151. uni.removeStorageSync('form_type_cart');
  152. },
  153. methods: {
  154. changeRegion(){
  155. this.display = true;
  156. },
  157. OnChangeAddress(address){
  158. this.latitude = ''
  159. this.longitude = ''
  160. this.isStreet = 0
  161. this.addressInfo = address;
  162. },
  163. // 地址数据
  164. // getCityList: function() {
  165. // let that = this;
  166. // getCityData(0).then(res => {
  167. // this.district = res.data
  168. // })
  169. // },
  170. // 关闭地址弹窗;
  171. changeClose: function() {
  172. this.display = false;
  173. },
  174. getUserAddress: function() {
  175. if (!this.id) return false;
  176. let that = this;
  177. getAddressDetail(this.id).then(res => {
  178. let region = [{label:res.data.province}, {label:res.data.city}, {label:res.data.district}, {label:res.data.street}];
  179. that.$set(that, 'userAddress', res.data);
  180. that.addressInfo = res.data.city_list;
  181. that.latitude = res.data.latitude;
  182. that.longitude = res.data.longitude;
  183. that.city_id = res.data.city_id;
  184. });
  185. },
  186. // 获取选中位置
  187. chooseLocation: function() {
  188. let self = this;
  189. uni.chooseLocation({
  190. success: (res) => {
  191. let latitude, longitude;
  192. latitude = res.latitude.toString();
  193. longitude = res.longitude.toString();
  194. this.latitude = res.latitude
  195. this.longitude = res.longitude
  196. getGeocoder({
  197. lat: latitude,
  198. long: longitude
  199. }).then(res => {
  200. const data = res.data;
  201. getCityList(data.address_component.province+'/'+data.address_component.city+'/'+data.address_component.district+'/'+(!data.address_reference.town ? '' : data.address_reference.town.title)).then(res=>{
  202. self.addressInfo = res.data;
  203. self.userAddress.detail = data.formatted_addresses.recommend;
  204. }).catch(err => {
  205. self.$util.Tips({
  206. title: err
  207. });
  208. });
  209. })
  210. },
  211. fail: (err)=>{
  212. console.log(err)
  213. }
  214. })
  215. },
  216. // 自动定位
  217. selfLocation() {
  218. let self = this
  219. uni.showLoading({
  220. title: '定位中',
  221. mask: true,
  222. });
  223. uni.getLocation({
  224. type: 'gcj02',
  225. success: (res) => {
  226. let latitude, longitude;
  227. latitude = res.latitude.toString();
  228. longitude = res.longitude.toString();
  229. this.latitude = res.latitude
  230. this.longitude = res.longitude
  231. getGeocoder({
  232. lat: latitude,
  233. long: longitude
  234. }).then(res => {
  235. const data = res.data;
  236. getCityList(data.address_component.province+'/'+data.address_component.city+'/'+data.address_component.district+'/'+(!data.address_reference.town ? '' : data.address_reference.town.title)).then(res=>{
  237. self.addressInfo = res.data;
  238. self.userAddress.detail = data.formatted_addresses.recommend;
  239. uni.hideLoading();
  240. })
  241. })
  242. },
  243. fail: (res) => {
  244. uni.hideLoading();
  245. uni.showToast({
  246. title: res,
  247. icon: 'none',
  248. duration: 1000
  249. });
  250. }
  251. });
  252. },
  253. // 导入共享地址(小程序)
  254. getWxAddress: function() {
  255. let that = this;
  256. uni.authorize({
  257. scope: 'scope.address',
  258. success: function(res) {
  259. uni.chooseAddress({
  260. success: function(res) {
  261. getCityList(res.provinceName+'/'+res.cityName+'/'+res.countyName).then(res=>{
  262. that.addressInfo = res.data;
  263. })
  264. that.userAddress.real_name = res.userName;
  265. that.userAddress.phone = res.telNumber;
  266. that.userAddress.detail = res.detailInfo;
  267. that.isStreet = 1;
  268. },
  269. fail: function(res) {
  270. if (res.errMsg == 'chooseAddress:cancel') return that.$util
  271. .Tips({
  272. title: '取消选择'
  273. });
  274. },
  275. })
  276. },
  277. fail: function(res) {
  278. uni.showModal({
  279. title: '您已拒绝导入微信地址权限',
  280. content: '是否进入权限管理,调整授权?',
  281. success(res) {
  282. if (res.confirm) {
  283. uni.openSetting({
  284. success: function(res) {}
  285. });
  286. } else if (res.cancel) {
  287. return that.$util.Tips({
  288. title: '已取消!'
  289. });
  290. }
  291. }
  292. })
  293. },
  294. })
  295. },
  296. // 导入共享地址(微信);
  297. getAddress() {
  298. let that = this;
  299. that.$wechat.openAddress().then(res => {
  300. getCityList(res.provinceName+'/'+res.cityName+'/'+res.countryName).then(res=>{
  301. that.addressInfo = res.data;
  302. })
  303. that.userAddress.real_name = res.userName;
  304. that.userAddress.phone = res.telNumber;
  305. that.userAddress.detail = res.detailInfo;
  306. that.isStreet = 1;
  307. }).catch(err => {
  308. that.$util.Tips({
  309. title: err
  310. });
  311. });
  312. },
  313. /**
  314. * 提交用户添加地址
  315. *
  316. */
  317. formSubmit: function(e) {
  318. let that = this,
  319. value = e.detail.value;
  320. if (!value.real_name) return that.$util.Tips({
  321. title: '请填写收货人姓名'
  322. });
  323. if (!value.phone) return that.$util.Tips({
  324. title: '请填写联系电话'
  325. });
  326. if (!/^1(3|4|5|7|8|9|6)\d{9}$/i.test(value.phone)) return that.$util.Tips({
  327. title: '请输入正确的手机号码'
  328. });
  329. if (!that.addressInfo.length) return that.$util.Tips({
  330. title: '请选择所在地区'
  331. });
  332. // if (that.region[0] == '省') return that.$util.Tips({
  333. // title: '请选择所在地区'
  334. // });
  335. if (!value.detail) return that.$util.Tips({
  336. title: '请填写详细地址'
  337. });
  338. // if(!that.longitude && !that.latitude) return that.$util.Tips({title:'请定位你的经纬度'})
  339. value.id = that.id;
  340. let regionArray = that.addressInfo;
  341. value.address = {
  342. province: regionArray[0].label,
  343. city: regionArray[1].label,
  344. district: regionArray[2].label,
  345. street: regionArray[3]?regionArray[3].label:'',
  346. city_id: regionArray[regionArray.length-1].id?regionArray[regionArray.length-1].id:that.city_id,
  347. };
  348. value.is_default = that.userAddress.is_default ? 1 : 0;
  349. // 经度
  350. value.longitude = that.longitude;
  351. // 纬度
  352. value.latitude = that.latitude;
  353. uni.showLoading({
  354. title: '保存中',
  355. mask: true
  356. })
  357. editAddress(value).then(res => {
  358. if (that.id)
  359. that.$util.Tips({
  360. title: '修改成功',
  361. icon: 'success'
  362. });
  363. else
  364. that.$util.Tips({
  365. title: '添加成功',
  366. icon: 'success'
  367. });
  368. setTimeout(function() {
  369. if (that.cartId) {
  370. let cartId = that.cartId;
  371. let pinkId = that.pinkId;
  372. let couponId = that.couponId;
  373. that.cartId = '';
  374. that.pinkId = '';
  375. that.couponId = '';
  376. uni.navigateTo({
  377. url: '/pages/goods/order_confirm/index?new=' + that.news +
  378. '&cartId=' + cartId + '&addressId=' + (that.id ? that.id :
  379. res.data.id) + '&pinkId=' + pinkId + '&couponId=' +
  380. couponId +
  381. '&noCoupon=' + that
  382. .noCoupon
  383. });
  384. } else {
  385. uni.navigateTo({
  386. url:'/pages/users/user_address_list/index'
  387. })
  388. }
  389. }, 1000);
  390. }).catch(err => {
  391. return that.$util.Tips({
  392. title: err
  393. });
  394. })
  395. },
  396. ChangeIsDefault: function(e) {
  397. this.$set(this.userAddress, 'is_default', !this.userAddress.is_default);
  398. },
  399. identify(){
  400. const options = {
  401. type: 0, // 哪种方式解析,0:正则,1:树查找
  402. textFilter: [], // 预清洗的字段
  403. nameMaxLength: 4, // 查找最大的中文名字长度
  404. }
  405. const parseResult = AddressParse(this.addressValue.trim(), options)
  406. // type参数0表示使用正则解析,1表示采用树查找, textFilter地址预清洗过滤字段。
  407. if(this.addressValue.trim()){
  408. getCityList(parseResult.province+'/'+parseResult.city+'/'+parseResult.area).then(res=>{
  409. this.addressInfo = res.data;
  410. this.userAddress.phone = parseResult.phone;
  411. this.userAddress.real_name = parseResult.name;
  412. this.userAddress.detail = parseResult.detail;
  413. }).catch(err=>{
  414. return this.$util.Tips({
  415. title: err
  416. });
  417. })
  418. }
  419. }
  420. }
  421. }
  422. </script>
  423. <style scoped lang="scss">
  424. .color-add {
  425. color:#cdcdcd;
  426. }
  427. .fontcolor{
  428. color: var(--view-theme);
  429. }
  430. .addAddress .list {
  431. background-color: #fff;
  432. }
  433. .addAddress .list .item {
  434. padding: 30rpx;
  435. border-top: 1rpx solid #eee;
  436. position: relative;
  437. }
  438. .addAddress .list .item .detail{
  439. width: 368rpx;
  440. }
  441. .addAddress .list .item .location{
  442. position: absolute;
  443. right: 46rpx;
  444. top: 50%;
  445. margin-top: -40rpx!important;
  446. font-size: 24rpx;
  447. text-align: center;
  448. }
  449. .addAddress .list .item .icon-dizhi{
  450. font-size: 36rpx!important;
  451. }
  452. .addAddress .list .item .name {
  453. width: 195rpx;
  454. font-size: 30rpx;
  455. color: #333;
  456. }
  457. .addAddress .list .item .address {
  458. // width: 412rpx;
  459. flex: 1;
  460. margin-left: 20rpx;
  461. }
  462. .addAddress .list .item .address .addressCon{
  463. width: 360rpx;
  464. }
  465. .addAddress .list .item .address .addressCon .tip{
  466. font-size: 21rpx;
  467. margin-top: 4rpx;
  468. }
  469. .addAddress .list .item input {
  470. // width: 475rpx;
  471. flex: 1;
  472. font-size: 30rpx;
  473. }
  474. .placeholder {
  475. color: #ccc;
  476. }
  477. // .addAddress .list .item {
  478. // width: 475rpx;
  479. // }
  480. .addAddress .list .item .picker {
  481. width: 430rpx;
  482. font-size: 30rpx;
  483. }
  484. .addAddress .list .item .iconfont {
  485. font-size: 30rpx;
  486. margin-top: 4rpx;
  487. }
  488. .addAddress .default {
  489. padding: 0 30rpx;
  490. height: 90rpx;
  491. background-color: #fff;
  492. margin-top: 23rpx;
  493. }
  494. .addAddress .default checkbox {
  495. margin-right: 15rpx;
  496. }
  497. .addAddress .keepBnt {
  498. width: 690rpx;
  499. height: 86rpx;
  500. border-radius: 50rpx;
  501. text-align: center;
  502. line-height: 86rpx;
  503. margin: 50rpx auto;
  504. font-size: 32rpx;
  505. color: #fff;
  506. }
  507. .addAddress .wechatAddress {
  508. width: 690rpx;
  509. height: 86rpx;
  510. border-radius: 50rpx;
  511. text-align: center;
  512. line-height: 86rpx;
  513. margin: 0 auto;
  514. font-size: 32rpx;
  515. color: var(--view-theme);
  516. border: 1px solid var(--view-theme);
  517. }
  518. .mt-22{
  519. margin-top: 22rpx;
  520. }
  521. </style>