四零语境前端代码仓库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

403 lines
9.7 KiB

  1. <template>
  2. <view class="book-container">
  3. <!-- 自定义顶部导航栏 -->
  4. <uv-status-bar></uv-status-bar>
  5. <view class="custom-navbar" :class="{ 'navbar-hidden': !showNavbar }">
  6. <uv-status-bar></uv-status-bar>
  7. <view class="navbar-content">
  8. <view class="navbar-left" @click="goBack">
  9. <uv-icon name="arrow-left" size="20" color="#262626"></uv-icon>
  10. </view>
  11. <view class="navbar-title">{{ bookTitle }}</view>
  12. <view class="navbar-right" @click="showMenu">
  13. <uv-icon name="more-dot-fill" size="20" color="#262626"></uv-icon>
  14. </view>
  15. </view>
  16. </view>
  17. <!-- Swiper内容区域 -->
  18. <swiper
  19. class="content-swiper"
  20. :current="currentPage - 1"
  21. @change="onSwiperChange"
  22. >
  23. <swiper-item
  24. v-for="(page, index) in bookPages"
  25. :key="index"
  26. class="swiper-item"
  27. >
  28. <view class="content-area" @click="toggleNavbar">
  29. <!-- 图片卡片页面 -->
  30. <view v-if="page.type === 'card'" class="card-content">
  31. <view class="card-line">
  32. <image src="/static/划重点图标.png" class="card-line-image" mode="aspectFill" />
  33. <text class="card-line-text">划线重点</text>
  34. </view>
  35. <image class="card-image" :src="page.image" mode="aspectFill"></image>
  36. <text class="english-text">{{ page.englishText }}</text>
  37. <text class="chinese-text">{{ page.chineseText }}</text>
  38. </view>
  39. <!-- 文本页面 -->
  40. <view v-else-if="page.type === 'text'" class="text-content">
  41. <text class="content-text">{{ page.content }}</text>
  42. </view>
  43. <!-- 视频页面 -->
  44. <view v-else-if="page.type === 'video'" class="video-content">
  45. <video :src="page.video" class="video-player" controls></video>
  46. </view>
  47. </view>
  48. </swiper-item>
  49. </swiper>
  50. <!-- 自定义底部控制栏 -->
  51. <view class="custom-tabbar" :class="{ 'tabbar-hidden': !showNavbar }">
  52. <view class="tabbar-content">
  53. <view class="tabbar-left">
  54. <view class="tab-button" @click="toggleSound">
  55. <image src="/static/课程图标.png" class="tab-icon" />
  56. <text class="tab-text">课程</text>
  57. </view>
  58. <view class="tab-button" @click="toggleSound">
  59. <image src="/static/音色切换图标.png" class="tab-icon" />
  60. <text class="tab-text">音色切换</text>
  61. </view>
  62. </view>
  63. <view class="tabbar-right">
  64. <view class="page-controls">
  65. <view class="page-numbers">
  66. <view
  67. v-for="(page, index) in bookPages"
  68. :key="index"
  69. class="page-number"
  70. :class="{ 'active': (index + 1) === currentPage }"
  71. @click="goToPage(index + 1)"
  72. >
  73. {{ index + 1 }}
  74. </view>
  75. </view>
  76. </view>
  77. </view>
  78. </view>
  79. <uv-safe-bottom></uv-safe-bottom>
  80. </view>
  81. </view>
  82. </template>
  83. <script>
  84. export default {
  85. data() {
  86. return {
  87. showNavbar: true,
  88. currentPage: 1,
  89. bookTitle: '看,乔治!',
  90. bookPages: [
  91. {
  92. type: 'card',
  93. englishText: 'I ought to have judged by deeds and not by words.',
  94. chineseText: '要对一个人下定论,不应听其言,而应观其行。',
  95. image: '/static/画重点图片.png'
  96. },
  97. {
  98. type: 'video',
  99. video: 'https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/2minute-demo.mp4'
  100. },
  101. {
  102. type: 'text',
  103. content: '索菲达以南几英里处,萨利和斯坦对着近旁河岸的斜坡流淌,水深且绿意盎然。水也很温暖,因为它在阳光下闪烁着,清澈黄色的沙子,才到达深深的池塘。河的一侧,金色的山丘斜坡向上蜿蜒,通往坚固多岩石的加比亚山脉,但在山谷一侧,水边排列着树木——柳树在春天新鲜而翠绿,它们的低垂接触处充满着各天的冰水残留物;还有枫树,它们现实的,白色的横枝条和树枝;吉他也是绿色的地塘,在河下游的河岸上,叶子能发出很大的啪啪声。傍晚时分,兔子们从灌木中出现,坐在沙子上,湖泊的平地上覆盖着沉重的夜晚迹,还有来自农场的狗的散布的垫子,以及前来暗黑中饮水的鹿的分裂形足迹。'
  104. },
  105. {
  106. type: 'text',
  107. content: '有一条穿过柳树和榆树之间的路,这条路从农场下来的男孩们踏得又硬又深;他们来深池游泳,也被那些上游运送货物公路上下来的流浪汉使得又硬又深。他们在水边停歇,在一棵巨大的榆树低垂的水平树枝前,有一个由许多火堆形成的灰烬堆,核桃被坐在上面的人留下光滑。'
  108. }
  109. ]
  110. }
  111. },
  112. methods: {
  113. toggleNavbar() {
  114. this.showNavbar = !this.showNavbar
  115. },
  116. goBack() {
  117. uni.navigateBack()
  118. },
  119. showMenu() {
  120. console.log('显示菜单')
  121. },
  122. toggleSound() {
  123. console.log('音色切换')
  124. },
  125. goToPage(page) {
  126. this.currentPage = page
  127. console.log('跳转到页面:', page)
  128. },
  129. onSwiperChange(e) {
  130. this.currentPage = e.detail.current + 1
  131. }
  132. }
  133. }
  134. </script>
  135. <style lang="scss" scoped>
  136. .book-container {
  137. width: 100%;
  138. height: 100vh;
  139. background-color: #F8F8F8;
  140. position: relative;
  141. overflow: hidden;
  142. }
  143. .custom-navbar {
  144. position: fixed;
  145. top: 0;
  146. left: 0;
  147. right: 0;
  148. background-color: #F8F8F8;
  149. z-index: 1000;
  150. transition: transform 0.3s ease;
  151. &.navbar-hidden {
  152. transform: translateY(-100%);
  153. }
  154. }
  155. .navbar-content {
  156. display: flex;
  157. align-items: center;
  158. justify-content: space-between;
  159. padding: 20rpx 32rpx;
  160. // padding-top: calc(20rpx + var(--status-bar-height, 0));
  161. height: 60rpx;
  162. }
  163. .navbar-left,
  164. .navbar-right {
  165. width: 80rpx;
  166. display: flex;
  167. align-items: center;
  168. }
  169. .navbar-right {
  170. justify-content: flex-end;
  171. }
  172. .navbar-title {
  173. flex: 1;
  174. text-align: center;
  175. font-family: PingFang SC;
  176. font-weight: 500;
  177. font-size: 32rpx;
  178. color: #262626;
  179. line-height: 48rpx;
  180. }
  181. .content-swiper {
  182. flex: 1;
  183. height: calc(100vh - 200rpx);
  184. margin-top: 100rpx;
  185. margin-bottom: 100rpx;
  186. }
  187. .swiper-item {
  188. height: 100%;
  189. }
  190. .content-area {
  191. flex: 1;
  192. padding: 0 40rpx;
  193. // background: linear-gradient(180deg, #DEFFFF 0%, #FBFEFF 22.65%, #F0FBFF 100%);
  194. height: 100%;
  195. box-sizing: border-box;
  196. overflow-y: auto;
  197. }
  198. .card-content {
  199. background: linear-gradient(180deg, #DEFFFF 0%, #FBFEFF 22.65%, #F0FBFF 100%);
  200. display: flex;
  201. flex-direction: column;
  202. gap: 32rpx;
  203. height: 1172rpx;
  204. margin-top: 20rpx;
  205. border-radius: 32rpx;
  206. // height: 100%;
  207. padding: 40rpx;
  208. // margin: 0
  209. border: 1px solid #FFFFFF;
  210. box-sizing: border-box;
  211. .card-line {
  212. display: flex;
  213. align-items: center;
  214. // margin-bottom: 20rpx;
  215. }
  216. .card-line-image {
  217. width: 48rpx;
  218. height: 48rpx;
  219. margin-right: 16rpx;
  220. }
  221. .card-line-text {
  222. font-family: PingFang SC;
  223. font-weight: 600;
  224. font-size: 30rpx;
  225. line-height: 48rpx;
  226. color: #3B3D3D;
  227. }
  228. .card-image {
  229. width: 590rpx;
  230. height: 268rpx;
  231. border-radius: 24rpx;
  232. // margin-bottom: 20rpx;
  233. }
  234. .english-text {
  235. display: block;
  236. font-family: PingFang SC;
  237. font-weight: 600;
  238. font-size: 32rpx;
  239. line-height: 48rpx;
  240. color: #3B3D3D;
  241. // margin-bottom: 16rpx;
  242. }
  243. .chinese-text {
  244. display: block;
  245. font-family: PingFang SC;
  246. // font-weight: 400;
  247. font-size: 28rpx;
  248. line-height: 48rpx;
  249. color: #4F4F4F;
  250. }
  251. }
  252. .video-content {
  253. width: 100vw;
  254. margin: 200rpx -40rpx 0;
  255. height: 500rpx;
  256. background-color: #FFFFFF;
  257. padding: 40rpx;
  258. border-radius: 24rpx;
  259. display: flex;
  260. align-items: center;
  261. justify-content: center;
  262. }
  263. .text-content {
  264. width: 100vw;
  265. background-color: #F6F6F6;
  266. height: 100%;
  267. padding: 40rpx;
  268. margin: -40rpx;
  269. box-sizing: border-box;
  270. }
  271. .content-text {
  272. font-family: PingFang SC;
  273. // font-weight: 400;
  274. font-size: 28rpx;
  275. color: #3B3D3D;
  276. line-height: 48rpx;
  277. letter-spacing: 0;
  278. text-align: justify;
  279. word-break: break-all;
  280. }
  281. .custom-tabbar {
  282. position: fixed;
  283. bottom: 0;
  284. left: 0;
  285. right: 0;
  286. background-color: #fff;
  287. border-top: 1rpx solid #EEEEEE;
  288. z-index: 1000;
  289. transition: transform 0.3s ease;
  290. &.tabbar-hidden {
  291. transform: translateY(100%);
  292. }
  293. }
  294. .tabbar-content {
  295. display: flex;
  296. align-items: center;
  297. justify-content: space-between;
  298. padding: 24rpx 62rpx;
  299. // padding-bottom: calc(24rpx + env(safe-area-inset-bottom));
  300. height: 88rpx;
  301. }
  302. .tabbar-left {
  303. display: flex;
  304. align-items: center;
  305. gap: 35rpx;
  306. }
  307. .tab-button {
  308. display: flex;
  309. align-items: center;
  310. flex-direction: column;
  311. gap: 8rpx;
  312. }
  313. .tab-icon {
  314. width: 52rpx;
  315. height: 52rpx;
  316. }
  317. .tab-text {
  318. font-family: PingFang SC;
  319. // font-weight: 400;
  320. font-size: 22rpx;
  321. color: #999;
  322. line-height: 24rpx;
  323. }
  324. .tabbar-right {
  325. flex: 1;
  326. display: flex;
  327. justify-content: flex-end;
  328. }
  329. .page-controls {
  330. display: flex;
  331. align-items: center;
  332. }
  333. .page-numbers {
  334. display: flex;
  335. align-items: center;
  336. gap: 8rpx;
  337. overflow-x: auto;
  338. max-width: 400rpx;
  339. &::-webkit-scrollbar {
  340. display: none;
  341. }
  342. }
  343. .page-number {
  344. min-width: 84rpx;
  345. height: 58rpx;
  346. display: flex;
  347. align-items: center;
  348. justify-content: center;
  349. border-radius: 100rpx;
  350. font-family: PingFang SC;
  351. // font-weight: 400;
  352. font-size: 30rpx;
  353. color: #3B3D3D;
  354. background-color: transparent;
  355. border: 1px solid #3B3D3D;
  356. transition: all 0.3s ease;
  357. &.active {
  358. border: 1px solid $primary-color;
  359. color: $primary-color;
  360. }
  361. }
  362. </style>