Files
medical-mall/pages/mall/consumer/address-list copy.uvue
2026-01-30 17:29:02 +08:00

220 lines
5.4 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="address-list-page">
<view class="address-list">
<view v-if="addresses.length === 0" class="empty-state">
<text class="empty-icon">📍</text>
<text class="empty-text">暂无收货地址</text>
</view>
<view v-else v-for="(item, index) in addresses" :key="item.id" class="address-item" @click="selectAddress(item)">
<view class="item-content">
<view class="item-header">
<text class="user-name">{{ item.name }}</text>
<text class="user-phone">{{ item.phone }}</text>
<text v-if="item.isDefault" class="default-tag">默认</text>
<text v-if="item.label" class="label-tag">{{ item.label }}</text>
</view>
<text class="address-text">{{ getFullAddress(item) }}</text>
</view>
<view class="item-actions">
<view class="action-item" @click.stop="editAddress(item.id)">
<text class="action-icon">📝</text>
</view>
<view class="action-item" @click.stop="deleteAddress(item.id)">
<text class="action-icon"><3E></text>
</view>
</view>
</view>
</view>
<view class="footer-btn">
<button class="add-btn" @click="addAddress">新建收货地址</button>
</view>
</view>
</template>
<script setup lang="uts">
import { ref, onMounted } from 'vue'
import { onShow } from '@dcloudio/uni-app'
type Address = {
id: string
name: string
phone: string
province: string
city: string
district: string
detail: string
isDefault: boolean
label?: string
}
const addresses = ref<Address[]>([])
const selectionMode = ref<boolean>(false)
let openerEventChannel: any = null
onShow(() => {
loadAddresses()
})
onMounted(() => {
try {
const ec = uni.getOpenerEventChannel()
openerEventChannel = ec
ec?.on('setSelectMode', (data: any) => {
if (data && typeof data.selectMode === 'boolean') {
selectionMode.value = data.selectMode
}
})
} catch (e) {
// ignore
}
})
const loadAddresses = () => {
const storedAddresses = uni.getStorageSync('addresses')
if (storedAddresses) {
try {
addresses.value = JSON.parse(storedAddresses as string) as Address[]
} catch (e) {
console.error('Failed to parse addresses', e)
addresses.value = []
}
} else {
// 初始Mock数据
addresses.value = [
{
id: 'addr_001',
name: '张三',
phone: '13800138000',
province: '北京市',
city: '北京市',
district: '朝阳区',
detail: '三里屯SOHO A座',
isDefault: true,
label: '公司'
}
]
uni.setStorageSync('addresses', JSON.stringify(addresses.value))
}
}
const getFullAddress = (item: Address): string => {
return `${item.province}${item.city}${item.district} ${item.detail}`
}
const addAddress = () => {
uni.navigateTo({
url: '/pages/mall/consumer/address-edit'
})
}
// 删除地址
const deleteAddress = (id: string) => {
uni.showModal({
title: '提示',
content: '确定要删除该地址吗?',
success: (res) => {
if (res.confirm) {
const index = addresses.value.findIndex(addr => addr.id === id)
if (index !== -1) {
addresses.value.splice(index, 1)
uni.setStorageSync('addresses', JSON.stringify(addresses.value))
uni.showToast({
title: '删除成功',
icon: 'success'
})
}
}
}
})
}
const editAddress = (id: string) => {
uni.navigateTo({
url: `/pages/mall/consumer/address-edit?id=${id}`
})
}
const selectAddress = (item: Address) => {
if (selectionMode.value && openerEventChannel) {
openerEventChannel.emit('addressSelected', {
id: item.id,
recipient_name: item.name,
phone: item.phone,
province: item.province,
city: item.city,
district: item.district,
detail: item.detail,
is_default: item.isDefault
})
uni.navigateBack()
} else {
editAddress(item.id)
}
}
</script>
<style>
.item-actions {
padding: 10px;
border-left: 1px solid #f0f0f0;
display: flex;
flex-direction: column; /* 竖向排列图标 */
justify-content: center;
align-items: center;
gap: 15px;
}
.footer-btn {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background-color: white;
padding: 10px 15px;
padding-bottom: calc(10px + env(safe-area-inset-bottom));
box-shadow: 0 -2px 10px rgba(0,0,0,0.05);
display: flex;
justify-content: center; /* 居中显示 */
align-items: center;
}
.add-btn {
background-color: #ff5000;
color: white;
border-radius: 25px;
font-size: 16px;
height: 44px;
line-height: 44px;
border: none;
width: 100%; /* 默认占满 */
max-width: 100%;
}
/* 响应式布局优化 */
@media screen and (min-width: 768px) {
.address-list {
max-width: 800px;
margin: 0 auto;
}
.address-list-page {
background-color: #f5f5f5;
}
.footer-btn {
max-width: 800px;
margin: 0 auto;
left: 50%;
transform: translateX(-50%);
box-shadow: 0 -2px 10px rgba(0,0,0,0.05);
border-radius: 12px 12px 0 0; /* 桌面端加点圆角更美观 */
}
.add-btn {
width: 300px; /* 桌面端限制宽度 */
}
}
</style>