parent
191f13df5a
commit
a184f61263
@ -0,0 +1,263 @@
|
||||
<template>
|
||||
<!-- 购物车 -->
|
||||
<el-popover
|
||||
popper-class="header-cart-popover"
|
||||
trigger="hover"
|
||||
placement="bottom"
|
||||
width="330"
|
||||
>
|
||||
<div
|
||||
slot="reference"
|
||||
class="header-cart-popover__refrence flex flex-middle"
|
||||
@click="onJumpCart"
|
||||
>
|
||||
<img src="~/assets/img/layout/icon-shop.png" />
|
||||
<span>购物车</span>
|
||||
<div v-if="cartProducts.length > 0" class="wrap-right-cart__tip">
|
||||
{{ cartProducts.length }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="header-cart-products scrollbar-self">
|
||||
<div
|
||||
v-for="item in products"
|
||||
:key="item.id"
|
||||
@click="onJumpGoodsDetail"
|
||||
class="header-cart-products__wrap flex flex-middle flex-between"
|
||||
>
|
||||
<div class="cart-products-wrap__left flex felx-middle">
|
||||
<div class="products-wrap-left__cover">
|
||||
<img :src="item.productMainPicture" />
|
||||
</div>
|
||||
<div class="products-wrap-left__info">
|
||||
<p class="wrap-left-info__title">{{ item.productName }}</p>
|
||||
<div class="wrap-left-info__detail flex">
|
||||
<span class="left-info-detail__skuname">{{
|
||||
item.productSku.name
|
||||
}}</span>
|
||||
<span class="left-info-detail__count">{{ item.number }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<UiMoney
|
||||
class="cart-products-wrap__right"
|
||||
:float="true"
|
||||
:money="item.product.startingPrice"
|
||||
/>
|
||||
</div>
|
||||
<!-- 失效商品 -->
|
||||
<template v-if="failureProducts.length > 0">
|
||||
<div class="header-cart-products__bar">以下商品已失效</div>
|
||||
<div
|
||||
v-for="item in failureProducts"
|
||||
:key="item.id"
|
||||
@click="onJumpGoodsDetail"
|
||||
class="header-cart-products__wrap flex flex-middle flex-between"
|
||||
>
|
||||
<div class="cart-products-wrap__left flex felx-middle">
|
||||
<div class="products-wrap-left__cover">
|
||||
<img :src="item.productMainPicture" />
|
||||
</div>
|
||||
<div class="products-wrap-left__info">
|
||||
<p
|
||||
class="wrap-left-info__title header-cart-products--failure-color"
|
||||
>
|
||||
{{ item.productName }}
|
||||
</p>
|
||||
<div class="wrap-left-info__detail flex">
|
||||
<span class="left-info-detail__skuname">{{
|
||||
item.productSku && item.productSku.name
|
||||
}}</span>
|
||||
<span class="left-info-detail__count">{{ item.number }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<UiMoney
|
||||
class="header-cart-products--failure-color"
|
||||
:float="true"
|
||||
:money="item.product.startingPrice"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class="header-cart-bottom flex flex-middle flex-between">
|
||||
<p>共{{ cartProducts.length }}件商品</p>
|
||||
<UiButton type="red_panel" :radius="true" @click="onJumCartPage"
|
||||
>去购物车</UiButton
|
||||
>
|
||||
</div>
|
||||
</el-popover>
|
||||
</template>
|
||||
<script>
|
||||
import { mapState } from "vuex";
|
||||
import UiButton from "@/components/UiButton.vue";
|
||||
|
||||
export default {
|
||||
name: "HeaderCart",
|
||||
components: { UiButton },
|
||||
data() {
|
||||
return {
|
||||
products: [],
|
||||
failureProducts: [], // 失效商品
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState(["cartProducts"]),
|
||||
},
|
||||
watch: {
|
||||
cartProducts: {
|
||||
immediate: true,
|
||||
deep: true,
|
||||
handler(val) {
|
||||
this.products = [];
|
||||
this.failureProducts = [];
|
||||
val.forEach((item) => {
|
||||
if (item.product.isEnable) {
|
||||
if (item.productSku && item.productSku.stock > 0) {
|
||||
// 商品未失效且有库存
|
||||
this.products.push(item);
|
||||
return;
|
||||
}
|
||||
this.failureProducts.push(item);
|
||||
return;
|
||||
}
|
||||
this.failureProducts.push(item);
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.$store.dispatch("getCartProducts");
|
||||
},
|
||||
methods: {
|
||||
onJumpCart() {
|
||||
if (!this.$isLoginValidate()) {
|
||||
return;
|
||||
}
|
||||
this.$router.push("/cart");
|
||||
},
|
||||
onJumpGoodsDetail(id) {
|
||||
this.$router.push(`/goods/detail/${id}`);
|
||||
},
|
||||
onJumCartPage() {
|
||||
this.$router.push("/cart");
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.header-cart-popover {
|
||||
padding: 16px 20px;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.header-cart-popover__refrence {
|
||||
padding: 0 18px;
|
||||
height: 42px;
|
||||
line-height: 42px;
|
||||
color: #999999;
|
||||
border-radius: 8px 8px 8px 8px;
|
||||
border: 1px solid #eeeeee;
|
||||
cursor: pointer;
|
||||
.wrap-right-cart__tip {
|
||||
min-width: 14px;
|
||||
height: 14px;
|
||||
padding: 0 3px;
|
||||
font-size: 10px;
|
||||
line-height: 14px;
|
||||
text-align: center;
|
||||
background: #ff512b;
|
||||
border-radius: 50%;
|
||||
color: #ffffff;
|
||||
}
|
||||
img {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin: 0 4px 0 10px;
|
||||
}
|
||||
}
|
||||
.header-cart-popover {
|
||||
padding: 20px 16px;
|
||||
.header-cart-products {
|
||||
padding: 0 10px 50px 0;
|
||||
max-height: 360px;
|
||||
overflow: auto;
|
||||
&--failure-color {
|
||||
color: #999999 !important;
|
||||
}
|
||||
.header-cart-products__wrap {
|
||||
margin-bottom: 20px;
|
||||
cursor: pointer;
|
||||
.cart-products-wrap__left {
|
||||
.products-wrap-left__cover {
|
||||
width: 54px;
|
||||
height: 54px;
|
||||
padding: 3px;
|
||||
border: 1px solid #eeeeee;
|
||||
border-radius: 4px;
|
||||
margin-right: 11px;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.products-wrap-left__info {
|
||||
font-size: 12px;
|
||||
color: #999999;
|
||||
.wrap-left-info__title {
|
||||
display: block;
|
||||
width: 120px;
|
||||
@include ellipsis;
|
||||
font-size: 14px;
|
||||
color: #333333;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.wrap-left-info__detail {
|
||||
.left-info-detail__skuname {
|
||||
display: block;
|
||||
width: 70px;
|
||||
@include ellipsis;
|
||||
}
|
||||
.left-info-detail__count {
|
||||
&::before {
|
||||
content: "X";
|
||||
font-size: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.cart-products-wrap__right {
|
||||
color: #ff512b;
|
||||
}
|
||||
}
|
||||
.header-cart-products__bar {
|
||||
font-size: 14px;
|
||||
width: 298px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
padding: 0 11px;
|
||||
background: #f8f8f8;
|
||||
color: #999999;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
}
|
||||
.header-cart-bottom {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
background: #eeeeee;
|
||||
padding: 0 16px;
|
||||
font-size: 14px;
|
||||
color: #666666;
|
||||
/deep/.ui-button {
|
||||
width: 84px;
|
||||
height: 30px;
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,219 @@
|
||||
<template>
|
||||
<div class="header-category">
|
||||
<!-- 热门分类 -->
|
||||
<div
|
||||
v-show="showCategroyTab"
|
||||
class="header-box-tab__category"
|
||||
@mouseenter="handleCategoryChange(true)"
|
||||
@mouseleave="handleCategoryChange(false)"
|
||||
>
|
||||
<div class="tab-category__label flex flex-center flex-middle">
|
||||
<img src="~/assets/img/layout/icon-category.png" />
|
||||
<span>热门分类</span>
|
||||
</div>
|
||||
<div
|
||||
v-show="isCategroyOpen || categroyVisible"
|
||||
class="tab-category__menu flex"
|
||||
@mouseenter="handleCategoryTwoChange(true)"
|
||||
@mouseleave="handleCategoryTwoChange(false)"
|
||||
>
|
||||
<!-- 左侧一级分类 -->
|
||||
<div class="tab-category-menu__left">
|
||||
<div
|
||||
v-for="item in categroyData"
|
||||
:key="item.id"
|
||||
@mouseenter="handleCategoryHover(item.id)"
|
||||
@click="onCategoryClick(item.id, CATEGROY_LEVEL.ONE)"
|
||||
class="menu-left__item flex flex-middle"
|
||||
:class="{
|
||||
'menu-left__item--light': item.id === currentCategroyId,
|
||||
}"
|
||||
>
|
||||
<img />
|
||||
<span>{{ item.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 右侧二级分类 -->
|
||||
<div
|
||||
v-show="categroyTwoVisible"
|
||||
class="tab-category-menu__right flex-1"
|
||||
>
|
||||
<div
|
||||
v-for="item in categroyData"
|
||||
:key="item.id"
|
||||
@mouseenter="handleCategoryHover(item.id)"
|
||||
class="category-menu-right__wrap"
|
||||
:class="{
|
||||
'category-menu-right__wrap--light': item.id === currentCategroyId,
|
||||
}"
|
||||
>
|
||||
<span
|
||||
v-for="itemList in item.list"
|
||||
:key="itemList.id"
|
||||
class="menu-right-wrap__item"
|
||||
@click="onCategoryClick(itemList.id, CATEGROY_LEVEL.TWO)"
|
||||
>{{ itemList.name }}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import {
|
||||
ApiGetCategoryOneList,
|
||||
ApiGetCategoryTwoAndGoods,
|
||||
} from "@/plugins/api/goods";
|
||||
const CATEGROY_HIDE_PAGES = [/\/account/]; // 隐藏热门分类tab的页面
|
||||
|
||||
export default {
|
||||
name: "HeaderCategory",
|
||||
data() {
|
||||
return {
|
||||
categroyTwoVisible: false, // 是否展示二级分类
|
||||
categroyVisible: false, // 是否展示一级分类
|
||||
currentCategroyId: 0, // 当前鼠标悬停的一级分类id
|
||||
categroyData: [],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
showCategroyTab() {
|
||||
return !CATEGROY_HIDE_PAGES.some((reg) => {
|
||||
return reg.test(this.$route.path);
|
||||
});
|
||||
},
|
||||
|
||||
// 热门分类默认打开
|
||||
isCategroyOpen() {
|
||||
return this.$route.path === "/";
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.getCategroyData();
|
||||
},
|
||||
methods: {
|
||||
// 获取热门分类信息
|
||||
async getCategroyData() {
|
||||
const { result } = await ApiGetCategoryOneList();
|
||||
if (result && result.length > 0) {
|
||||
this.categroyData = await Promise.all(
|
||||
result.map(async (item) => {
|
||||
const { result: resultGoods } = await ApiGetCategoryTwoAndGoods({
|
||||
categoryId: item.id,
|
||||
});
|
||||
if (resultGoods && resultGoods.length > 0) {
|
||||
return {
|
||||
...item,
|
||||
list: resultGoods,
|
||||
};
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
},
|
||||
// 一级分类鼠标悬停
|
||||
handleCategoryHover(id) {
|
||||
this.currentCategroyId = id;
|
||||
},
|
||||
// 分类点击
|
||||
onCategoryClick(id, levelType) {
|
||||
this.categroyVisible = false;
|
||||
this.categroyTwoVisible = false;
|
||||
this.$router.push({
|
||||
path: "/goods/list",
|
||||
query: {
|
||||
id,
|
||||
levelType,
|
||||
},
|
||||
});
|
||||
},
|
||||
// 一级分类是否可见
|
||||
handleCategoryChange(val) {
|
||||
this.categroyVisible = val;
|
||||
if (!val) {
|
||||
this.currentCategroyId = 0;
|
||||
}
|
||||
},
|
||||
// 二级分类是否可见
|
||||
handleCategoryTwoChange(val) {
|
||||
this.categroyTwoVisible = val;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.header-category {
|
||||
height: 100%;
|
||||
.header-box-tab__category {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
.tab-category__label {
|
||||
width: 190px;
|
||||
height: 100%;
|
||||
background: linear-gradient(270deg, #ffa25a 0%, #ff7f39 100%);
|
||||
border-radius: 4px 4px 0px 0px;
|
||||
font-weight: bold;
|
||||
color: #ffffff;
|
||||
cursor: pointer;
|
||||
img {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-right: 16px;
|
||||
}
|
||||
}
|
||||
.tab-category__menu {
|
||||
position: absolute;
|
||||
top: 38px;
|
||||
left: 0;
|
||||
font-size: 14px;
|
||||
color: #333333;
|
||||
.tab-category-menu__left {
|
||||
width: 190px;
|
||||
padding: 15px 0;
|
||||
background: #ffffff;
|
||||
.menu-left__item {
|
||||
height: 50px;
|
||||
cursor: pointer;
|
||||
padding: 0 24px 0 41px;
|
||||
&:hover,
|
||||
&--light {
|
||||
color: #ff875b;
|
||||
}
|
||||
img {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-right: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.tab-category-menu__right {
|
||||
padding: 15px 26px;
|
||||
box-shadow: 7px 0px 10px 1px rgba(0, 0, 0, 0.1);
|
||||
border: 1px solid #eeeeee;
|
||||
background: #ffffff;
|
||||
.category-menu-right__wrap {
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
padding: 0 16px;
|
||||
font-size: 12px;
|
||||
color: #999999;
|
||||
white-space: nowrap;
|
||||
&:hover,
|
||||
&--light {
|
||||
background: #f8f8f8;
|
||||
}
|
||||
.menu-right-wrap__item {
|
||||
color: #999999;
|
||||
margin-right: 20px;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
color: #ff875b;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
Loading…
Reference in new issue