更改了购物车逻辑,增加了地址管理

This commit is contained in:
2025-08-27 10:16:48 +08:00
parent 2ae7f21b68
commit ff5b70345e
7 changed files with 1626 additions and 90 deletions

View File

@@ -23,20 +23,43 @@
<div class="address-section">
<div class="address-header">
<el-icon><Location /></el-icon>
<span class="address-label">收货 地址</span>
<el-icon class="edit-icon"><Edit /></el-icon>
<span class="address-label">收货地址</span>
<el-button
type="text"
@click="goToAddressManage"
class="manage-address-btn"
>
管理地址
</el-button>
</div>
<div class="address-content">
<div v-if="!showAddressEdit" class="address-text" @click="showAddressEdit = true">{{ shippingAddress }}</div>
<el-input
v-else
v-model="shippingAddress"
@blur="showAddressEdit = false"
@keyup.enter="showAddressEdit = false"
placeholder="请输入收货地址"
class="address-input"
autofocus
/>
<el-select
v-model="selectedAddressId"
placeholder="请选择收货地址"
class="address-select"
@change="handleAddressChange"
>
<el-option
v-for="address in addresses"
:key="address.id"
:label="`${address.recipientName} ${address.recipientPhone} ${address.province}${address.city}${address.district}${address.detailAddress}`"
:value="address.id"
>
<div class="address-option">
<div class="address-info">
<span class="recipient-info">{{ address.recipientName }} {{ address.recipientPhone }}</span>
<el-tag v-if="address.isDefault" type="danger" size="small" class="default-tag">默认</el-tag>
</div>
<div class="address-detail">{{ address.province }}{{ address.city }}{{ address.district }}{{ address.detailAddress }}</div>
</div>
</el-option>
</el-select>
<div v-if="addresses.length === 0" class="no-address">
<span class="no-address-text">暂无收货地址</span>
<el-button type="text" @click="goToAddressManage" class="add-address-btn">
立即添加
</el-button>
</div>
</div>
</div>
@@ -115,7 +138,6 @@
class="note-input"
autofocus
/>
<el-icon v-if="!showNoteEdit" class="arrow-icon"><ArrowRight /></el-icon>
</div>
</div>
@@ -127,7 +149,7 @@
<el-button
size="large"
class="cart-button"
@click="addToCart"
@click="handleAddToCart"
:disabled="!canPurchase"
>
加入购物车
@@ -170,9 +192,10 @@ const categories = ref([])
const sizes = ref([])
const selectedCategory = ref(null)
const selectedSize = ref(null)
const shippingAddress = ref('请输入收货地址')
const addresses = ref([])
const selectedAddressId = ref('')
const selectedAddress = ref(null)
const orderNote = ref('')
const showAddressEdit = ref(false)
const showNoteEdit = ref(false)
// 计算属性
@@ -272,15 +295,21 @@ const addToCart = async () => {
}
}
// 立即购买功能
const handlePurchase = async () => {
if (!canPurchase.value) {
ElMessage.error('请选择完整的商品信息')
return
}
if (!selectedAddress.value) {
ElMessage.error('请选择收货地址')
return
}
try {
// 先将商品添加到购物车
const cartItem = {
// 创建单独的购买订单
const orderData = {
productId: product.value.id,
quantity: quantity.value,
categoryId: selectedCategory.value.id,
@@ -289,11 +318,11 @@ const handlePurchase = async () => {
name: product.value.name,
image: product.value.image,
stock: product.value.stock,
shippingAddress: shippingAddress.value,
addressId: selectedAddress.value.id,
orderNote: orderNote.value
}
const response = await api.post('/cart/add', cartItem)
const response = await api.post('/cart/buy-now', orderData)
if (response.data.success) {
const cartId = response.data.data.cartId
@@ -306,13 +335,73 @@ const handlePurchase = async () => {
}
})
} else {
throw new Error(response.data.message || '添加到购物车失败')
throw new Error(response.data.message || '创建订单失败')
}
} catch (error) {
ElMessage.error(error.message || '操作失败,请重试')
}
}
// 添加到购物车功能(新增)
const handleAddToCart = async () => {
if (!canPurchase.value) {
ElMessage.error('请选择完整的商品信息')
return
}
try {
const cartItem = {
productId: product.value.id,
quantity: quantity.value,
categoryId: selectedCategory.value.id,
sizeId: selectedSize.value.id,
points: product.value.points,
name: product.value.name,
image: product.value.image,
stock: product.value.stock
}
const response = await api.post('/cart/add', cartItem)
if (response.data.success) {
ElMessage.success('商品已加入购物车!')
// 可以选择返回上一页或跳转到购物车页面
router.go(-1)
} else {
throw new Error(response.data.message || '添加到购物车失败')
}
} catch (error) {
ElMessage.error(error.message || '添加到购物车失败,请重试')
}
}
// 获取用户地址列表
const getAddressList = async () => {
try {
const response = await api.get('/address/list')
addresses.value = response.data.data.addresses || []
// 如果有默认地址,自动选中
const defaultAddress = addresses.value.find(addr => addr.isDefault)
if (defaultAddress) {
selectedAddressId.value = defaultAddress.id
selectedAddress.value = defaultAddress
}
} catch (error) {
console.error('获取地址列表失败:', error)
ElMessage.error('获取地址列表失败')
}
}
// 处理地址选择变化
const handleAddressChange = (addressId) => {
selectedAddress.value = addresses.value.find(addr => addr.id === addressId)
}
// 跳转到地址管理页面
const goToAddressManage = () => {
router.push('/address')
}
// 生命周期
onMounted(() => {
// 从URL参数获取初始数量
@@ -324,6 +413,7 @@ onMounted(() => {
getProductInfo()
getCategories()
getSizes()
getAddressList()
})
</script>
@@ -382,10 +472,7 @@ onMounted(() => {
color: #666;
}
.address-text {
color: #666;
font-size: 14px;
}
.product-section {
background: white;
@@ -557,12 +644,67 @@ onMounted(() => {
color: #999;
}
.arrow-icon {
color: #ccc;
.address-select {
width: 100%;
margin-top: 10px;
}
.address-input {
margin-top: 8px;
.manage-address-btn {
color: #409eff;
font-size: 14px;
margin-left: auto;
}
.manage-address-btn:hover {
color: #66b1ff;
}
.address-option {
padding: 8px 0;
}
.address-info {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 4px;
}
.recipient-info {
font-weight: 500;
color: #303133;
}
.default-tag {
margin-left: 8px;
}
.address-detail {
color: #606266;
font-size: 12px;
line-height: 1.4;
}
.no-address {
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
color: #909399;
font-size: 14px;
}
.no-address-text {
margin-right: 8px;
}
.add-address-btn {
color: #409eff;
font-size: 14px;
}
.add-address-btn:hover {
color: #66b1ff;
}
.note-input {
@@ -575,10 +717,7 @@ onMounted(() => {
flex: 1;
}
.address-text {
cursor: pointer;
padding: 4px 0;
}
.note-content {
cursor: pointer;