Ver código fonte

添加 tabber、我的、书城、书架

wangzhiqiang 4 meses atrás
pai
commit
a7d5085889

+ 122 - 0
components/custom-tabbar.vue

@@ -0,0 +1,122 @@
+<template>
+	<view class="custom-tabbar" v-if="isShowTabbar">
+		<view v-for="(item, index) in list" :key="index" class="tabbar-item" @click="switchTab(index)">
+			<!-- <view v-if="item.text === '新建'" class="menu-item">
+				<image class="add_icon" :src="item.icon" mode="scaleToFill" />
+			</view> -->
+			<view class="menu-item">
+				<image v-if="currentIndex === index" class="w-48 h-48" :src="item.check_icon" mode="scaleToFill" />
+				<image v-else class="w-48 h-48" :src="item.icon" mode="scaleToFill" />
+				<text class="mgt-4" :class="{ active: currentIndex === index }">{{ item.text }}</text>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script setup>
+import { ref } from 'vue';
+
+// 当前选中的 Tab 索引
+const props = defineProps(["currentIndex"])
+
+// TabBar 列表
+const list = ref([{
+	text: "书架",
+	pagePath: "/pages/index/index",
+	icon: '/static/image/tabbar/bookshelf.png',
+	check_icon: '/static/image/tabbar/bookshelf_on.png'
+},
+{
+	text: "书城",
+	pagePath: "/pages/bookMall/index",
+	icon: '/static/image/tabbar/bookMall.png',
+	check_icon: '/static/image/tabbar/bookMall_on.png'
+},
+{
+	text: "我的",
+	pagePath: "/pages/my/index",
+	icon: '/static/image/tabbar/my.png',
+	check_icon: '/static/image/tabbar/my_on.png'
+},
+]);
+
+// 定义 isShowTabbar 变量
+const isShowTabbar = ref(true);
+
+// // 监听 props.currentIndex 变化,控制 tabbar 显示状态
+// watch(() => props.currentIndex, (newIndex) => {
+// 	if (list.value[newIndex]?.text === "新建") {
+// 		isShowTabbar.value = false; // 隐藏 tabbar
+// 	} else {
+// 		isShowTabbar.value = true; // 显示 tabbar
+// 	}
+// });
+
+// 切换 Tab
+const switchTab = (index) => {
+	/* if(index == 1) {
+		uni.navigateTo({
+			url: "/pages/creat/newBook",
+		});
+	} else { */
+	uni.switchTab({
+		url: list.value[index].pagePath,
+	});
+	// }
+};
+</script>
+
+<style scoped>
+.custom-tabbar {
+	position: fixed;
+	left: 0;
+	right: 0;
+	bottom: 0;
+	z-index: 999;
+	display: flex;
+	height: 100rpx;
+	/* 适配安全区 */
+	padding-top: 10rpx;
+	/* 默认 Android */
+	padding-bottom: 10rpx;
+	background-color: #ffffff;
+	/* background-color: transparent; */
+	justify-content: space-between;
+}
+
+/* 兼容 iOS 安全区域 */
+@supports (bottom: env(safe-area-inset-bottom)) {
+	.custom-tabbar {
+		height: calc(100rpx + env(safe-area-inset-bottom));
+		padding-bottom: env(safe-area-inset-bottom);
+	}
+}
+
+.tabbar-item {
+	flex: 1;
+
+
+}
+
+.menu-item {
+	position: relative;
+	display: flex;
+	flex-direction: column;
+	align-items: center;
+	color: #E5DCD6;
+	font-size: 20rpx;
+
+
+}
+
+.add_icon {
+	position: absolute;
+	top: -30rpx;
+	width: 96rpx;
+	height: 96rpx;
+}
+
+.active {
+	color: #FFA74F;
+}
+</style>

+ 36 - 1
pages.json

@@ -2,6 +2,27 @@
 	"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
 		{
 			"path": "pages/index/index",
+			"style": {
+				"navigationBarTitleText": "书架",
+				"navigationStyle": "custom"
+			}
+		},
+		{
+			"path": "pages/bookMall/index",
+			"style": {
+				"navigationBarTitleText": "书城",
+				"navigationStyle": "custom"
+			}
+		},
+		{
+			"path": "pages/my/index",
+			"style": {
+				"navigationBarTitleText": "我的",
+				"navigationStyle": "custom"
+			}
+		},
+		{
+			"path": "pages/toolsMall/index",
 			"style": {
 				"navigationBarTitleText": "工具广场",
 				"navigationStyle": "custom"
@@ -81,5 +102,19 @@
 		"navigationBarBackgroundColor": "#F8F8F8",
 		"backgroundColor": "#F8F8F8"
 	},
-	"uniIdRouter": {}
+	"uniIdRouter": {},
+	"tabBar": {
+	  "custom": true,
+	  "list": [
+	    {
+	      "pagePath": "pages/index/index"
+	    },
+	    {
+	      "pagePath": "pages/bookMall/index"
+	    },
+	    {
+	      "pagePath": "pages/my/index"
+	    }
+	  ]
+	},
 }

+ 51 - 0
pages/bookMall/index.vue

@@ -0,0 +1,51 @@
+<template>
+    <view class="container">
+        <view class="navBarBox">
+            <!-- 状态栏占位 -->
+            <view class="statusBar" :style="{ paddingTop: statusBarHeight + 'px' }"></view>
+            <!-- 真正的导航栏内容 -->
+            <view class="navBar">
+                小说书城
+            </view>
+        </view>
+
+
+    </view>
+    <!-- 引入自定义 TabBar -->
+    <custom-tabbar :currentIndex='1' />
+</template>
+
+<script setup>
+import { ref, onBeforeMount } from "vue";
+import CustomTabbar from "@/components/custom-tabbar.vue";
+
+// 状态栏高度
+let statusBarHeight = ref(0);
+// 导航栏高度
+let navBarHeight = ref(0);
+onBeforeMount(() => {
+    statusBarHeight.value = uni.getSystemInfoSync()['statusBarHeight'];
+    const custom = uni.getMenuButtonBoundingClientRect();
+    // 导航栏的高度 = 胶囊的高度 + (胶囊距离顶部的距离 - 状态栏的高度)* 2
+    //                                   即胶囊的上下边距
+    navBarHeight.value = custom.height + (custom.top - statusBarHeight.value) * 2;
+});
+
+
+
+</script>
+
+<style lang="scss" scoped>
+.container {
+    .navBarBox {
+        .navBar {
+            width: 100%;
+            height: 80rpx !important;
+            line-height: 80rpx;
+            padding-left: 30rpx;
+            font-size: 32rpx;
+            color: #333;
+        }
+    }  
+}
+</style>

+ 100 - 99
pages/index/index.vue

@@ -1,117 +1,118 @@
 <template>
-	<view class="content">
-		<view class="p-rel">
-			<image class="h-350 bg-999 mgb-20 w" mode="scaleToFill"
-			src="/static/image/index_banner.jpg"></image>
-			<view class="p-abs left-40 bottom-100 text-52 text-b text-2283ee">发现无限可能</view>
-			<view class="p-abs left-40 bottom-60 text-20">尽在功能广场 享受更多可能性</view>
+	<view class="container">
+		<view class="navBarBox">
+			<!-- 状态栏占位 -->
+			<view class="statusBar" :style="{ paddingTop: statusBarHeight + 'px' }"></view>
+			<!-- 真正的导航栏内容 -->
+			<view class="navBar">
+				书架
+			</view>
 		</view>
-		<view class="fnBox" v-for="(item,index) in funtions">
-			<view class="title">
-				{{ item.title }}
+
+
+
+		<view class="side_help">
+			<view class="help">
+				<image class="w-30 h-30 mgb-10" src="/static//image/index/help.png" mode="scaleToFill" />
+				<view class="text">帮助</view>
 			</view>
-			<view class="itemBox">
-				<view class="item" 
-				:style="{ background:`linear-gradient(to bottom, ${items.bg}, #fff)`, }"
-				v-for="(items,indexs) in item.list">
-					<view class="icon">
-						
-					</view>
-					<view class="name"
-					:style="{ color:`${items.color}`, }">
-						{{ items.name }}
-					</view>
-					<view class="btn flex" @click="goPage(items.path)"
-					:style="{ background:`${items.color}`, }"
-					>
-						立即使用<text style="transform: scale(0.6);">▶</text>
-					</view>
-				</view>
+			<view class="mgt-20">
+				<image class="w-30 h-30 mgb-10" src="/static//image/index/complaint.png" mode="scaleToFill" />
+				<view class="text">投诉</view>
 			</view>
 		</view>
+
+		<view class="tools" @click="toTools">
+			<image class="w-80 h-80" src="/static/image/index/tools_icon.png" mode="scaleToFill" />
+			<view class="title">工具广场</view>
+		</view>
+
+
 	</view>
+	<!-- 引入自定义 TabBar -->
+	<custom-tabbar :currentIndex='0' />
 </template>
 
 <script setup>
-	import { ref, reactive, onMounted } from "vue";
-	const title = ref('Hello33')
-	const funtions = reactive([
-		{
-			title:'基础功能',
-			list:[
-				{name:'一键省电',icon:'',bg:'#cfffcd',color:'#60b956',path:'yiJianShengDian'},
-				{name:'声波除尘',icon:'',bg:'#ffd8db',color:'#fb5e53',path:'shengBoChuChen'},
-				{name:'网络信息',icon:'',bg:'#ccccfe',color:'#8370ee',path:'wangLuoXinXi'},
-				{name:'手机测距',icon:'',bg:'#80fafb',color:'#02cfdf',path:'shouJiCeJu'},
-				{name:'WiFi管理',icon:'',bg:'#9ed1fe',color:'#3d9aee',path:'wifiGuanLi'},
-				{name:'手机清理',icon:'',bg:'#fad2ec',color:'#ff4bb9',path:'shouJiQingLi'},
-				{name:'精选壁纸',icon:'',bg:'#fec2f8',color:'#c95884',path:'jingXuanBiZhi'},
-			],
-		},
-		{
-			title:'趣味测评',
-			list:[
-				{name:'趣味测评',icon:'',bg:'#e8ffc4',color:'#98ec05',path:'quWeiCePing'},
-			],
-		},
-		{
-			title:'知识课堂',
-			list:[
-				{name:'养生课堂',icon:'',bg:'#fdd1c0',color:'#fc7f43',path:'yangShengKeTang'},
-				{name:'运动计步',icon:'',bg:'#9ce4fd',color:'#3d9afb',path:'yunDongJiBu'},
-				{name:'字体大小',icon:'',bg:'#edcbfd',color:'#d617d1',path:'ziTiDaXiao'},
-			],
-		}
-	])
-	const goPage = ((url)=>{
-		uni.navigateTo({
-			url:'/pages/tools/' + url
-		})
-	})
+import { ref, onBeforeMount } from "vue";
+import CustomTabbar from "@/components/custom-tabbar.vue";
+
+// 状态栏高度
+let statusBarHeight = ref(0);
+// 导航栏高度
+let navBarHeight = ref(0);
+onBeforeMount(() => {
+	statusBarHeight.value = uni.getSystemInfoSync()['statusBarHeight'];
+	const custom = uni.getMenuButtonBoundingClientRect();
+	// 导航栏的高度 = 胶囊的高度 + (胶囊距离顶部的距离 - 状态栏的高度)* 2
+	//                                   即胶囊的上下边距
+	navBarHeight.value = custom.height + (custom.top - statusBarHeight.value) * 2;
+});
+
+
+const toTools = () => {
+	console.log(111)
+	uni.navigateTo({
+		url: "/pages/toolsMall/index",
+	});
+}
+
 </script>
 
 <style lang="scss" scoped>
-	.fnBox{
-		padding: 20rpx;
-		.title{
+.container  {
+	.navBarBox {
+		.navBar {
+			width: 100%;
+			height: 80rpx !important;
+			line-height: 80rpx;
+			padding-left: 30rpx;
 			font-size: 32rpx;
-			margin: 0rpx 0 30rpx 0;
-			font-weight: 500;
+			color: #333;
+		}
+	}
+
+	.side_help {
+		position: fixed;
+		left: 0;
+		bottom: 20%;
+		width: 50rpx;
+		background-color: red;
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+		justify-content: center;
+		color: #fff;
+		text-align: center;
+		padding: 20rpx 0;
+		border-radius: 0 30rpx 30rpx 0;
+
+		.text {
+			text-align: center;
 		}
-		.itemBox{
+	}
+
+	.tools {
+		position: fixed;
+		right: 20rpx;
+		bottom: 33%;
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+		justify-content: center;
+
+		.title {
+			margin-top: 2rpx;
+			font-size: 20rpx;
+			width: 100rpx;
+			height: 30rpx;
 			display: flex;
-			white-space: pre-wrap;
-			flex-wrap: wrap;
-			gap: 20rpx 40rpx;
-			.item{
-				width: 330rpx;
-				height: 200rpx;
-				border: 1rpx solid #eee;
-				border-radius: 20rpx;
-				position: relative;
-				.icon{
-					
-				}
-				.name{
-					position: absolute;
-					font-size: 30rpx;
-					font-weight: 600;
-					letter-spacing: 2rpx;
-					right: 50rpx;
-					top: 40rpx;
-				}
-				.btn{
-					position: absolute;
-					background-color: skyblue;
-					cursor: pointer;
-					padding: 8rpx 10rpx;
-					border-radius: 30rpx;
-					color: #fff;
-					font-size: 24rpx;
-					right: 40rpx;
-					bottom: 30rpx;
-				}
-			}
+			align-items: center;
+			justify-content: center;
+			background: linear-gradient(to right, #c7dae2, #84c9e6);
+			border-radius: 50rpx;
+			color: #fff;
 		}
 	}
+}
 </style>

+ 51 - 0
pages/my/index.vue

@@ -0,0 +1,51 @@
+<template>
+    <view class="container">
+        <view class="navBarBox">
+            <!-- 状态栏占位 -->
+            <view class="statusBar" :style="{ paddingTop: statusBarHeight + 'px' }"></view>
+            <!-- 真正的导航栏内容 -->
+            <view class="navBar">
+                个人中心
+            </view>
+        </view>
+
+
+    </view>
+    <!-- 引入自定义 TabBar -->
+    <custom-tabbar :currentIndex='2' />
+</template>
+
+<script setup>
+import { ref, onBeforeMount } from "vue";
+import CustomTabbar from "@/components/custom-tabbar.vue";
+
+// 状态栏高度
+let statusBarHeight = ref(0);
+// 导航栏高度
+let navBarHeight = ref(0);
+onBeforeMount(() => {
+    statusBarHeight.value = uni.getSystemInfoSync()['statusBarHeight'];
+    const custom = uni.getMenuButtonBoundingClientRect();
+    // 导航栏的高度 = 胶囊的高度 + (胶囊距离顶部的距离 - 状态栏的高度)* 2
+    //                                   即胶囊的上下边距
+    navBarHeight.value = custom.height + (custom.top - statusBarHeight.value) * 2;
+});
+
+
+
+</script>
+
+<style lang="scss" scoped>
+.container {
+    .navBarBox {
+        .navBar {
+            width: 100%;
+            height: 80rpx !important;
+            line-height: 80rpx;
+            padding-left: 30rpx;
+            font-size: 32rpx;
+            color: #333;
+        }
+    }
+}
+</style>

+ 117 - 0
pages/toolsMall/index.vue

@@ -0,0 +1,117 @@
+<template>
+	<view class="content">
+		<view class="p-rel">
+			<image class="h-350 bg-999 mgb-20 w" mode="scaleToFill"
+			src="/static/image/index_banner.jpg"></image>
+			<view class="p-abs left-40 bottom-100 text-52 text-b text-2283ee">发现无限可能</view>
+			<view class="p-abs left-40 bottom-60 text-20">尽在功能广场 享受更多可能性</view>
+		</view>
+		<view class="fnBox" v-for="(item,index) in funtions">
+			<view class="title">
+				{{ item.title }}
+			</view>
+			<view class="itemBox">
+				<view class="item" 
+				:style="{ background:`linear-gradient(to bottom, ${items.bg}, #fff)`, }"
+				v-for="(items,indexs) in item.list">
+					<view class="icon">
+						
+					</view>
+					<view class="name"
+					:style="{ color:`${items.color}`, }">
+						{{ items.name }}
+					</view>
+					<view class="btn flex" @click="goPage(items.path)"
+					:style="{ background:`${items.color}`, }"
+					>
+						立即使用<text style="transform: scale(0.6);">▶</text>
+					</view>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script setup>
+	import { ref, reactive, onMounted } from "vue";
+	const title = ref('Hello33')
+	const funtions = reactive([
+		{
+			title:'基础功能',
+			list:[
+				{name:'一键省电',icon:'',bg:'#cfffcd',color:'#60b956',path:'yiJianShengDian'},
+				{name:'声波除尘',icon:'',bg:'#ffd8db',color:'#fb5e53',path:'shengBoChuChen'},
+				{name:'网络信息',icon:'',bg:'#ccccfe',color:'#8370ee',path:'wangLuoXinXi'},
+				{name:'手机测距',icon:'',bg:'#80fafb',color:'#02cfdf',path:'shouJiCeJu'},
+				{name:'WiFi管理',icon:'',bg:'#9ed1fe',color:'#3d9aee',path:'wifiGuanLi'},
+				{name:'手机清理',icon:'',bg:'#fad2ec',color:'#ff4bb9',path:'shouJiQingLi'},
+				{name:'精选壁纸',icon:'',bg:'#fec2f8',color:'#c95884',path:'jingXuanBiZhi'},
+			],
+		},
+		{
+			title:'趣味测评',
+			list:[
+				{name:'趣味测评',icon:'',bg:'#e8ffc4',color:'#98ec05',path:'quWeiCePing'},
+			],
+		},
+		{
+			title:'知识课堂',
+			list:[
+				{name:'养生课堂',icon:'',bg:'#fdd1c0',color:'#fc7f43',path:'yangShengKeTang'},
+				{name:'运动计步',icon:'',bg:'#9ce4fd',color:'#3d9afb',path:'yunDongJiBu'},
+				{name:'字体大小',icon:'',bg:'#edcbfd',color:'#d617d1',path:'ziTiDaXiao'},
+			],
+		}
+	])
+	const goPage = ((url)=>{
+		uni.navigateTo({
+			url:'/pages/tools/' + url
+		})
+	})
+</script>
+
+<style lang="scss" scoped>
+	.fnBox{
+		padding: 20rpx;
+		.title{
+			font-size: 32rpx;
+			margin: 0rpx 0 30rpx 0;
+			font-weight: 500;
+		}
+		.itemBox{
+			display: flex;
+			white-space: pre-wrap;
+			flex-wrap: wrap;
+			gap: 20rpx 40rpx;
+			.item{
+				width: 330rpx;
+				height: 200rpx;
+				border: 1rpx solid #eee;
+				border-radius: 20rpx;
+				position: relative;
+				.icon{
+					
+				}
+				.name{
+					position: absolute;
+					font-size: 30rpx;
+					font-weight: 600;
+					letter-spacing: 2rpx;
+					right: 50rpx;
+					top: 40rpx;
+				}
+				.btn{
+					position: absolute;
+					background-color: skyblue;
+					cursor: pointer;
+					padding: 8rpx 10rpx;
+					border-radius: 30rpx;
+					color: #fff;
+					font-size: 24rpx;
+					right: 40rpx;
+					bottom: 30rpx;
+				}
+			}
+		}
+	}
+</style>

BIN
static/image/index/complaint.png


BIN
static/image/index/help.png


BIN
static/image/index/tools_icon.png


BIN
static/image/tabbar/bookMall.png


BIN
static/image/tabbar/bookMall_on.png


BIN
static/image/tabbar/bookshelf.png


BIN
static/image/tabbar/bookshelf_on.png


BIN
static/image/tabbar/my.png


BIN
static/image/tabbar/my_on.png