fix: 重构购物车移动端布局

- 添加移动端专用底部行元素 item-mobile-bottom
- 第一行:复选框+商品信息+删除按钮(绝对定位)
- 第二行:单价+数量选择器+小计(居中分布)
- 使用flex+flex-wrap替代不稳定的grid布局
- 桌面端隐藏移动端元素,移动端显示

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-01 00:08:38 +08:00
parent 51a2496211
commit 5a7c1a0964
+84 -79
View File
@@ -22,17 +22,17 @@
</div>
<div class="cart-list">
<div
v-for="item in items"
:key="item.id"
<div
v-for="item in items"
:key="item.id"
class="cart-item"
:class="{ 'item-disabled': !item.product?.is_active }"
>
<el-checkbox v-model="selectedIds" :value="item.id" />
<el-checkbox v-model="selectedIds" :value="item.id" class="item-check" />
<div class="item-product" @click="$router.push(`/products/${item.product?.id}`)">
<el-image
:src="getFirstImage(item.product?.images)"
<el-image
:src="getFirstImage(item.product?.images)"
fit="cover"
class="item-image"
>
@@ -55,11 +55,11 @@
<p v-if="!item.product?.is_active" class="item-off">已下架</p>
</div>
</div>
<div class="item-price">
<span class="price-current">¥{{ item.product?.price }}</span>
</div>
<div class="item-quantity">
<el-input-number
v-model="item.quantity"
@@ -72,14 +72,27 @@
仅剩 {{ item.product?.stock }}
</span>
</div>
<div class="item-subtotal">
<span class="subtotal-price">¥{{ ((item.product?.price || 0) * item.quantity).toFixed(2) }}</span>
</div>
<div class="item-action">
<el-button link type="danger" size="small" @click="removeItem(item.id)">删除</el-button>
</div>
<!-- 移动端底部行单价+数量+小计 -->
<div class="item-mobile-bottom">
<span class="mobile-price">¥{{ item.product?.price }}</span>
<el-input-number
v-model="item.quantity"
:min="1"
:max="getMaxQuantity(item.product)"
size="small"
@change="(val: number) => updateQuantity(item, val)"
/>
<span class="mobile-subtotal">¥{{ ((item.product?.price || 0) * item.quantity).toFixed(2) }}</span>
</div>
</div>
</div>
</div>
@@ -523,6 +536,7 @@ onMounted(() => {
padding: 16px 20px;
border-bottom: 1px solid rgba(255, 255, 255, 0.04);
transition: background 0.2s;
position: relative;
&:hover {
background: rgba(255, 255, 255, 0.02);
@@ -639,6 +653,11 @@ onMounted(() => {
flex-shrink: 0;
}
/* 移动端底部行 - 桌面端隐藏 */
.item-mobile-bottom {
display: none;
}
.checkout-section {
background: #2d2d44;
border: 1px solid rgba(255, 255, 255, 0.06);
@@ -966,63 +985,84 @@ onMounted(() => {
display: flex !important;
flex-wrap: wrap !important;
padding: 12px !important;
gap: 10px !important;
gap: 8px !important;
align-items: flex-start !important;
}
/* 第一行:复选框 + 商品信息 + 删除 */
.cart-item > .el-checkbox {
order: 1 !important;
flex: 0 0 auto !important;
width: auto !important;
/* 隐藏桌面端元素 */
.cart-item > .item-price,
.cart-item > .item-quantity,
.cart-item > .item-subtotal {
display: none !important;
}
/* 复选框 */
.cart-item > .item-check {
flex: 0 0 20px !important;
width: 20px !important;
margin-right: 0 !important;
}
/* 商品信息 */
.cart-item > .item-product {
order: 2 !important;
flex: 1 1 auto !important;
flex: 1 1 calc(100% - 80px) !important;
min-width: 0 !important;
display: flex !important;
gap: 10px !important;
align-items: flex-start !important;
padding-right: 40px !important;
}
/* 删除按钮 */
.cart-item > .item-action {
order: 3 !important;
position: absolute !important;
right: 12px !important;
top: 12px !important;
flex: 0 0 auto !important;
width: auto !important;
}
/* 第二行:单价 + 数量 + 小计 */
.cart-item > .item-price {
order: 4 !important;
flex: 0 0 auto !important;
/* 移动端底部行 - 显示 */
.item-mobile-bottom {
display: flex !important;
flex: 0 0 100% !important;
width: 100% !important;
align-items: center !important;
margin-left: 32px !important;
width: auto !important;
justify-content: space-between !important;
padding-left: 28px !important;
gap: 8px !important;
margin-top: 4px !important;
}
.cart-item > .item-quantity {
order: 5 !important;
flex: 1 1 auto !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
width: auto !important;
min-width: 100px !important;
.item-mobile-bottom .mobile-price {
font-size: 13px !important;
color: rgba(255, 255, 255, 0.8) !important;
white-space: nowrap !important;
}
.cart-item > .item-subtotal {
order: 6 !important;
flex: 0 0 auto !important;
width: auto !important;
text-align: right !important;
.item-mobile-bottom :deep(.el-input-number) {
width: 90px !important;
}
.item-mobile-bottom :deep(.el-input-number .el-input__wrapper) {
padding: 0 2px !important;
}
.item-mobile-bottom :deep(.el-input-number .el-input__inner) {
font-size: 13px !important;
}
.item-mobile-bottom .mobile-subtotal {
font-size: 15px !important;
font-weight: 600 !important;
color: #f56c6c !important;
white-space: nowrap !important;
}
/* 商品图片 */
.item-product .item-image {
width: 60px !important;
height: 60px !important;
width: 55px !important;
height: 55px !important;
flex-shrink: 0 !important;
border-radius: 6px !important;
}
@@ -1034,9 +1074,9 @@ onMounted(() => {
}
.item-name {
font-size: 14px !important;
line-height: 1.4 !important;
margin-bottom: 4px !important;
font-size: 13px !important;
line-height: 1.35 !important;
margin-bottom: 2px !important;
word-break: break-all !important;
display: -webkit-box !important;
-webkit-line-clamp: 2 !important;
@@ -1045,44 +1085,9 @@ onMounted(() => {
}
.item-tags {
flex-wrap: wrap !important;
gap: 4px !important;
.el-tag {
font-size: 10px !important;
padding: 0 4px !important;
height: 18px !important;
line-height: 16px !important;
}
}
/* 单价 */
.item-price .price-current {
font-size: 14px !important;
}
/* 数量选择器 */
.item-quantity :deep(.el-input-number) {
width: 90px !important;
}
.item-quantity :deep(.el-input-number .el-input__wrapper) {
padding: 0 2px !important;
}
.item-quantity :deep(.el-input-number .el-input__inner) {
font-size: 13px !important;
}
.item-quantity .stock-tip {
display: none !important;
}
/* 小计 */
.item-subtotal .subtotal-price {
font-size: 15px !important;
}
/* 地址 */
.checkout-section {
padding: 12px !important;