dl_mer_uniapp/components/homeIndex/homeComb.vue
2025-03-04 16:03:38 +08:00

828 lines
19 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<!-- 组合组件 -->
<view class="page_count tui-skeleton" :data-theme="theme">
<!--logo-->
<view class="bg-img" :style="{'background-image': bgColor}">
<img :src="bgColor" alt="">
</view>
<!--头部-->
<view :class="{scrolled:isScrolled, 'my-main': true}" :style="{ height: myMainHeight+'px' }">
<!--搜索-->
<!-- #ifdef H5 -->
<view class="header">
<view class="serch-wrapper acea-row">
<view v-if="logoConfig" class="logo skeleton-rect">
<image :src="logoUrl" mode="scaleToFill"></image>
</view>
<navigator v-if="hotWords.length > 0" :url="'/pages/goods/goods_search/index?searchVal='+searchVal"
:style="[searchBoxStyle]" :class="logoConfig ? 'input' : 'uninput'" hover-class="none" class="input">
<i class="iconfont icon-sousuo8"/>
<view class='swiperTxt'>
<swiper :indicator-dots="indicatorDots" :autoplay="true" :interval="interval"
:duration="duration" vertical="true" circular="true" @change="textChange">
<block v-for="(item,index) in hotWords" :key='index'>
<swiper-item catchtouchmove='catchTouchMove'>
<view class=''>
<view class='text'>
<view class='newsTitle line1'>{{item.val}}</view>
</view>
</view>
</swiper-item>
</block>
</swiper>
</view>
</navigator>
<navigator v-else :style="[searchBoxStyle]" :class="logoConfig ? 'input' : 'uninput'" url="/pages/goods/goods_search/index" class="input" hover-class="none">
<text class="iconfont icon-sousuo8"></text>
<text class="line1">{{placeWords}}</text>
</navigator>
</view>
</view>
<!-- #endif -->
<!-- #ifdef MP || APP-PLUS-->
<view class="mp-header">
<view class="sys-head" :style="{ height: statusBarHeight+'px' }"></view>
<view class="serch-box" style="margin-top: 9px;margin-right: 2px;">
<view class="serch-wrapper acea-row">
<view v-if="logoConfig" class="logo tui-skeleton-rect">
<image :src="logoUrl" mode="scaleToFill"></image>
</view>
<navigator v-if="hotWords.length > 0"
:url="'/pages/goods/goods_search/index?searchVal='+searchVal" :style="[searchBoxStyle]"
hover-class="none" class="input" :class="logoConfig ? 'input' : 'uninput'">
<text class="iconfont icon-sousuo8"></text>
<view class='swiperTxt'>
<swiper :indicator-dots="indicatorDots" :autoplay="true" :interval="interval"
:duration="duration" vertical="true" circular="true" @change="textChange">
<block v-for="(item,index) in hotWords" :key='index'>
<swiper-item catchtouchmove='catchTouchMove'>
<view class='acea-row row-between-wrapper'>
<view class='text'>
<view class='newsTitle line1'>{{item.val}}</view>
</view>
</view>
</swiper-item>
</block>
</swiper>
</view>
</navigator>
<navigator v-else :style="[searchBoxStyle]" :class="logoConfig ? 'input' : 'uninput'" url="/pages/goods/goods_search/index" class="input" hover-class="none">
<text class="iconfont icon-sousuo8"></text>
<text class="line1">{{placeWords}}</text>
</navigator>
</view>
</view>
</view>
<!-- #endif -->
<view class="navTabBox tabNav tui-skeletonpictrue acea-row" :style="'top:'+isTop">
<view class="longTab">
<scroll-view scroll-x="true" style="white-space: nowrap; display: flex;" scroll-with-animation
:scroll-left="tabLeft" show-scrollbar="true">
<view class="longItem" :data-index="index" v-for="(item,index) in tabList" :key="index"
:id="'id'+index" @click="longClick(index,item)"
:style="'color:' + (index == tabClick ? checkColor : textColor)"
:class="tabClick === index? 'navChecked':''">
<view class="acea-row row-middle">
<view class="name tui-skeleton-rect">{{item.title}}</view>
<view class="underlineBox" v-if="index===tabClick">
<!-- <view class="underline"></view> -->
</view>
</view>
</view>
</scroll-view>
</view>
<view class="category">
<text v-if="isShow" class="iconfont icon-xiangshang" @click="isShow=false"></text>
<text v-if="!isShow" class="iconfont icon-xiangxia" @click="isShow=true"></text>
</view>
</view>
<view v-if="isShow" class="navChangeBox" catchtouchmove="true" :style="'top:'+isTop">
<view class="navChange">
<block v-for="(item,index) in tabList" :key="index">
<view class="titleBox" >
<text :style="{ color: tabClick === index ? dataConfig.checkColor.color[0].item : textColor }" class="title line1" :id="'id'+index" @click="longClick(index,item)">{{item.title}}</text>
</view>
</block>
</view>
<view class="mask" @touchmove.prevent :hidden="!isShow" @click="isShow=false"></view>
</view>
</view>
<!-- banner -->
<view class="swiperBg" :style="{ marginTop: swiperTop+'px'}">
<view class="swiper page_swiper" v-if="navIndex === 0">
<swiper :autoplay="true" :circular="circular" :interval="intervalBanner" :duration="duration"
previous-margin="30rpx" next-margin="30rpx" :current="swiperCur" @change="swiperChange">
<block v-for="(item,index) in banner" :key="index">
<swiper-item :style="[contentStyleBanner]" :class="{ active: index == swiperCur }"
class="scalex">
<view @click="menusTap(item.info[1].value)"
class='slide-navigator acea-row row-between-wrapper tui-skeleton-rect'>
<image :style="[contentStyleBanner]" :src="item.img" class="slide-image aa"></image>
</view>
</swiper-item>
</block>
</swiper>
<view v-if="docType === 0" class="dots" :style="[dotStyle]">
<block v-for="(item,index) in banner" :key="index">
<view class="dot-item"
:style="{'background-color': swiperCur === index ? dataConfig.docColor.color[0].item : ''}">
</view>
</block>
</view>
<view v-if="docType === 1" class="dots" :style="[dotStyle]">
<block v-for="(item,index) in banner" :key="index">
<view class="dot"
:style="{'background-color': swiperCur === index ? dataConfig.docColor.color[0].item : ''}">
</view>
</block>
</view>
</view>
</view>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB赋能开发者助力企业发展 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2024 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEB并不是自由软件未经许可不能去掉CRMEB相关版权
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
import {
getCategoryFirst,
getCategoryThird
} from '@/api/api.js';
let app = getApp();
import {
goPage
} from '@/libs/iframe.js'
import animationType from '@/utils/animationType.js'
export default {
name: 'homeComb',
props: {
dataConfig: {
type: Object,
default: () => {}
},
//判断首页显示内容1显示分类页和商品0首页
navIndex: {
type: Number,
default: 0
},
//是否开始滚动
isScrolled: {
type: Boolean,
default: false
}
},
data() {
return {
myMainHeight: 0, //头部tab切换页和搜索按钮的高度和
indicatorDots: false,
circular: true,
autoplay: false,
duration: 500,
searchH: 0,
swiperTop: 0,
statusBarHeight: app.globalData.statusBarHeight, //手机端头部显示时间位置的高度
swiperCur: 0,
showSkeleton: true,
tabClick: 0, //导航栏被点击
isLeft: 0, //导航栏下划线位置
isWidth: 0, //每个导航栏占位
mainWidth: app.globalData.mainWidth,
theme: app.globalData.theme,
tabLeft: 0,
bgColor: '',
isTop: 0,
navHeight: 0,
isShow: false,
marTop: 0,
searchVal: '',
intervalBanner: 2500
};
},
watch: {
banner: {
handler(val) {
this.bgColor = val[0].img;
},
immediate: true
},
},
computed: {
//搜索提示语
placeWords(){
return this.dataConfig.placeWords.val;
},
//轮播切换时间
interval(){
return this.dataConfig.titleConfig.val * 1000
},
//指示器类型0圆1直2无
docType() {
return this.dataConfig.docConfig.tabVal
},
//搜索热词列表
hotWords() {
return this.dataConfig.hotWords.list
},
//分类选中颜色
// lineColor() {
// return {
// backgroundColor: this.dataConfig.checkColor.color[0].item
// }
// },
//判断logo图是否展示
logoConfig() {
return this.dataConfig.logoConfig.url && this.dataConfig.searConfig.tabVal === 1
},
//logo图
logoUrl() {
return this.dataConfig.logoConfig.url
},
//标签文字颜色
textColor() {
return this.dataConfig.fontColor.color[0].item;
},
checkColor() {
return this.dataConfig.checkColor.color[0].item
},
//分类列表
tabList() {
//type=0微页面1分类2首页
let tabList = this.dataConfig.listConfig.list;
tabList.unshift({
title: '首页',
type: 2,
val: 0
})
return tabList
},
//轮播列表
banner() {
return this.dataConfig.swiperConfig.list
},
//搜索框样式
searchBoxStyle() {
return {
borderRadius: this.dataConfig.contentStyle.val ? this.dataConfig.contentStyle.val + 'px' : '0',
backgroundColor: this.dataConfig.borderColor.color[0].item,
color: this.dataConfig.textColor.color[0].item,
textAlign: this.dataConfig.textPosition.list[this.dataConfig.textPosition.tabVal].style
}
},
//指示器样式
dotStyle() {
return {
padding: '0 22px',
justifyContent: this.dataConfig.txtStyle.tabVal === 1 ? 'center' : this.dataConfig.txtStyle
.tabVal === 2 ? 'flex-end' : 'flex-start'
}
},
//轮播图圆角
contentStyleBanner() {
return {
'borderRadius': this.dataConfig.contentStyleBanner.val ? this.dataConfig.contentStyleBanner
.val + 'px' : '0'
}
},
},
created() {
// #ifdef MP || APP-PLUS
this.isTop = (this.statusBarHeight + 48) + 'px' //分类的top值
// #endif
// #ifdef H5
this.isTop = 0
// #endif
this.isWidth = (this.mainWidth - 65) / 4;
setTimeout((e) => {
const query = uni.createSelectorQuery().in(this);
query.select('.header').boundingClientRect(res => {
if (res) this.marTop = res.height //头部的高度
}).exec();
query.select('.navTabBox').boundingClientRect(data => {
this.navHeight = data.height //元素navHeight的高度
// #ifdef H5
this.swiperTop = this.navHeight + this.marTop + this.statusBarHeight + 4; //轮播图的top值
this.myMainHeight = this.marTop + 35 //头部tab切换页和搜索按钮的高度和
//#endif
// #ifndef H5
this.swiperTop = this.statusBarHeight + 85; //轮播图的top值
this.myMainHeight = this.statusBarHeight + 40 + 42; //头部tab切换页和搜索按钮的高度和
//#endif
}).exec();
}, 200)
},
methods: {
//轮播图跳转
menusTap(url) {
this.$util.navigateTo(url);
},
swiperChange(e) {
let {
current,
source
} = e.detail;
if (source === 'autoplay' || source === 'touch') {
this.swiperCur = e.detail.current;
this.bgColor = this.banner[e.detail.current]['img']
}
},
textChange(e) {
let {
current,
source
} = e.detail;
if (source === 'autoplay' || source === 'touch') {
this.searchVal = this.hotWords[e.detail.current]['val']
}
},
// 导航栏点击
longClick(index, item) {
this.tabClick = index; //设置导航点击了哪一个
this.$nextTick(() => {
let id = 'id' + index;
this.tabLeft = (index - 2) * this.isWidth //设置下划线位置
this.$emit('changeTab', index, item);
})
},
parentEmit(id, index) {
this.$emit('changeTab', id, index);
}
}
}
</script>
<style lang="scss" scoped>
.uninput {
/* #ifdef MP */
width: 510rpx !important;
/* #endif */
/* #ifndef MP */
width: 100% !important;
/* #endif */
}
.icon-sousuo8 {
font-size: 15px;
}
.bgwhite {
background-color: #fff !important;
}
.mask {
z-index: 999;
top: 260rpx;
}
.navChangeBox {
position: relative;
}
.navChange {
background-color: #fff;
position: absolute;
z-index: 999999;
width: 100%;
border-radius: 0px 0px 16rpx 16rpx;
padding: 24rpx 20rpx;
display: grid;
grid-template-rows: auto;
grid-template-columns: repeat(5, 1fr);
grid-column-gap: 10rpx;
grid-row-gap: 20rpx;
.nobg {
background-color: #fff !important;
}
.titleBox {
height: 58rpx;
background: #F2F2F2;
border-radius: 8rpx;
text-align: center;
}
.title {
margin: 0 auto;
display: inline-block;
width: 118rpx;
height: 58rpx;
line-height: 58rpx;
text-align: center;
opacity: 1;
color: #333333;
font-size: 24rpx;
}
.titleBox:nth-child(5n) {
margin-right: 0;
}
.titleBox:last-child {
margin-bottom: 0;
}
.changed {
border-radius: 8rpx;
@include cate-two-btn(theme);
@include coupons_border_color(theme);
.title {
@include main_color(theme);
}
}
}
.row-middle {
flex-direction: column;
}
.navTabBox {
width: 100%;
height: 66rpx;
color: rgba(255, 255, 255, 1);
position: relative;
padding: 0 24rpx 0 24rpx;
display: flex;
justify-content: space-between;
z-index: 9;
&.isFixed {
z-index: 10;
position: fixed;
left: 0;
width: 100%;
/* #ifdef H5 */
top: 0;
/* #endif */
}
.click {
color: white;
}
.longTab {
width: 94%;
.longItem {
//height: 72rpx;
display: inline-block;
// line-height: 52rpx;
text-align: center;
font-size: 28rpx;
color: #fff;
white-space: nowrap;
text-overflow: ellipsis;
margin-right: 42rpx;
&.click {
font-weight: bold;
font-size: 30rpx;
color: #fff;
font-weight: bold;
}
.name {
height: 48rpx;
}
}
.underlineBox {
margin-top: 8rpx;
height: 3px;
transition: .5s;
.underline {
width: 33rpx;
height: 4rpx;
}
}
}
.category {
height: 66rpx;
line-height: 46rpx;
z-index: 3;
// padding: 0 15rpx 0 25rpx;
.iconfont {
font-size: 24rpx;
}
}
}
.swiperBg {
z-index: 1;
margin-top: 10rpx;
.colorBg {
position: absolute;
left: 0;
top: 0;
height: 130rpx;
width: 100%;
}
.page_swiper {
position: relative;
width: 100%;
height: auto;
margin: 0 auto;
border-radius: 10rpx;
overflow: hidden;
z-index: 8;
padding: 0 0rpx 20rpx 0rpx;
.swiper-item,
image,
.acea-row.row-between-wrapper {
width: 100%;
height: 310rpx;
margin: 0 auto;
border-radius: 10rpx;
}
swiper {
width: 100%;
display: block;
height: 310rpx;
&.scalex {
/deep/.uni-swiper-slide-frame {
transform: translate(0, 0) !important;
}
}
}
image {
transform: scale(0.96);
transition: all 0.6s ease;
}
/deep/ swiper-item.active {
image {
transform: scale(1);
}
}
/*用来包裹所有的小圆点 */
.dots {
display: flex;
flex-direction: row;
position: absolute;
bottom: 40rpx;
align-items: center;
width: 100%;
}
.dot-item {
width: 10rpx;
height: 10rpx;
background-color: rgba(255, 255, 255, .4);
border-radius: 50%;
margin: 0 6rpx;
}
/*未选中时的小圆点样式 */
.dot {
width: 16rpx;
height: 6rpx;
border-radius: 6rpx;
margin-right: 6rpx;
background-color: rgba(255, 255, 255, .4);
}
}
}
.scrolled {
z-index: 5000;
position: fixed;
left: 0;
top: 0;
width: 100%;
background-color: #fff !important;
color: #000 !important;
transition: background-color .5s ease;
.longItem,
.click,
.category text {
color: #000 !important;
}
.btn .iconfont {
color: #333 !important;
}
.iconnum {
background: #333 !important;
}
.underline {
background: #000 !important;
}
.click {
&::after {
background-color: #fff !important;
}
}
.input,
.uninput {
background-color: #eee !important;
}
}
.page_count {
position: relative;
overflow: hidden;
background-repeat: no-repeat;
.bg-img {
position: absolute;
width: 100%;
height: 100%;
top: 0;
/* #ifdef MP || APP-PLUS */
z-index: -1;
/* #endif */
/* #ifdef H5 */
z-index: 0;
/* #endif */
z-index: 0;
filter: blur(0);
overflow: hidden;
img {
width: 100%;
height: 100%;
filter: blur(30rpx);
transform: scale(1.5);
}
}
}
.my-main {
left: 0;
position: fixed;
top: 0;
width: 100%;
z-index: 30;
transition: background-color .5s ease;
}
.page_count {
.header {
width: 100%;
padding: 24rpx;
.serch-wrapper {
align-items: center;
.logo {
width: 118rpx;
margin-right: 24rpx;
}
image {
width: 118rpx;
height: 42rpx;
}
.input {
display: flex;
align-items: center;
width: 546rpx;
height: 55rpx;
padding-left: 20rpx;
font-size: 26rpx;
padding-right: 4rpx;
box-sizing: border-box;
.iconfont {
margin-right: 16rpx;
font-size: 30rpx;
color: #666666;
}
}
}
.tabNav {
padding-top: 24rpx;
}
}
/* #ifdef MP || APP-PLUS */
.mp-header {
z-index: 999;
position: fixed;
left: 0;
top: 0;
width: 100%;
/* #ifdef H5 */
padding-bottom: 20rpx;
/* #endif */
.serch-wrapper {
height: 100%;
align-items: center;
padding: 0 24rpx 0 24rpx;
image {
width: 118rpx;
height: 42rpx;
margin-right: 30rpx;
}
.input {
display: flex;
align-items: center;
/* #ifdef MP */
width: 365rpx;
/* #endif */
/* #ifndef MP */
width: 546rpx;
/* #endif */
/* #ifdef APP-PLUS */
flex: 1;
/* #endif */
height: 50rpx;
padding-left: 20rpx;
font-size: 28rpx;
box-sizing: border-box;
.iconfont {
margin-right: 20rpx;
}
}
}
}
/* #endif */
.swiperTxt {
width: 100%;
/* #ifndef MP */
//width: 484rpx;
/* #endif */
/* #ifdef MP */
//width: 333rpx;
/* #endif */
height: 100%;
line-height: 52rpx;
overflow: hidden;
}
.swiperTxt .text {
/* #ifndef MP */
width: 480rpx;
/* #endif */
/* #ifdef MP */
width: 289rpx;
/* #endif */
}
.swiperTxt .text .label {
font-size: 20rpx;
color: #ff4c48;
width: 64rpx;
height: 30rpx;
border-radius: 40rpx;
text-align: center;
line-height: 28rpx;
border: 2rpx solid #ff4947;
}
.swiperTxt .text .newsTitle {
/* #ifndef MP */
// width: 484rpx;
// /* #endif */
// /* #ifdef MP */
// width: 446rpx;
/* #endif */
font-size: 24rpx;
}
.swiperTxt swiper {
height: 100%;
}
}
.navChecked{
font-size: 32rpx !important;
font-weight: 500;
}
</style>