index.vue 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. <template>
  2. <view class="live-container">
  3. <image class="live-bg" src="/static/home_top_bg.png" mode="aspectFill"></image>
  4. <!-- 顶部导航栏 -->
  5. <view class="custom-navbar" :style="{ paddingTop: statusBarHeight + 'px' }">
  6. <view class="navbar-content">
  7. <text class="page-title">精选课程</text>
  8. <view class="search-box">
  9. <image class="search-icon" src="/static/icon_search_org.png" mode="aspectFit"></image>
  10. <input class="search-input" type="text" placeholder="搜索课程" placeholder-class="search-placeholder" />
  11. <button class="search-btn">搜索</button>
  12. </view>
  13. </view>
  14. </view>
  15. <!-- 分类标签栏 - 悬浮在导航栏下方 -->
  16. <view class="category-tabs-wrap" :style="{ top: (statusBarHeight + 44) + 'px' }">
  17. <scroll-view scroll-x class="category-tabs">
  18. <view class="tab-item" :class="{ active: activeCategory === index }" v-for="(category, index) in categories" :key="index" @click="selectCategory(index)">
  19. <text>{{ category }}</text>
  20. </view>
  21. </scroll-view>
  22. </view>
  23. <!-- 页面内容区域 - 可滚动 -->
  24. <scroll-view scroll-y class="page-content-scroll" :style="{ paddingTop: (statusBarHeight +88) + 'px' }">
  25. <!-- 课程列表 -->
  26. <view class="course-list">
  27. <view class="course-card-horizontal" v-for="(item, index) in courses" :key="index" @click="goCourseDetail(item.id)">
  28. <view class="course-cover-wrap">
  29. <image class="course-cover" :src="item.imgUrl || '/static/course_img.png'" mode="aspectFill"></image>
  30. <view class="tag-yangsheng" v-if="item.tag">{{ item.tag }}</view>
  31. </view>
  32. <view class="course-content">
  33. <view class="course-title ellipsis-1">{{ item.title }}</view>
  34. <view class="course-tags">
  35. <text class="tag-orange" v-if="item.tag">{{ item.tag }}</text>
  36. <text class="meta-text">{{ item.playCount }}次播放</text>
  37. <text class="meta-text">|</text>
  38. <text class="meta-text">{{ item.likes }}人喜欢</text>
  39. </view>
  40. <view class="course-footer">
  41. <view class="author-box">
  42. <image class="author-avatar" :src="item.authorAvatar || '/static/avatar.png'" mode="aspectFill"></image>
  43. <text class="author-name">{{ item.authorName }}</text>
  44. </view>
  45. <view class="study-btn-orange">立即学习</view>
  46. </view>
  47. </view>
  48. </view>
  49. </view>
  50. <!-- 底部安全区占位 -->
  51. <view class="bottom-safe-area"></view>
  52. </scroll-view>
  53. </view>
  54. </template>
  55. <script>
  56. export default {
  57. data() {
  58. return {
  59. statusBarHeight: uni.getSystemInfoSync().statusBarHeight,
  60. categories: ['全部', '养生', '饮食', '运动', '心理', '国学', '乐器'],
  61. activeCategory: 0,
  62. courses: [{
  63. id: 1,
  64. title: '中医基础理论与养生智慧',
  65. tag: '养生',
  66. playCount: '2468',
  67. likes: '900',
  68. authorName: '李医生',
  69. authorAvatar: '/static/avatar.png',
  70. imgUrl: '/static/famous_doctor_img.png'
  71. }, {
  72. id: 2,
  73. title: '上班族 30 分钟每日养生计划',
  74. tag: '养生',
  75. playCount: '2468',
  76. likes: '900',
  77. authorName: '李医生',
  78. authorAvatar: '/static/avatar.png',
  79. imgUrl: '/static/famous_doctor_img2.png'
  80. }, {
  81. id: 3,
  82. title: '马年四季养生课:跟着节气养生',
  83. tag: '养生',
  84. playCount: '2468',
  85. likes: '900',
  86. authorName: '李医生',
  87. authorAvatar: '/static/avatar.png',
  88. imgUrl: '/static/course_img.png'
  89. }, {
  90. id: 4,
  91. title: '科学膳食与慢性病管理',
  92. tag: '健康',
  93. playCount: '2468',
  94. likes: '900',
  95. authorName: '张教授',
  96. authorAvatar: '/static/avatar.png',
  97. imgUrl: '/static/famous_doctor_img.png'
  98. }, {
  99. id: 5,
  100. title: '乐器入门:古筝基础教程',
  101. tag: '艺术',
  102. playCount: '2468',
  103. likes: '900',
  104. authorName: '王老师',
  105. authorAvatar: '/static/avatar.png',
  106. imgUrl: '/static/famous_doctor_img2.png'
  107. }]
  108. };
  109. },
  110. methods: {
  111. selectCategory(index) {
  112. this.activeCategory = index;
  113. },
  114. goCourseDetail(id) {
  115. uni.navigateTo({
  116. url: '/pages_course/learn?courseId=' + id
  117. });
  118. }
  119. }
  120. }
  121. </script>
  122. <style lang="scss" scoped>
  123. .live-container {
  124. min-height: 100vh;
  125. background-color: #F8F8F8;
  126. position: relative;
  127. .live-bg {
  128. position: absolute;
  129. top: 0;
  130. left: 0;
  131. width: 100%;
  132. height: 380rpx;
  133. z-index: 0;
  134. }
  135. }
  136. .custom-navbar {
  137. position: fixed;
  138. top: 0;
  139. left: 0;
  140. width: 100%;
  141. z-index: 100;
  142. .navbar-content {
  143. height: 44px;
  144. display: flex;
  145. align-items: center;
  146. padding: 0 30rpx;
  147. .page-title {
  148. font-size: 36rpx;
  149. font-weight: bold;
  150. color: #333333;
  151. }
  152. .search-box {
  153. display: flex;
  154. align-items: center;
  155. background-color: #ffffff;
  156. padding: 8rpx 8rpx 8rpx 24rpx;
  157. width: 324rpx;
  158. margin-left: 30rpx;
  159. border-radius: 36rpx;
  160. border: 2rpx solid #F5723A;
  161. .search-icon {
  162. width: 32rpx;
  163. height: 32rpx;
  164. margin-right: 10rpx;
  165. }
  166. .search-input {
  167. flex: 1;
  168. font-size: 26rpx;
  169. color: #333333;
  170. height: 100%;
  171. }
  172. .search-placeholder {
  173. color: #999999;
  174. }
  175. .search-btn {
  176. background: linear-gradient(180deg, #FFA33B 0%, #F5723A 100%);
  177. border-radius: 58rpx;
  178. color: #FFFFFF;
  179. font-size: 24rpx;
  180. padding: 12rpx 24rpx;
  181. line-height: 1;
  182. height: auto;
  183. border: none;
  184. margin: 0;
  185. &::after {
  186. border: none;
  187. }
  188. }
  189. }
  190. }
  191. }
  192. .category-tabs-wrap {
  193. position: fixed;
  194. left: 0;
  195. width: 100%;
  196. z-index: 99;
  197. padding: 20rpx 0;
  198. .category-tabs {
  199. white-space: nowrap;
  200. padding: 0 30rpx;
  201. .tab-item {
  202. display: inline-block;
  203. margin-right: 68rpx;
  204. font-size: 30rpx;
  205. color: #666666;
  206. position: relative;
  207. padding-bottom: 10rpx;
  208. &.active {
  209. color: #333333;
  210. font-weight: bold;
  211. &::after {
  212. content: '';
  213. position: absolute;
  214. bottom: 0;
  215. left: 50%;
  216. transform: translateX(-50%);
  217. width: 40rpx;
  218. height: 6rpx;
  219. background-color: #F5723A;
  220. border-radius: 3rpx;
  221. }
  222. }
  223. }
  224. }
  225. }
  226. .page-content-scroll {
  227. height: 100vh;
  228. box-sizing: border-box;
  229. .course-list {
  230. padding: 20rpx 24rpx;
  231. .course-card-horizontal {
  232. display: flex;
  233. background-color: #FFFFFF;
  234. border-radius: 20rpx;
  235. margin-bottom: 24rpx;
  236. padding: 24rpx;
  237. .course-cover-wrap {
  238. position: relative;
  239. width: 220rpx;
  240. height: 160rpx;
  241. margin-right: 24rpx;
  242. flex-shrink: 0;
  243. .course-cover {
  244. width: 100%;
  245. height: 100%;
  246. border-radius: 16rpx;
  247. }
  248. .tag-yangsheng {
  249. position: absolute;
  250. top: 0;
  251. left: 0;
  252. background: rgba(0,0,0,0.4);
  253. color: #FFFFFF;
  254. font-size: 20rpx;
  255. padding: 4rpx 12rpx;
  256. border-top-left-radius: 16rpx;
  257. border-bottom-right-radius: 16rpx;
  258. }
  259. }
  260. .course-content {
  261. flex: 1;
  262. display: flex;
  263. flex-direction: column;
  264. justify-content: space-between;
  265. .course-title {
  266. font-size: 30rpx;
  267. font-weight: bold;
  268. color: #333333;
  269. }
  270. .course-tags {
  271. display: flex;
  272. align-items: center;
  273. margin-top: 8rpx;
  274. .tag-orange {
  275. background: #FFF1E8;
  276. color: #F8792B;
  277. font-size: 22rpx;
  278. padding: 2rpx 12rpx;
  279. border-radius: 8rpx;
  280. margin-right: 16rpx;
  281. }
  282. .meta-text {
  283. font-size: 24rpx;
  284. color: #999999;
  285. margin-right: 12rpx;
  286. }
  287. }
  288. .course-footer {
  289. display: flex;
  290. justify-content: space-between;
  291. align-items: center;
  292. margin-top: 10rpx;
  293. .author-box {
  294. display: flex;
  295. align-items: center;
  296. .author-avatar {
  297. width: 40rpx;
  298. height: 40rpx;
  299. border-radius: 50%;
  300. margin-right: 12rpx;
  301. }
  302. .author-name {
  303. font-size: 24rpx;
  304. color: #666666;
  305. }
  306. }
  307. .study-btn-orange {
  308. background: linear-gradient(180deg, #FFA33B 0%, #F5723A 100%);
  309. color: #FFFFFF;
  310. font-size: 24rpx;
  311. padding: 10rpx 24rpx;
  312. border-radius: 86rpx;
  313. }
  314. }
  315. }
  316. }
  317. }
  318. }
  319. .bottom-safe-area {
  320. height: 40rpx;
  321. padding-bottom: env(safe-area-inset-bottom);
  322. }
  323. .ellipsis-1 {
  324. overflow: hidden;
  325. text-overflow: ellipsis;
  326. white-space: nowrap;
  327. }
  328. </style>