index.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661
  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. const openAddress = uni.getStorageSync('addressOpen')||false;
  221. if(!openAddress){
  222. uni.showModal({
  223. title: '权限申请',
  224. content: '是否允许APP使用定位功能用于配送货',
  225. success: res => {
  226. if(res.confirm){
  227. this.openAddress();
  228. uni.setStorageSync("addressOpen",true)
  229. }
  230. },
  231. });
  232. }else{
  233. this.openAddress();
  234. }
  235. },
  236. openAddress(){
  237. uni.chooseLocation({
  238. success: (res) => {
  239. let latitude, longitude;
  240. latitude = res.latitude.toString();
  241. longitude = res.longitude.toString();
  242. this.latitude = res.latitude
  243. this.longitude = res.longitude
  244. getGeocoder({
  245. lat: latitude,
  246. long: longitude
  247. }).then(res => {
  248. const data = res.data;
  249. getCityList(data.address_component.province + '/' + data.address_component.city + '/' + data.address_component.district + '/' + (!data
  250. .address_reference.town ? '' : data.address_reference.town.title)).then(res => {
  251. self.addressInfo = res.data;
  252. self.userAddress.detail = data.formatted_addresses.recommend;
  253. }).catch(err => {
  254. self.$util.Tips({
  255. title: err
  256. });
  257. });
  258. })
  259. },
  260. fail: (err) => {
  261. console.log(err)
  262. }
  263. })
  264. },
  265. // 自动定位
  266. selfLocation() {
  267. let self = this
  268. uni.showLoading({
  269. title: '定位中',
  270. mask: true,
  271. });
  272. uni.getLocation({
  273. type: 'gcj02',
  274. success: (res) => {
  275. let latitude, longitude;
  276. latitude = res.latitude.toString();
  277. longitude = res.longitude.toString();
  278. this.latitude = res.latitude
  279. this.longitude = res.longitude
  280. getGeocoder({
  281. lat: latitude,
  282. long: longitude
  283. }).then(res => {
  284. const data = res.data;
  285. getCityList(data.address_component.province + '/' + data.address_component.city + '/' + data.address_component.district + '/' + (!data.address_reference
  286. .town ? '' : data.address_reference.town.title)).then(res => {
  287. self.addressInfo = res.data;
  288. self.userAddress.detail = data.formatted_addresses.recommend;
  289. uni.hideLoading();
  290. })
  291. })
  292. },
  293. fail: (res) => {
  294. uni.hideLoading();
  295. uni.showToast({
  296. title: res,
  297. icon: 'none',
  298. duration: 1000
  299. });
  300. }
  301. });
  302. },
  303. // 导入共享地址(小程序)
  304. getWxAddress: function() {
  305. let that = this;
  306. uni.authorize({
  307. scope: 'scope.address',
  308. success: function(res) {
  309. uni.chooseAddress({
  310. success: function(res) {
  311. getCityList(res.provinceName + '/' + res.cityName + '/' + res.countyName + '/' + res.streetName).then(res => {
  312. that.addressInfo = res.data;
  313. }).catch(err=>{
  314. return that.$util.Tips({
  315. title: err
  316. });
  317. })
  318. that.userAddress.real_name = res.userName;
  319. that.userAddress.phone = res.telNumber;
  320. that.userAddress.detail = res.detailInfo;
  321. },
  322. fail: function(res) {
  323. if (res.errMsg == 'chooseAddress:cancel') return that.$util
  324. .Tips({
  325. title: '取消选择'
  326. });
  327. },
  328. })
  329. },
  330. fail: function(res) {
  331. uni.showModal({
  332. title: '您已拒绝导入微信地址权限',
  333. content: '是否进入权限管理,调整授权?',
  334. success(res) {
  335. if (res.confirm) {
  336. uni.openSetting({
  337. success: function(res) {}
  338. });
  339. } else if (res.cancel) {
  340. return that.$util.Tips({
  341. title: '已取消!'
  342. });
  343. }
  344. }
  345. })
  346. },
  347. })
  348. },
  349. // 导入共享地址(微信);
  350. getAddress() {
  351. let that = this;
  352. that.$wechat.openAddress().then(res => {
  353. getCityList(res.provinceName + '/' + res.cityName + '/' + res.countryName + '/' + res.streetName).then(res => {
  354. that.addressInfo = res.data;
  355. })
  356. that.userAddress.real_name = res.userName;
  357. that.userAddress.phone = res.telNumber;
  358. that.userAddress.detail = res.detailInfo;
  359. }).catch(err => {
  360. that.$util.Tips({
  361. title: err
  362. });
  363. });
  364. },
  365. /**
  366. * 提交用户添加地址
  367. *
  368. */
  369. formSubmit: function(e) {
  370. let that = this,
  371. value = e.detail.value;
  372. if (!value.real_name) return that.$util.Tips({
  373. title: '请填写收货人姓名'
  374. });
  375. if (!value.phone) return that.$util.Tips({
  376. title: '请填写联系电话'
  377. });
  378. if (!/^1(3|4|5|7|8|9|6)\d{9}$/i.test(value.phone)) return that.$util.Tips({
  379. title: '请输入正确的手机号码'
  380. });
  381. if (!that.addressInfo.length) return that.$util.Tips({
  382. title: '请选择所在地区'
  383. });
  384. if (that.addressInfo.length < 3) return that.$util.Tips({
  385. title: '请补全所在地区信息'
  386. });
  387. // if (that.region[0] == '省') return that.$util.Tips({
  388. // title: '请选择所在地区'
  389. // });
  390. if (!value.detail) return that.$util.Tips({
  391. title: '请填写详细地址'
  392. });
  393. // if(!that.longitude && !that.latitude) return that.$util.Tips({title:'请定位你的经纬度'})
  394. value.id = that.id;
  395. let regionArray = that.addressInfo;
  396. value.address = {
  397. province: regionArray[0].label,
  398. city: regionArray[1].label,
  399. district: regionArray[2].label,
  400. street: regionArray[3] ? regionArray[3].label : '',
  401. city_id: regionArray[regionArray.length - 1].id ? regionArray[regionArray.length - 1].id : that.city_id,
  402. };
  403. value.is_default = that.userAddress.is_default ? 1 : 0;
  404. // 经度
  405. value.longitude = that.longitude;
  406. // 纬度
  407. value.latitude = that.latitude;
  408. uni.showLoading({
  409. title: '保存中',
  410. mask: true
  411. })
  412. editAddress(value).then(res => {
  413. if (that.id)
  414. that.$util.Tips({
  415. title: '修改成功',
  416. icon: 'success'
  417. });
  418. else
  419. that.$util.Tips({
  420. title: '添加成功',
  421. icon: 'success'
  422. });
  423. setTimeout(function() {
  424. if (that.cartId) {
  425. let cartId = that.cartId;
  426. let pinkId = that.pinkId;
  427. let couponId = that.couponId;
  428. that.cartId = '';
  429. that.pinkId = '';
  430. that.couponId = '';
  431. uni.navigateTo({
  432. url: '/pages/goods/order_confirm/index?new=' + that.news +
  433. '&cartId=' + cartId + '&addressId=' + (that.id ? that.id :
  434. res.data.id) + '&pinkId=' + pinkId + '&couponId=' +
  435. couponId +
  436. '&noCoupon=' + that
  437. .noCoupon + '&delivery_type=' + that.deliveryType + '&store_id=' + that.storeId + '&store_name=' + that.store_name + '&product_id=' + that
  438. .product_id
  439. });
  440. } else if(that.fromType){
  441. uni.$emit('activeAddress');
  442. uni.navigateBack();
  443. } else {
  444. uni.navigateTo({
  445. url: '/pages/users/user_address_list/index'
  446. })
  447. }
  448. }, 1000);
  449. }).catch(err => {
  450. return that.$util.Tips({
  451. title: err
  452. });
  453. })
  454. },
  455. ChangeIsDefault: function(e) {
  456. this.$set(this.userAddress, 'is_default', !this.userAddress.is_default);
  457. },
  458. identify() {
  459. const options = {
  460. type: 0, // 哪种方式解析,0:正则,1:树查找
  461. textFilter: [], // 预清洗的字段
  462. nameMaxLength: 4, // 查找最大的中文名字长度
  463. }
  464. const parseResult = AddressParse(this.addressValue.trim(), options)
  465. // type参数0表示使用正则解析,1表示采用树查找, textFilter地址预清洗过滤字段。
  466. if (this.addressValue.trim()) {
  467. getCityList(parseResult.province + '/' + parseResult.city + '/' + parseResult.area).then(res => {
  468. this.addressInfo = res.data;
  469. this.userAddress.phone = parseResult.phone;
  470. this.userAddress.real_name = parseResult.name;
  471. this.userAddress.detail = parseResult.detail;
  472. }).catch(err => {
  473. return this.$util.Tips({
  474. title: err
  475. });
  476. })
  477. }
  478. }
  479. }
  480. }
  481. </script>
  482. <style scoped lang="scss">
  483. .color-add {
  484. color: #cdcdcd;
  485. }
  486. .location1 {
  487. .iconfont {
  488. margin-right: 8rpx;
  489. }
  490. }
  491. .fontcolor {
  492. color: var(--view-theme);
  493. }
  494. .addAddress {
  495. padding: 24rpx 20rpx;
  496. }
  497. .addAddress .input-wrapper {
  498. margin-bottom: 20rpx;
  499. }
  500. .addAddress .list {
  501. padding: 8rpx 0;
  502. border-radius: 16rpx;
  503. background-color: #fff;
  504. }
  505. .addAddress .list .item {
  506. padding: 32rpx 24rpx;
  507. // border-top: 1rpx solid #eee;
  508. position: relative;
  509. }
  510. .addAddress .list .item .detail {
  511. width: 368rpx;
  512. }
  513. .addAddress .list .item .location {
  514. position: absolute;
  515. right: 46rpx;
  516. top: 50%;
  517. margin-top: -40rpx !important;
  518. font-size: 24rpx;
  519. text-align: center;
  520. }
  521. .addAddress .list .item .icon-dizhi {
  522. font-size: 36rpx !important;
  523. }
  524. .addAddress .list .item .name {
  525. width: 195rpx;
  526. font-size: 30rpx;
  527. color: #333;
  528. }
  529. .addAddress .list .item .address {
  530. // width: 412rpx;
  531. flex: 1;
  532. // margin-left: 20rpx;
  533. }
  534. .addAddress .list .item .address .addressCon {
  535. width: 360rpx;
  536. }
  537. .addAddress .list .item .address .addressCon .tip {
  538. font-size: 21rpx;
  539. margin-top: 4rpx;
  540. }
  541. .addAddress .list .item input {
  542. // width: 475rpx;
  543. flex: 1;
  544. font-size: 30rpx;
  545. }
  546. .placeholder {
  547. color: #ccc;
  548. }
  549. // .addAddress .list .item {
  550. // width: 475rpx;
  551. // }
  552. .addAddress .list .item .picker {
  553. width: 430rpx;
  554. font-size: 30rpx;
  555. }
  556. .addAddress .list .item .iconfont {
  557. font-size: 30rpx;
  558. margin-top: 4rpx;
  559. }
  560. .addAddress .default {
  561. padding: 0 25rpx;
  562. height: 128rpx;
  563. border-radius: 16rpx;
  564. background-color: #fff;
  565. }
  566. .addAddress .default .switch {
  567. position: relative;
  568. width: 79rpx;
  569. height: 46rpx;
  570. border: 2rpx solid #DDDDDD;
  571. border-radius: 46rpx;
  572. background-color: #DDDDDD;
  573. transition: background-color 0.3s;
  574. box-sizing: content-box;
  575. &.on {
  576. border-color: var(--view-theme);
  577. background-color: var(--view-theme);
  578. .inner {
  579. transform: translateX(33rpx);
  580. }
  581. }
  582. }
  583. .addAddress .default .switch .inner {
  584. position: absolute;
  585. top: 2rpx;
  586. left: 2rpx;
  587. width: 42rpx;
  588. height: 42rpx;
  589. border-radius: 100%;
  590. background-color: #FFFFFF;
  591. box-shadow: 0rpx 3rpx 6rpx 0rpx rgba(0, 0, 0, 0.08);
  592. transition: transform 0.3s cubic-bezier(0.3, 1.05, 0.4, 1.05);
  593. }
  594. .addAddress .default checkbox {
  595. margin-right: 15rpx;
  596. }
  597. .addAddress .keepBnt {
  598. position: fixed;
  599. right: 20rpx;
  600. bottom: 40rpx;
  601. left: 20rpx;
  602. height: 80rpx;
  603. border-radius: 40rpx;
  604. text-align: center;
  605. line-height: 80rpx;
  606. font-size: 28rpx;
  607. color: #fff;
  608. }
  609. .addAddress .wechatAddress {
  610. // width: 690rpx;
  611. height: 100rpx;
  612. padding: 0 24rpx;
  613. border-radius: 24rpx;
  614. background-color: #FFFFFF;
  615. text-align: center;
  616. line-height: 100rpx;
  617. margin: 0 0 20rpx;
  618. font-size: 30rpx;
  619. color: #3D3D3D;
  620. // border: 1px solid var(--view-theme);
  621. .icon-ic_wechat {
  622. margin-right: 20rpx;
  623. font-size: 48rpx;
  624. color: #00C800;
  625. }
  626. }
  627. .mt-22 {
  628. margin-top: 22rpx;
  629. }
  630. </style>