Browse Source

refactor(novel): 重构小说详情页和阅读页,优化代码结构和样式

- 将投票功能从 `vote.vue` 迁移到 `novelVotePopup.vue` 组件中
- 更新小说详情页的导航栏和投票弹窗逻辑
- 优化阅读页的全屏模式和滚动体验
- 修复样式问题,提升页面响应速度
master
前端-胡立永 1 week ago
parent
commit
a17bfdae95
19 changed files with 984 additions and 947 deletions
  1. +17
    -1
      .trae/rules/project_rules.md
  2. +8
    -3
      components/base/navbar.vue
  3. +0
    -3
      pages.json
  4. +21
    -13
      pages/index/index.vue
  5. +12
    -38
      pages_order/components/novel/novelVotePopup.vue
  6. +457
    -448
      pages_order/novel/novelDetail.vue
  7. +469
    -441
      pages_order/novel/readnovels.vue
  8. BIN
      pages_order/static/book/bd.png
  9. BIN
      pages_order/static/book/dj.png
  10. BIN
      pages_order/static/book/level.png
  11. BIN
      static/image/home/notice.png
  12. BIN
      static/image/tabbar/bookshelf-a.png
  13. BIN
      static/image/tabbar/bookshelf.png
  14. BIN
      static/image/tabbar/category-a.png
  15. BIN
      static/image/tabbar/category.png
  16. BIN
      static/image/tabbar/center-a.png
  17. BIN
      static/image/tabbar/center.png
  18. BIN
      static/image/tabbar/home-a.png
  19. BIN
      static/image/tabbar/home.png

+ 17
- 1
.trae/rules/project_rules.md View File

@ -8,4 +8,20 @@
- components 放主包组件
- pages 只放主页面
- pages_order 放其他页面
- components 放分包组件
- components 放分包组件
css语法按照scss的嵌套写法例如
.a{
xxx
.b{
.c{
xxx
}
}
}
.d{
.f{
}
}

+ 8
- 3
components/base/navbar.vue View File

@ -2,7 +2,9 @@
<!-- <view class="navbar"
:style="{backgroundColor : bgColor}"> -->
<view class="title"
:style="{backgroundColor : bgColor,color}">
:style="{backgroundColor : bgColor,color,
position
}">
<view class="left">
<uv-icon name="home"
@ -73,7 +75,11 @@
},
color : {
default : '#333'
}
},
position : {
type : String,
default : 'sticky'
}
},
created() {
},
@ -105,7 +111,6 @@
// padding-top: var(--status-bar-height);
// }
.title{
position: sticky;
top: 0;
left: 0;
padding-top: calc(var(--status-bar-height) + 20rpx);


+ 0
- 3
pages.json View File

@ -55,9 +55,6 @@
{
"path": "novel/novelDetail"
},
{
"path": "novel/vote"
},
{
"path": "announcement/announcementDetail"
},


+ 21
- 13
pages/index/index.vue View File

@ -53,12 +53,15 @@
<!-- 通知区域 -->
<view class="notice" @click="viewNotice">
<view class="notice-left">
<view class="notice-tag">通讯</view>
<view class="notice-icon">
<image src="https://img95.699pic.com/xsj/0z/ld/62.jpg!/fw/700/watermark/url/L3hzai93YXRlcl9kZXRhaWwyLnBuZw/align/southeast" mode="aspectFill"></image>
<image src="/static/image/home/notice.png" mode="aspectFill"></image>
</view>
<view class="">
全部共告
</view>
</view>
<view class="notice-center">
<view class="notice-tag">通讯</view>
<view class="notice-text" @click="viewNotice">
2025年2月平台福利活动截稿作品公示
</view>
@ -356,16 +359,10 @@
display: flex;
align-items: center;
margin-right: 20rpx;
.notice-tag {
font-size: 22rpx;
color: #666;
background-color: #f5f5f5;
padding: 4rpx 12rpx;
border-radius: 6rpx;
margin-right: 10rpx;
}
flex-direction: column;
font-size: 22rpx;
width: 90rpx;
justify-content: center;
.notice-icon {
width: 60rpx;
height: 60rpx;
@ -382,9 +379,20 @@
.notice-center {
flex: 1;
.notice-tag {
font-size: 22rpx;
color: #666;
background-color: #f5f5f5;
padding: 4rpx 12rpx;
border-radius: 6rpx;
margin-right: 10rpx;
width: fit-content;
margin-bottom: 10rpx;
}
.notice-text {
font-size: 28rpx;
font-size: 26rpx;
color: #333;
overflow: hidden;
white-space: nowrap;


pages_order/novel/vote.vue → pages_order/components/novel/novelVotePopup.vue View File

@ -1,14 +1,10 @@
<template>
<view class="vote-container">
<!-- Empty space at the top -->
<view class="empty-space"></view>
<!-- Bottom sheet with voting interface -->
<uv-popup ref="popup" :round="30">
<view class="vote-sheet">
<view class="sheet-header">
<text class="sheet-title">投推荐票</text>
</view>
<view class="vote-options">
<text class="option-label">推荐投票</text>
<view class="quick-options">
@ -16,7 +12,7 @@
<view class="option-btn" @click="setVotes(5)">5</view>
<view class="option-btn" @click="setVotes(10)">10</view>
</view>
<text class="option-label">手动设置</text>
<view class="manual-input">
<view class="minus-btn" @click="decreaseVotes">-</view>
@ -26,53 +22,31 @@
<view class="plus-btn" @click="increaseVotes">+</view>
</view>
</view>
<button class="submit-btn" @click="submitVote">投票</button>
</view>
</view>
</uv-popup>
</template>
<script>
export default {
data() {
return {
voteCount: 1
}
},
methods: {
setVotes(count) {
this.voteCount = count
},
increaseVotes() {
this.voteCount++
open() {
this.$refs.popup.open('bottom')
},
decreaseVotes() {
if (this.voteCount > 1) {
this.voteCount--
}
close() {
this.$refs.popup.close()
},
submitVote() {
// TODO: Implement vote submission
uni.showToast({
title: `已投${this.voteCount}`,
icon: 'success'
})
}
}
}
</script>
<style lang="scss">
.vote-container {
display: flex;
flex-direction: column;
height: 100vh;
background-color: rgba(0, 0, 0, 0.4);
}
.empty-space {
flex: 1;
}
<style scoped lang="scss">
.vote-sheet {
background-color: #fff;
@ -160,4 +134,4 @@
align-items: center;
justify-content: center;
}
</style>
</style>

+ 457
- 448
pages_order/novel/novelDetail.vue View File

@ -1,13 +1,7 @@
<template>
<!-- 小说详情页面 -->
<view class="novel-detail">
<!-- 顶部返回导航 -->
<uv-navbar title="小说详情" :autoBack="true" fixed placeholder titleStyle="color: #333; font-weight: 700;"
:border="false">
<template #left>
<BackArrow :size="56" color="#333" @back="goBack" />
</template>
</uv-navbar>
<navbar title="小说详情" leftClick @leftClick="$utils.navigateBack" />
<!-- 小说基本信息 -->
<view class="novel-info">
@ -39,7 +33,7 @@
</view>
<view class="rec-divider"></view>
<view class="rec-right">
<button class="recommend-btn" @click="recommendNovel">
<button class="recommend-btn" @click="$refs.novelVotePopup.open()">
<text class="btn-icon">📑</text>
投推荐票
</button>
@ -53,15 +47,29 @@
<view class="user-level">
<view class="level-left">
<view class="level-title">
<text class="title-icon">👑</text>
<!-- <text class="title-icon">👑</text> -->
<image style="width: 30rpx;height: 30rpx;" src="/pages_order/static/book/level.png"
mode="aspectFill"></image>
<text>我的等级</text>
</view>
<view class="level-info">
<image class="user-avatar"
src="https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain"
mode="aspectFill"></image>
src="/pages_order/static/book/dj.png"
mode="aspectFill"></image>
<view class="user-details">
<text class="username">周海</text>
<text class="username">
<image
src="https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain"
mode="aspectFill"></image>
<view class="name">
周海
</view>
</text>
<view class="user-score">
<text class="score-value">6785452</text>
<text class="score-label">亲密值</text>
@ -72,10 +80,7 @@
</view>
<view class="level-right">
<view class="rank-btn">
<image class="rank-icon"
src="https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain"
mode="aspectFit"></image>
<text>读者榜单</text>
<image class="rank-icon" src="/pages_order/static/book/bd.png" mode="aspectFit"></image>
<text class="check-text">点击查看</text>
</view>
</view>
@ -149,6 +154,8 @@
<button class="read-now-btn" @click="startReading">立即阅读</button>
</view>
</view>
<novelVotePopup ref="novelVotePopup"/>
<chapterPopup ref="chapterPopup" />
</view>
@ -156,15 +163,15 @@
<script>
import catalogpopup from '@/components/novel/CatalogPopup.vue'
import BackArrow from './components/BackArrow.vue'
import chapterPopup from '../components/novel/chapterPopup.vue'
import commentItem from '../components/comment/commentItem.vue'
import novelVotePopup from '../components/novel/novelVotePopup.vue'
export default {
components: {
catalogpopup,
BackArrow,
chapterPopup,
commentItem,
novelVotePopup,
},
data() {
return {
@ -267,462 +274,464 @@
min-height: 100vh;
background-color: #f5f5f5;
padding-bottom: calc(env(safe-area-inset-bottom) + 30rpx);
}
.nav-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20rpx 30rpx;
background-color: transparent;
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 100;
}
.novel-info {
padding: 20rpx;
display: flex;
background: #fff;
}
.novel-cover {
width: 200rpx;
height: 280rpx;
margin-right: 20rpx;
}
.novel-cover image {
width: 100%;
height: 100%;
border-radius: 8rpx;
}
.novel-basic {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.title {
font-size: 36rpx;
font-weight: bold;
margin-bottom: 16rpx;
}
.author-line,
.status-line {
display: flex;
align-items: center;
margin-bottom: 12rpx;
font-size: 28rpx;
color: #666;
}
.label {
color: #999;
margin-right: 8rpx;
}
.score-line {
margin-top: 16rpx;
}
.score {
font-size: 32rpx;
color: #333;
font-weight: bold;
}
.score-label {
font-size: 24rpx;
color: #999;
margin-left: 8rpx;
}
.recommendation-section {
padding: 24rpx 32rpx;
background: #fff;
display: flex;
justify-content: space-between;
align-items: center;
position: relative;
}
.rec-left {
display: flex;
flex-direction: column;
align-items: flex-start;
margin-left: 70rpx;
}
.rec-count {
font-size: 44rpx;
font-weight: 500;
color: #333;
line-height: 1.2;
}
.rec-label {
font-size: 26rpx;
color: #999;
margin-top: 4rpx;
}
.rec-divider {
position: absolute;
right: 160rpx;
top: 20rpx;
bottom: 20rpx;
width: 2rpx;
background: #eee;
}
.rec-right {
flex-shrink: 0;
}
.recommend-btn {
background: #fff;
color: #4a90e2;
border: 2rpx solid #4a90e2;
border-radius: 40rpx;
padding: 12rpx 32rpx;
font-size: 28rpx;
display: flex;
align-items: center;
line-height: 1;
height: 64rpx;
}
.btn-icon {
margin-right: 8rpx;
font-size: 32rpx;
}
.action-buttons {
display: flex;
padding: 30rpx;
gap: 20rpx;
button {
flex: 1;
height: 80rpx;
border-radius: 40rpx;
font-size: 32rpx;
.nav-header {
display: flex;
justify-content: space-between;
align-items: center;
justify-content: center;
}
.read-btn {
background-color: #4a90e2;
color: #fff;
}
.collect-btn {
background-color: #f0f0f0;
color: #666;
}
}
.user-level {
margin: 20rpx 30rpx;
background-color: #fff;
border-radius: 12rpx;
padding: 24rpx 32rpx;
display: flex;
justify-content: space-between;
align-items: stretch;
}
.level-left {
flex: 1;
}
.level-title {
display: flex;
align-items: center;
gap: 8rpx;
margin-bottom: 20rpx;
margin-left: 20rpx;
.title-icon {
font-size: 36rpx;
color: #FFB800;
}
text {
font-size: 32rpx;
font-weight: 500;
color: #333;
}
}
.level-info {
display: flex;
align-items: flex-start;
gap: 20rpx;
}
.user-avatar {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
border: 2rpx solid #f0f0f0;
}
.user-details {
display: flex;
flex-direction: column;
gap: 8rpx;
}
.username {
font-size: 28rpx;
color: #333;
font-weight: 500;
}
.user-score {
display: flex;
align-items: center;
gap: 8rpx;
.score-value {
font-size: 28rpx;
color: #333;
}
.score-label {
font-size: 24rpx;
color: #999;
padding: 20rpx 30rpx;
background-color: transparent;
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 100;
}
}
.user-role {
font-size: 24rpx;
color: #666;
background: #f5f5f5;
padding: 4rpx 12rpx;
border-radius: 4rpx;
display: inline-block;
}
.level-right {
display: flex;
align-items: center;
}
.rank-btn {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 0 20rpx;
.rank-icon {
width: 200rpx;
height: 60rpx;
margin-bottom: 8rpx;
}
text {
font-size: 26rpx;
color: #333;
line-height: 1.4;
}
.check-text {
font-size: 22rpx;
color: #999;
}
}
.novel-intro {
margin: 20rpx 30rpx;
background-color: #fff;
border-radius: 12rpx;
padding: 24rpx;
}
.intro-title {
font-size: 32rpx;
font-weight: 500;
color: #333;
margin-bottom: 16rpx;
}
.intro-content {
font-size: 28rpx;
color: #666;
line-height: 1.6;
display: flex;
flex-direction: column;
gap: 16rpx;
text {
display: block;
}
}
.comments-section {
margin: 20rpx 30rpx;
background-color: #fff;
border-radius: 12rpx;
padding: 24rpx;
}
.comments-header {
display: flex;
align-items: center;
margin-bottom: 24rpx;
border-bottom: 2rpx solid #f5f5f5;
padding-bottom: 24rpx;
justify-content: flex-start;
}
.header-left {
display: flex;
align-items: center;
gap: 8rpx;
.title-icon {
font-size: 32rpx;
}
text {
.novel-info {
padding: 20rpx;
display: flex;
align-items: center;
font-size: 32rpx;
font-weight: 500;
color: #333;
white-space: nowrap;
background: #fff;
.novel-cover {
width: 200rpx;
height: 280rpx;
margin-right: 20rpx;
image {
width: 100%;
height: 100%;
border-radius: 8rpx;
}
}
.novel-basic {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
.title {
font-size: 36rpx;
font-weight: bold;
margin-bottom: 16rpx;
}
.author-line,
.status-line {
display: flex;
align-items: center;
margin-bottom: 12rpx;
font-size: 28rpx;
color: #666;
}
.label {
color: #999;
margin-right: 8rpx;
}
.score-line {
margin-top: 16rpx;
.score {
font-size: 32rpx;
color: #333;
font-weight: bold;
}
.score-label {
font-size: 24rpx;
color: #999;
margin-left: 8rpx;
}
}
}
}
}
.header-right {
margin-left: auto;
}
.comment-list {
display: flex;
flex-direction: column;
gap: 32rpx;
}
.like-icon {
font-size: 24rpx;
color: #999;
}
.like-count {
font-size: 24rpx;
color: #999;
}
.novel-catalog {
margin: 20rpx 30rpx;
background-color: #fff;
border-radius: 12rpx;
padding: 24rpx;
.catalog-header {
.recommendation-section {
padding: 24rpx 32rpx;
background: #fff;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 2rpx solid #f5f5f5;
.catalog-title {
position: relative;
.rec-left {
display: flex;
align-items: center;
gap: 8rpx;
.title-icon {
font-size: 32rpx;
}
text {
font-size: 32rpx;
flex-direction: column;
align-items: flex-start;
margin-left: 70rpx;
.rec-count {
font-size: 44rpx;
font-weight: 500;
color: #333;
line-height: 1.2;
}
.rec-label {
font-size: 26rpx;
color: #999;
margin-top: 4rpx;
}
}
.rec-divider {
position: absolute;
right: 160rpx;
top: 20rpx;
bottom: 20rpx;
width: 2rpx;
background: #eee;
}
.rec-right {
flex-shrink: 0;
.recommend-btn {
background: #fff;
color: #4a90e2;
border: 2rpx solid #4a90e2;
border-radius: 40rpx;
padding: 12rpx 32rpx;
font-size: 28rpx;
display: flex;
align-items: center;
line-height: 1;
height: 64rpx;
.btn-icon {
margin-right: 8rpx;
font-size: 32rpx;
}
}
}
}
.chapter-nav {
.action-buttons {
display: flex;
align-items: center;
gap: 8rpx;
.current-chapter {
font-size: 28rpx;
padding: 30rpx;
gap: 20rpx;
button {
flex: 1;
height: 80rpx;
border-radius: 40rpx;
font-size: 32rpx;
display: flex;
align-items: center;
justify-content: center;
}
.read-btn {
background-color: #4a90e2;
color: #fff;
}
.collect-btn {
background-color: #f0f0f0;
color: #666;
}
.nav-arrow {
}
.user-level {
margin: 20rpx 30rpx;
background-color: #fff;
border-radius: 12rpx;
padding: 24rpx 32rpx;
display: flex;
justify-content: space-between;
align-items: stretch;
.level-left {
flex: 1;
.level-title {
display: flex;
align-items: center;
gap: 8rpx;
margin-bottom: 20rpx;
margin-left: 20rpx;
.title-icon {
font-size: 36rpx;
color: #FFB800;
}
text {
font-size: 32rpx;
font-weight: 500;
color: #333;
}
}
.level-info {
display: flex;
align-items: flex-start;
gap: 20rpx;
.user-avatar {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
border: 2rpx solid #f0f0f0;
}
.user-details {
display: flex;
flex-direction: column;
gap: 8rpx;
.username {
display: flex;
font-size: 28rpx;
color: #333;
font-weight: 500;
image {
width: 60rpx;
height: 60rpx;
}
}
.user-score {
display: flex;
align-items: center;
gap: 8rpx;
.score-value {
font-size: 28rpx;
color: #333;
}
.score-label {
font-size: 24rpx;
color: #999;
}
}
.user-role {
font-size: 24rpx;
color: #666;
background: #f5f5f5;
padding: 4rpx 12rpx;
border-radius: 4rpx;
display: inline-block;
}
}
}
}
.level-right {
display: flex;
align-items: center;
.rank-btn {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 0 20rpx;
.rank-icon {
width: 200rpx;
height: 60rpx;
margin-bottom: 8rpx;
}
text {
font-size: 26rpx;
color: #333;
line-height: 1.4;
}
.check-text {
font-size: 22rpx;
color: #999;
}
}
}
}
.novel-intro {
margin: 20rpx 30rpx;
background-color: #fff;
border-radius: 12rpx;
padding: 24rpx;
.intro-title {
font-size: 32rpx;
font-weight: 500;
color: #333;
margin-bottom: 16rpx;
}
.intro-content {
font-size: 28rpx;
color: #666;
line-height: 1.6;
display: flex;
flex-direction: column;
gap: 16rpx;
text {
display: block;
}
}
}
.comments-section {
margin: 20rpx 30rpx;
background-color: #fff;
border-radius: 12rpx;
padding: 24rpx;
.comments-header {
display: flex;
align-items: center;
margin-bottom: 24rpx;
border-bottom: 2rpx solid #f5f5f5;
padding-bottom: 24rpx;
justify-content: flex-start;
.header-left {
display: flex;
align-items: center;
gap: 8rpx;
.title-icon {
font-size: 32rpx;
}
text {
display: flex;
align-items: center;
font-size: 32rpx;
font-weight: 500;
color: #333;
white-space: nowrap;
}
}
.header-right {
margin-left: auto;
}
}
.comment-list {
display: flex;
flex-direction: column;
gap: 32rpx;
}
.like-icon {
font-size: 24rpx;
color: #999;
}
.like-count {
font-size: 24rpx;
color: #999;
}
}
}
.novel-bottom {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 100rpx;
background: #fff;
display: flex;
align-items: center;
padding: 0 30rpx;
padding-bottom: env(safe-area-inset-bottom);
box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);
.bottom-left {
flex: 1;
display: flex;
gap: 40rpx;
.novel-catalog {
margin: 20rpx 30rpx;
background-color: #fff;
border-radius: 12rpx;
padding: 24rpx;
.catalog-header {
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 2rpx solid #f5f5f5;
.catalog-title {
display: flex;
align-items: center;
gap: 8rpx;
.title-icon {
font-size: 32rpx;
}
text {
font-size: 32rpx;
font-weight: 500;
color: #333;
}
}
.chapter-nav {
display: flex;
align-items: center;
gap: 8rpx;
.current-chapter {
font-size: 28rpx;
color: #666;
}
.nav-arrow {
font-size: 28rpx;
color: #999;
}
}
}
}
.action-btn {
.novel-bottom {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 100rpx;
background: #fff;
display: flex;
flex-direction: column;
align-items: center;
gap: 4rpx;
.btn-icon {
font-size: 40rpx;
line-height: 1;
padding: 0 30rpx;
padding-bottom: env(safe-area-inset-bottom);
box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);
.bottom-left {
flex: 1;
display: flex;
gap: 40rpx;
.action-btn {
display: flex;
flex-direction: column;
align-items: center;
gap: 4rpx;
.btn-icon {
font-size: 40rpx;
line-height: 1;
}
text {
font-size: 24rpx;
color: #666;
}
}
}
text {
font-size: 24rpx;
color: #666;
.bottom-right {
flex-shrink: 0;
.read-now-btn {
background: #1a237e;
color: #fff;
font-size: 32rpx;
height: 80rpx;
line-height: 80rpx;
padding: 0 60rpx;
border-radius: 40rpx;
border: none;
}
}
}
.bottom-right {
flex-shrink: 0;
}
.read-now-btn {
background: #1a237e;
color: #fff;
font-size: 32rpx;
height: 80rpx;
line-height: 80rpx;
padding: 0 60rpx;
border-radius: 40rpx;
border: none;
}
}
</style>

+ 469
- 441
pages_order/novel/readnovels.vue View File

@ -1,451 +1,479 @@
<template>
<!-- 小说文本页面 -->
<view class="reader-container" @click.native="toggleFullScreen">
<uv-navbar title="这游戏也太真实了" :autoBack="true" fixed placeholder titleStyle="color: #333; font-weight: 700;" :border="false">
<template #left>
<BackArrow :size="56" color="#333" @back="$emit('back')" />
</template>
</uv-navbar>
<view class="chapter-title">第1章 2004</view>
<scroll-view scroll-y class="chapter-content" style="height: 70vh;" @touchend="handleTouchEnd" @scroll="handleScroll" @tap="handleContentClick">
<text>
华星华东地区某个省市区不知名街后居民
读朱自清的荷塘月色品读鲁迅的从百草园到三味书屋看梁实秋的雅舍!一篇篇经典散文想起来就像藏在脑海里的动画优雅唯美的画面好像夜晚的微风轻抚着凝望远方的脸颊!美文入心!感慨万千!下面是100篇名家经典散文摘抄敬请你的欣赏!
<!-- 小说文本页面 -->
<view class="reader-container">
<view class="top-controls" :class="{'top-controls-hidden': isFullScreen}">
<view class="controls-inner">
<view class="left">
<uv-icon name="arrow-left" @click="$utils.navigateBack" color="#333" size="46rpx"></uv-icon>
</view>
<view class="center">
<text class="title">{{ novelTitle }}</text>
<text class="chapter">{{ currentChapter }}</text>
</view>
<!-- <view class="right">
<uv-icon name="more-dot-fill" color="#333" size="46rpx"></uv-icon>
</view> -->
</view>
<view class="progress-bar">
<view class="progress-inner" :style="{width: readProgress + '%'}"></view>
</view>
</view>
<scroll-view scroll-y class="chapter-content" :class="{'full-content': isFullScreen}"
@scroll="handleScroll" @tap="handleContentClick">
<view class="chapter-content-item">
<view class="chapter-title">第1章 重回2004</view>
<view class="paragraph-content">
<view class="paragraph" v-for="(paragraph, index) in paragraphs" :key="index">
{{ paragraph }}
</view>
</view>
</view>
100篇名家经典散文摘抄
叶圣陶散文"名家经典珍藏"丛书之一收录了叶圣陶先生的散文精品数十篇这些作品内容丰富题材各异构思精巧文笔精巧语言幽默内蕴深厚风格恬淡充分显示了叶圣陶先生的文学功底及丰富的人生阅历从一个侧面反映了作者的思想感情及创作风格非常值得一读叶圣陶是20世纪中国一位杰出的作家教育家和出版家又是中国现代儿童文学创作的先行者作为散文家他早期和周作人朱自清共同成为文学研究会散文创作的中坚后来又成为开明派散文的代表其散文被一九三五年出版的中国新文学大系选录的篇数仅次于周作人鲁迅和朱自清
1朱自清荷塘月色片段
路上只我一个人背着手踱着这一片天地好像是我的;我也像超出了平常旳自己到了另一世界里我爱热闹也爱冷静;爱群居也爱独处像今晚上一个人在这苍茫旳月下什么都可以想什么都可以不想便觉是个自由的人白天里一定要做的事一定要说的话现在都可不理这是独处的妙处我且受用这无边的荷香月色好了
曲曲折折的荷塘上面弥望旳是田田的叶子叶子出水很高像亭亭旳舞女旳裙层层的叶子中间零星地点缀着些白花有袅娜(niǎo,nuó)地开着旳有羞涩地打着朵儿旳;正如一粒粒的明珠又如碧天里的星星又如刚出浴的美人微风过处送来缕缕清香仿佛远处高楼上渺茫的歌声似的这时候叶子与花也有一丝的颤动像闪电般霎时传过荷塘的那边去了叶子本是肩并肩密密地挨着这便宛然有了一道凝碧的波痕叶子底下是脉脉()的流水遮住了不能见一些颜色;而叶子却更见风致了
月光如流水一般静静地泻在这一片叶子和花上薄薄的青雾浮起在荷塘里叶子和花仿佛在牛乳中洗过一样;又像笼着轻纱的梦虽然是满月天上却有一层淡淡的云所以不能朗照;但我以为这恰是到了好处酣眠固不可少小睡也别有风味的月光是隔了树照过来的高处丛生的灌木落下参差的斑驳的黑影峭楞楞如鬼一般;弯弯的杨柳的稀疏的倩影却又像是画在荷叶上塘中的月色并不均匀;但光与影有着和谐的旋律如梵婀(ē)(英语violin小提琴的译音)上奏着的名曲
荷塘的四面远远近近高高低低都是树而杨柳最多这些树将一片荷塘重重围住;只在小路一旁漏着几段空隙像是特为月光留下的树色一例是阴阴的乍看像一团烟雾;但杨柳的丰姿便在烟雾里也辨得出树梢上隐隐约约的是一带远山只有些大意罢了树缝里也漏着一两点路灯光没精打采的是渴睡人的眼这时候最热闹的要数树上的蝉声与水里的蛙声;但热闹是它们的我什么也没有
2鲁迅从百草园到三味书屋片段
100篇名家经典散文摘抄
叶圣陶散文"名家经典珍藏"丛书之一收录了叶圣陶先生的散文精品数十篇这些作品内容丰富题材各异构思精巧文笔精巧语言幽默内蕴深厚风格恬淡充分显示了叶圣陶先生的文学功底及丰富的人生阅历从一个侧面反映了作者的思想感情及创作风格非常值得一读叶圣陶是20世纪中国一位杰出的作家教育家和出版家又是中国现代儿童文学创作的先行者作为散文家他早期和周作人朱自清共同成为文学研究会散文创作的中坚后来又成为开明派散文的代表其散文被一九三五年出版的中国新文学大系选录的篇数仅次于周作人鲁迅和朱自清
1朱自清荷塘月色片段
路上只我一个人背着手踱着这一片天地好像是我的;我也像超出了平常旳自己到了另一世界里我爱热闹也爱冷静;爱群居也爱独处像今晚上一个人在这苍茫旳月下什么都可以想什么都可以不想便觉是个自由的人白天里一定要做的事一定要说的话现在都可不理这是独处的妙处我且受用这无边的荷香月色好了
曲曲折折的荷塘上面弥望旳是田田的叶子叶子出水很高像亭亭旳舞女旳裙层层的叶子中间零星地点缀着些白花有袅娜(niǎo,nuó)地开着旳有羞涩地打着朵儿旳;正如一粒粒的明珠又如碧天里的星星又如刚出浴的美人微风过处送来缕缕清香仿佛远处高楼上渺茫的歌声似的这时候叶子与花也有一丝的颤动像闪电般霎时传过荷塘的那边去了叶子本是肩并肩密密地挨着这便宛然有了一道凝碧的波痕叶子底下是脉脉()的流水遮住了不能见一些颜色;而叶子却更见风致了
月光如流水一般静静地泻在这一片叶子和花上薄薄的青雾浮起在荷塘里叶子和花仿佛在牛乳中洗过一样;又像笼着轻纱的梦虽然是满月天上却有一层淡淡的云所以不能朗照;但我以为这恰是到了好处酣眠固不可少小睡也别有风味的月光是隔了树照过来的高处丛生的灌木落下参差的斑驳的黑影峭楞楞如鬼一般;弯弯的杨柳的稀疏的倩影却又像是画在荷叶上塘中的月色并不均匀;但光与影有着和谐的旋律如梵婀(ē)(英语violin小提琴的译音)上奏着的名曲
荷塘的四面远远近近高高低低都是树而杨柳最多这些树将一片荷塘重重围住;只在小路一旁漏着几段空隙像是特为月光留下的树色一例是阴阴的乍看像一团烟雾;但杨柳的丰姿便在烟雾里也辨得出树梢上隐隐约约的是一带远山只有些大意罢了树缝里也漏着一两点路灯光没精打采的是渴睡人的眼这时候最热闹的要数树上的蝉声与水里的蛙声;但热闹是它们的我什么也没有
2鲁迅从百草园到三味书屋片段
100篇名家经典散文摘抄
<!-- 这里填充章节内容后续可通过props或API获取 -->
</text>
</scroll-view>
<view class="bottom-bar" v-if="!isFullScreen">
<view class="bottom-left">
<view class="bar-item">
<view class="bar-icon"> <uv-icon name="plus"></uv-icon> </view>
<text class="bar-label">加入书架</text>
</view>
<view class="bar-item">
<view class="bar-icon"> <uv-icon name="eye-fill"></uv-icon> </view>
<text class="bar-label">夜间</text>
</view>
</view>
<view class="bottom-right">
<button class="outline-btn"><text class="btn-text">上一章</text></button>
<button class="outline-btn" @click="showCatalog = true"><text class="btn-text">目录</text></button>
<button class="outline-btn"><text class="btn-text">下一章</text></button>
</view>
</view>
<uv-popup v-model="showPopup" mode="center" :closeOnClickOverlay="true">
<view style="padding: 48rpx 32rpx; text-align: center; background: #fff; border-radius: 24rpx; min-width: 500rpx;">
<view style="font-size: 32rpx; font-weight: bold; color: #222; margin-bottom: 24rpx;">这是付费章节 需要订阅后才能阅读</view>
<view style="font-size: 26rpx; color: #999; margin-bottom: 40rpx;">订阅后可继续阅读本章内容</view>
<view style="display: flex; justify-content: center; gap: 24rpx;">
<button style="background: #ff9800; color: #fff; border-radius: 32rpx; font-size: 28rpx; padding: 0 32rpx; border: none;" @click="goToSubscription">订阅本章</button>
<button style="background: #fff3e0; color: #ff9800; border-radius: 32rpx; font-size: 28rpx; padding: 0 32rpx; border: 1px solid #ff9800;">观看视频解锁</button>
<button style="background: #fff; color: #ff9800; border-radius: 32rpx; font-size: 28rpx; padding: 0 32rpx; border: 1px solid #ff9800;">批量订阅</button>
</view>
</view>
</uv-popup>
<!-- 目录弹窗顶部196px边距底部无边距宽度100vw高度自适应顶部圆角底部无圆角 -->
<view v-if="showCatalog" class="catalog-popup-fullscreen" style="top:196px;bottom:0;height:auto;min-height:calc(100vh - 196px);">
<view class="catalog-header">
<view class="header-left" @click="showCatalog = false">
<uv-icon name="arrow-down" size="46" color="#333" @click="goBack" />
</view>
<view class="header-title">目录</view>
<view class="header-right" @click="reverseOrder">倒序</view>
</view>
<scroll-view scroll-y class="catalog-list" style="padding-bottom:0;margin-bottom:0;">
<view v-for="(item, idx) in displayList" :key="item.id" @click="selectChapter(idx)"
:class="['catalog-item', {active: idx === currentIndex}]">
<view class="item-main">
<text class="item-title">{{ item.title }}</text>
<text v-if="item.vip" class="vip-tag" @click.stop="showPayPopup = true">付费</text>
</view>
</view>
</scroll-view>
</view>
<view v-if="showPayPopup" class="pay-popup-mask" @click="showPayPopup = false">
<view class="pay-popup" @click.stop>
<view class="pay-title">这是付费章节 需要订阅后才能阅读</view>
<view class="pay-desc">订阅后可继续阅读本章内容</view>
<view class="pay-btns">
<button class="pay-btn" @click="goToSubscription">订阅本章</button>
<button class="pay-btn pay-btn-video">观看视频解锁</button>
<button class="pay-btn pay-btn-batch">批量订阅</button>
</view>
</view>
</view>
</view>
</scroll-view>
<view class="bottom-bar" :class="{'bottom-bar-hidden': isFullScreen}">
<view class="bottom-left">
<view class="bar-item">
<view class="bar-icon"> <uv-icon name="plus"></uv-icon> </view>
<text class="bar-label">加入书架</text>
</view>
<view class="bar-item">
<view class="bar-icon"> <uv-icon name="eye-fill"></uv-icon> </view>
<text class="bar-label">夜间</text>
</view>
</view>
<view class="bottom-right">
<button class="outline-btn"><text class="btn-text">上一章</text></button>
<button class="outline-btn" @click="$refs.chapterPopup.open()"><text class="btn-text">目录</text></button>
<button class="outline-btn"><text class="btn-text">下一章</text></button>
</view>
</view>
<uv-popup v-model="showPopup" mode="center" :closeOnClickOverlay="true">
<view
style="padding: 48rpx 32rpx; text-align: center; background: #fff; border-radius: 24rpx; min-width: 500rpx;">
<view style="font-size: 32rpx; font-weight: bold; color: #222; margin-bottom: 24rpx;">这是付费章节 需要订阅后才能阅读
</view>
<view style="font-size: 26rpx; color: #999; margin-bottom: 40rpx;">订阅后可继续阅读本章内容</view>
<view style="display: flex; justify-content: center; gap: 24rpx;">
<button
style="background: #ff9800; color: #fff; border-radius: 32rpx; font-size: 28rpx; padding: 0 32rpx; border: none;"
@click="goToSubscription">订阅本章</button>
<button
style="background: #fff3e0; color: #ff9800; border-radius: 32rpx; font-size: 28rpx; padding: 0 32rpx; border: 1px solid #ff9800;">观看视频解锁</button>
<button
style="background: #fff; color: #ff9800; border-radius: 32rpx; font-size: 28rpx; padding: 0 32rpx; border: 1px solid #ff9800;">批量订阅</button>
</view>
</view>
</uv-popup>
<view v-if="showPayPopup" class="pay-popup-mask" @click="showPayPopup = false">
<view class="pay-popup" @click.stop>
<view class="pay-title">这是付费章节 需要订阅后才能阅读</view>
<view class="pay-desc">订阅后可继续阅读本章内容</view>
<view class="pay-btns">
<button class="pay-btn" @click="goToSubscription">订阅本章</button>
<button class="pay-btn pay-btn-video">观看视频解锁</button>
<button class="pay-btn pay-btn-batch">批量订阅</button>
</view>
</view>
</view>
<novelVotePopup ref="novelVotePopup"/>
<chapterPopup ref="chapterPopup" />
</view>
</template>
<script>
import BackArrow from './components/BackArrow.vue';
import chapterPopup from '../components/novel/chapterPopup.vue'
import novelVotePopup from '../components/novel/novelVotePopup.vue'
export default {
components: {
chapterPopup,
novelVotePopup,
},
data() {
return {
isFullScreen: false,
showPopup: false,
popupShown: false, //
showPayPopup: false,
novelTitle: "这游戏也太真实了",
currentChapter: "第1章 重回2004",
readProgress: 15, //
paragraphs: [
"华东地区某个不知名街区,2004年冬。",
"天还没有亮,王明就起床了。他要去赶早市,今天是进货的日子,错过了就要等下周。他轻轻地穿好衣服,不想吵醒还在熟睡的妻子。",
"天气比想象中冷,他裹紧了身上那件略显破旧的棉袄。出门前,他看了眼床头那个旧闹钟,四点半,还算准时。",
"街上几乎没有人,只有零星的几辆三轮车和面包车正往市场方向驶去。王明加快了脚步,他知道好位置都是先到先得。",
"这一年,互联网刚刚开始在中国普及,但对于像王明这样的小摊贩来说,生活并没有什么变化。每天起早贪黑,挣扎在温饱线上。",
"然而就在今天,他的生活将迎来一场他从未预料到的变化。",
"市场入口处,一个陌生人递给他一张名片,上面写着:\"电子产品批发,价格优惠\"。王明随手接过,塞进了口袋,继续往里走。",
"他不知道的是,这张小小的名片,将成为改变他命运的第一步。",
"几个小时后,当他收摊准备回家时,他偶然摸到了那张名片。出于好奇,他决定去看看。",
"名片上的地址在城市的另一边,是一个他从未去过的工业区。坐了将近一个小时的公交车,他终于找到了那个地方。",
"那是一个不起眼的仓库,门口停着几辆货车。王明犹豫了一下,还是推门走了进去。",
"里面的景象让他震惊。货架上整齐地摆放着各种电子产品:MP3播放器、数码相机、U盘……这些在当时都是新奇而昂贵的物品。",
"\"您是新顾客吧?\"一个中年男人走过来,热情地招呼道。",
"\"是的,我看到了你的名片。\"王明有些拘谨地回答。",
"\"那您来得正是时候,我们刚收到一批新货,价格特别优惠。\"",
"王明被带到一个展示台前,上面摆着几个小巧的设备。\"这是最新款的MP3,容量大,音质好,在市场上很受欢迎。\"",
"王明拿起一个仔细端详。他虽然没什么文化,但做生意的直觉告诉他,这东西可能有市场。",
"\"多少钱一个?\"他问道。",
"\"批发价150元,零售价可以卖到300元以上。\"",
"王明心里快速计算着。他今天的存款只有3000元,如果全买这个,可以拿20个。要是真能卖出去,就是3000元的利润。",
"但风险也很大。万一卖不出去,这可是他半年的积蓄啊。",
"就在他犹豫的时候,旁边传来一个熟悉的声音:\"老王,你也来这进货啊?\"",
"是他在市场上认识的李东。李东比他年轻,做生意也比他精明。",
"\"你觉得这东西怎么样?\"王明问道。",
"\"那必须相当不错啊。我上周进了一批,三天就卖光了。现在是过节嘛,年轻人喜欢这些新鲜玩意儿。\"李东拍了拍他的肩膀,\"要我说,你应该赶紧进一批,过了这个村可就没这个店了。\"",
"看到李东的信心,王明心里的天平开始倾斜。",
"\"那...好吧,给我来20个。\"他终于下定决心,从口袋里掏出了钱。",
"这一决定,将彻底改变他的人生轨迹...",
]
}
},
methods: {
handleContentClick() {
this.toggleFullScreen();
},
handleScroll(e) {
//
const scrollTop = e.detail.scrollTop;
export default {
components: {
BackArrow,
'uv-popup': () => import('@/uni_modules/uv-popup/components/uv-popup/uv-popup.vue')
},
data() {
return {
isFullScreen: false,
lastTap: 0,
showPopup: false,
popupShown: false, //
showCatalog: false,
orderAsc: true,
currentIndex: 0,
chapterList: [
{ id: 1, title: '第一章 重回2004', vip: false },
{ id: 2, title: '第二章 陈年旧恨', vip: false },
{ id: 3, title: '第三章 再相见', vip: false },
{ id: 4, title: '第四章 李东的邀请', vip: false },
{ id: 5, title: '第五章 小气的男', vip: false },
{ id: 6, title: '第六章 先送谁?', vip: false },
{ id: 7, title: '第七章 打听行情', vip: false },
{ id: 8, title: '第八章 省城探路', vip: false },
{ id: 9, title: '第九章 订货', vip: false },
{ id: 10, title: '第十章 第一桶金', vip: true },
{ id: 11, title: '第十一章 高富帅来袭', vip: true },
{ id: 12, title: '第十二章 故学后,挥场见!', vip: true },
{ id: 13, title: '第十三章 你来我往', vip: true },
{ id: 14, title: '第十四章 你来我往', vip: true },
{ id: 15, title: '第十五章 你来我往', vip: true },
{ id: 16, title: '第十六章 你来我往', vip: true },
{ id: 17, title: '第十七章 你来我往', vip: true },
{ id: 18, title: '第十八章 你来我往', vip: true },
],
showPayPopup: false
}
},
computed: {
displayList() {
return this.orderAsc ? this.chapterList : [...this.chapterList].reverse()
}
},
methods: {
handleContentClick() {
this.toggleFullScreen();
},
handleTouchEnd(e) {
this.toggleFullScreen();
},
handleScroll(e) {
//
const scrollTop = e.detail.scrollTop;
console.log('scrollTop:', scrollTop);
// 50
if (scrollTop > 50 && !this.popupShown) {
this.showPopup = true;
this.popupShown = true;
}
},
toggleFullScreen() {
this.isFullScreen = !this.isFullScreen
},
reverseOrder() {
this.orderAsc = !this.orderAsc
},
selectChapter(idx) {
this.currentIndex = this.orderAsc ? idx : this.chapterList.length - 1 - idx
this.showCatalog = false
// TODO:
},
goToSubscription() {
uni.navigateTo({
url: '/pages_order/novel/SubscriptionInformation'
})
}
},
mounted() {
// #ifdef H5
if (typeof window !== 'undefined') {
window.onscroll = () => {
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
if (scrollTop > 50 && !this.popupShown) {
this.showPopup = true;
this.popupShown = true;
}
};
}
// #endif
},
beforeDestroy() {
// #ifdef H5
if (typeof window !== 'undefined') {
window.onscroll = null;
}
// #endif
},
onLoad(options) {
// idid
// this.novelId = options.id
}
}
//
if (scrollTop > 50 && !this.popupShown) {
this.showPopup = true;
this.popupShown = true;
}
},
toggleFullScreen() {
this.isFullScreen = !this.isFullScreen
},
goToSubscription() {
uni.navigateTo({
url: '/pages_order/novel/SubscriptionInformation'
})
}
},
mounted() {
//
this.isFullScreen = true;
// #ifdef H5
if (typeof window !== 'undefined') {
window.onscroll = () => {
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
if (scrollTop > 50 && !this.popupShown) {
this.showPopup = true;
this.popupShown = true;
}
};
}
// #endif
},
beforeDestroy() {
// #ifdef H5
if (typeof window !== 'undefined') {
window.onscroll = null;
}
// #endif
},
onLoad() {
// idid
}
}
</script>
<style lang="scss" scoped>
.reader-container {
min-height: 100vh;
background: #fff;
display: flex;
flex-direction: column;
}
.chapter-title {
font-size: 32rpx;
font-weight: bold;
margin: 40rpx 32rpx 24rpx 32rpx;
}
.chapter-content {
flex: 1;
padding: 0 32rpx;
font-size: 28rpx;
color: #222;
line-height: 2.2;
margin-bottom: 120rpx;
}
.bottom-bar {
position: fixed;
left: 0;
right: 0;
bottom: 0;
background: #fff;
display: flex;
justify-content: center;
align-items: center;
height: 180rpx;
box-shadow: 0 -2rpx 10rpx rgba(0,0,0,0.05);
z-index: 10;
padding: 0 40rpx 10rpx 40rpx;
}
.bottom-left {
display: flex;
align-items: flex-end;
gap: 48rpx;
}
.bar-item {
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-end;
}
.bar-icon {
width: 48rpx;
height: 48rpx;
margin-bottom: 4rpx;
margin-right: 1rpx;
}
.bar-label {
font-size: 22rpx;
color: #b3b3b3;
margin-top: 2rpx;
}
.bottom-right {
display: flex;
align-items: flex-end;
gap: 32rpx;
margin-left: 40rpx;
}
.outline-btn {
min-width: 110rpx;
padding: 0 28rpx;
height: 60rpx;
line-height: 60rpx;
background: #fff;
color: #223a7a;
border: 2rpx solid #223a7a;
border-radius: 32rpx;
font-size: 28rpx;
font-weight: bold;
margin: 0;
display: flex;
align-items: center;
justify-content: center;
}
.btn-text {
font-weight: bold;
color: #223a7a;
font-size: 28rpx;
border-bottom: 2rpx solid #223a7a;
padding-bottom: 2rpx;
}
.catalog-popup-fullscreen {
position: fixed;
left: 0;
top: 0;
width: 100vw;
height: 100vh;
background: #fff;
z-index: 9999;
border-top-left-radius: 32rpx;
border-top-right-radius: 32rpx;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
display: flex;
flex-direction: column;
box-shadow: 0 8rpx 48rpx rgba(0,0,0,0.18);
overflow: hidden;
}
.catalog-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 24rpx;
height: 96rpx;
border-bottom: 1px solid #eee;
position: sticky;
top: 0;
background: #fff;
z-index: 2;
}
.header-left {
width: 60rpx;
display: flex;
align-items: center;
justify-content: flex-start;
}
.header-title {
flex: 1;
text-align: center;
font-size: 32rpx;
font-weight: bold;
color: #222;
}
.header-right {
color: #223a7a;
font-size: 28rpx;
font-weight: 500;
min-width: 80rpx;
text-align: right;
}
.catalog-list {
flex: 1;
overflow: auto;
padding-bottom: 40rpx;
}
.catalog-item {
padding: 0 32rpx;
min-height: 80rpx;
display: flex;
flex-direction: column;
justify-content: center;
border-bottom: 1px solid #f5f5f5;
background: #fff;
color: #222;
font-size: 30rpx;
position: relative;
}
.catalog-item.active {
color: #ff5a5f;
background: #fff7f7;
}
.item-main {
display: flex;
align-items: center;
gap: 16rpx;
}
.item-title {
font-size: 30rpx;
}
.vip-tag {
background: #ffe1b2;
color: #ff9900;
border-radius: 20rpx;
font-size: 24rpx;
padding: 2rpx 18rpx;
margin-left: 16rpx;
}
.pay-popup-mask {
position: fixed;
left: 0; top: 0; right: 0; bottom: 0;
background: rgba(0,0,0,0.5);
z-index: 10000;
}
.pay-popup {
position: absolute;
left: 0;
right: 0;
bottom: 0;
background: #232323;
border-top-left-radius: 24rpx;
border-top-right-radius: 24rpx;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
min-width: 500rpx;
width: 100%;
padding: 48rpx 32rpx 32rpx 32rpx;
text-align: center;
color: #fff;
}
.pay-title {
font-size: 32rpx;
font-weight: bold;
color: #fff;
margin-bottom: 24rpx;
margin-right: 50rpx;
}
.pay-desc {
font-size: 26rpx;
color: #999;
margin-bottom: 40rpx;
margin-right: 50rpx;
}
.pay-btns {
display: flex;
justify-content: center;
gap: 24rpx;
margin-right: 50rpx;
.reader-container {
min-height: 100vh;
background: #fff;
display: flex;
flex-direction: column;
position: relative;
overflow: hidden;
.top-controls {
position: fixed;
top: 0;
left: 0;
right: 0;
background: rgba(255, 255, 255, 0.98);
padding-top: calc(var(--status-bar-height) + 10rpx);
z-index: 100;
transform: translateY(0);
transition: transform 0.3s ease-in-out, opacity 0.3s ease-in-out;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
.controls-inner {
display: flex;
align-items: center;
justify-content: space-between;
padding: 20rpx 32rpx;
position: relative;
.left {
width: 100rpx;
display: flex;
justify-content: flex-start;
align-items: center;
}
.center {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.title {
font-size: 32rpx;
font-weight: 500;
color: #333;
margin-bottom: 4rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 320rpx;
}
.chapter {
font-size: 24rpx;
color: #666;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 320rpx;
}
}
.right {
width: 100rpx;
display: flex;
justify-content: flex-end;
align-items: center;
}
}
.progress-bar {
height: 4rpx;
background: #f0f0f0;
width: 100%;
position: relative;
.progress-inner {
height: 100%;
background: #4a90e2;
transition: width 0.3s;
}
}
&.top-controls-hidden {
transform: translateY(-100%);
opacity: 0;
}
}
.chapter-content {
flex: 1;
padding: 0 32rpx;
font-size: 28rpx;
color: #222;
line-height: 2.2;
padding-top: 160rpx; /* 为导航栏预留空间,不随状态变化 */
padding-bottom: 180rpx;
width: 100%;
box-sizing: border-box;
overflow-x: hidden;
.chapter-content-item {
width: 100%;
.chapter-title {
font-size: 36rpx;
font-weight: bold;
margin: 20rpx 0 40rpx 0;
text-align: center;
word-break: break-word;
white-space: normal;
}
.paragraph-content {
width: 100%;
.paragraph {
text-indent: 2em;
margin-bottom: 30rpx;
line-height: 1.8;
font-size: 30rpx;
color: #333;
word-wrap: break-word;
word-break: normal;
white-space: normal;
}
}
}
&.full-content {
/* 不再修改顶部padding,保持内容位置不变 */
}
}
.bottom-bar {
position: fixed;
left: 0;
right: 0;
bottom: 0;
background: #fff;
display: flex;
justify-content: center;
align-items: center;
height: 180rpx;
box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);
z-index: 10;
padding: 0 40rpx 10rpx 40rpx;
transform: translateY(0);
transition: transform 0.3s ease-in-out;
&.bottom-bar-hidden {
transform: translateY(100%);
}
.bottom-left {
display: flex;
align-items: flex-end;
gap: 48rpx;
.bar-item {
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-end;
.bar-icon {
width: 48rpx;
height: 48rpx;
margin-bottom: 4rpx;
margin-right: 1rpx;
}
.bar-label {
font-size: 22rpx;
color: #b3b3b3;
margin-top: 2rpx;
}
}
}
.bottom-right {
display: flex;
align-items: flex-end;
gap: 32rpx;
margin-left: 40rpx;
.outline-btn {
min-width: 110rpx;
padding: 0 28rpx;
height: 60rpx;
line-height: 60rpx;
background: #fff;
color: #223a7a;
border: 2rpx solid #223a7a;
border-radius: 32rpx;
font-size: 28rpx;
font-weight: bold;
margin: 0;
display: flex;
align-items: center;
justify-content: center;
.btn-text {
font-weight: bold;
color: #223a7a;
font-size: 28rpx;
border-bottom: 2rpx solid #223a7a;
padding-bottom: 2rpx;
}
}
}
}
}
}
.pay-btn {
background: #ff9800;
color: #fff;
border-radius: 32rpx;
font-size: 28rpx;
padding: 0 32rpx;
border: none;
}
.pay-btn-video {
background: #ff9800;
color: #fff;
border-radius: 32rpx;
font-size: 28rpx;
padding: 0 32rpx;
border: none;
}
.pay-btn-batch {
background: #ff9800;
color: #fff;
border-radius: 32rpx;
font-size: 28rpx;
padding: 0 32rpx;
border: none;
}
</style>
.pay-popup-mask {
position: fixed;
left: 0;
top: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 10000;
.pay-popup {
position: absolute;
left: 0;
right: 0;
bottom: 0;
background: #232323;
border-top-left-radius: 24rpx;
border-top-right-radius: 24rpx;
min-width: 500rpx;
width: 100%;
padding: 48rpx 32rpx 32rpx 32rpx;
text-align: center;
color: #fff;
box-sizing: border-box;
.pay-title {
font-size: 32rpx;
font-weight: bold;
color: #fff;
margin-bottom: 24rpx;
margin-right: 50rpx;
word-wrap: break-word;
white-space: normal;
}
.pay-desc {
font-size: 26rpx;
color: #999;
margin-bottom: 40rpx;
margin-right: 50rpx;
word-wrap: break-word;
white-space: normal;
}
.pay-btns {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 24rpx;
margin-right: 50rpx;
.pay-btn {
background: #ff9800;
color: #fff;
border-radius: 32rpx;
font-size: 28rpx;
padding: 0 32rpx;
border: none;
margin-bottom: 16rpx;
word-break: keep-all;
&.pay-btn-video,
&.pay-btn-batch {
background: #ff9800;
color: #fff;
border-radius: 32rpx;
font-size: 28rpx;
padding: 0 32rpx;
border: none;
}
}
}
}
}
</style>

BIN
pages_order/static/book/bd.png View File

Before After
Width: 183  |  Height: 58  |  Size: 17 KiB Width: 244  |  Height: 77  |  Size: 31 KiB

BIN
pages_order/static/book/dj.png View File

Before After
Width: 64  |  Height: 64  |  Size: 12 KiB

BIN
pages_order/static/book/level.png View File

Before After
Width: 32  |  Height: 32  |  Size: 2.4 KiB

BIN
static/image/home/notice.png View File

Before After
Width: 57  |  Height: 56  |  Size: 4.8 KiB

BIN
static/image/tabbar/bookshelf-a.png View File

Before After
Width: 47  |  Height: 46  |  Size: 1.6 KiB Width: 93  |  Height: 92  |  Size: 4.2 KiB

BIN
static/image/tabbar/bookshelf.png View File

Before After
Width: 29  |  Height: 28  |  Size: 644 B Width: 57  |  Height: 56  |  Size: 1.0 KiB

BIN
static/image/tabbar/category-a.png View File

Before After
Width: 47  |  Height: 46  |  Size: 1.6 KiB Width: 93  |  Height: 92  |  Size: 4.2 KiB

BIN
static/image/tabbar/category.png View File

Before After
Width: 29  |  Height: 28  |  Size: 475 B Width: 57  |  Height: 56  |  Size: 730 B

BIN
static/image/tabbar/center-a.png View File

Before After
Width: 47  |  Height: 46  |  Size: 2.0 KiB Width: 93  |  Height: 92  |  Size: 4.9 KiB

BIN
static/image/tabbar/center.png View File

Before After
Width: 29  |  Height: 28  |  Size: 945 B Width: 57  |  Height: 56  |  Size: 1.7 KiB

BIN
static/image/tabbar/home-a.png View File

Before After
Width: 47  |  Height: 46  |  Size: 1.6 KiB Width: 93  |  Height: 92  |  Size: 4.2 KiB

BIN
static/image/tabbar/home.png View File

Before After
Width: 47  |  Height: 43  |  Size: 2.2 KiB Width: 57  |  Height: 56  |  Size: 703 B

Loading…
Cancel
Save