| <template> | |
|   <view class="directory-container"> | |
|     <view class="book-container"> | |
|       <view class="book-info"> | |
|       <view class="book-cover"> | |
|         <image :src="bookInfo.booksImg" mode="aspectFill" :style="{width: '100%', height: '100%'}"></image> | |
|       </view> | |
|       <view class="book-details"> | |
|         <view class="book-title">{{ bookInfo.translate }}</view> | |
|         <view class="book-subtitle">{{ bookInfo.booksName }}</view> | |
|         <view class="book-author">{{ bookInfo.booksAuthor }}</view> | |
|         <view class="book-level" :class="classMap[bookInfo.vipInfo.title]">{{ bookInfo.vipInfo.title }}</view> | |
|       </view> | |
|       </view> | |
|       <view class="book-knowledge"> | |
|         <view class="book-knowledge-title"> | |
|           <text> | |
|             适合词汇量 | |
|           </text> | |
|           <text class="book-knowledge-vocabulary"> | |
|             {{ bookInfo.vocabularyRange }} | |
|           </text> | |
|         </view> | |
|         <view class="border" />  | |
|         <view class="book-knowledge-detail"> | |
|           <view class="book-knowledge-detail-title"> | |
|             知识收获 | |
|           </view> | |
|           <uv-parse :content="bookInfo.knowledgePoints"></uv-parse> | |
|         </view> | |
|       </view> | |
|     </view> | |
| 
 | |
|     <!-- 课程和简介容器 --> | |
|     <view class="content-container"> | |
|       <!-- 课程部分 --> | |
|       <view class="course-section"> | |
|         <view class="course-header"> | |
|           <view class="course-title">课程</view> | |
|         </view> | |
|         <view class="course-list"> | |
|           <!-- 限制在做多五個課程 --> | |
|           <view  | |
|           v-for="(course, index) in courseList.records.slice(0, 5)"  | |
|           @click="startLearning(course.id)" | |
|             :key="index" | |
|             class="course-item" | |
|           > | |
|             <view class="course-number">{{ String(index + 1).padStart(2, '0') }}</view> | |
|             <view class="course-content"> | |
|               <view class="course-name">{{ course.english }}</view> | |
|               <view class="course-subtitle">{{ course.chinese }}</view> | |
|             </view> | |
|           </view> | |
|         </view> | |
|         <view class="course-footer"> | |
|           <view class="course-total" @click="showAllCoursePopup">全部课程 · {{ courseList.total }}节</view> | |
|           <uv-icon name="arrow-right" size="24rpx" color="#999"></uv-icon> | |
|         </view> | |
|       </view> | |
|  | |
|       <!-- 简介部分 --> | |
|       <view class="intro-section"> | |
|         <view class="intro-title">简介</view> | |
|         <uv-parse :content="bookInfo.booksIntro" class="intro-content"></uv-parse> | |
|       </view> | |
|  | |
|       <!-- 作者部分 --> | |
|       <view class="author-section"> | |
|         <view class="author-title">作者</view> | |
|         <view class="author-info"> | |
|           <view class="author-avatar"> | |
|             <image :src="bookInfo.aouthorImg" mode="aspectFill"></image> | |
|             <view> | |
|               <view class="author-name">{{ bookInfo.enAuthor }}</view> | |
|               <view class="author-subtitle">{{ bookInfo.booksAuthor }}</view> | |
|             </view> | |
|           </view> | |
|           <view class="author-details"> | |
|             <view class="author-description"> | |
|               {{ bookInfo.aouthorIntro }} | |
|             </view> | |
|           </view> | |
|         </view> | |
|       </view> | |
|     </view> | |
|      | |
|     <!-- 底部固定操作栏 --> | |
|     <view class="bottom-action-bar"> | |
|       <view class="bottom-action-container"> | |
|         <view class="action-button secondary" @click="joinCourse"> | |
|           <image src="/static/课程图标.png" class="button-icon" mode="aspectFill"></image> | |
|           <text>加入课程</text> | |
|         </view> | |
|         <view class="action-button primary" @click="startLearning(courseList.records[0].id)"> | |
|           <image src="/static/内容图标.png" class="button-icon" ></image> | |
|           <text>内容朗读</text> | |
|         </view> | |
|         <uv-button @click="startLearning(courseList.records[0].id)" type="primary" :custom-style="{ | |
|           width: '400rpx', | |
|           height: '80rpx', | |
|           borderRadius: '198rpx', | |
|           background: '#06DADC', | |
|           fontSize: '28rpx', | |
|           fontWeight: '600' | |
|         }" >开始学习</uv-button> | |
|       </view> | |
|       <uv-safe-bottom></uv-safe-bottom> | |
|     </view> | |
|      | |
|     <!-- 全部課程彈出窗 --> | |
|     <uv-popup  | |
|       mode="bottom"  | |
|       ref="allCoursePopup" | |
|       round="32rpx" | |
|       bg-color="#f8f8f8" | |
|     > | |
|       <view class="course-popup"> | |
|         <view class="popup-header"> | |
|           <view> | |
|             <uv-icon name="arrow-down" color="black" size="20"></uv-icon> | |
|           </view> | |
|           <view class="popup-title">全部课程</view> | |
|           <view class="popup-title" @click="toggleCourseSort"> | |
|             倒序 | |
|           </view> | |
|         </view> | |
|         <view class="course-list"> | |
|           <view  | |
|             v-for="(course, index) in displayAllCourseList"  | |
|             :key="course.id" | |
|             class="course-item" | |
|             @click="startLearning(course.id)" | |
|           > | |
|             <view class="course-number">{{ String(course.index || index + 1).padStart(2, '0') }}</view> | |
|             <view class="course-content"> | |
|               <view class="course-english">{{ course.english }}</view> | |
|               <view class="course-chinese">{{ course.chinese }}</view> | |
|             </view> | |
|           </view> | |
|         </view> | |
|       </view> | |
|     </uv-popup> | |
|      | |
|   </view> | |
| </template> | |
|  | |
| <script> | |
| export default { | |
|   data() { | |
|     return { | |
|       classMap: { | |
|         '朵蕾会员': 'book-level-1', | |
|         '萌芽会员': 'book-level-2', | |
|         '盛放会员': 'book-level-3', | |
|       }, | |
|       bookInfo: { | |
|        | |
|       }, | |
|       id: '', | |
|       courseList: [ | |
|         | |
|       ], | |
|       allCourseList: [], // 全部課程列表 | |
|       isCourseSortReversed: false, // 課程排序是否倒序 | |
|     } | |
|   }, | |
|   computed: { | |
|     // 顯示的全部課程列表(支持倒序) | |
|     displayAllCourseList() { | |
|       const list = this.allCourseList.length > 0 ? this.allCourseList : this.courseList.records || []; | |
|       return this.isCourseSortReversed ? [...list].reverse() : list; | |
|     } | |
|   }, | |
|   methods: { | |
|     goBack() { | |
|       uni.navigateBack() | |
|     }, | |
|     // 加入课程 | |
|     async joinCourse() { | |
|       const joinRes = await this.$api.book.addStand({ | |
|         id: this.id | |
|       }) | |
|       if (joinRes.code === 200){ | |
|         uni.showToast({ | |
|           title: '加入成功', | |
|           icon: 'success', | |
|           duration: 2000 | |
|         }) | |
|       } | |
|     }, | |
|     // 开始学习 | |
|     startLearning(id) {   | |
|       // 默认学第一堂课 | |
|       uni.navigateTo({ | |
|         url: '/subPages/home/book?courseId=' + id + '&bookId=' + this.id + '&memberId=' + this.bookInfo.vip | |
|       }) | |
|     }, | |
|     // 获取书籍详情 | |
|     async getDetail() { | |
|       const detailRes = await this.$api.book.detail({ | |
|         id: this.id | |
|       }) | |
|       if (detailRes.code === 200){ | |
|         this.bookInfo = detailRes.result | |
|       } | |
|     },  | |
|     // 获取书籍的课程 | |
|     async getCourse() { | |
|       const courseRes = await this.$api.book.course({ | |
|         id: this.id, | |
|         pageNo: 1, | |
|         pageSize: 5 | |
|       }) | |
|       if (courseRes.code === 200){ | |
|         this.courseList = courseRes.result | |
|         // 同時設置全部課程列表 | |
|         this.allCourseList = courseRes.result.records || [] | |
|       } | |
|     }, | |
|      | |
|     // 顯示全部課程彈出窗 | |
|     showAllCoursePopup() { | |
|       this.$refs.allCoursePopup.open() | |
|     }, | |
|      | |
|     // 切換課程排序 | |
|     toggleCourseSort() { | |
|       this.isCourseSortReversed = !this.isCourseSortReversed | |
|     }, | |
|   }, | |
|   onLoad(options) { | |
|     if (options.id){ | |
|       this.id = options.id | |
|       Promise.all([ | |
|         this.getDetail(), | |
|         this.getCourse() | |
|       ]) | |
|     } | |
|   } | |
| } | |
| </script> | |
|  | |
| <style scoped lang="scss"> | |
| .directory-container { | |
|   min-height: 100vh; | |
|   background-color: #264C8F; | |
|    | |
| 
 | |
| } | |
| .book-container{ | |
|   position: sticky; | |
|   left: 0; | |
|   right: 0; | |
|   top: 0; | |
|   padding: 30rpx; | |
|   z-index: 1; | |
| } | |
| .book-info { | |
|   display: flex; | |
|   align-items: start; | |
|    | |
|   gap: 32rpx; | |
|   .book-cover { | |
|     width: 208rpx; | |
|     height: 292rpx; | |
|     border-radius: 16rpx; | |
|   } | |
|   .book-details{ | |
|      color: white; | |
|      display: flex; | |
|      flex-direction: column; | |
|      gap: 16rpx; | |
|     .book-title{ | |
|       font-weight: 500; | |
|       font-size: 40rpx; | |
|     } | |
|     .book-subtitle{ | |
|       font-weight: 500; | |
|       font-size: 30rpx; | |
|     } | |
|     .book-author{ | |
|       font-size: 24rpx; | |
|     } | |
|     .book-level{ | |
|       font-size: 24rpx; | |
|       width: 124rpx; | |
|       height: 38rpx; | |
|       border-radius: 8rpx; | |
|       text-align: center; | |
|       line-height: 38rpx; | |
|       color: #080D21; | |
|     } | |
|     .book-level-1{ | |
|       background: #E9F1FF; | |
|       border: 2rpx solid #C4DAFF | |
|     } | |
|     .book-level-2{ | |
|       background: #FFE9E9; | |
|       border: 2rpx solid #FFDBC4 | |
|     } | |
|     .book-level-3{ | |
|       background: #FFF4E9; | |
|       border: 2rpx solid #FFE2C4 | |
|     } | |
|   } | |
| } | |
| .book-knowledge{ | |
|   box-shadow: 0px 1px 5px 0px #103577; | |
|   background: #234684; | |
|   color: #fff; | |
|   margin-top: 32rpx; | |
|   border: 2rpx solid #FFFFFF3B; | |
|   border-radius: 32rpx; | |
|   padding-top: 32rpx; | |
|   padding-right: 40rpx; | |
|   padding-bottom: 32rpx; | |
|   padding-left: 40rpx; | |
|   gap: 24rpx; | |
|   display: flex; | |
|   flex-direction: column; | |
|   gap: 22rpx; | |
|   .book-knowledge-title{ | |
|     font-size: 32rpx; | |
|     font-weight: 600; | |
|     display: flex; | |
|     justify-content: space-between; | |
|     .book-knowledge-vocabulary{ | |
|       font-size: 40rpx; | |
|       color: #06DADC; | |
|     } | |
|   } | |
| 
 | |
|   .border { | |
|     width: 100%; | |
|     border: 2rpx solid; | |
|     border-image-source: linear-gradient(90deg, rgba(233, 181, 123, 0) 0%, rgba(255, 255, 255, 0.79) 50.48%, rgba(233, 181, 123, 0) 100%); | |
|     border-image-slice: 1; | |
|   } | |
| 
 | |
|   .book-knowledge-detail-title{ | |
|     font-size: 32rpx; | |
|     font-weight: 600; | |
|     margin-bottom: 16rpx; | |
|   } | |
| 
 | |
| } | |
| 
 | |
| /* 课程和简介容器 */ | |
| .content-container { | |
|   padding: 40rpx 32rpx 240rpx; | |
|   border-radius: 40rpx 40rpx 0 0; | |
|   overflow: hidden; | |
|   background: #fff; | |
|   display: flex; | |
|   gap: 24rpx; | |
|   flex-direction: column; | |
|   position: relative; | |
|   z-index: 9999; | |
| } | |
| 
 | |
| /* 课程部分 */ | |
| .course-section { | |
|   background: #F8F8F8; | |
|   border-radius: 32rpx; | |
|   border-radius: 32rpx; | |
|   padding-top: 36rpx; | |
|   padding-right: 32rpx; | |
|   padding-bottom: 36rpx; | |
|   padding-left: 32rpx; | |
|   gap: 36rpx; | |
|   display: flex; | |
|   flex-direction: column; | |
| } | |
| 
 | |
| 
 | |
| 
 | |
| .course-title { | |
|   font-size: 32rpx; | |
|   font-weight: 600; | |
|   color: #3B3D3D; | |
| } | |
| 
 | |
| .course-list { | |
|   // margin-bottom: 32rpx; | |
|   display: flex; | |
|   flex-direction: column; | |
|   gap: 24rpx; | |
| } | |
| 
 | |
| .course-item { | |
|   display: flex; | |
|   align-items: center; | |
|   // background: red; | |
|   border-bottom: 2rpx solid #EEEEEE; | |
|   padding-bottom: 20rpx; | |
|   gap: 36rpx; | |
| } | |
| 
 | |
| .course-item:last-child { | |
|   border-bottom: none; | |
| } | |
| 
 | |
| .course-number { | |
|   font-size: 36rpx; | |
|   color: #999; | |
|    | |
| 
 | |
| } | |
| 
 | |
| .course-content { | |
|   flex: 1; | |
| } | |
| 
 | |
| .course-name { | |
|   font-size: 32rpx; | |
|   font-weight: 600; | |
|   color: #3B3D3D; | |
|   margin-bottom: 8rpx; | |
| } | |
| 
 | |
| .course-subtitle { | |
|   font-size: 28rpx; | |
|   color: #3B3D3D; | |
| } | |
| 
 | |
| .course-footer { | |
|   display: flex; | |
|   align-items: center; | |
|   // justify-content: space-between; | |
| } | |
| 
 | |
| .course-total { | |
|   font-size: 24rpx; | |
|   color: #999; | |
|   cursor: pointer; | |
| } | |
| 
 | |
| /* 课程弹出窗样式 */ | |
| .course-popup { | |
|   padding: 0 32rpx; | |
|   max-height: 80vh; | |
| 
 | |
| 
 | |
| .popup-header { | |
|   display: flex; | |
|   justify-content: space-between; | |
|   align-items: center; | |
|   padding: 20rpx 0; | |
|   border-bottom: 2rpx solid #EEEEEE | |
|   // margin-bottom: 40rpx; | |
| } | |
| 
 | |
| .popup-title { | |
|   font-family: PingFang SC; | |
|   font-weight: 500; | |
|   font-size: 34rpx; | |
|   color: #181818; | |
| } | |
| 
 | |
| 
 | |
| .course-list { | |
|   max-height: 60vh; | |
|   overflow-y: auto; | |
| } | |
| 
 | |
| .course-item { | |
|   display: flex; | |
|   align-items: center; | |
|   gap: 24rpx; | |
|   padding-top: 24rpx; | |
|   padding-right: 8rpx; | |
|   padding-bottom: 24rpx; | |
|   padding-left: 8rpx; | |
| 
 | |
|   border-bottom: 1px solid #EEEEEE; | |
|   cursor: pointer; | |
|    | |
|   &:last-child { | |
|     border-bottom: none; | |
|   } | |
| } | |
| 
 | |
| .course-number { | |
|   width: 80rpx; | |
|   font-family: PingFang SC; | |
|   // font-weight: 400; | |
|   font-size: 36rpx; | |
|   color: #999; | |
|   &.highlight { | |
|     color: $primary-color; | |
|   } | |
|   // margin-right: 24rpx; | |
| } | |
| 
 | |
| .course-content { | |
|   flex: 1; | |
| } | |
| 
 | |
| .course-english { | |
|   font-family: PingFang SC; | |
|   font-weight: 600; | |
|   font-size: 36rpx; | |
|   line-height: 44rpx; | |
|   color: #252545; | |
|   margin-bottom: 8rpx; | |
|    | |
|   &.highlight { | |
|     color: $primary-color; | |
|   } | |
| } | |
| 
 | |
| .course-chinese { | |
|   font-size: 28rpx; | |
|   line-height: 48rpx; | |
|   color: #3B3D3D; | |
|   &.highlight { | |
|     color: $primary-color; | |
|   } | |
| } | |
| } | |
| 
 | |
| /* 简介部分 */ | |
| .intro-section { | |
|   background: #F8F8F8; | |
| 
 | |
| border-radius: 32rpx; | |
| padding: 32rpx; | |
| 
 | |
| } | |
| 
 | |
| .intro-title { | |
|   font-size: 32rpx; | |
|   font-weight: 600; | |
|   color: #3B3D3D; | |
|   margin-bottom: 24rpx; | |
| } | |
| 
 | |
| .intro-content { | |
|   font-size: 28rpx; | |
|   line-height: 48rpx; | |
|   color: #4F4F4F; | |
| } | |
| 
 | |
| /* 作者部分 */ | |
| .author-section { | |
|   background: #F8F8F8; | |
|   border-radius: 32rpx; | |
|   padding: 32rpx; | |
| 
 | |
|   .author-title { | |
|     font-size: 32rpx; | |
|     font-weight: 600; | |
|     color: #3B3D3D; | |
|     margin-bottom: 24rpx; | |
|   } | |
| 
 | |
|   .author-info { | |
|     display: flex; | |
|     gap: 24rpx; | |
|     align-items: flex-start; | |
|     flex-direction: column; | |
|     .author-avatar { | |
|        | |
|       display: flex; | |
|        | |
|       align-items: center; | |
|       gap: 16rpx; | |
|       image { | |
|         width: 80rpx; | |
|         height: 80rpx; | |
|         border-radius: 50%; | |
|         overflow: hidden; | |
|         flex-shrink: 0; | |
|         | |
|       } | |
|       .author-name { | |
|         font-size: 36rpx; | |
|         font-weight: 600; | |
|         color: #252545; | |
|         margin-bottom: 12rpx; | |
|       } | |
| 
 | |
|       .author-subtitle { | |
|         font-size: 28rpx; | |
|         color: #3B3D3D; | |
|         // margin-bottom: 16rpx; | |
|       } | |
| 
 | |
|     } | |
| 
 | |
|     .author-details { | |
|       flex: 1; | |
| 
 | |
|       | |
|       .author-description { | |
|         font-size: 28rpx; | |
|         line-height: 48rpx; | |
|         color: #4F4F4F; | |
|       } | |
|     } | |
|   } | |
| } | |
| 
 | |
| /* 底部固定操作栏 */ | |
| .bottom-action-bar { | |
|   position: fixed; | |
|   bottom: 0; | |
|   left: 0; | |
|   right: 0; | |
|   background: #fff; | |
|   padding: 24rpx 32rpx 0; | |
|   box-shadow: 0rpx -2rpx 0rpx 0rpx #0000001A; | |
|   z-index: 10000; | |
| 
 | |
|   .bottom-action-container{ | |
|     display: flex; | |
|     align-items: center; | |
|     gap: 20rpx; | |
| 
 | |
|     .action-button { | |
|       display: flex; | |
|       flex-direction: column; | |
|       align-items: center; | |
|       justify-content: center; | |
|       padding: 16rpx 0rpx; | |
|       border-radius: 16rpx; | |
|       min-width: 120rpx; | |
|       gap: 8rpx; | |
|    | |
|       .button-icon { | |
|         width: 44rpx; | |
|         height: 44rpx; | |
|       } | |
|    | |
|       text { | |
|         font-size: 24rpx; | |
|         color: #999999; | |
|       } | |
| 
 | |
|     } | |
| 
 | |
|   } | |
| } | |
| </style> |