mirror of
https://gitee.com/TSpecific/tuniao-ui.git
synced 2026-06-07 03:53:57 +08:00
640 lines
20 KiB
Vue
640 lines
20 KiB
Vue
<template>
|
||
<view class="template-tuniao tn-safe-area-inset-bottom">
|
||
<!-- 顶部自定义导航 -->
|
||
<!-- <tn-nav-bar fixed alpha customBack>
|
||
<view slot="back" class='tn-custom-nav-bar__back'
|
||
@click="goBack">
|
||
<text class='icon tn-icon-left'></text>
|
||
<text class='icon tn-icon-home-capsule-fill'></text>
|
||
</view>
|
||
</tn-nav-bar> -->
|
||
|
||
<!-- 顶部自定义导航 -->
|
||
<tn-nav-bar fixed :isBack="false" :bottomShadow="false" :backgroundColor="navBarBackgroundColor">
|
||
<view id="navbar" class="custom-nav tn-flex tn-flex-col-center tn-flex-row-left" :style="[navBarStyle]">
|
||
<!-- 图标logo -->
|
||
<view class="custom-nav__back">
|
||
<view class="logo-pic" style="background-image:url('https://resource.tuniaokj.com/images/logo/logo.jpg')">
|
||
<view class="logo-image">
|
||
</view>
|
||
</view>
|
||
<!-- <view class="tn-icon-left"></view> -->
|
||
</view>
|
||
<!-- 搜索框 -->
|
||
<view class="custom-nav__search tn-flex tn-flex-col-center tn-flex-row-center">
|
||
<view class="custom-nav__search__box tn-flex tn-flex-col-center tn-flex-row-left tn-color-gray--dark tn-bg-gray--light">
|
||
<view class="custom-nav__search__icon tn-icon-search"></view>
|
||
<view class="custom-nav__search__text tn-padding-left-xs">好想搜点什么</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</tn-nav-bar>
|
||
|
||
<view class="tn-margin-top-sm" :style="{paddingTop: vuex_custom_bar_height + 'px'}">
|
||
<view id="page_tips" class="tn-flex tn-flex-row-between">
|
||
<view class="justify-content-item tn-margin tn-text-bold tn-text-xxl">
|
||
Hi,早午晚都好吖
|
||
</view>
|
||
<view class="justify-content-item tn-margin tn-text-bold tn-text-xxl">
|
||
<text class="tn-icon-share-triangle"></text>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="tn-margin-left tn-margin-right tn-margin-top-sm">
|
||
<tn-swiper :list="banner" :height="320" :effect3d="false" mode="round"></tn-swiper>
|
||
</view>
|
||
|
||
<view class="tn-flex tn-flex-row-between tn-margin-top-xl">
|
||
<view class="justify-content-item tn-margin tn-text-bold tn-text-xxl">
|
||
热门项目
|
||
</view>
|
||
<view class="justify-content-item tn-margin tn-text-lg tn-color-gray--disabled">
|
||
<text class="tn-padding-xs">全部</text>
|
||
<text class="tn-icon-topics"></text>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="tn-flex tn-margin-left tn-margin-right tn-margin-top-sm">
|
||
<view class="tn-flex-2">
|
||
|
||
<view class="image-pic tn-margin-right" style="background-image:url('https://resource.tuniaokj.com/images/shop/cup2.jpg')">
|
||
<view class="image-tuniao1">
|
||
</view>
|
||
</view>
|
||
|
||
</view>
|
||
<view class="tn-flex-1">
|
||
<view class="image-pic" style="background-image:url('https://resource.tuniaokj.com/images/shop/phonecase1.jpg')">
|
||
<view class="image-tuniao2">
|
||
</view>
|
||
</view>
|
||
<view class="image-pic tn-margin-top" style="background-image:url('https://resource.tuniaokj.com/images/shop/banner1.jpg')">
|
||
<view class="image-tuniao2">
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
|
||
<view class="tn-flex tn-flex-row-between tn-margin-top">
|
||
<view class="justify-content-item tn-margin tn-text-bold tn-text-xxl">
|
||
业务范围
|
||
</view>
|
||
<!-- <view class="justify-content-item tn-margin tn-text-xxl tn-color-gray--disabled">
|
||
<text class="tn-padding-xs">全部</text>
|
||
<text class="tn-icon-topics"></text>
|
||
</view> -->
|
||
</view>
|
||
|
||
<view class="tn-info__container tn-flex tn-flex-wrap tn-flex-col-center tn-flex-row-between tn-margin-left tn-margin-right">
|
||
<block v-for="(item, index) in tuniaoData" :key="index">
|
||
<view class="tn-info__item tn-flex tn-flex-direction-row tn-flex-col-center tn-flex-row-between tn-color-white" :class="[`tn-bg-${item.color}`]">
|
||
<view class="tn-info__item__left tn-flex tn-flex-direction-row tn-flex-col-center tn-flex-row-left">
|
||
<!-- <view class="tn-info__item__left--icon tn-flex tn-flex-col-center tn-flex-row-center" :class="[`tn-bg-${item.color}--light tn-color-${item.color}`]">
|
||
<view :class="[`tn-icon-${item.icon}`]"></view>
|
||
</view> -->
|
||
<view class="tn-info__item__left__content">
|
||
<view class="tn-info__item__left__content--title tn-text-xxl">{{ item.title }}</view>
|
||
<view class="tn-info__item__left__content--data tn-padding-top-xs">
|
||
{{ item.value }}
|
||
<text class="tn-icon-right tn-padding-left-xs"></text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="tn-info__item__right">
|
||
<view class="tn-info__item__right--icon">
|
||
<view :class="[`tn-icon-${item.icon}`]"></view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</block>
|
||
</view>
|
||
|
||
</view>
|
||
|
||
|
||
<view class="bg-tabbar-shadow"></view>
|
||
<view class="tabbar__placeholder"></view>
|
||
|
||
<!-- 底部导航栏 -->
|
||
<view class="tabbar">
|
||
<view class="tabbar__bg" :style="[wrapStyle]"></view>
|
||
<view class="tabbar__list">
|
||
<block v-for="(item, index) in tabbar" :key="index">
|
||
<view :id="`tabbar_item_${index}`" class="tabbar__item" :class="[{'tabbar__item--active': index === currentTabbarIndex}]" @click="changeTabbar(index)">
|
||
<view class="tabbar__item__icon" :class="[item.icon]"></view>
|
||
<view class="tabbar__item__text">{{ item.name }}</view>
|
||
</view>
|
||
</block>
|
||
</view>
|
||
<!-- <view class="tabbar__select-active-bg" :class="[showActiceBg ? 'tabbar__select-active-bg--show' : 'tabbar__select-active-bg--hide']" :style="[activeBgStyle]"></view> -->
|
||
<view class="tabbar__select-active-bg" :animation="activeBgAnimation"></view>
|
||
</view>
|
||
|
||
<!-- 回到首页悬浮按钮-->
|
||
<nav-index-button></nav-index-button>
|
||
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import template_page_mixin from '@/libs/mixin/template_page_mixin.js'
|
||
import NavIndexButton from '@/libs/components/nav-index-button.vue'
|
||
export default {
|
||
name: 'TemplateCourse',
|
||
mixins: [template_page_mixin],
|
||
components: { NavIndexButton },
|
||
data(){
|
||
return {
|
||
banner: [{
|
||
image: 'https://resource.tuniaokj.com/images/swiper/tnbanner1.jpg'
|
||
}, {
|
||
image: 'https://resource.tuniaokj.com/images/swiper/tnbanner2.jpg'
|
||
}, {
|
||
image: 'https://resource.tuniaokj.com/images/swiper/tnbanner3.jpg'
|
||
}, {
|
||
image: 'https://resource.tuniaokj.com/images/swiper/tnbanner4.jpg'
|
||
}],
|
||
tuniaoData: [
|
||
{
|
||
title: 'UI设计',
|
||
icon: 'image-text-fill',
|
||
color: 'red',
|
||
value: '前往咨询'
|
||
},
|
||
{
|
||
title: '小程序',
|
||
icon: 'data-fill',
|
||
color: 'orange',
|
||
value: '前往咨询'
|
||
},
|
||
{
|
||
title: '网站开发',
|
||
icon: 'statistics-fill',
|
||
color: 'purple',
|
||
value: '前往咨询'
|
||
},
|
||
{
|
||
title: '其他业务',
|
||
icon: 'bankcard-fill',
|
||
color: 'blue',
|
||
value: '前往咨询'
|
||
}
|
||
],
|
||
wrapMaskPositionLeft: 0,
|
||
activeBgPositionLeft: 0,
|
||
showActiceBg: false,
|
||
prevTabbarIndex: 0,
|
||
currentTabbarIndex: 0,
|
||
tabbarRectInfo: [],
|
||
tabbar: [
|
||
{ name: '首页', icon: 'tn-icon-home' },
|
||
{ name: '圈子', icon: 'tn-icon-discover' },
|
||
{ name: '数据', icon: 'tn-icon-data' },
|
||
{ name: '我的', icon: 'tn-icon-my' }
|
||
],
|
||
navBarRectInfo: {},
|
||
navBarChangebaseLineHeight: 0,
|
||
navBarStyle: {
|
||
opacity: 1,
|
||
display: 'flex'
|
||
},
|
||
navBarBackgroundColor: 'rgba(255, 255, 255, 1)',
|
||
activeBgAnimation: {}
|
||
}
|
||
},
|
||
computed: {
|
||
wrapStyle() {
|
||
return {
|
||
'-webkit-mask-position': `${this.wrapMaskPositionLeft}px -1px, 100%`
|
||
}
|
||
},
|
||
activeBgStyle() {
|
||
return {
|
||
'left': `${this.activeBgPositionLeft}px`
|
||
}
|
||
}
|
||
},
|
||
onReady() {
|
||
this.$nextTick(() => {
|
||
this.getTabbarItemInfo()
|
||
this.initNavBarRectInfo()
|
||
})
|
||
},
|
||
onPageScroll() {
|
||
this.updateNavBarRectInfo()
|
||
},
|
||
methods: {
|
||
// 初始化导航栏信息
|
||
async initNavBarRectInfo() {
|
||
const navBarRectInfo = await this._tGetRect('#navbar')
|
||
const pageTipsRectInfo = await this._tGetRect('#page_tips')
|
||
// console.log(navBarRectInfo, pageTipsRectInfo);
|
||
if (!(navBarRectInfo?.top) || !(pageTipsRectInfo?.top)) {
|
||
setTimeout(() => {
|
||
this.initNavBarRectInfo()
|
||
}, 10)
|
||
return
|
||
}
|
||
this.navBarRectInfo = {
|
||
top: navBarRectInfo.top
|
||
}
|
||
this.navBarChangebaseLineHeight = pageTipsRectInfo.top - navBarRectInfo.top
|
||
},
|
||
// 更新导航栏信息
|
||
updateNavBarRectInfo() {
|
||
this._tGetRect('#page_tips').then((res) => {
|
||
const top = res?.top || 0
|
||
if (!top) {
|
||
return
|
||
}
|
||
const differHeight = top - this.navBarRectInfo.top
|
||
const opacity = differHeight / this.navBarChangebaseLineHeight
|
||
if (opacity < 0) {
|
||
this.navBarStyle.opacity = 0
|
||
this.navBarStyle.display = 'none'
|
||
this.navBarBackgroundColor = `rgba(255, 255, 255, 0)`
|
||
} else {
|
||
this.navBarStyle.opacity = opacity
|
||
this.navBarStyle.display = 'flex'
|
||
this.navBarBackgroundColor = `rgba(255, 255, 255, ${opacity})`
|
||
}
|
||
|
||
// console.log(top, differHeight, opacity);
|
||
})
|
||
},
|
||
// 获取底部元素的位置
|
||
getTabbarItemInfo() {
|
||
const view = uni.createSelectorQuery().in(this)
|
||
for(let i = 0; i < this.tabbar.length; i++) {
|
||
view.select('#tabbar_item_' + i).boundingClientRect()
|
||
}
|
||
view.exec(res => {
|
||
if (!res.length) {
|
||
setTimeout(() => {
|
||
this.getTabbarItemInfo()
|
||
}, 10)
|
||
return
|
||
}
|
||
|
||
// 将信息存入数组中
|
||
res.map((item) => {
|
||
this.tabbarRectInfo.push({
|
||
left: item.left,
|
||
width: item.width
|
||
})
|
||
})
|
||
this.updateHollowsPosition()
|
||
this.updateActiveBgPosition(true)
|
||
// console.log(this.tabbarRectInfo)
|
||
})
|
||
},
|
||
// 更新凹陷位置
|
||
updateHollowsPosition() {
|
||
const { width, left } = this.tabbarRectInfo[this.currentTabbarIndex]
|
||
// 计算掩模图片的宽高比
|
||
// const imageRatio = 200 / 92
|
||
// 计算定高的宽比
|
||
const imageFixedHeightWidthRatioValue = 300 * (uni.upx2px(64) / 92)
|
||
this.wrapMaskPositionLeft = left - ((imageFixedHeightWidthRatioValue - width) / 2)
|
||
// console.log(imageFixedHeightWidthRatioValue, this.wrapMaskPositionLeft);
|
||
},
|
||
// 更新激活时背景的位置
|
||
updateActiveBgPosition(init = false) {
|
||
const { width, left } = this.tabbarRectInfo[this.currentTabbarIndex]
|
||
const oldActiveBgPositionLeft = this.activeBgPositionLeft
|
||
this.activeBgPositionLeft = left + ((width - uni.upx2px(100)) / 2)
|
||
// console.log(oldActiveBgPositionLeft, this.activeBgPositionLeft);
|
||
// if (!init) {
|
||
// this.showActiceBg = false
|
||
// setTimeout(() => {
|
||
// this.showActiceBg = true
|
||
// }, 150)
|
||
// } else {
|
||
// this.showActiceBg = true
|
||
// }
|
||
if (!init) {
|
||
const animation = uni.createAnimation({
|
||
duration: 200,
|
||
timingFunction: "ease-out"
|
||
})
|
||
animation.top(uni.upx2px(50)).left(oldActiveBgPositionLeft + ((this.activeBgPositionLeft - oldActiveBgPositionLeft) / 2)).scale(0.5).step()
|
||
animation.left(this.activeBgPositionLeft).top(uni.upx2px(-54)).scale(1).step()
|
||
this.activeBgAnimation = animation.export()
|
||
} else {
|
||
const animation = uni.createAnimation({
|
||
duration: 100,
|
||
timingFunction: "ease-out"
|
||
})
|
||
animation.left(this.activeBgPositionLeft).top(uni.upx2px(-54)).step()
|
||
this.activeBgAnimation = animation.export()
|
||
}
|
||
|
||
},
|
||
// 修改当前选中的tabbar
|
||
changeTabbar(index) {
|
||
if (this.currentTabbarIndex === index) return
|
||
this.prevTabbarIndex = this.currentTabbarIndex
|
||
this.currentTabbarIndex = index
|
||
this.$nextTick(() => {
|
||
this.updateHollowsPosition()
|
||
this.updateActiveBgPosition()
|
||
})
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
@import '@/static/css/templatePage/custom_nav_bar.scss';
|
||
|
||
.template-tuniao {
|
||
// background-color: #FBFBFB;
|
||
}
|
||
/* 底部tabbar假阴影 start*/
|
||
.bg-tabbar-shadow{
|
||
background-image: repeating-linear-gradient(to top, rgba(0,0,0,0.1) 10rpx, #FFFFFF , #FFFFFF);
|
||
position: fixed;
|
||
bottom: 0;
|
||
height: 450rpx;
|
||
width: 100vw;
|
||
z-index: -1;
|
||
}
|
||
|
||
/* 自定义导航栏内容 start */
|
||
.custom-nav {
|
||
height: 100%;
|
||
|
||
&__back {
|
||
margin: auto 5rpx;
|
||
font-size: 40rpx;
|
||
margin-right: 10rpx;
|
||
margin-left: 30rpx;
|
||
flex-basis: 5%;
|
||
}
|
||
|
||
&__search {
|
||
flex-basis: 60%;
|
||
width: 100%;
|
||
height: 100%;
|
||
|
||
&__box {
|
||
width: 100%;
|
||
height: 70%;
|
||
padding: 10rpx 0;
|
||
margin: 0 30rpx;
|
||
border-radius: 60rpx 60rpx 0 60rpx;
|
||
font-size: 24rpx;
|
||
}
|
||
|
||
&__icon {
|
||
padding-right: 10rpx;
|
||
margin-left: 20rpx;
|
||
font-size: 30rpx;
|
||
}
|
||
|
||
&__text {
|
||
color: #AAAAAA;
|
||
}
|
||
}
|
||
}
|
||
.logo-image{
|
||
width: 65rpx;
|
||
height: 65rpx;
|
||
position: relative;
|
||
}
|
||
.logo-pic{
|
||
background-size: cover;
|
||
background-repeat:no-repeat;
|
||
// background-attachment:fixed;
|
||
background-position:top;
|
||
border-radius: 50%;
|
||
}
|
||
/* 自定义导航栏内容 end */
|
||
|
||
|
||
/* 热门图片 start*/
|
||
.image-tuniao1{
|
||
padding: 164rpx 0rpx;
|
||
font-size: 40rpx;
|
||
font-weight: 300;
|
||
position: relative;
|
||
}
|
||
.image-tuniao2{
|
||
padding: 75rpx 0rpx;
|
||
font-size: 40rpx;
|
||
font-weight: 300;
|
||
position: relative;
|
||
}
|
||
.image-tuniao3{
|
||
padding: 90rpx 0rpx;
|
||
font-size: 40rpx;
|
||
font-weight: 300;
|
||
position: relative;
|
||
}
|
||
.image-pic{
|
||
background-size: cover;
|
||
background-repeat:no-repeat;
|
||
// background-attachment:fixed;
|
||
background-position:top;
|
||
border-radius: 10rpx;
|
||
}
|
||
|
||
/* 业务展示 start */
|
||
.tn-info {
|
||
|
||
&__container {
|
||
margin-top: 10rpx;
|
||
margin-bottom: 50rpx;
|
||
}
|
||
|
||
&__item {
|
||
width: 48%;
|
||
margin: 15rpx 0rpx;
|
||
padding: 40rpx 30rpx;
|
||
border-radius: 15rpx;
|
||
|
||
|
||
position: relative;
|
||
z-index: 1;
|
||
|
||
&::after {
|
||
content: " ";
|
||
position: absolute;
|
||
z-index: -1;
|
||
width: 100%;
|
||
height: 100%;
|
||
left: 0;
|
||
bottom: 0;
|
||
border-radius: inherit;
|
||
opacity: 1;
|
||
transform: scale(1, 1);
|
||
background-size: 100% 100%;
|
||
background-image: url(https://resource.tuniaokj.com/images/cool_bg_image/3.png);
|
||
}
|
||
|
||
&__left {
|
||
|
||
&--icon {
|
||
width: 80rpx;
|
||
height: 80rpx;
|
||
border-radius: 50%;
|
||
font-size: 40rpx;
|
||
margin-right: 20rpx;
|
||
position: relative;
|
||
z-index: 1;
|
||
|
||
&::after {
|
||
content: " ";
|
||
position: absolute;
|
||
z-index: -1;
|
||
width: 100%;
|
||
height: 100%;
|
||
left: 0;
|
||
bottom: 0;
|
||
border-radius: inherit;
|
||
opacity: 1;
|
||
transform: scale(1, 1);
|
||
background-size: 100% 100%;
|
||
background-image: url(https://resource.tuniaokj.com/images/cool_bg_image/icon_bg5.png);
|
||
}
|
||
}
|
||
|
||
&__content {
|
||
font-size: 30rpx;
|
||
|
||
&--data {
|
||
margin-top: 5rpx;
|
||
font-weight: bold;
|
||
}
|
||
}
|
||
}
|
||
|
||
&__right {
|
||
&--icon {
|
||
position: absolute;
|
||
right: 0rpx;
|
||
top: 50rpx;
|
||
font-size: 100rpx;
|
||
width: 108rpx;
|
||
height: 108rpx;
|
||
text-align: center;
|
||
line-height: 60rpx;
|
||
opacity: 0.15;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
/* 业务展示 end */
|
||
|
||
/* 底部导航 statr */
|
||
.tabbar {
|
||
width: 100%;
|
||
height: calc(110rpx + env(safe-area-inset-bottom));
|
||
position: fixed;
|
||
bottom: 0;
|
||
left: 0;
|
||
right: 0;
|
||
background-color: transparent;
|
||
z-index: 998;
|
||
|
||
&__bg {
|
||
position: absolute;
|
||
width: 100%;
|
||
height: 100%;
|
||
bottom: 0;
|
||
left: 0;
|
||
background-color: #FFFFFF;
|
||
-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 61.5'%3E%3Cpath d='M100 0H0c32.9 0 49.3 61.5 100 61.5S167.1 0 200 0H100z'/%3E%3C/svg%3E"), linear-gradient(#000, #000);
|
||
-webkit-mask-size: auto 64rpx, cover;
|
||
-webkit-mask-repeat: no-repeat;
|
||
-webkit-mask-composite: xor; /*只显示不重合的地方, chorem 、safari 支持*/
|
||
z-index: 998;
|
||
transition: 0.5s;
|
||
}
|
||
|
||
&__list {
|
||
position: absolute;
|
||
z-index: 999;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
}
|
||
|
||
&__item {
|
||
height: 100%;
|
||
width: 100%;
|
||
flex: 1;
|
||
text-align: center;
|
||
font-size: 28rpx;
|
||
position: relative;
|
||
|
||
&--active {
|
||
.tabbar__item__icon {
|
||
top: -30rpx;
|
||
}
|
||
|
||
.tabbar__item__text {
|
||
opacity: 1;
|
||
}
|
||
}
|
||
|
||
&__icon {
|
||
font-size: 56rpx;
|
||
position: absolute;
|
||
left: 0;
|
||
right: 0;
|
||
top: 20rpx;
|
||
transition: 0.5s;
|
||
}
|
||
|
||
&__text {
|
||
position: absolute;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: calc(10rpx + env(safe-area-inset-bottom));
|
||
transition: 0.5s;
|
||
opacity: 0;
|
||
}
|
||
}
|
||
|
||
&__select-active-bg {
|
||
position: absolute;
|
||
width: 100rpx;
|
||
height: 100rpx;
|
||
border-radius: 50%;
|
||
background-color: #FFFFFF;
|
||
// transition: 0.5s;
|
||
z-index: -1;
|
||
// box-shadow: 0rpx 0rpx 50rpx 0rpx rgba(0, 0, 0, 0.05);
|
||
// box-shadow: inset 0rpx 0rpx 50rpx 0rpx rgba(0, 0, 0, 0.05);
|
||
box-shadow: 0rpx 10rpx 30rpx rgba(70,23,129, 0.07),
|
||
0rpx -8rpx 40rpx rgba(255, 255, 255, 0.07),
|
||
inset 0rpx -10rpx 10rpx rgba(70,23,129, 0.07),
|
||
inset 0rpx 10rpx 20rpx rgba(255, 255, 255, 1);
|
||
// transition: box-shadow .2s ease-out;
|
||
|
||
&--hide {
|
||
top: calc(110rpx + 50rpx);
|
||
}
|
||
|
||
&--show {
|
||
top: -54rpx;
|
||
}
|
||
}
|
||
|
||
&__placeholder {
|
||
height: calc(110rpx + env(safe-area-inset-bottom));
|
||
// display: initial;
|
||
}
|
||
}
|
||
/* 底部导航 end */
|
||
|
||
</style>
|