fix: 简化购物车移动端布局结构
- 统一桌面/移动端DOM结构,避免重复 - 移动端:复选框+图片+内容区三列布局 - 内容区内:标题行(名称+删除按钮),底部行(价格+数量) - 删除按钮与商品名同行,右对齐 - 价格和数量选择器在底部行,左右分布 - 整体结构更清晰,元素位置更合理 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -31,34 +31,7 @@
|
||||
<!-- 复选框 -->
|
||||
<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)"
|
||||
fit="cover"
|
||||
class="item-image"
|
||||
>
|
||||
<template #error>
|
||||
<div class="image-placeholder">
|
||||
<el-icon><Picture /></el-icon>
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
<div class="item-info">
|
||||
<h4 class="item-name">{{ item.product?.name }}</h4>
|
||||
<div class="item-tags">
|
||||
<el-tag v-if="item.product?.require_credit" size="small" type="warning">
|
||||
需要: {{ item.product?.credit_cost }}
|
||||
</el-tag>
|
||||
<el-tag v-if="item.product?.credit_reward > 0" size="small" type="success">
|
||||
+{{ item.product?.credit_reward }}
|
||||
</el-tag>
|
||||
</div>
|
||||
<p v-if="!item.product?.is_active" class="item-off">已下架</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 移动端商品图片 -->
|
||||
<!-- 商品图片 -->
|
||||
<div class="item-image-wrap" @click="$router.push(`/products/${item.product?.id}`)">
|
||||
<el-image
|
||||
:src="getFirstImage(item.product?.images)"
|
||||
@@ -73,12 +46,14 @@
|
||||
</el-image>
|
||||
</div>
|
||||
|
||||
<!-- 移动端商品信息区 -->
|
||||
<!-- 商品信息区 -->
|
||||
<div class="item-content">
|
||||
<div class="item-header">
|
||||
<!-- 标题行:商品名 + 删除按钮 -->
|
||||
<div class="item-title-row">
|
||||
<h4 class="item-name" @click="$router.push(`/products/${item.product?.id}`)">{{ item.product?.name }}</h4>
|
||||
<el-button class="item-delete" link type="danger" size="small" @click="removeItem(item.id)">删除</el-button>
|
||||
<el-button class="btn-delete" link type="danger" @click.stop="removeItem(item.id)">删除</el-button>
|
||||
</div>
|
||||
<!-- 标签 -->
|
||||
<div class="item-tags" v-if="item.product?.require_credit || item.product?.credit_reward > 0">
|
||||
<el-tag v-if="item.product?.require_credit" size="small" type="warning">
|
||||
需要: {{ item.product?.credit_cost }}
|
||||
@@ -88,23 +63,27 @@
|
||||
</el-tag>
|
||||
</div>
|
||||
<p v-if="!item.product?.is_active" class="item-off">已下架</p>
|
||||
<div class="item-footer">
|
||||
<span class="item-price-mobile">¥{{ 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)"
|
||||
/>
|
||||
<!-- 底部:价格 + 数量 -->
|
||||
<div class="item-bottom-row">
|
||||
<span class="item-price-val">¥{{ item.product?.price }}</span>
|
||||
<div class="quantity-wrap">
|
||||
<el-input-number
|
||||
v-model="item.quantity"
|
||||
:min="1"
|
||||
:max="getMaxQuantity(item.product)"
|
||||
size="small"
|
||||
@change="(val: number) => updateQuantity(item, val)"
|
||||
/>
|
||||
</div>
|
||||
</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"
|
||||
@@ -118,10 +97,12 @@
|
||||
</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>
|
||||
@@ -582,8 +563,10 @@ onMounted(() => {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
> .el-checkbox { width: 60px; flex-shrink: 0; }
|
||||
> .item-product { flex: 1; min-width: 200px; display: flex; gap: 12px; }
|
||||
/* 桌面端布局 */
|
||||
> .item-check { width: 40px; flex-shrink: 0; }
|
||||
> .item-image-wrap { width: 70px; flex-shrink: 0; }
|
||||
> .item-content { flex: 1; min-width: 200px; }
|
||||
> .item-price { width: 100px; text-align: center; flex-shrink: 0; }
|
||||
> .item-quantity { width: 140px; display: flex; flex-direction: column; align-items: center; gap: 4px; flex-shrink: 0; }
|
||||
> .item-subtotal { width: 100px; text-align: center; flex-shrink: 0; }
|
||||
@@ -616,6 +599,43 @@ onMounted(() => {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 桌面端图片和信息布局 */
|
||||
.item-image-wrap {
|
||||
margin-right: 12px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.item-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
/* 桌面端隐藏标题行和底部行的特殊样式 */
|
||||
.item-title-row {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.item-bottom-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.btn-delete {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.quantity-wrap {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.item-price-val {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.image-placeholder {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -1035,7 +1055,7 @@ onMounted(() => {
|
||||
gap: 10px !important;
|
||||
}
|
||||
|
||||
/* 商品项 - 主流电商布局 */
|
||||
/* 商品项 */
|
||||
.cart-item {
|
||||
display: flex !important;
|
||||
flex-direction: row !important;
|
||||
@@ -1050,7 +1070,6 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
/* 隐藏桌面端元素 */
|
||||
.cart-item > .item-product,
|
||||
.cart-item > .item-price,
|
||||
.cart-item > .item-quantity,
|
||||
.cart-item > .item-subtotal,
|
||||
@@ -1063,15 +1082,14 @@ onMounted(() => {
|
||||
flex: 0 0 20px !important;
|
||||
width: 20px !important;
|
||||
margin-right: 0 !important;
|
||||
align-self: flex-start !important;
|
||||
margin-top: 2px !important;
|
||||
}
|
||||
|
||||
/* 移动端商品图片 */
|
||||
/* 图片 */
|
||||
.cart-item > .item-image-wrap {
|
||||
display: block !important;
|
||||
flex: 0 0 80px !important;
|
||||
width: 80px !important;
|
||||
margin-right: 0 !important;
|
||||
}
|
||||
|
||||
.item-image-wrap .item-image {
|
||||
@@ -1080,17 +1098,17 @@ onMounted(() => {
|
||||
border-radius: 4px !important;
|
||||
}
|
||||
|
||||
/* 移动端商品信息区 */
|
||||
/* 内容区 */
|
||||
.cart-item > .item-content {
|
||||
display: flex !important;
|
||||
flex: 1 1 0 !important;
|
||||
min-width: 0 !important;
|
||||
display: flex !important;
|
||||
flex-direction: column !important;
|
||||
gap: 6px !important;
|
||||
}
|
||||
|
||||
/* 商品名称行 + 删除按钮 */
|
||||
.item-content .item-header {
|
||||
/* 标题行:名称 + 删除 */
|
||||
.item-content .item-title-row {
|
||||
display: flex !important;
|
||||
justify-content: space-between !important;
|
||||
align-items: flex-start !important;
|
||||
@@ -1110,7 +1128,9 @@ onMounted(() => {
|
||||
overflow: hidden !important;
|
||||
}
|
||||
|
||||
.item-content .item-delete {
|
||||
/* 删除按钮 */
|
||||
.item-content .btn-delete {
|
||||
display: block !important;
|
||||
flex-shrink: 0 !important;
|
||||
font-size: 12px !important;
|
||||
padding: 0 !important;
|
||||
@@ -1130,29 +1150,37 @@ onMounted(() => {
|
||||
line-height: 14px !important;
|
||||
}
|
||||
|
||||
/* 价格 + 数量行 */
|
||||
.item-content .item-footer {
|
||||
/* 底部行:价格 + 数量 */
|
||||
.item-content .item-bottom-row {
|
||||
display: flex !important;
|
||||
justify-content: space-between !important;
|
||||
align-items: center !important;
|
||||
margin-top: auto !important;
|
||||
padding-top: 4px !important;
|
||||
}
|
||||
|
||||
.item-content .item-price-mobile {
|
||||
/* 价格 */
|
||||
.item-content .item-price-val {
|
||||
display: block !important;
|
||||
font-size: 16px !important;
|
||||
font-weight: 600 !important;
|
||||
color: #f2270c !important;
|
||||
}
|
||||
|
||||
.item-content .item-footer :deep(.el-input-number) {
|
||||
/* 数量选择器 */
|
||||
.item-content .quantity-wrap {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.item-content .quantity-wrap :deep(.el-input-number) {
|
||||
width: 100px !important;
|
||||
}
|
||||
|
||||
.item-content .item-footer :deep(.el-input-number .el-input__wrapper) {
|
||||
.item-content .quantity-wrap :deep(.el-input-number .el-input__wrapper) {
|
||||
padding: 0 4px !important;
|
||||
}
|
||||
|
||||
.item-content .item-footer :deep(.el-input-number .el-input__inner) {
|
||||
.item-content .quantity-wrap :deep(.el-input-number .el-input__inner) {
|
||||
font-size: 13px !important;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user