123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 |
- <!-- @format -->
- <script lang="ts" setup>
- import { ref, watch } from 'vue'
- import { getCategoryListApi } from '~/api/model/common'
- import { useCommonStore } from '@/stores/modules/common'
- import {
- getFeatureListApi,
- } from '~/api/model/feature'
- getCategories()
- const route = useRoute()
- const commonStore = useCommonStore()
- const categories = ref<any>([])
- const featureList = ref<any>([])
- const categoryList = ref<any>([])
- const secondCategoryList = ref<any>([])
- const status = ref(false)
- const firstCategory = ref()
- const headerBg = ref('#fff')
- const router = useRouter()
- const secondCategoryCache = new Map()
- const list = [
- // {
- // label: 'Collections',
- // link: '/collections',
- // key: 'Featured',
- // slug: 'featured',
- // type: '',
- // },
- {
- label: 'Brands',
- link: '/suppliers/all-brands',
- key: 'Brands',
- slug: 'brands',
- type: '',
- },
- ]
- async function getCategories() {
- const data = await getCategoryListApi({ all: false })
- data.forEach((item: any) => {
- item.link = 'categories-id'
- item.type = 'category'
- })
- categoryList.value = data
- categories.value = [...list, ...data]
- }
- function setSelectedCategory(data: any) {
- const linkName = useRoute().name
- if (linkName === data[0].link)
- commonStore.setSelectedCategory(useRoute().params.id)
- else
- commonStore.setSelectedCategory('')
- }
- async function getFeatureList() {
- const params = {
- pageNo: 1,
- pageSize: 4,
- }
- const res: any = await getFeatureListApi(params)
- featureList.value = res.records
- }
- getFeatureList()
- async function onSelectedCategory(item: any) {
- const keys = list.map(item => item.key)
- firstCategory.value = item
- if (keys.includes(item.key)) {
- status.value = false
- return
- }
- // 缓存当前下的分类
- if (secondCategoryCache.get(item.key)) {
- secondCategoryList.value = secondCategoryCache.get(item.key)
- status.value = true
- return
- }
- const data = await getCategoryListApi({ code: item.code, all: true })
- secondCategoryList.value = data
- secondCategoryCache.set(item.key, data)
- status.value = true
- }
- watch(
- () => route.path,
- (value: any) => {
- const newList = list.filter((item: any) => item.link === value)
- if (newList.length) {
- commonStore.setSelectedCategory(newList[0].slug)
- }
- else {
- if (!categoryList.value.length)
- return
- setSelectedCategory(categoryList.value)
- }
- },
- {
- immediate: true,
- },
- )
- // function handleSelectedCategory(key: any) {
- // router.push({
- // path: `/categories/${encodeURIComponent(firstCategory.value.slug)}`,
- // query: {
- // secondKey: key,
- // },
- // })
- // status.value = false
- // }
- // function onClickFeature(item: any) {
- // router.push({
- // path: `/collections/${item.slug}`,
- // })
- // status.value = false
- // }
- watch(() => router.currentRoute.value.path, (v: any) => {
- if (v === '/')
- headerBg.value = '#FAF5F1'
- else
- headerBg.value = '#fff'
- }, {
- immediate: true,
- })
- </script>
- <template>
- <div class="mt-30px w-1400px mx-auto pb-30px">
- <div class="flex justify-center gap-x-50px" @mouseleave="status = false">
- <div
- v-for="item in categories"
- :key="item.key"
- class="category-item position-relative cursor-pointer text-#666666"
- :class="commonStore.selectedCategory === item.slug && 'active fw-500'"
- @mouseover="onSelectedCategory(item)"
- >
- <el-dropdown v-if="item.type">
- <NuxtLink :to="{ name: item.link, params: { id: item.slug } }">
- {{ item.label }}
- </NuxtLink>
- <template v-if="item.type" #dropdown>
- <el-dropdown-menu>
- <el-dropdown-item v-for="item, index in secondCategoryList" :index="item.key">
- <nuxt-link :to="{ name: 'categories-id', params: { id: firstCategory?.slug }, query: { secondKey: item.key } }">
- {{ item.title }}
- </nuxt-link>
- </el-dropdown-item>
- </el-dropdown-menu>
- </template>
- </el-dropdown>
- <NuxtLink v-else :to="item.link">
- {{ item.label }}
- </NuxtLink>
- </div>
- </div>
- <!-- <div :class="status ? 'h-420px opacity-100' : 'h-0 overflow-hidden opacity-0'" :style="{ backgroundColor: headerBg }" class="transition-duration-300 pos-absolute left-0 top-120px right-0 z-1000 custom-banner" @mouseover="status = true" @mouseleave="status = false">
- <div class=" w-1400px mx-auto py-30px ">
- <div class="flex">
- <div class="w-250px pos-relative after:pos-absolute after:content-empty after:top-0 after:bottom-0 after:w-1px after:right-0 after:bg-#D8D8D8">
- <div class="fw-600 text-22px text-#333 !mb-30px">
- Categories
- </div>
- <div class="h-300px overflow-y-scroll hidden-scrollbar">
- <banner-category-sider :list="secondCategoryList" @click="handleSelectedCategory" />
- </div>
- </div>
- <div class="ml-40px w-full">
- <div class="fw-600 text-22px text-#333">
- Collection
- </div>
- <div class="flex mt-30px">
- <div class="grid grid-gap-x-20px grid-gap-y-20px flex-1 grid-cols-2">
- <div v-for="(item, index) in featureList" :key="item.id" :class="(index === 1 || index === 2) ? 'bg-#F4F6F6' : 'bg-#FFF5EF'" class="p-20px b-rd-10px flex justify-between h-140px">
- <div>
- <div class="fw-600 text-20px text-#363C40 custom-title-font w-200px line-clamp-2">
- {{ item.headImageText }}
- </div>
- <div class="mt-10px text-#C58C64 underline cursor-pointer" @click="onClickFeature(item)">
- Shop Now
- </div>
- </div>
- <img :src="item.thumbnailUrl" class="w-120px h-100px b-rd-4px object-cover" alt="" srcset="">
- </div>
- </div>
- <div class="w-285px text-center ml-40px">
- <nuxt-link to="/suppliers/all-brands">
- <img src="~/assets/images/header_banner.png" class="w-260px h-260px cursor-pointer" alt="">
- <div class="mt-18px">
- Shop Top Brands
- </div>
- </nuxt-link>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div> -->
- </div>
- </template>
- <style lang="less" scoped>
- .category-item{
- &::before{
- position: absolute;
- content: "";
- bottom: 20%;
- top: 20%;
- right: -26px;
- width: 1px;
- background: #CCCCCC;
- border-radius: 2px;
- }
- &:last-child::before{
- display: none;
- }
- }
- .category-item:hover,
- .active {
- color: var(--primary-hover-color);
- }
- .category-item:hover::after,
- .active::after {
- position: absolute;
- content: "";
- bottom: -10px;
- left: 0;
- width: 100%;
- height: 2px;
- background: var(--primary-hover-color);
- border-radius: 2px;
- z-index: 100;
- transition: height 0.3s, background 0.3s; /* 明确过渡效果 */
- }
- .hidden-scrollbar{
- &::-webkit-scrollbar{
- display: none;
- }
- }
- .custom-banner{
- box-shadow: 0px 3px 6px 1px rgba(0,0,0,0.06);
- }
- </style>
|