|
|
|
<template>
|
|
|
|
<view>
|
|
|
|
<!-- 遮罩层 -->
|
|
|
|
<view class="overlay" v-if="showMenu" @click="closeMenu"></view>
|
|
|
|
|
|
|
|
<!-- 固定导航按钮 -->
|
|
|
|
<view class="fixed-nav" :class="{ hidden: showMenu }" @click="showNavMenu">
|
|
|
|
<image
|
|
|
|
class="nav-icon"
|
|
|
|
:class="{ rotated: iconRotated, 'bounce-back': iconBounceBack }"
|
|
|
|
src="https://des.dayunyuanjian.cn/epicSoul/taozi/nav-icon.png"
|
|
|
|
mode="aspectFill"
|
|
|
|
></image>
|
|
|
|
</view>
|
|
|
|
|
|
|
|
<!-- 侧边导航菜单 -->
|
|
|
|
<view class="nav-menu" :class="{ show: showMenu }">
|
|
|
|
<view
|
|
|
|
class="nav-item"
|
|
|
|
:class="{ 'item-active': isItemActive(item) }"
|
|
|
|
v-for="item in menuItems"
|
|
|
|
:key="item.targetIndex"
|
|
|
|
@click="() => jumpToPage(item.targetIndex)"
|
|
|
|
>
|
|
|
|
<view v-if="item.text.includes('#Chapter')" class="chapter-text">
|
|
|
|
<text class="chapter-title">#Chapter</text>
|
|
|
|
<text :class="{ active: isItemActive(item) }" class="chapter-number">
|
|
|
|
{{ item.text.replace("#Chapter", "") }}
|
|
|
|
</text>
|
|
|
|
</view>
|
|
|
|
<text v-else :class="{ active: isItemActive(item) }">{{
|
|
|
|
item.text
|
|
|
|
}}</text>
|
|
|
|
</view>
|
|
|
|
</view>
|
|
|
|
</view>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
|
|
|
export default {
|
|
|
|
name: "SideNav",
|
|
|
|
props: {
|
|
|
|
currentIndex: {
|
|
|
|
type: Number,
|
|
|
|
default: 0,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
data() {
|
|
|
|
return {
|
|
|
|
showMenu: false,
|
|
|
|
iconRotated: false,
|
|
|
|
iconBounceBack: false,
|
|
|
|
menuItems: [
|
|
|
|
{
|
|
|
|
text: "序章",
|
|
|
|
targetIndex: 0,
|
|
|
|
path: "/pig/home/home",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
text: "第一章猪的起源",
|
|
|
|
targetIndex: 4,
|
|
|
|
path: "/pig/chapter1/chapter1",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
text: "第二章驯为良伴",
|
|
|
|
targetIndex: 5,
|
|
|
|
path: "/pig/chapter2/chapter2",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
text: "第三章身份之谜",
|
|
|
|
targetIndex: 6,
|
|
|
|
path: "/pig/chapter3/chapter3",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
text: "第四章 东方之猪",
|
|
|
|
targetIndex: 7,
|
|
|
|
path: "/pig/chapter4/chapter4",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
text: "点击购买",
|
|
|
|
targetIndex: 8,
|
|
|
|
path: "/subPackages/techan/detail?id=38",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
text: '购物车',
|
|
|
|
targetIndex: 10,
|
|
|
|
path: "/subPackages/user/gwc"
|
|
|
|
}
|
|
|
|
],
|
|
|
|
};
|
|
|
|
},
|
|
|
|
methods: {
|
|
|
|
showNavMenu() {
|
|
|
|
this.iconRotated = true;
|
|
|
|
setTimeout(() => {
|
|
|
|
this.showMenu = true;
|
|
|
|
}, 300);
|
|
|
|
},
|
|
|
|
|
|
|
|
closeMenu() {
|
|
|
|
this.showMenu = false;
|
|
|
|
setTimeout(() => {
|
|
|
|
this.iconBounceBack = true;
|
|
|
|
this.iconRotated = false;
|
|
|
|
setTimeout(() => {
|
|
|
|
this.iconBounceBack = false;
|
|
|
|
}, 500);
|
|
|
|
}, 300);
|
|
|
|
},
|
|
|
|
jumpToPage(targetIndex) {
|
|
|
|
const menuItem = this.menuItems.find(
|
|
|
|
(item) => item.targetIndex === targetIndex
|
|
|
|
);
|
|
|
|
if (menuItem) {
|
|
|
|
// 如果有path属性,进行页面跳转
|
|
|
|
if (menuItem.path) {
|
|
|
|
uni.navigateTo({
|
|
|
|
url:
|
|
|
|
menuItem.path +
|
|
|
|
(targetIndex > 0 ? `?targetIndex=${targetIndex}` : ""),
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
// 否则触发事件让父组件处理
|
|
|
|
this.$emit("navigate", targetIndex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
this.closeMenu();
|
|
|
|
},
|
|
|
|
isItemActive(item) {
|
|
|
|
return this.currentIndex === item.targetIndex;
|
|
|
|
},
|
|
|
|
},
|
|
|
|
};
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
.overlay {
|
|
|
|
position: fixed;
|
|
|
|
top: 0;
|
|
|
|
left: 0;
|
|
|
|
right: 0;
|
|
|
|
bottom: 0;
|
|
|
|
background-color: rgba(0, 0, 0, 0.3);
|
|
|
|
z-index: 10;
|
|
|
|
}
|
|
|
|
|
|
|
|
.fixed-nav {
|
|
|
|
width: 80rpx;
|
|
|
|
height: 80rpx;
|
|
|
|
background-color: rgb(0 0 0 / 0.7);
|
|
|
|
border-radius: 10rpx 0 0 10rpx;
|
|
|
|
position: fixed;
|
|
|
|
right: 0;
|
|
|
|
top: 0;
|
|
|
|
bottom: 0;
|
|
|
|
margin: auto 0;
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
justify-content: center;
|
|
|
|
z-index: 9;
|
|
|
|
transition: transform 0.3s ease, opacity 0.3s ease;
|
|
|
|
}
|
|
|
|
|
|
|
|
.fixed-nav.hidden {
|
|
|
|
transform: translateX(100%);
|
|
|
|
opacity: 0;
|
|
|
|
pointer-events: none;
|
|
|
|
}
|
|
|
|
|
|
|
|
.nav-icon {
|
|
|
|
width: 35rpx;
|
|
|
|
height: 35rpx;
|
|
|
|
transition: transform 0.3s ease;
|
|
|
|
}
|
|
|
|
|
|
|
|
.nav-icon.rotated {
|
|
|
|
transform: rotate(180deg);
|
|
|
|
}
|
|
|
|
|
|
|
|
.nav-icon.bounce-back {
|
|
|
|
animation: bounceRotation 0.5s ease;
|
|
|
|
}
|
|
|
|
|
|
|
|
@keyframes bounceRotation {
|
|
|
|
0% {
|
|
|
|
transform: rotate(180deg);
|
|
|
|
}
|
|
|
|
|
|
|
|
50% {
|
|
|
|
transform: rotate(-20deg);
|
|
|
|
}
|
|
|
|
|
|
|
|
75% {
|
|
|
|
transform: rotate(10deg);
|
|
|
|
}
|
|
|
|
|
|
|
|
100% {
|
|
|
|
transform: rotate(0deg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.nav-menu {
|
|
|
|
position: fixed;
|
|
|
|
top: 50%;
|
|
|
|
right: 0;
|
|
|
|
transform: translate(100%, -50%);
|
|
|
|
z-index: 11;
|
|
|
|
background-color: rgba(255, 255, 255, 0.95);
|
|
|
|
border-radius: 16rpx 0 0 16rpx;
|
|
|
|
box-shadow: -4px 0 15px rgba(0, 0, 0, 0.1);
|
|
|
|
transition: transform 0.3s ease;
|
|
|
|
}
|
|
|
|
|
|
|
|
.nav-menu.show {
|
|
|
|
transform: translate(0, -50%);
|
|
|
|
}
|
|
|
|
|
|
|
|
.nav-item {
|
|
|
|
padding: 20rpx;
|
|
|
|
text-align: center;
|
|
|
|
|
|
|
|
text {
|
|
|
|
color: #333;
|
|
|
|
opacity: 0.7;
|
|
|
|
font-size: 28rpx;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.item-active {
|
|
|
|
background-color: rgba(0, 0, 0, 0.1);
|
|
|
|
}
|
|
|
|
|
|
|
|
.nav-item .active {
|
|
|
|
color: #333;
|
|
|
|
opacity: 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
.chapter-text {
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
align-items: center;
|
|
|
|
line-height: 1.3;
|
|
|
|
}
|
|
|
|
|
|
|
|
.chapter-title {
|
|
|
|
color: #333;
|
|
|
|
opacity: 0.7;
|
|
|
|
font-size: 24rpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
.chapter-number {
|
|
|
|
color: #333;
|
|
|
|
opacity: 0.7;
|
|
|
|
font-size: 28rpx;
|
|
|
|
margin-top: 8rpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
.item-active .chapter-title,
|
|
|
|
.item-active .chapter-number.active {
|
|
|
|
opacity: 1;
|
|
|
|
}
|
|
|
|
</style>
|