address-list.vue 3.75 KB
<template>
  <view class="page-shell address-list-page">
    <view class="page-blur"></view>
    <view class="page-blur-secondary"></view>
    <view class="page-blur-tertiary"></view>

    <view class="page-content subpage-content">
      <view class="subpage-nav">
        <view class="subpage-back" @tap="goBack">‹</view>
        <view class="subpage-title-wrap">
          <text class="subpage-title">地址管理</text>
          <text class="subpage-subtitle">让配送信息保持简洁清晰,也保持足够从容</text>
        </view>
      </view>

      <view v-for="item in addresses" :key="item.id" class="address-card glass-card" @tap="editAddress(item)">
        <view class="address-top">
          <text class="address-name">{{ item.receiverName }}</text>
          <text class="address-phone">{{ item.receiverPhone }}</text>
          <text v-if="item.isDefault === 1" class="default-chip">默认</text>
        </view>
        <text class="address-detail">{{ fullAddress(item) }}</text>
        <view class="address-actions">
          <text v-if="item.isDefault !== 1" class="address-action" @tap.stop="setDefault(item)">设为默认</text>
          <text class="address-action" @tap.stop="editAddress(item)">编辑</text>
        </view>
      </view>

      <view v-if="!addresses.length" class="empty-tip">还没有收货地址,点击下方新增</view>

      <view class="primary-button add-button" @tap="addAddress">新增地址</view>
    </view>
  </view>
</template>

<script>
import { getAddressList, setDefaultAddress } from '@/api/mall'

export default {
  data() {
    return {
      addresses: []
    }
  },
  onShow() {
    this.loadList()
  },
  methods: {
    loadList() {
      getAddressList()
        .then((data) => {
          this.addresses = data || []
        })
        .catch(() => {})
    },
    fullAddress(item) {
      return `${item.province || ''}${item.city || ''}${item.district || ''}${item.detailAddress || ''}`
    },
    setDefault(item) {
      setDefaultAddress(item.id)
        .then(() => {
          uni.showToast({ title: '已设为默认', icon: 'none' })
          this.loadList()
        })
        .catch(() => {})
    },
    goBack() {
      uni.navigateBack({ fail: () => uni.redirectTo({ url: '/pages/profile/profile' }) })
    },
    editAddress(item) {
      uni.navigateTo({ url: `/packageProfile/address-edit/address-edit?id=${item.id}` })
    },
    addAddress() {
      uni.navigateTo({ url: '/packageProfile/address-edit/address-edit?mode=create' })
    }
  }
}
</script>

<style lang="scss" scoped>
@import '@/styles/mixins.scss';
@import '@/styles/subpage.scss';

.address-card {
  padding: 30rpx;
  margin-bottom: 22rpx;
  transition: transform 320ms cubic-bezier(0.22, 1, 0.36, 1), box-shadow 320ms ease;
  animation: lfRevealUp 760ms cubic-bezier(0.22, 1, 0.36, 1) both;
}

.address-card:nth-of-type(1) { animation-delay: 0.08s; }
.address-card:nth-of-type(2) { animation-delay: 0.16s; }
.address-card:nth-of-type(3) { animation-delay: 0.24s; }

.address-card:active {
  transform: translateY(-4rpx);
}

.address-top {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 12rpx;
}

.address-name {
  font-size: 30rpx;
  font-weight: 700;
}

.address-phone {
  font-size: 24rpx;
  color: $text-secondary;
}

.default-chip {
  @include chip-soft;
  padding: 8rpx 18rpx;
  animation: lfPulseSoft 4.8s ease-in-out infinite;
}

.address-detail {
  display: block;
  margin-top: 16rpx;
  font-size: 25rpx;
  line-height: 1.8;
  color: $text-primary;
}

.address-actions {
  display: flex;
  justify-content: flex-end;
  gap: 28rpx;
  margin-top: 18rpx;
}

.address-action {
  font-size: 24rpx;
  color: $brand-primary-deep;
}

.add-button {
  width: 100%;
  animation: lfRevealUp 780ms cubic-bezier(0.22, 1, 0.36, 1) 0.18s both;
}
</style>