index.vue 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. <template>
  2. <view class="container">
  3. <view class="addres-list">
  4. <view class="address-item" v-for="(item, index) in list" :key="index">
  5. <view class="contacts">
  6. <text class="name">{{ item.name }}</text>
  7. <text class="phone">{{ item.phone }}</text>
  8. </view>
  9. <view class="address">
  10. <text class="region" v-for="(region, idx) in item.region" :key="idx">{{ region }}</text>
  11. <text class="detail">{{ item.detail }}</text>
  12. </view>
  13. <view class="line"></view>
  14. <view class="item-option">
  15. <view class="_left">
  16. <label class="item-radio" @click.stop="handleSetDefault(item.address_id)">
  17. <radio class="radio" color="#fa2209" :checked="item.address_id == defaultId"></radio>
  18. <text class="text">{{ item.address_id == defaultId ? '默认' : '选择' }}</text>
  19. </label>
  20. </view>
  21. <view class="_right">
  22. <view class="events">
  23. <view class="event-item" @click="handleUpdate(item.address_id)">
  24. <text class="iconfont icon-edit"></text>
  25. <text class="title">编辑</text>
  26. </view>
  27. <view class="event-item" @click="handleRemove(item.address_id)">
  28. <text class="iconfont icon-delete"></text>
  29. <text class="title">删除</text>
  30. </view>
  31. </view>
  32. </view>
  33. </view>
  34. </view>
  35. </view>
  36. <empty v-if="!list.length" :isLoading="isLoading" tips="亲,暂无收货地址" />
  37. <!-- 底部操作按钮 -->
  38. <view class="footer-fixed">
  39. <view class="btn-wrapper">
  40. <view class="btn-item btn-item-main" @click="handleCreate()">添加新地址</view>
  41. </view>
  42. </view>
  43. </view>
  44. </template>
  45. <script>
  46. import * as AddressApi from '@/api/address'
  47. import Empty from '@/components/empty'
  48. export default {
  49. components: {
  50. Empty
  51. },
  52. data() {
  53. return {
  54. //当前页面参数
  55. options: {},
  56. // 正在加载
  57. isLoading: true,
  58. // 收货地址列表
  59. list: [],
  60. // 默认收货地址
  61. defaultId: null
  62. }
  63. },
  64. /**
  65. * 生命周期函数--监听页面加载
  66. */
  67. onLoad(options) {
  68. // 当前页面参数
  69. this.options = options
  70. },
  71. /**
  72. * 生命周期函数--监听页面显示
  73. */
  74. onShow() {
  75. // 获取页面数据
  76. this.getPageData()
  77. },
  78. methods: {
  79. // 获取页面数据
  80. getPageData() {
  81. const app = this
  82. app.isLoading = true
  83. Promise.all([app.getDefaultId(), app.getAddressList()])
  84. .then(() => {
  85. // 列表排序把默认收货地址放到最前
  86. app.onReorder()
  87. })
  88. .finally(() => app.isLoading = false)
  89. },
  90. // 获取收货地址列表
  91. getAddressList() {
  92. const app = this
  93. return new Promise((resolve, reject) => {
  94. AddressApi.list()
  95. .then(result => {
  96. app.list = result.data.list
  97. resolve(result)
  98. })
  99. .catch(reject)
  100. })
  101. },
  102. // 获取默认的收货地址
  103. getDefaultId() {
  104. return new Promise((resolve, reject) => {
  105. const app = this
  106. AddressApi.defaultId()
  107. .then(result => {
  108. app.defaultId = result.data.defaultId
  109. resolve(result)
  110. })
  111. .catch(reject)
  112. })
  113. },
  114. // 列表排序把默认收货地址放到最前
  115. onReorder() {
  116. const app = this
  117. app.list.sort(item => {
  118. return item.address_id == app.defaultId ? -1 : 1
  119. })
  120. },
  121. /**
  122. * 添加新地址
  123. */
  124. handleCreate() {
  125. this.$navTo('pages/address/create')
  126. },
  127. /**
  128. * 编辑地址
  129. * @param {int} addressId 收货地址ID
  130. */
  131. handleUpdate(addressId) {
  132. this.$navTo('pages/address/update', { addressId })
  133. },
  134. /**
  135. * 删除收货地址
  136. * @param {int} addressId 收货地址ID
  137. */
  138. handleRemove(addressId) {
  139. const app = this
  140. uni.showModal({
  141. title: "提示",
  142. content: "您确定要删除当前收货地址吗?",
  143. success({ confirm }) {
  144. confirm && app.onRemove(addressId)
  145. }
  146. });
  147. },
  148. /**
  149. * 确认删除收货地址
  150. * @param {int} addressId 收货地址ID
  151. */
  152. onRemove(addressId) {
  153. const app = this
  154. AddressApi.remove(addressId)
  155. .then(result => {
  156. app.getPageData()
  157. })
  158. },
  159. /**
  160. * 设置为默认地址
  161. * @param {Object} addressId
  162. */
  163. handleSetDefault(addressId) {
  164. const app = this
  165. AddressApi.setDefault(addressId)
  166. .then(result => {
  167. app.defaultId = addressId
  168. app.options.from === 'checkout' && uni.navigateBack()
  169. })
  170. }
  171. }
  172. }
  173. </script>
  174. <style lang="scss" scoped>
  175. .addres-list {
  176. padding-top: 20rpx;
  177. // 设置ios刘海屏底部横线安全区域
  178. padding-bottom: calc(constant(safe-area-inset-bottom) + 140rpx);
  179. padding-bottom: calc(env(safe-area-inset-bottom) + 140rpx);
  180. }
  181. // 项目内容
  182. .address-item {
  183. margin: 20rpx auto 20rpx auto;
  184. padding: 30rpx 40rpx;
  185. width: 94%;
  186. box-shadow: 0 1rpx 5rpx 0px rgba(0, 0, 0, 0.05);
  187. border-radius: 16rpx;
  188. background: #fff;
  189. }
  190. .contacts {
  191. font-size: 30rpx;
  192. margin-bottom: 16rpx;
  193. .name {
  194. margin-right: 16rpx;
  195. }
  196. }
  197. .address {
  198. font-size: 28rpx;
  199. .region {
  200. margin-right: 10rpx;
  201. }
  202. }
  203. .line {
  204. margin: 20rpx 0;
  205. border-bottom: 1rpx solid #f3f3f3;
  206. }
  207. .item-option {
  208. display: flex;
  209. justify-content: space-between;
  210. height: 48rpx;
  211. // 单选框
  212. .item-radio {
  213. font-size: 28rpx;
  214. .radio {
  215. vertical-align: middle;
  216. transform: scale(0.76)
  217. }
  218. .text {
  219. vertical-align: middle;
  220. }
  221. }
  222. // 操作
  223. .events {
  224. display: flex;
  225. align-items: center;
  226. line-height: 48rpx;
  227. .event-item {
  228. font-size: 28rpx;
  229. margin-right: 26rpx;
  230. color: #4c4c4c;
  231. &:last-child {
  232. margin-right: 0;
  233. }
  234. .title {
  235. margin-left: 8rpx;
  236. }
  237. }
  238. }
  239. }
  240. // 底部操作栏
  241. .footer-fixed {
  242. position: fixed;
  243. bottom: var(--window-bottom);
  244. left: 0;
  245. right: 0;
  246. min-height: 120rpx;
  247. z-index: 11;
  248. box-shadow: 0 -4rpx 40rpx 0 rgba(151, 151, 151, 0.24);
  249. background: #fff;
  250. // 设置ios刘海屏底部横线安全区域
  251. padding-bottom: constant(safe-area-inset-bottom);
  252. padding-bottom: env(safe-area-inset-bottom);
  253. .btn-wrapper {
  254. height: 120rpx;
  255. display: flex;
  256. align-items: center;
  257. padding: 0 40rpx;
  258. }
  259. .btn-item {
  260. flex: 1;
  261. font-size: 28rpx;
  262. height: 80rpx;
  263. line-height: 80rpx;
  264. text-align: center;
  265. color: #fff;
  266. border-radius: 50rpx;
  267. }
  268. .btn-item-main {
  269. background: linear-gradient(to right, #f9211c, #ff6335);
  270. }
  271. }
  272. </style>