uniapp实现书架

来咯先看效果
小程序效果如下
在这里插入图片描述
app 效果如下:
在这里插入图片描述


前言

哦豁,前几天遇到一个需求,做一个图书馆这样的,我看别人都是书架这种
写着写着感觉还是挺容易的,就是调试样式比较麻烦而已,app 小程序都适配


一、来看看代码吧?

我自己已经对接了接口了

<template>
	<view class="container">
		<view class="head"
			:style="{ height: isScrolled ? '7.8rem' : '7rem', backgroundColor: isScrolled ? 'rgb(26 51 86 / 73%)' : '#1a3356'}">
			<view style="color:#fff;position: fixed;top: 4rem;left: 1rem;">
				电子图书馆 <br>
				<text style="font-size: 11px;">Original designer</text>
			</view>
		</view>
		<view style="width: 100%; height: 7rem;"></view>

		<scroll-view scroll-y style="height: 100vh;" class="content">
			<view class="bookshelf">
				<view v-for="(book, index) in paginatedBooks" :key="book.id"
					:class="['book-item', isInLastTwoRows(index) ? 'small-book' : '']" @click="openBook(book)">
					<text class="book-title">{{ book.name }}</text>
					<view class="book-cover-container">
						<image :src="book.coverImage" class="book-cover" />
						<view class="book-spine"></view>
					</view>

				</view>
			</view>
			<button class="prev-page-button" @click="prevPage">上一页</button>
			<button class="next-page-button" @click="nextPage">下一页</button>
		</scroll-view>
		<u-toast ref="uToast"></u-toast>
	</view>
</template>

<script>
	import {
		getbookList
	} from "@/api/ebook/ebook_api.js";

	export default {
		data() {
			return {
				isScrolled: false,
				innerAudioContext: null,
				books: [],
				pageNum: 1,
				pageSize: 9,
				totalPages: 1
			};
		},
		computed: {
			// 当前分页显示的数据
			paginatedBooks() {
				return this.books;
			}
		},
		mounted() {
			this.innerAudioContext = uni.createInnerAudioContext();
			this.innerAudioContext.src = 'https://linda-uni.oss-cn-guangzhou.aliyuncs.com/images/integration/no_input.mp3';
			this.fetchBooks(); // 初始化加载第一页数据
		},
		methods: {
			// 调用接口获取图书数据
			async fetchBooks() {
				try {
					const response = await getbookList({
						pageNum: this.pageNum,
						pageSize: this.pageSize
					});

					this.books = response.records;
					this.totalPages = Math.ceil(response.total / this.pageSize);

				} catch (error) {
					console.error("Failed to fetch books:", error);
				}
			},
			openBook(item) {


				const itemData = encodeURIComponent(JSON.stringify(item));
				uni.vibrateShort();
				this.innerAudioContext.play(); // 播放音频
				this.$refs.uToast.show({
					type: 'loading',
					title: '稍等,马上就好...',
					message: '稍等,马上就好...',
					iconUrl: 'https://cdn.uviewui.com/uview/demo/toast/loading.png',
					complete() {
						uni.navigateTo({
							url: `/pages/library/ebookdetails/ebookdetails?itemData=${itemData}`,
						});
					},
				});


			},
			// 判断书籍是否在倒数两排,倒数两排将应用缩小样式
			isInLastTwoRows(index) {
				const booksPerRow = 3;
				const totalRows = Math.ceil(this.books.length / booksPerRow);
				const currentRow = Math.ceil((index + 1) / booksPerRow);
				return currentRow >= totalRows - 1;
			},
			// 点击下一页
			nextPage() {
				if (this.pageNum < this.totalPages) {
					this.pageNum += 1;
					this.fetchBooks();
				} else {
					console.log("已经是最后一页");
				}
			},
			// 点击上一页
			prevPage() {
				if (this.pageNum > 1) {
					this.pageNum -= 1;
					this.fetchBooks();
				} else {
					console.log("已经是第一页");
				}
			}
		},
		beforeDestroy() {
			if (this.innerAudioContext) {
				this.innerAudioContext.destroy();
			}
		}
	};
</script>

<style>
	page {
		background-color: #F5F3FC;
	}

	.container {
		position: relative;
		height: 100vh;
		width: 100vw;
		overflow: hidden;
	}

	.head {
		width: 100%;
		background-color: #1a3356;
		position: fixed;
		top: 0px;
		left: 0%;
		z-index: 99999;
	}

	.bookshelf {
		display: grid;
		grid-template-columns: repeat(3, 1fr);
		grid-template-rows: 160px 160px 160px;
		grid-gap: 10px;
		width: 100%;
		background-image: url('https://linda-uni.oss-cn-guangzhou.aliyuncs.com/images/and/staff_1024.jpg');
		background-size: cover;
		height: 100vh;
	}

	.book-item {
		width: 74px;
		height: 120px;
		display: flex;
		flex-direction: column;
		align-items: center;
		margin-top: 49px;
		margin-left: 34px;
	}

	.small-book {
		width: 74px;
		height: 113px;

		margin-top: 60px;
	}

	.book-cover-container {
		position: relative;
		width: 100%;
		height: 100%;
		transform-style: preserve-3d;
	}

	.book-cover {
		width: 100%;
		height: 100%;
		border-radius: 5px;
		box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
		backface-visibility: hidden;
	}

	.book-spine {
		position: absolute;
		top: 0;
		right: -3px;
		width: 5px;
		height: 100%;
		background: linear-gradient(180deg, #ded5d0, #a49994);
		border-top-right-radius: 5px;
		border-bottom-right-radius: 5px;
		box-shadow: inset -2px 0px 5px rgba(0, 0, 0, 0.2);
		transform: rotateY(15deg);
		backface-visibility: hidden;
	}

	.book-title {
		margin-top: 5px;
		font-size: 12px;
		color: #ffffffcc;
		text-align: center;
		position: relative;
		top: -0.5rem;
		left: 0px;
		border-radius: 6px;

	}

	.next-page-button {
		width: 100px;
		align-self: center;
		padding: 10px;
		font-size: 14px;
		color: #fff;
		background-color: #fff8f547;
		border: none;
		border-radius: 5px;
		cursor: pointer;
		position: fixed;
		right: 11px;
		bottom: 72px;
	}

	.prev-page-button {
		width: 100px;
		align-self: center;
		padding: 10px;
		font-size: 14px;
		color: #fff;
		background-color: #fff8f547;
		border: none;
		border-radius: 5px;
		cursor: pointer;
		position: fixed;
		left: 36px;
		bottom: 72px;
	}

	/* 针对更大屏幕的调整 */
	@media (min-width: 375px) and (max-width: 400px) {
		.next-page-button {
			bottom: 4.5rem;
		}

		.prev-page-button {
			bottom: 4.5rem;
		}

		.book-item {
			margin-top: 49px;
		}

		.small-book {
			margin-top: 60px;
		}
	}

	@media (min-width: 401px) {
		.next-page-button {
			bottom: 6rem;
		}

		.prev-page-button {
			bottom: 6rem;
		}

		.book-item {
			margin-top: 4rem;
		}

		.small-book {
			margin-top: 6rem;
		}
	}
</style>

点进去的话就是真实的翻书效果 嘎嘎的

总结

人生就是无常,漠漠水田飞白鹭,阴阴夏木啭黄鹂。来看看小老弟的小程序
在这里插入图片描述

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部