refactor(product): 将商品列表组件拆分为独立组件
将ProductList.vue中的商品展示和购物车逻辑提取到新的ProductContainer组件中,提升代码可维护性
This commit is contained in:
parent
b9e0077b4d
commit
c43ab6a184
|
@ -13,6 +13,7 @@ import { useWxStore } from "@/pinia/stores/wx"
|
|||
import { bindQyUserApi } from "@/common/apis/ab98"
|
||||
import { getShopListApi } from "@/common/apis/shop"
|
||||
import { ShopEntity } from "@/common/apis/shop/type"
|
||||
import ProductContainer from "./components/ProductContainer.vue"
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
@ -20,13 +21,10 @@ const route = useRoute()
|
|||
const productStore = useProductStore();
|
||||
const cartStore = useCartStore();
|
||||
const wxStore = useWxStore();
|
||||
const { cartItems, totalPrice, totalQuantity } = storeToRefs(cartStore); // 新增购物车状态
|
||||
// 从 store 解构分类标签和商品数据
|
||||
const { labels, categories } = storeToRefs(productStore);
|
||||
|
||||
const { openid, corpidLogin, ab98User, qyUserId } = storeToRefs(wxStore);
|
||||
|
||||
// 当前选中的分类索引
|
||||
const activeCategory = ref(0)
|
||||
|
||||
// 滚动容器引用
|
||||
const scrollContainer = ref<HTMLElement>()
|
||||
// 顶部头图高度(随滚动变化)
|
||||
|
@ -40,19 +38,6 @@ const showShopList = ref(true);
|
|||
const shopList = ref<ShopEntity[]>([]);
|
||||
const shopId = ref<number>(0);
|
||||
|
||||
// 商品详情弹窗控制
|
||||
const showDetailPopup = ref(false)
|
||||
// 当前查看的商品ID
|
||||
const currentProductId = ref<number>()
|
||||
// 当前商品详情计算属性
|
||||
const currentProduct = computed(() =>
|
||||
categories.value.find(p => p.id === currentProductId.value)
|
||||
)
|
||||
// 购物车弹窗控制
|
||||
const showCartPopup = ref(false)
|
||||
|
||||
const searchQuery = ref('');
|
||||
|
||||
const name = ref('');
|
||||
const idNum = ref('');
|
||||
const showAb98BindPopup = ref(false);
|
||||
|
@ -64,77 +49,8 @@ function handleShopSelect(selectedShopId: number) {
|
|||
productStore.setSelectedShop(shopList.value.find(shop => shop.shopId === selectedShopId)!);
|
||||
productStore.getGoods(selectedShopId);
|
||||
cartStore.clearCart();
|
||||
activeCategory.value = 0;
|
||||
}
|
||||
function handleBackToShopList() {
|
||||
showShopList.value = true;
|
||||
shopId.value = 0;
|
||||
cartStore.clearCart();
|
||||
}
|
||||
|
||||
function handleCategoryClick(index: number) {
|
||||
activeCategory.value = index
|
||||
}
|
||||
|
||||
// 节流的滚动位置计算(用于切换左侧导航激活状态)
|
||||
/* const throttledUpdate = throttle(() => {
|
||||
if (!scrollContainer.value || !categoryRefs.value.length) return
|
||||
|
||||
// 添加数组元素存在性检查
|
||||
const validRefs = categoryRefs.value.filter(Boolean)
|
||||
if (!validRefs.length) return
|
||||
|
||||
const containerTop = scrollContainer.value.getBoundingClientRect().top
|
||||
const offsets = validRefs.map((el) => {
|
||||
return el.getBoundingClientRect().top - containerTop
|
||||
})
|
||||
let activeIndex = 0
|
||||
for (let i = offsets.length - 1; i >= 0; i--) {
|
||||
if (offsets[i] < 100) {
|
||||
activeIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
// activeCategory.value = activeIndex
|
||||
}, 100) */
|
||||
|
||||
// 节流的头部高度计算(实现顶部图片缩放效果)
|
||||
const throttledScroll = throttle(() => {
|
||||
if (!scrollContainer.value) return
|
||||
const scrollTop = scrollContainer.value.scrollTop
|
||||
headerHeight.value = Math.max(150 - scrollTop * 0.5, 60)
|
||||
}, 100)
|
||||
|
||||
// 打开商品详情弹窗
|
||||
function showProductDetail(productId: number) {
|
||||
currentProductId.value = productId
|
||||
showDetailPopup.value = true
|
||||
}
|
||||
|
||||
function handleAddToCart(product: Product) {
|
||||
cartStore.addToCart(product)
|
||||
}
|
||||
|
||||
function handleRemoveFromCart(product: Product) {
|
||||
cartStore.removeFromCart(product.cellId)
|
||||
}
|
||||
|
||||
function getCartItemCount(cellId: number) {
|
||||
const item = cartItems.value.find(item => item.product.cellId === cellId)
|
||||
return item ? item.quantity : 0
|
||||
}
|
||||
|
||||
function filterProductsByName(products: Product[], query: string) {
|
||||
if (!query) return products
|
||||
return products.filter(p =>
|
||||
p.name.toLowerCase().includes(query.toLowerCase())
|
||||
)
|
||||
}
|
||||
|
||||
const currentProducts = computed(() => {
|
||||
const filteredByCategory = categories.value.filter(c => c.label === labels.value[activeCategory.value].id)
|
||||
return filterProductsByName(filteredByCategory, searchQuery.value)
|
||||
})
|
||||
|
||||
// 组件挂载时添加滚动监听
|
||||
onMounted(() => {
|
||||
|
@ -153,7 +69,7 @@ onMounted(() => {
|
|||
} else {
|
||||
productStore.getGoods(shopId.value);
|
||||
}
|
||||
scrollListener.push(scrollContainer.value?.addEventListener("scroll", throttledScroll))
|
||||
// scrollListener.push(scrollContainer.value?.addEventListener("scroll", throttledScroll))
|
||||
// scrollListener.push(scrollContainer.value?.addEventListener("scroll", throttledUpdate))
|
||||
})
|
||||
|
||||
|
@ -241,83 +157,11 @@ async function handleAb98Bind() {
|
|||
<div class="shop-header" :style="{ height: `${headerHeight}px` }">
|
||||
<van-image :src="`${publicPath}cover.png`" class="shop-cover" fit="cover" />
|
||||
</div>
|
||||
<div class="product-container">
|
||||
<!-- 左侧分类导航 -->
|
||||
<div>
|
||||
<van-button icon="revoke" type="default" class="showShopListBtn" @click="showShopList = true">重选地址</van-button>
|
||||
<van-sidebar v-model="activeCategory" class="category-nav" @change="handleCategoryClick">
|
||||
<van-sidebar-item v-for="label in labels" :key="label.id" :title="label.name" />
|
||||
</van-sidebar>
|
||||
</div>
|
||||
|
||||
<!-- 右侧商品列表 -->
|
||||
<div ref="scrollContainer" class="product-list">
|
||||
<van-search v-model="searchQuery" placeholder="搜索商品名称" shape="round" class="search-box" />
|
||||
<div class="category-section">
|
||||
<van-cell v-for="product in currentProducts" :key="product.id" class="product-item">
|
||||
<template #icon>
|
||||
<van-image :src="product.image" width="80" height="80" @click.stop="showProductDetail(product.id)"
|
||||
class="product-image">
|
||||
<div v-if="product.stock === 0" class="sold-out-overlay">
|
||||
<span class="sold-out-text">已售罄</span>
|
||||
</div>
|
||||
<!-- 真正的图片错误处理 -->
|
||||
<template #error>
|
||||
<div class="custom-error">
|
||||
图片加载失败
|
||||
</div>
|
||||
</template>
|
||||
</van-image>
|
||||
</template>
|
||||
<div class="product-info">
|
||||
<div class="product-name van-ellipsis" @click.stop="showProductDetail(product.id)">
|
||||
{{ product.name }}
|
||||
</div>
|
||||
<div class="product-price" @click.stop="showProductDetail(product.id)">
|
||||
¥{{ product.price.toFixed(2) }}
|
||||
</div>
|
||||
<div class="action-row">
|
||||
<span v-if="product.stock > 0" class="stock-count">
|
||||
还剩{{ product.stock }}份
|
||||
</span>
|
||||
<div class="cart-actions">
|
||||
<van-button v-if="getCartItemCount(product.cellId)" size="mini" icon="minus"
|
||||
@click.stop="handleRemoveFromCart(product)" />
|
||||
<span v-if="getCartItemCount(product.cellId)" class="cart-count">{{ getCartItemCount(product.cellId)
|
||||
}}</span>
|
||||
<van-button size="mini" type="primary" class="add-cart-btn" icon="plus"
|
||||
:disabled="product.stock === 0" @click.stop="handleAddToCart(product)" :style="{
|
||||
opacity: product.stock === 0 ? 0.6 : 1,
|
||||
}" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-cell>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 底部购物车栏 -->
|
||||
<div v-if="cartItems.length" class="shopping-cart-bar">
|
||||
<div class="cart-info">
|
||||
<van-badge :content="totalQuantity" @click.stop="showCartPopup = true">
|
||||
<van-icon name="shopping-cart-o" size="24" />
|
||||
</van-badge>
|
||||
<div class="total-price">
|
||||
合计:¥{{ totalPrice.toFixed(2) }}
|
||||
</div>
|
||||
</div>
|
||||
<van-button type="primary" size="small" @click="handleCheckout" class="checkout-btn">
|
||||
去结算
|
||||
</van-button>
|
||||
</div>
|
||||
</div>
|
||||
<ProductContainer
|
||||
@backToShopList="showShopList = true"
|
||||
@checkout="handleCheckout"
|
||||
/>
|
||||
</div>
|
||||
<VanPopup v-model:show="showDetailPopup" position="bottom" :style="{ height: '80%' }" round>
|
||||
<Detail class="detail-container" @detail-close="showDetailPopup = false" v-if="currentProduct"
|
||||
:product="currentProduct" />
|
||||
</VanPopup>
|
||||
<VanPopup v-model:show="showCartPopup" position="bottom" :style="{ height: '80%' }" round>
|
||||
<Cart class="detail-container" @cart-close="showCartPopup = false" />
|
||||
</VanPopup>
|
||||
<VanPopup v-model:show="showAb98BindPopup" position="center" :style="{ padding: '12px' }" round>
|
||||
<div style="text-align: center; font-size: 16px; font-weight: bold; margin-bottom: 16px;">请绑定汇邦云账号</div>
|
||||
<van-form @submit="handleAb98Bind">
|
||||
|
@ -601,6 +445,7 @@ async function handleAb98Bind() {
|
|||
justify-content: start;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.shop-cover-img {
|
||||
width: 100%;
|
||||
height: 80px;
|
||||
|
|
|
@ -0,0 +1,397 @@
|
|||
<!-- ProductList.vue -->
|
||||
<script setup lang="ts">
|
||||
import { publicPath } from "@/common/utils/path"
|
||||
import { useCartStore } from "@/pinia/stores/cart"
|
||||
import { Product, useProductStore } from "@/pinia/stores/product"
|
||||
import { throttle } from "lodash-es"
|
||||
import { storeToRefs } from "pinia"
|
||||
import VanPopup from "vant/es/popup"
|
||||
import { computed, onMounted, onBeforeUnmount, ref, watch } from "vue"
|
||||
import Cart from "./cart.vue" // 假设 Cart 和 Detail 也在同级或components文件夹中
|
||||
import Detail from "./detail.vue" // 假设 Cart 和 Detail 也在同级或components文件夹中
|
||||
|
||||
// 定义Props
|
||||
|
||||
// 定义Emit事件
|
||||
const emit = defineEmits<{
|
||||
(e: 'backToShopList'): void;
|
||||
(e: 'checkout'): void;
|
||||
}>();
|
||||
|
||||
// 状态管理
|
||||
const productStore = useProductStore();
|
||||
const { labels, categories } = storeToRefs(productStore);
|
||||
const cartStore = useCartStore();
|
||||
const { cartItems, totalPrice, totalQuantity } = storeToRefs(cartStore);
|
||||
|
||||
// 从props接收的数据
|
||||
const activeCategory = ref(0);
|
||||
|
||||
// 滚动容器引用
|
||||
const scrollContainer = ref<HTMLElement>();
|
||||
// 顶部头图高度(随滚动变化),这里保持在组件内部控制,或者也可以通过prop传入
|
||||
const headerHeight = ref(150);
|
||||
let scrollListener: any[] = [];
|
||||
|
||||
// 商品详情弹窗控制
|
||||
const showDetailPopup = ref(false);
|
||||
// 当前查看的商品ID
|
||||
const currentProductId = ref<number>();
|
||||
// 当前商品详情计算属性
|
||||
const currentProduct = computed(() =>
|
||||
categories.value.find(p => p.id === currentProductId.value)
|
||||
);
|
||||
// 购物车弹窗控制
|
||||
const showCartPopup = ref(false);
|
||||
|
||||
const searchQuery = ref('');
|
||||
|
||||
// 点击分类导航
|
||||
function handleCategoryClick(index: number) {
|
||||
activeCategory.value = index;
|
||||
}
|
||||
|
||||
// 节流的头部高度计算(实现顶部图片缩放效果)
|
||||
/* const throttledScroll = throttle(() => {
|
||||
if (!scrollContainer.value) return;
|
||||
const scrollTop = scrollContainer.value.scrollTop;
|
||||
headerHeight.value = Math.max(150 - scrollTop * 0.5, 60);
|
||||
}, 100); */
|
||||
|
||||
// 打开商品详情弹窗
|
||||
function showProductDetail(productId: number) {
|
||||
currentProductId.value = productId;
|
||||
showDetailPopup.value = true;
|
||||
}
|
||||
|
||||
function handleAddToCart(product: Product) {
|
||||
cartStore.addToCart(product);
|
||||
}
|
||||
|
||||
function handleRemoveFromCart(cellId: number) { // 接收 cellId
|
||||
cartStore.removeFromCart(cellId);
|
||||
}
|
||||
|
||||
function getCartItemCount(cellId: number) {
|
||||
const item = cartItems.value.find(item => item.product.cellId === cellId);
|
||||
return item ? item.quantity : 0;
|
||||
}
|
||||
|
||||
function filterProductsByName(products: Product[], query: string) {
|
||||
if (!query) return products;
|
||||
return products.filter(p =>
|
||||
p.name.toLowerCase().includes(query.toLowerCase())
|
||||
);
|
||||
}
|
||||
|
||||
const currentProducts = computed(() => {
|
||||
const filteredByCategory = categories.value.filter(c => c.label === labels.value[activeCategory.value]?.id);
|
||||
return filterProductsByName(filteredByCategory, searchQuery.value);
|
||||
});
|
||||
|
||||
// 组件挂载时添加滚动监听
|
||||
onMounted(() => {
|
||||
// scrollListener.push(scrollContainer.value?.addEventListener("scroll", throttledScroll));
|
||||
});
|
||||
|
||||
// 组件卸载前清理事件监听
|
||||
onBeforeUnmount(() => {
|
||||
scrollListener.forEach(listener => scrollContainer.value?.removeEventListener("scroll", listener));
|
||||
scrollListener = [];
|
||||
});
|
||||
|
||||
// 结算方法
|
||||
function handleCheckout() {
|
||||
// 这里的路由跳转可能需要父组件通过emit来处理,或者直接在子组件中导入router
|
||||
// 为了封装性,这里emit给父组件处理
|
||||
emit('checkout');
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="product-container">
|
||||
<!-- 左侧分类导航 -->
|
||||
<div>
|
||||
<van-button icon="revoke" type="default" class="showShopListBtn" @click="emit('backToShopList')">重选地址</van-button>
|
||||
<van-sidebar v-model="activeCategory" class="category-nav" @change="handleCategoryClick">
|
||||
<van-sidebar-item v-for="label in labels" :key="label.id" :title="label.name" />
|
||||
</van-sidebar>
|
||||
</div>
|
||||
|
||||
<!-- 右侧商品列表 -->
|
||||
<div ref="scrollContainer" class="product-list">
|
||||
<van-search v-model="searchQuery" placeholder="搜索商品名称" shape="round" class="search-box" />
|
||||
<div class="category-section">
|
||||
<van-cell v-for="product in currentProducts" :key="product.id" class="product-item">
|
||||
<template #icon>
|
||||
<van-image :src="product.image" width="80" height="80" @click.stop="showProductDetail(product.id)"
|
||||
class="product-image">
|
||||
<div v-if="product.stock === 0" class="sold-out-overlay">
|
||||
<span class="sold-out-text">已售罄</span>
|
||||
</div>
|
||||
<!-- 真正的图片错误处理 -->
|
||||
<template #error>
|
||||
<div class="custom-error">
|
||||
图片加载失败
|
||||
</div>
|
||||
</template>
|
||||
</van-image>
|
||||
</template>
|
||||
<div class="product-info">
|
||||
<div class="product-name van-ellipsis" @click.stop="showProductDetail(product.id)">
|
||||
{{ product.name }}
|
||||
</div>
|
||||
<div class="product-price" @click.stop="showProductDetail(product.id)">
|
||||
¥{{ product.price.toFixed(2) }}
|
||||
</div>
|
||||
<div class="action-row">
|
||||
<span v-if="product.stock > 0" class="stock-count">
|
||||
还剩{{ product.stock }}份
|
||||
</span>
|
||||
<div class="cart-actions">
|
||||
<van-button v-if="getCartItemCount(product.cellId)" size="mini" icon="minus"
|
||||
@click.stop="handleRemoveFromCart(product.cellId)" />
|
||||
<span v-if="getCartItemCount(product.cellId)" class="cart-count">{{ getCartItemCount(product.cellId)
|
||||
}}</span>
|
||||
<van-button size="mini" type="primary" class="add-cart-btn" icon="plus" :disabled="product.stock === 0"
|
||||
@click.stop="handleAddToCart(product)" :style="{
|
||||
opacity: product.stock === 0 ? 0.6 : 1,
|
||||
}" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-cell>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 底部购物车栏 -->
|
||||
<div v-if="cartItems.length" class="shopping-cart-bar">
|
||||
<div class="cart-info">
|
||||
<van-badge :content="totalQuantity" @click.stop="showCartPopup = true">
|
||||
<van-icon name="shopping-cart-o" size="24" />
|
||||
</van-badge>
|
||||
<div class="total-price">
|
||||
合计:¥{{ totalPrice.toFixed(2) }}
|
||||
</div>
|
||||
</div>
|
||||
<van-button type="primary" size="small" @click="handleCheckout" class="checkout-btn">
|
||||
去结算
|
||||
</van-button>
|
||||
</div>
|
||||
</div>
|
||||
<VanPopup v-model:show="showDetailPopup" position="bottom" :style="{ height: '80%' }" round>
|
||||
<Detail class="detail-container" @detail-close="showDetailPopup = false" v-if="currentProduct"
|
||||
:product="currentProduct" />
|
||||
</VanPopup>
|
||||
<VanPopup v-model:show="showCartPopup" position="bottom" :style="{ height: '80%' }" round>
|
||||
<Cart class="detail-container" @cart-close="showCartPopup = false" />
|
||||
</VanPopup>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.product-container {
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
background: #f7f8fa;
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
position: relative;
|
||||
border-top: 1px solid #e0e0e0;
|
||||
/* 顶部边框 */
|
||||
border-top-left-radius: 8px;
|
||||
/* 左上圆角 */
|
||||
border-top-right-radius: 8px;
|
||||
/* 右上圆角 */
|
||||
overflow: hidden;
|
||||
/* 确保圆角生效 */
|
||||
}
|
||||
|
||||
.category-nav {
|
||||
width: 100px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.showShopListBtn {
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.product-list {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 10px 16px 60px;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.category-section {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.category-title {
|
||||
margin: 5px;
|
||||
padding: 0;
|
||||
font-size: 16px;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
/* background: linear-gradient(to right, #f7f8fa, transparent); */
|
||||
/* position: sticky; */
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.product-item {
|
||||
margin-bottom: 10px;
|
||||
padding: min(2.667vw, 20px) 0;
|
||||
/* border-radius: 4px; */
|
||||
/* box-shadow: 0 2px 4px rgba(0,0,0,0.05); */
|
||||
}
|
||||
|
||||
.product-image {
|
||||
margin-right: 12px;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.product-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
height: 80px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.product-name {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
line-height: 1.4;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.product-price {
|
||||
font-size: 16px;
|
||||
color: #e95d5d;
|
||||
font-weight: bold;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.add-cart-btn {
|
||||
align-self: flex-end;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.van-sidebar-item--select:before {
|
||||
background-color: #e95d5d;
|
||||
}
|
||||
|
||||
.van-button--primary {
|
||||
background-color: #e95d5d;
|
||||
border: 0;
|
||||
border-color: #e95d5d;
|
||||
}
|
||||
|
||||
.sold-out-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.sold-out-text {
|
||||
color: #999;
|
||||
font-size: 14px;
|
||||
transform: rotate(-15deg);
|
||||
border: 1px solid #eee;
|
||||
padding: 2px 8px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.action-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-end;
|
||||
/* 底部对齐 */
|
||||
margin-top: auto;
|
||||
/* 推到容器底部 */
|
||||
}
|
||||
|
||||
.stock-count {
|
||||
font-size: 11px;
|
||||
color: #bbbbbb;
|
||||
margin-right: 8px;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
height: 100%;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
/* 禁用状态样式 */
|
||||
.van-button--disabled {
|
||||
background-color: #ccc !important;
|
||||
border-color: #ccc !important;
|
||||
}
|
||||
|
||||
/* 商品项置灰 */
|
||||
.product-item:has(.sold-out-overlay) {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.detail-container {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* 修改购物车栏样式 */
|
||||
.shopping-cart-bar {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 50px;
|
||||
background: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 16px;
|
||||
box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.05);
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.cart-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.total-price {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.checkout-btn {
|
||||
background-color: #e95d5d;
|
||||
border: none;
|
||||
border-radius: 16px;
|
||||
padding: 0 24px;
|
||||
}
|
||||
|
||||
.cart-actions {
|
||||
margin-left: auto;
|
||||
align-self: flex-end;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
/* margin-left: 8px; */
|
||||
|
||||
.cart-count {
|
||||
font-size: 12px;
|
||||
min-width: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
Loading…
Reference in New Issue