Переглянути джерело

feat(详情页): 添加商品详情页面及相关组件

- 新增商品详情页面基础结构和布局
- 实现商品信息卡片、服务卡片、底部操作栏等组件
- 添加商品内容展示和推荐书籍功能
- 更新页面路由配置
- 替换部分静态图片资源
ylong 5 днів тому
батько
коміт
6b2f6d6535

+ 110 - 0
pages-sell/components/detail/footer-bar.vue

@@ -0,0 +1,110 @@
+<template>
+	<view class="footer-bar safe-area-inset-bottom">
+		<view class="icons-area">
+			<view class="icon-item">
+				<image src="/pages-sell/static/goods/icon-home.png" class="bar-icon" mode="widthFix" style="width: 36rpx;"></image>
+				<text>首页</text>
+			</view>
+			<view class="icon-item">
+				<image src="/pages-sell/static/goods/icon-star.png" class="bar-icon" mode="aspectFit"></image>
+				<text>收藏</text>
+			</view>
+			<view class="icon-item">
+				<image src="/pages-sell/static/goods/icon-car.png" class="bar-icon" mode="aspectFit"></image>
+				<text>购物车</text>
+			</view>
+		</view>
+
+		<view class="action-btn-area">
+			<view v-if="hasStock" class="action-btn in-stock" @click="onAddCart">
+				<text>加入购物车</text>
+			</view>
+			<view v-else class="action-btn no-stock" @click="onNotify">
+				<text>到货通知</text>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	name: 'FooterBar',
+	props: {
+		hasStock: {
+			type: Boolean,
+			default: true
+		}
+	},
+	methods: {
+		onAddCart() {
+			this.$emit('addCart');
+		},
+		onNotify() {
+			this.$emit('notify');
+		}
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+.footer-bar {
+	position: fixed;
+	bottom: 0;
+	left: 0;
+	width: 100%;
+	height: 200rpx;
+	background: #fff;
+	display: flex;
+	align-items: center;
+	justify-content: space-between;
+	padding: 0 20rpx;
+	box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);
+	z-index: 100;
+	padding-bottom: env(safe-area-inset-bottom);
+
+	.icons-area {
+		display: flex;
+		margin-right: 20rpx;
+
+		.icon-item {
+			display: flex;
+			flex-direction: column;
+			align-items: center;
+			justify-content: center;
+			width: 80rpx;
+			margin-right: 10rpx;
+
+			.bar-icon {
+				width: 40rpx;
+				height: 40rpx;
+				margin-bottom: 6rpx;
+			}
+
+			text {
+				font-size: 20rpx;
+				color: #666;
+				text-align: center;
+			}
+		}
+	}
+
+	.action-btn-area {
+		flex: 1;
+		display: flex;
+		height: 80rpx;
+		max-width: 360rpx;
+
+		.action-btn {
+			flex: 1;
+			display: flex;
+			align-items: center;
+			justify-content: center;
+			border-radius: 40rpx;
+			font-size: 30rpx;
+			color: #fff;
+			font-weight: bold;
+			background: linear-gradient(0deg, #38C248 0%, #5FEA6F 100%);
+		}
+	}
+}
+</style>

+ 115 - 0
pages-sell/components/detail/info-card.vue

@@ -0,0 +1,115 @@
+<template>
+	<view class="info-card">
+		<view class="title-row">
+			<text class="book-title">{{ product.title }}</text>
+		</view>
+		
+		<view class="price-row">
+			<text class="currency">¥</text>
+			<text class="price">{{ product.price }}</text>
+			<view class="balance-tag">
+				<text>余额价 {{ product.balancePrice }}</text>
+			</view>
+		</view>
+		
+		<view class="meta-row">
+			<text class="label">原价:</text>
+			<text class="original-price">¥{{ product.originalPrice }}</text>
+		</view>
+		
+		<view class="author-row">
+			<text class="author">作者:{{ product.author }}</text>
+			<view class="works-link">
+				<text>作品</text>
+				<u-icon name="arrow-right" size="24" color="#F2950A"></u-icon>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	name: 'InfoCard',
+	props: {
+		product: {
+			type: Object,
+			default: () => ({})
+		}
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+.info-card {
+	background: #fff;
+	border-radius: 24rpx 24rpx 0 0;
+	padding: 30rpx;
+	
+	.title-row {
+		margin-bottom: 20rpx;
+		.book-title {
+			font-size: 40rpx;
+			font-weight: bold;
+			color: #333;
+		}
+	}
+	
+	.price-row {
+		display: flex;
+		align-items: center;
+		margin-bottom: 10rpx;
+		
+		.currency {
+			font-size: 32rpx;
+			color: #D81A00;
+			font-weight: bold;
+		}
+		
+		.price {
+			font-size: 48rpx;
+			color: #D81A00;
+			font-weight: bold;
+			margin-right: 20rpx;
+		}
+		
+		.balance-tag {
+			background: #EFA941;
+			border-radius: 20rpx;
+			padding: 2rpx 16rpx;
+			
+			text {
+				font-size: 22rpx;
+				color: #fff;
+			}
+		}
+	}
+	
+	.meta-row {
+		margin-bottom: 20rpx;
+		font-size: 26rpx;
+		color: #999;
+		
+		.original-price {
+			text-decoration: line-through;
+			margin-left: 10rpx;
+		}
+	}
+	
+	.author-row {
+		display: flex;
+		justify-content: space-between;
+		align-items: center;
+		font-size: 28rpx;
+		color: #F2950A;
+		
+		.author {
+			flex: 1;
+		}
+		
+		.works-link {
+			display: flex;
+			align-items: center;
+		}
+	}
+}
+</style>

+ 135 - 0
pages-sell/components/detail/product-content.vue

@@ -0,0 +1,135 @@
+<template>
+	<view class="detail-content">
+		<!-- Tab 1 Content: Product Details -->
+		<view v-show="currentTab === 0">
+			<!-- Basic Info List -->
+			<view class="section-title">基本信息</view>
+			<view class="info-list">
+				<view class="info-item"><text class="label">书名:</text><text>{{ product.title }}</text></view>
+				<view class="info-item"><text class="label">作者:</text><text>{{ product.authorFull }}</text></view>
+				<view class="info-item"><text class="label">出版社:</text><text>{{ product.publisher }}</text></view>
+				<view class="info-item"><text class="label">出版日期:</text><text>{{ product.publishDate }}</text></view>
+				<view class="info-item"><text class="label">ISBN:</text><text>{{ product.isbn }}</text></view>
+				<view class="info-item"><text class="label">纸张:</text><text>胶版纸</text></view>
+				<view class="info-item"><text class="label">开本:</text><text>16开</text></view>
+			</view>
+
+			<u-gap height="30"></u-gap>
+			
+			<!-- Intro Section -->
+			<view class="section-title">内容简介</view>
+			<view class="text-content">
+				{{ product.intro }}
+			</view>
+			
+			<u-gap height="30"></u-gap>
+
+			<!-- Catalog Section -->
+			<view class="section-title">目录</view>
+			<view class="text-content">
+				{{ product.catalog }}
+			</view>
+
+			<!-- Product Tips Component -->
+			<ProductTips :content="tipsContent"></ProductTips>
+		</view>
+		
+		<!-- Tab 2 Content: Related Books -->
+		<view v-show="currentTab === 1">
+			<RelatedBooks :books="relatedBooksList" @click="onBookClick"></RelatedBooks>
+		</view>
+	</view>
+</template>
+
+<script>
+import ProductTips from '../product-tips/index.vue'
+import RelatedBooks from '../related-books/index.vue'
+
+export default {
+	name: 'ProductContent',
+	components: {
+		ProductTips,
+		RelatedBooks
+	},
+	props: {
+		currentTab: {
+			type: Number,
+			default: 0
+		},
+		product: {
+			type: Object,
+			default: () => ({})
+		},
+		tipsContent: {
+			type: Array,
+			default: () => []
+		},
+		relatedBooksList: {
+			type: Array,
+			default: () => []
+		}
+	},
+	methods: {
+		onBookClick(book) {
+			this.$emit('bookClick', book);
+		}
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+.detail-content {
+	background: #fff;
+	padding: 30rpx;
+	min-height: 500rpx;
+	border-radius: 24rpx 24rpx 0 0; /* Added based on context */
+	margin-top: 20rpx; /* Added based on context */
+	
+	.section-title {
+		font-size: 32rpx;
+		font-weight: bold;
+		margin-bottom: 30rpx;
+		color: #333;
+		position: relative;
+		padding-left: 20rpx;
+		
+		&:before {
+			content: '';
+			position: absolute;
+			left: 0;
+			top: 8rpx;
+			width: 6rpx;
+			height: 30rpx;
+			background: #38C248;
+			border-radius: 4rpx;
+		}
+	}
+	
+	.info-list {
+		.info-item {
+			display: flex;
+			margin-bottom: 20rpx;
+			font-size: 28rpx;
+			line-height: 1.5;
+			
+			.label {
+				color: #999;
+				width: 150rpx;
+				flex-shrink: 0;
+			}
+			
+			text:last-child {
+				color: #333;
+				flex: 1;
+			}
+		}
+	}
+	
+	.text-content {
+		font-size: 28rpx;
+		color: #666;
+		line-height: 1.8;
+		text-align: justify;
+	}
+}
+</style>

+ 114 - 0
pages-sell/components/detail/service-card.vue

@@ -0,0 +1,114 @@
+<template>
+	<view class="service-card">
+		<view class="service-row" @click="onClick">
+			<view class="icon-box">
+				<image src="/pages-sell/static/goods/icon-down.png" class="service-icon" mode="aspectFit"></image>
+			</view>
+			<text class="service-label">可降</text>
+			<text class="separator">|</text>
+			<text class="service-val red">分享一人助力,可降 1.5 元</text>
+			<u-icon name="arrow-right" size="24" color="#999" class="arrow"></u-icon>
+		</view>
+		<view class="service-row">
+			<view class="icon-box">
+				<image src="/pages-sell/static/goods/icon-fee.png" class="service-icon" mode="aspectFit"></image>
+			</view>
+			<text class="service-label">运费</text>
+			<text class="separator">|</text>
+			<text class="service-val green">全场满 5.8 元包邮(偏远地区除外)</text>
+		</view>
+		<view class="service-row">
+			<view class="icon-box">
+				<image src="/pages-sell/static/goods/icon-fire.png" class="service-icon" mode="aspectFit"></image>
+			</view>
+			<text class="service-label">活动</text>
+			<text class="separator">|</text>
+			<text class="service-val red">每满 48 元减 5 元</text>
+		</view>
+		<view class="service-row last">
+			<view class="icon-box">
+				<image src="/pages-sell/static/goods/icon-service.png" class="service-icon" mode="aspectFit"></image>
+			</view>
+			<text class="service-label">服务</text>
+			<text class="separator">|</text>
+			<text class="service-val">破损包赔 · 降价补差 · 24 小时发货</text>
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	name: 'ServiceCard',
+	methods: {
+		onClick() {
+			this.$emit('click');
+		}
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+.service-card {
+	background: #fff;
+	border-radius: 24rpx 24rpx 0 0;
+	padding: 0 30rpx;
+	margin-bottom: 20rpx;
+
+	.service-row {
+		display: flex;
+		align-items: center;
+		padding: 30rpx 0;
+		font-size: 26rpx;
+		position: relative;
+		border-bottom: 1rpx solid #F5F5F5;
+
+		&.last {
+			border-bottom: none;
+		}
+
+		.icon-box {
+			width: 32rpx;
+			height: 32rpx;
+			margin-right: 12rpx;
+			display: flex;
+			align-items: center;
+			justify-content: center;
+			
+			.service-icon {
+				width: 100%;
+				height: 100%;
+			}
+		}
+
+		.service-label {
+			color: #333;
+			font-weight: bold;
+			width: 50rpx; // Fixed width for 2 characters to ensure alignment
+			text-align: justify;
+			text-align-last: justify;
+		}
+
+		.separator {
+			color: #eee;
+			margin: 0 10rpx;
+		}
+
+		.service-val {
+			color: #666;
+
+			&.red {
+				color: #D81A00;
+			}
+			
+			&.green {
+				color: #38C248;
+			}
+		}
+
+		.arrow {
+			position: absolute;
+			right: 0;
+		}
+	}
+}
+</style>

+ 56 - 0
pages-sell/components/product-tips/index.vue

@@ -0,0 +1,56 @@
+<template>
+	<view class="product-tips">
+		<view class="section-title">温馨提示</view>
+		<view class="tips-container">
+			<view v-for="(tip, index) in content" :key="index" class="tip-item">
+				<text>{{ index + 1 }}.{{ tip }}</text>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	name: 'ProductTips',
+	props: {
+		content: {
+			type: Array,
+			default: () => []
+		}
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+.product-tips {
+	margin-top: 30rpx;
+	padding: 0 0 30rpx 0;
+	background: #fff;
+	
+	.section-title {
+		font-size: 30rpx;
+		font-weight: bold;
+		color: #333;
+		margin-bottom: 20rpx;
+		font-family: 'Source Han Sans SC';
+	}
+	
+	.tips-container {
+		background-color: #F8F8F8;
+		padding: 24rpx;
+		border-radius: 12rpx;
+		
+		.tip-item {
+			font-size: 26rpx;
+			color: #666;
+			line-height: 1.6;
+			margin-bottom: 12rpx;
+			text-align: justify;
+			
+			&:last-child {
+				margin-bottom: 0;
+			}
+		}
+	}
+}
+</style>

+ 69 - 0
pages-sell/components/related-books/index.vue

@@ -0,0 +1,69 @@
+<template>
+	<view class="related-books">
+		<view class="books-grid">
+			<view v-for="(book, index) in books" :key="index" class="book-item" @click="onBookClick(book)">
+				<image :src="book.cover" mode="aspectFill" class="book-cover"></image>
+				<text class="book-title u-line-1">{{ book.title }}</text>
+				<text class="book-edition u-line-1">{{ book.edition }}</text>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	name: 'RelatedBooks',
+	props: {
+		books: {
+			type: Array,
+			default: () => []
+		}
+	},
+	methods: {
+		onBookClick(book) {
+			this.$emit('click', book);
+		}
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+.related-books {
+	background: transparent;
+	padding-top: 20rpx;
+	
+	.books-grid {
+		display: flex;
+		flex-wrap: wrap;
+		margin: 0 -10rpx; /* Compensate for item padding */
+		
+		.book-item {
+			width: 33.33%;
+			padding: 0 10rpx 30rpx 10rpx;
+			box-sizing: border-box;
+			display: flex;
+			flex-direction: column;
+			
+			.book-cover {
+				width: 100%;
+				height: 280rpx;
+				border-radius: 8rpx;
+				background: #eee;
+				margin-bottom: 12rpx;
+			}
+			
+			.book-title {
+				font-size: 26rpx;
+				color: #333;
+				font-weight: 500;
+				margin-bottom: 4rpx;
+			}
+			
+			.book-edition {
+				font-size: 22rpx;
+				color: #999;
+			}
+		}
+	}
+}
+</style>

+ 1 - 1
pages-sell/components/sell-container/index.vue

@@ -145,7 +145,7 @@
 
 				<scroll-view scroll-x class="book-scroll" :show-scrollbar="false">
 					<view class="book-list">
-						<view class="book-item" v-for="(book, index) in recommendBooks" :key="index">
+						<view class="book-item" v-for="(book, index) in recommendBooks" :key="index" @click="navigateTo('/pages-sell/pages/detail')">
 							<image :src="book.cover" class="book-image" mode="aspectFill"></image>
 							<text class="book-name">{{ book.title }}</text>
 							<view class="price-row">

+ 332 - 0
pages-sell/pages/detail.vue

@@ -0,0 +1,332 @@
+<template>
+    <view class="detail-page">
+        <!-- Top Background -->
+        <view class="header-bg"></view>
+
+        <!-- Custom Navbar -->
+        <Navbar title="非暴力沟通" :titleSize="32" title-color="#fff" back-icon-color="#fff" background="transparent">
+        </Navbar>
+
+        <!-- Notification Bar -->
+        <view class="notification-bar">
+            <u-avatar size="40" src="https://img.yzcdn.cn/vant/cat.jpeg"></u-avatar>
+            
+            <text class="notif-text">微 ** 用户 购买了 《苏菲的世界》</text>
+        </view>
+
+        <view class="content-scroll">
+            <!-- Book Cover Area -->
+            <view class="cover-area">
+                <image class="book-cover" :src="product.cover" mode="aspectFit"></image>
+                <view class="share-btn">
+                    <image src="/pages-sell/static/goods/icon-share.png" class="share-icon"></image>
+                    <text>分享</text>
+                </view>
+            </view>
+
+            <!-- Product Info Card -->
+            <InfoCard :product="product"></InfoCard>
+
+            <!-- Banner -->
+            <view class="banner-area">
+                <image src="/pages-sell/static/top-banner.png" class="banner-img" mode="widthFix"></image>
+            </view>
+
+            <!-- Service Info -->
+            <ServiceCard @click="showServicePopup"></ServiceCard>
+
+            <!-- Customer Service Float -->
+            <FloatingDrag :width="120" :height="120" :initial-position="servicePosition"
+                @position-change="handlePositionChange" :z-index="20">
+                <!-- #ifdef MP-ALIPAY -->
+                <button class="service-btn" @click="navigateToCustomerService">
+                    <image src="/pages-sell/static/goods/icon-kefu.png" class="cs-icon" style="width: 100rpx;" mode="widthFix"></image>
+                </button>
+                <!-- #endif -->
+                <!-- #ifndef MP-ALIPAY -->
+                <button class="service-btn" open-type="contact">
+                    <image src="/pages-sell/static/goods/icon-kefu.png" class="cs-icon" style="width: 100rpx" mode="widthFix"></image>
+                </button>
+                <!-- #endif -->
+            </FloatingDrag>
+
+            <!-- Tabs -->
+            <view class="tabs-header">
+                <view class="tab-item" :class="{ active: currentTab === 0 }" @click="switchTab(0)">
+                    <text>商品详情</text>
+                    <view class="indicator" v-if="currentTab === 0"></view>
+                </view>
+                <view class="tab-item" :class="{ active: currentTab === 1 }" @click="switchTab(1)">
+                    <text>相关推荐</text>
+                    <view class="indicator" v-if="currentTab === 1"></view>
+                </view>
+            </view>
+            
+            <!-- Product Detail Content -->
+            <ProductContent 
+                :currentTab="currentTab" 
+                :product="product" 
+                :tipsContent="tipsContent" 
+                :relatedBooksList="relatedBooksList" 
+                @bookClick="onBookClick">
+            </ProductContent>
+            
+            <u-gap height="220"></u-gap>
+        </view>
+
+        <!-- Footer -->
+        <FooterBar :hasStock="hasStock" @addCart="openSelectPopup" @notify="handleNotify"></FooterBar>
+
+        <!-- Select Popup -->
+        <SelectGoodPopup ref="selectPopup" @confirm="onPopupConfirm"></SelectGoodPopup>
+    </view>
+</template>
+
+<script>
+import Navbar from '@/components/navbar/navbar.vue'
+import SelectGoodPopup from '../components/select-good-popup/index.vue'
+import InfoCard from '../components/detail/info-card.vue'
+import ServiceCard from '../components/detail/service-card.vue'
+import ProductContent from '../components/detail/product-content.vue'
+import FooterBar from '../components/detail/footer-bar.vue'
+import FloatingDrag from "@/components/floating-drag.vue";
+
+export default {
+    components: {
+        Navbar,
+        SelectGoodPopup,
+        InfoCard,
+        ServiceCard,
+        ProductContent,
+        FooterBar,
+        FloatingDrag
+    },
+    data() {
+        return {
+            currentTab: 0,
+            hasStock: true, // Toggle this to test stock status
+            tipsContent: [
+                '印刷版次较多,二手图书封面、版次、原价等信息可能与商品介绍有差异,具体以收到实物为准;',
+                '二手图书性质特殊,不保证随新书赠送的光盘、海报、卡片等内容,仅支持图书质量问题退款,否则将扣除运费成本;',
+                '收到的图书如有质量问题,请于七天内联系客服处理,超出售后时效,不予处理。'
+            ],
+            relatedBooksList: [
+                { title: '工程数学线性代数第六版', edition: '同济大学数学系编', cover: 'https://img.yzcdn.cn/vant/cat.jpeg' },
+                { title: '高等数学第七版(上册)', edition: '同济大学数学系', cover: 'https://img.yzcdn.cn/vant/cat.jpeg' },
+                { title: 'C++ Primer Plus', edition: '第6版 中文版', cover: 'https://img.yzcdn.cn/vant/cat.jpeg' },
+                { title: '深入理解计算机系统', edition: '原书第3版', cover: 'https://img.yzcdn.cn/vant/cat.jpeg' },
+                { title: '算法导论', edition: '原书第3版', cover: 'https://img.yzcdn.cn/vant/cat.jpeg' },
+                { title: 'Java编程思想', edition: '第4版', cover: 'https://img.yzcdn.cn/vant/cat.jpeg' }
+            ],
+            product: {
+                id: 1,
+                title: '非暴力沟通',
+                author: '美 · 马歇尔 XXXX',
+                authorFull: '马歇尔·卢森堡著 阮胤华',
+                price: '13.80',
+                balancePrice: '6.8',
+                originalPrice: '36.80',
+                cover: 'https://img.yzcdn.cn/vant/cat.jpeg', // Using placeholder for now
+                publisher: '华夏出版社',
+                publishDate: '2018-08',
+                isbn: '9787508095226',
+                intro: '作为一个遵纪守法的好人,也许我们从来没有把谈话和“暴力”扯上关系。不过如果稍微留意一下现实生活中的谈话方式,并且用心体会各种谈话方式给我们的不同感受,我们一定会发现,有些话确实伤人!言语上的指责、嘲讽、否定、说教以及任意打断、拒不回应、随意出口的评价和结论给我们带来的情感和精神上的创伤甚至比肉体的伤害更加令人痛苦。',
+                catalog: '前言\n第一章 让爱融入生活\n第二章 是什么蒙蔽了爱?\n第三章 区分观察和评论\n第四章 体会和表达感受\n第五章 感受的根源\n第六章 请求帮助\n...'
+            },
+            servicePosition: {
+                left: "auto",
+                right: 0,
+                bottom: "300rpx",
+            },
+        }
+    },
+    methods: {
+        switchTab(index) {
+            this.currentTab = index;
+        },
+        openSelectPopup() {
+            this.$refs.selectPopup.open(this.product);
+        },
+        handleNotify() {
+            uni.showToast({
+                title: '已订阅到货通知',
+                icon: 'success'
+            });
+        },
+        onPopupConfirm(data) {
+            console.log('Added to cart:', data);
+            uni.showToast({
+                title: '已加入购物车',
+                icon: 'success'
+            });
+        },
+        showServicePopup() {
+            // Placeholder for service popup
+        },
+        onBookClick(book) {
+            console.log('Book clicked:', book);
+            uni.navigateTo({
+                url: '/pages-sell/pages/detail?id=' + encodeURIComponent(book.title)
+            });
+        },
+        // 处理位置变更
+        handlePositionChange(position) {
+            this.servicePosition = position;
+        },
+        //支付宝小程序的客服
+        navigateToCustomerService() {
+            uni.navigateTo({
+                url: "/pages-mine/pages/customer-service",
+            });
+        },
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+.detail-page {
+    min-height: 100vh;
+    background-color: #f5f5f5;
+    position: relative;
+    padding-bottom: 100rpx;
+}
+
+.header-bg {
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 664rpx;
+    background: linear-gradient(0deg, #4ED868 0%, #D1FFE5 100%);
+    z-index: 0;
+}
+
+.notification-bar {
+    position: fixed;
+    top: 180rpx;
+    /* Adjust based on navbar height */
+    left: 30rpx;
+    z-index: 10;
+    background: rgba(0, 0, 0, 0.3);
+    border-radius: 30rpx;
+    padding: 6rpx 20rpx 6rpx 6rpx;
+    display: flex;
+    align-items: center;
+
+    .notif-text {
+        font-size: 24rpx;
+        color: #fff;
+        margin-left: 10rpx;
+    }
+}
+
+.content-scroll {
+    position: relative;
+    z-index: 1;
+    height: 100vh;
+}
+
+.cover-area {
+    position: relative;
+    display: flex;
+    justify-content: center;
+    padding-top: 60rpx;
+    padding-bottom: 40rpx;
+
+    .book-cover {
+        width: 360rpx;
+        height: 360rpx;
+        box-shadow: 0 10rpx 20rpx rgba(0, 0, 0, 0.1);
+    }
+
+    .share-btn {
+        position: absolute;
+        right: 50rpx;
+        top: 50rpx;
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+
+        .share-icon {
+            width: 40rpx;
+            height: 40rpx;
+            margin-bottom: 4rpx;
+        }
+
+        text {
+            font-size: 20rpx;
+            color: #333;
+        }
+    }
+}
+
+.banner-area {
+    background: #f5f5f5;
+    padding: 20rpx;
+
+    .banner-img {
+        width: 100%;
+        border-radius: 20rpx;
+    }
+}
+
+.service-btn {
+    padding: 0;
+    margin: 0;
+    background-color: transparent;
+    line-height: 1;
+    border-radius: 0;
+    
+    &::after {
+        border: none;
+    }
+}
+
+.tabs-header {
+    display: flex;
+    justify-content: center;
+    /* Center the tabs */
+    background: #F8F8F8;
+    padding: 20rpx 0;
+    /* Remove horizontal padding as we center items */
+
+    .tab-item {
+        padding: 0 30rpx;
+        /* Add internal padding for hit area */
+        position: relative;
+
+        text {
+            font-family: 'Source Han Sans SC';
+            font-size: 30rpx;
+            /* Assuming 30px from design tool = 30rpx */
+            color: #666666;
+            transition: all 0.3s;
+        }
+
+        &.active {
+            text {
+                font-size: 30rpx;
+                /* Keep consistent size or adjust if 'big' effect needed, user said 30px */
+                font-weight: bold;
+                color: #333333;
+            }
+
+            .indicator {
+                position: absolute;
+                bottom: 2rpx;
+                /* Adjust vertical position */
+                left: 50%;
+                transform: translateX(-50%);
+                width: 120rpx;
+                /* Make it wider or relative to text? Usually fixed or text width. Let's try matching text width visually or a fixed width */
+                height: 8rpx;
+                /* Slightly thicker for gradient visibility */
+                background: linear-gradient(90deg, rgba(78, 217, 100, 0.1) 0%, #4ED964 100%);
+                border-radius: 4rpx;
+            }
+        }
+    }
+}
+
+
+</style>

+ 7 - 0
pages.json

@@ -317,6 +317,13 @@
                         "navigationStyle": "custom",
                         "navigationBarTitleText": ""
                     }
+                },
+                {
+                    "path": "pages/detail",
+                    "style": {
+                        "navigationStyle": "custom",
+                        "navigationBarTitleText": ""
+                    }
                 }
             ]
         }

BIN
static/tabbar/cart.png


BIN
static/tabbar/cart2.png


BIN
static/tabbar/person.png


BIN
static/tabbar/sell.png


BIN
static/tabbar/sell2.png