index.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605
  1. <template>
  2. <view>
  3. <form @submit="formSubmit" report-submit="true">
  4. <view class="addAddress">
  5. <view class="list borRadius14">
  6. <view class="item acea-row row-between-wrapper" style="border: none">
  7. <view class="name">姓名</view>
  8. <input type="text" placeholder="请输入姓名" placeholder-style="color:#ccc;" name="realName"
  9. :value="userAddress.realName" placeholder-class="placeholder" maxlength="4" />
  10. </view>
  11. <view class="item acea-row row-between-wrapper">
  12. <view class="name">联系电话</view>
  13. <input type="number" placeholder="请输入联系电话" placeholder-style="color:#ccc;" name="phone"
  14. :value="userAddress.phone" placeholder-class="placeholder" maxlength="11" />
  15. </view>
  16. <view class="item acea-row row-between-wrapper relative">
  17. <view class="name">所在地区</view>
  18. <view class="address">
  19. <picker mode="multiSelector" @change="bindRegionChange" @columnchange="bindMultiPickerColumnChange"
  20. :value="valueRegion" :range="multiArray">
  21. <view class="acea-row">
  22. <view class="picker line1">{{ region[0] }},{{ region[1] }},{{ region[2] }}</view>
  23. <image class="abs_right" src="@/static/images/right.png" mode=""></image>
  24. </view>
  25. </picker>
  26. </view>
  27. </view>
  28. <view class="item">
  29. <view class="name">详细地址</view>
  30. <!-- <input type="text" placeholder="请填写具体地址" placeholder-style="color:#ccc;" name="detail"
  31. placeholder-class="placeholder" v-model="userAddress.detail" maxlength="100" /> -->
  32. <view class="ipt">
  33. <textarea v-model="userAddress.detail" maxlength="100" placeholder="请填写具体地址"
  34. placeholder-style="color:#999999;" name="detail"></textarea>
  35. </view>
  36. <view class="iconfont icon-dizhi font-color abs_right" @tap="chooseLocation"></view>
  37. </view>
  38. <view class="item acea-row row-between-wrapper">
  39. <view class="name">设为默认</view>
  40. <switch @change="ChangeIsDefault" color="#F8C008" style="transform:scale(0.8)" :checked="userAddress.isDefault"></switch>
  41. </view>
  42. </view>
  43. <view class="footer">
  44. <button class="keepBnt" form-type="submit">立即保存</button>
  45. </view>
  46. <!-- #ifdef MP -->
  47. <view class="wechatAddress" v-if="!id" @click="getWxAddress">导入微信地址</view>
  48. <!-- #endif -->
  49. <!-- #ifdef H5 -->
  50. <view class="wechatAddress" v-if="wechat.isWeixin() && !id" @click="getAddress">导入微信地址</view>
  51. <!-- #endif -->
  52. </view>
  53. </form>
  54. <!-- #ifdef MP -->
  55. <!-- <authorize @onLoadFun="onLoadFun" :isAuto="isAuto" :isShowAuth="isShowAuth" @authColse="authColse"></authorize> -->
  56. <!-- #endif -->
  57. <!-- <home></home> -->
  58. </view>
  59. </template>
  60. <script setup>
  61. import {
  62. onLoad
  63. } from "@dcloudio/uni-app";
  64. import {
  65. ref,
  66. reactive,
  67. watch
  68. } from "vue";
  69. import {
  70. useAppStore
  71. } from "@/stores/app.js";
  72. import {
  73. editAddress,
  74. getAddressDetail
  75. } from "@/api/user.js";
  76. import {
  77. getCity
  78. } from "@/api/api.js";
  79. import {
  80. toLogin
  81. } from "@/libs/login.js";
  82. import {
  83. useToast
  84. } from "@/hooks/useToast.js";
  85. import wechat from "@/libs/wechat.js";
  86. import Cache from "@/utils/cache";
  87. // #ifdef MP
  88. // import authorize from '@/components/Authorize';
  89. // #endif
  90. import home from "@/components/home";
  91. const {
  92. Toast
  93. } = useToast();
  94. const appStore = useAppStore();
  95. const regionDval = ["浙江省", "杭州市", "滨江区"];
  96. const cartId = ref("");
  97. const pinkId = ref(0);
  98. const couponId = ref(0);
  99. const id = ref(0);
  100. const userAddress = reactive({
  101. isDefault: false,
  102. realName: "",
  103. phone: "",
  104. detail: "",
  105. });
  106. const region = ref(["省", "市", "区"]);
  107. const valueRegion = ref([0, 0, 0]);
  108. const isAuto = ref(false);
  109. const isShowAuth = ref(false);
  110. const district = ref([]);
  111. const multiArray = ref([
  112. [],
  113. [],
  114. []
  115. ]);
  116. const multiIndex = ref([0, 0, 0]);
  117. const cityId = ref(0);
  118. const defaultRegion = ["广东省", "广州市", "番禺区"];
  119. const defaultRegionCode = "440113";
  120. const bargain = ref(false);
  121. const combination = ref(false);
  122. const secKill = ref(false);
  123. const preOrderNo = ref(0);
  124. const isFlashSale = ref(false); // 秒杀标记
  125. const isGroupBuy = ref(false); // 团购标记
  126. watch(
  127. () => appStore.isLogin,
  128. (newV) => {
  129. if (newV) {
  130. getUserAddress();
  131. getCityList();
  132. }
  133. }
  134. );
  135. onLoad((options) => {
  136. if (appStore.isLogin) {
  137. preOrderNo.value = options.preOrderNo || 0;
  138. id.value = options.id || 0;
  139. isFlashSale.value = options.isFlashSale === "1";
  140. isGroupBuy.value = options.isGroupBuy === "1";
  141. uni.setNavigationBarTitle({
  142. title: options.id ? "修改地址" : "新增地址",
  143. });
  144. getUserAddress();
  145. if (Cache.has("cityList")) {
  146. district.value = Cache.getItem("cityList");
  147. initialize();
  148. } else {
  149. getCityList();
  150. }
  151. } else {
  152. toLogin();
  153. }
  154. });
  155. function getCityList() {
  156. getCity().then((res) => {
  157. district.value = res.data;
  158. let oneDay = 24 * 3600 * 1000;
  159. Cache.setItem({
  160. name: "cityList",
  161. value: res.data,
  162. expires: oneDay * 7
  163. }); //设置七天过期时间
  164. initialize();
  165. });
  166. }
  167. function initialize() {
  168. if (district.value.length) {
  169. let province = [],
  170. city = [],
  171. area = [];
  172. let cityChildren = district.value[0].child || [];
  173. let areaChildren = cityChildren.length ? cityChildren[0].child || [] : [];
  174. district.value.forEach((item) => province.push(item.name));
  175. cityChildren.forEach((item) => city.push(item.name));
  176. areaChildren.forEach((item) => area.push(item.name));
  177. multiArray.value = [province, city, area];
  178. }
  179. }
  180. function bindRegionChange(e) {
  181. const mi = multiIndex.value;
  182. const province = district.value[mi[0]] || {
  183. child: []
  184. };
  185. const city = province.child[mi[1]] || {
  186. cityId: 0
  187. };
  188. const ma = multiArray.value;
  189. const value = e.detail.value;
  190. region.value = [ma[0][value[0]], ma[1][value[1]], ma[2][value[2]]];
  191. cityId.value = city.cityId;
  192. valueRegion.value = [0, 0, 0];
  193. initialize();
  194. }
  195. function bindMultiPickerColumnChange(e) {
  196. const column = e.detail.column;
  197. const value = e.detail.value;
  198. const ma = multiArray.value;
  199. const mi = multiIndex.value;
  200. mi[column] = value;
  201. switch (column) {
  202. case 0:
  203. const currentCity = district.value[value] || {
  204. child: []
  205. };
  206. const areaList = currentCity.child[0] || {
  207. child: []
  208. };
  209. ma[1] = currentCity.child.map((item) => item.name);
  210. ma[2] = areaList.child.map((item) => item.name);
  211. break;
  212. case 1:
  213. const cityList = district.value[mi[0]].child[mi[1]].child || [];
  214. ma[2] = cityList.map((item) => item.name);
  215. break;
  216. case 2:
  217. break;
  218. }
  219. multiArray.value = [...ma];
  220. multiIndex.value = [...mi];
  221. }
  222. function getUserAddress() {
  223. if (!id.value) return;
  224. getAddressDetail(id.value).then((res) => {
  225. const regionArr = [res.data.province, res.data.city, res.data.district];
  226. Object.assign(userAddress, res.data);
  227. region.value = regionArr;
  228. cityId.value = res.data.cityId;
  229. });
  230. }
  231. function chooseLocation() {
  232. uni.chooseLocation({
  233. success: (res) => {
  234. userAddress.detail = res.address.replace(
  235. /.+?(省|市|自治区|自治州|县|区)/g,
  236. ""
  237. );
  238. },
  239. });
  240. }
  241. // 导入微信地址(小程序)
  242. function getWxAddress() {
  243. uni.authorize({
  244. scope: "scope.address",
  245. success: function() {
  246. uni.chooseAddress({
  247. success: function(res) {
  248. let addressP = {
  249. province: res.provinceName,
  250. city: res.cityName,
  251. district: res.countyName,
  252. cityId: 0,
  253. };
  254. editAddress({
  255. address: addressP,
  256. isDefault: 1,
  257. realName: res.userName,
  258. postCode: res.postalCode,
  259. phone: res.telNumber,
  260. detail: res.detailInfo,
  261. id: 0,
  262. })
  263. .then((res2) => {
  264. setTimeout(() => {
  265. const newAddressId = id.value ? id.value : res2.data.id;
  266. if (isFlashSale.value && preOrderNo.value > 0) {
  267. // 秒杀页面
  268. uni.redirectTo({
  269. url: `/pages/users/utils/flashSale/confirmOrder?preOrderNo=${preOrderNo.value}&addressId=${newAddressId}`,
  270. });
  271. } else if (isGroupBuy.value && preOrderNo.value > 0) {
  272. // 团购页面
  273. uni.redirectTo({
  274. url: `/pages/group_buying/paydetail?preOrderNo=${preOrderNo.value}&addressId=${newAddressId}`,
  275. });
  276. } else if (cartId.value) {
  277. let url =
  278. `/pages/users/order_confirm/index?cartId=${cartId.value}&addressId=${newAddressId}&pinkId=${pinkId.value}&couponId=${couponId.value}&secKill=${secKill.value}&combination=${combination.value}&bargain=${bargain.value}`;
  279. cartId.value = "";
  280. pinkId.value = "";
  281. couponId.value = "";
  282. uni.navigateTo({
  283. url
  284. });
  285. } else {
  286. uni.navigateBack({
  287. delta: 1
  288. });
  289. }
  290. }, 1000);
  291. Toast({
  292. title: "添加成功",
  293. icon: "success"
  294. });
  295. })
  296. .catch((err) => {
  297. Toast({
  298. title: err
  299. });
  300. });
  301. },
  302. fail: function(res) {
  303. if (res.errMsg == "chooseAddress:cancel")
  304. return Toast({
  305. title: "取消选择"
  306. });
  307. },
  308. });
  309. },
  310. fail: function() {
  311. uni.showModal({
  312. title: "您已拒绝导入微信地址权限",
  313. content: "是否进入权限管理,调整授权?",
  314. success(res) {
  315. if (res.confirm) {
  316. uni.openSetting({});
  317. } else if (res.cancel) {
  318. Toast({
  319. title: "已取消!"
  320. });
  321. }
  322. },
  323. });
  324. },
  325. });
  326. }
  327. // 导入共享地址(微信);
  328. function getAddress() {
  329. wechat
  330. .openAddress()
  331. .then((userInfo) => {
  332. editAddress({
  333. id: id.value,
  334. realName: userInfo.userName,
  335. phone: userInfo.telNumber,
  336. address: {
  337. province: userInfo.provinceName,
  338. city: userInfo.cityName,
  339. district: userInfo.countryName,
  340. cityId: 0,
  341. },
  342. detail: userInfo.detailInfo,
  343. isDefault: 1,
  344. postCode: userInfo.postalCode,
  345. })
  346. .then((res2) => {
  347. setTimeout(() => {
  348. const newAddressId = id.value ? id.value : res2.data.id;
  349. if (isFlashSale.value && preOrderNo.value > 0) {
  350. // 秒杀页面
  351. uni.navigateTo({
  352. url: `/pages/users/utils/flashSale/confirmOrder?preOrderNo=${preOrderNo.value}&addressId=${newAddressId}`,
  353. });
  354. } else if (isGroupBuy.value && preOrderNo.value > 0) {
  355. // 团购页面
  356. uni.navigateTo({
  357. url: `/pages/group_buying/paydetail?preOrderNo=${preOrderNo.value}&addressId=${newAddressId}`,
  358. });
  359. } else if (cartId.value) {
  360. let url =
  361. `/pages/users/order_confirm/index?cartId=${cartId.value}&addressId=${newAddressId}&pinkId=${pinkId.value}&couponId=${couponId.value}&secKill=${secKill.value}&combination=${combination.value}&bargain=${bargain.value}`;
  362. cartId.value = "";
  363. pinkId.value = "";
  364. couponId.value = "";
  365. uni.navigateTo({
  366. url
  367. });
  368. } else {
  369. uni.navigateTo({
  370. url: "/pages/users/user_address_list/index"
  371. });
  372. }
  373. }, 1000);
  374. Toast({
  375. title: "添加成功",
  376. icon: "success"
  377. });
  378. })
  379. .catch((err) => {
  380. Toast({
  381. title: err || "添加失败"
  382. });
  383. });
  384. })
  385. .catch((err) => {
  386. console.log(err);
  387. });
  388. }
  389. function formSubmit(e) {
  390. const value = e.detail.value;
  391. if (!value.realName) return Toast({
  392. title: "请填写收货人姓名"
  393. });
  394. if (!value.phone) return Toast({
  395. title: "请填写联系电话"
  396. });
  397. if (!/^1(3|4|5|7|8|9|6)\d{9}$/i.test(value.phone))
  398. return Toast({
  399. title: "请输入正确的手机号码"
  400. });
  401. if (region.value == "省-市-区") return Toast({
  402. title: "请选择所在地区"
  403. });
  404. if (!value.detail) return Toast({
  405. title: "请填写详细地址"
  406. });
  407. value.id = id.value;
  408. let regionArray = region.value;
  409. value.address = {
  410. province: regionArray[0],
  411. city: regionArray[1],
  412. district: regionArray[2],
  413. cityId: cityId.value,
  414. };
  415. value.isDefault = userAddress.isDefault;
  416. uni.showLoading({
  417. title: "保存中",
  418. mask: true,
  419. });
  420. editAddress(value)
  421. .then((res2) => {
  422. Toast({
  423. title: id.value ? "修改成功" : "添加成功",
  424. icon: "success",
  425. });
  426. setTimeout(() => {
  427. const newAddressId = id.value ? id.value : res2.data.id;
  428. // 根据来源页面返回到相应的页面
  429. if (isFlashSale.value && preOrderNo.value > 0) {
  430. // 秒杀页面:返回秒杀确认订单页
  431. uni.redirectTo({
  432. url: `/pages/users/utils/flashSale/confirmOrder?preOrderNo=${preOrderNo.value}&addressId=${newAddressId}`,
  433. });
  434. } else if (isGroupBuy.value && preOrderNo.value > 0) {
  435. // 团购页面:返回团购支付详情页
  436. uni.redirectTo({
  437. url: `/pages/group_buying/paydetail?preOrderNo=${preOrderNo.value}&addressId=${newAddressId}`,
  438. });
  439. } else if (preOrderNo.value > 0) {
  440. // 普通订单确认页
  441. uni.redirectTo({
  442. url: `/pages/users/order_confirm/index?preOrderNo=${preOrderNo.value}&addressId=${newAddressId}`,
  443. });
  444. } else {
  445. // 没有来源页面,直接返回
  446. // #ifdef H5
  447. history.back();
  448. // #endif
  449. // #ifndef H5
  450. uni.navigateBack({
  451. delta: 1
  452. });
  453. // #endif
  454. }
  455. }, 1000);
  456. })
  457. .catch((err) => {
  458. Toast({
  459. title: err
  460. });
  461. });
  462. }
  463. function ChangeIsDefault() {
  464. userAddress.isDefault = !userAddress.isDefault;
  465. }
  466. </script>
  467. <style>
  468. page {
  469. background: #F9F7F0;
  470. }
  471. </style>
  472. <style scoped lang="scss">
  473. .addAddress {}
  474. .addAddress .list {
  475. padding: 16rpx;
  476. }
  477. .addAddress .list .item {
  478. padding: 28rpx 16rpx;
  479. border-radius: 16rpx;
  480. background: #FFFFFF;
  481. margin-bottom: 16rpx;
  482. &:last-child {
  483. margin-bottom: 0;
  484. }
  485. }
  486. .addAddress .list .item .name {
  487. font-size: 28rpx;
  488. color: #333333;
  489. }
  490. .addAddress .list .item .address {
  491. flex: 1;
  492. }
  493. .addAddress .list .item input {
  494. flex: 1;
  495. text-align: right;
  496. font-size: 28rpx;
  497. }
  498. .addAddress .list .item .placeholder {
  499. color: #ccc;
  500. }
  501. .addAddress .list .item picker .picker {
  502. flex: 1;
  503. text-align: right;
  504. font-size: 28rpx;
  505. }
  506. .ipt {
  507. margin-top: 16rpx;
  508. padding: 16rpx;
  509. height: 264rpx;
  510. background: #F9F7F0;
  511. border-radius: 16rpx;
  512. textarea {
  513. font-size: 28rpx;
  514. }
  515. }
  516. .acea-row {
  517. align-items: center;
  518. }
  519. .footer {
  520. width: 100%;
  521. bottom: 0;
  522. position: fixed;
  523. padding: 22rpx 32rpx 56rpx;
  524. }
  525. .addAddress .keepBnt {
  526. background: #F8C008;
  527. border-radius: 16rpx;
  528. text-align: center;
  529. line-height: 88rpx;
  530. font-size: 32rpx;
  531. color: #333333;
  532. font-weight: bold;
  533. &::after {
  534. width: 0;
  535. border: none;
  536. }
  537. }
  538. .addAddress .wechatAddress {
  539. width: 690rpx;
  540. height: 86rpx;
  541. border-radius: 50rpx;
  542. text-align: center;
  543. line-height: 86rpx;
  544. margin: 0 auto;
  545. font-size: 32rpx;
  546. color: #e93323;
  547. border: 1px solid #e93323;
  548. }
  549. .relative {
  550. position: relative;
  551. }
  552. .icon-dizhi {
  553. font-size: 44rpx;
  554. z-index: 100;
  555. }
  556. .abs_right {
  557. width: 32rpx;
  558. height: 32rpx;
  559. margin-left: 16rpx;
  560. }
  561. </style>