index.vue 17 KB

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