四零语境前端代码仓库
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.

671 lines
16 KiB

1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
  1. <template>
  2. <view class="home-container">
  3. <!-- 状态栏安全区域 -->
  4. <uv-status-bar></uv-status-bar>
  5. <!-- 顶部搜索栏 -->
  6. <view class="header">
  7. <view class="search-container" @click="goSearch">
  8. <uv-search
  9. placeholder="请输入要查询的内容"
  10. :show-action="false"
  11. shape="round"
  12. bg-color="#f5f5f5"
  13. color="#666"
  14. height="38"
  15. margin="0 200rpx 0 0"
  16. placeholderColor="#c6c6c6"
  17. ></uv-search>
  18. </view>
  19. </view>
  20. <!-- Tab栏 -->
  21. <view class="tab-container">
  22. <scroll-view show-scrollbar="false" class="tab-scroll" scroll-x="true" >
  23. <view class="tab-list">
  24. <view
  25. v-for="(tab, index) in tabs"
  26. :key="index"
  27. class="tab-item"
  28. :class="{ active: activeTab === index }"
  29. @click="switchTab(index)"
  30. >
  31. {{ tab }}
  32. </view>
  33. </view>
  34. </scroll-view>
  35. </view>
  36. <!-- 轮播图 -->
  37. <view class="swiper-container">
  38. <uv-swiper
  39. :list="bannerList"
  40. keyName="image"
  41. height="121"
  42. radius="12"
  43. indicator
  44. ndicatorInactiveColor="#fff"
  45. :loading="false"
  46. indicatorMode="dot"
  47. indicatorActiveColor="#F95A01"
  48. @click="onBannerClick"
  49. ></uv-swiper>
  50. </view>
  51. <!-- 今日更新 -->
  52. <view class="section">
  53. <view class="section-header">
  54. <text class="section-title">今日更新</text>
  55. <view class="section-more">
  56. <text>更多</text>
  57. <uv-icon name="arrow-right" size="14" color="#888"></uv-icon>
  58. </view>
  59. </view>
  60. <scroll-view show-scrollbar="false" class="content-scroll" scroll-x="true" >
  61. <view class="content-list">
  62. <view
  63. v-for="(item, index) in todayUpdates"
  64. :key="index"
  65. class="content-item"
  66. >
  67. <view class="item-cover">
  68. <image :src="item.cover" mode="aspectFill"></image>
  69. </view>
  70. <view class="item-info">
  71. <text class="item-title">{{ item.title }}</text>
  72. <text class="item-author">{{ item.author }}</text>
  73. <view class="item-duration"><image src="/static/播放图标.png" class="item-icon" /><text>{{ item.duration }}</text></view>
  74. </view>
  75. </view>
  76. </view>
  77. </scroll-view>
  78. </view>
  79. <!-- 推荐书籍 -->
  80. <view class="section">
  81. <view class="section-header">
  82. <text class="section-title">推荐书籍</text>
  83. <view class="section-more">
  84. <text>更多</text>
  85. <uv-icon name="arrow-right" size="14" color="#999"></uv-icon>
  86. </view>
  87. </view>
  88. <scroll-view show-scrollbar="false" class="content-scroll" scroll-x="true" >
  89. <view class="book-list">
  90. <view
  91. v-for="(book, index) in recommendBooks"
  92. :key="index"
  93. class="book-item"
  94. @click="goBook"
  95. >
  96. <view class="book-cover">
  97. <image :src="book.cover" mode="aspectFill"></image>
  98. <!-- <view class="book-duration">
  99. <uv-icon name="time" size="10" color="#fff"></uv-icon>
  100. <text>{{ book.duration }}</text>
  101. </view> -->
  102. <view class="book-overlay">
  103. <view class="book-duration">
  104. <image src="/static/闹钟图标.png" class="book-duration-icon" />
  105. <text class="book-duration-text">{{ book.duration }}</text>
  106. </view>
  107. <view class="book-title">{{ book.title }}</view>
  108. </view>
  109. </view>
  110. </view>
  111. </view>
  112. </scroll-view>
  113. </view>
  114. <!-- 四级精讲短文合集书 -->
  115. <view class="section">
  116. <view class="section-header">
  117. <text class="section-title">四级精讲短文合集书</text>
  118. <view class="section-more">
  119. <text>更多</text>
  120. <uv-icon name="arrow-right" size="14" color="#999"></uv-icon>
  121. </view>
  122. </view>
  123. <view class="book-grid">
  124. <view
  125. v-for="(book, index) in bookGridList"
  126. :key="index"
  127. class="book-grid-item"
  128. >
  129. <view class="book-grid-cover">
  130. <image :src="book.cover" mode="aspectFill"></image>
  131. </view>
  132. <view class="book-grid-info">
  133. <text class="book-grid-title">{{ book.title }}</text>
  134. <view class="book-grid-meta">
  135. <text class="book-grid-grade">{{ book.grade }}/</text>
  136. <image src="/static/播放图标.png" class="book-grid-duration-icon" />
  137. <text class="book-grid-duration">{{ book.duration }}</text>
  138. </view>
  139. </view>
  140. </view>
  141. </view>
  142. </view>
  143. <!-- 推荐内容列表 -->
  144. <view class="section">
  145. <view class="recommend-list">
  146. <view
  147. @click="goPlan(item.id, item.type)"
  148. v-for="(item, index) in recommendList"
  149. :key="index"
  150. class="recommend-item"
  151. >
  152. <image :src="item.img" mode="aspectFill" class="recommend-image"></image>
  153. </view>
  154. </view>
  155. </view>
  156. </view>
  157. </template>
  158. <script>
  159. export default {
  160. data() {
  161. return {
  162. // Tab数据
  163. tabs: ['为你推荐', '精选', '短文', '专栏', '初中', '四六级'],
  164. activeTab: 0,
  165. // 轮播图数据
  166. bannerList: [
  167. ],
  168. // 今日更新数据
  169. todayUpdates: [
  170. {
  171. cover: '/static/默认图片.png',
  172. title: '全脑孩子:12项革命性策略...',
  173. author: 'Daniel J. Siegel / Tina Payne Bryso...',
  174. duration: '03:24'
  175. },
  176. {
  177. cover: '/static/默认图片.png',
  178. title: '全脑孩子:12项革命性策略...',
  179. author: 'Daniel J. Siegel / Tina Payne Bryso...',
  180. duration: '03:24'
  181. },
  182. {
  183. cover: '/static/默认图片.png',
  184. title: '全脑孩子:12项革命性策略...',
  185. author: 'Daniel J. Siegel / Tina Payne Bryso...',
  186. duration: '03:24'
  187. },
  188. {
  189. cover: '/static/默认图片.png',
  190. title: '全脑孩子:12项革命性策略...',
  191. author: 'Daniel J. Siegel / Tina Payne Bryso...',
  192. duration: '03:24'
  193. },
  194. ],
  195. // 推荐书籍数据
  196. recommendBooks: [
  197. {
  198. cover: '/static/默认图片.png',
  199. title: 'The Power of Now 擦拭才:The Power of Now :The Power of Now :',
  200. duration: '03:24'
  201. },
  202. {
  203. cover: '/static/默认图片.png',
  204. title: 'Dealing in Desire 擦擦:The Power of Now :The Power of Now :',
  205. duration: '03:24'
  206. },
  207. {
  208. cover: '/static/默认图片.png',
  209. title: 'A New Earth擦超2 :The Power of Now :The Power of Now :',
  210. duration: '03:24'
  211. }
  212. ],
  213. // 书籍网格数据
  214. bookGridList: [
  215. {
  216. cover: '/static/默认图片.png',
  217. title: '精讲短文',
  218. grade: '四级',
  219. duration: '03:24'
  220. },
  221. {
  222. cover: '/static/默认图片.png',
  223. title: '精讲短文',
  224. grade: '四级',
  225. duration: '03:24'
  226. },
  227. {
  228. cover: '/static/默认图片.png',
  229. title: '精讲短文',
  230. grade: '四级',
  231. duration: '03:24'
  232. },
  233. {
  234. cover: '/static/默认图片.png',
  235. title: '精讲短文',
  236. grade: '四级',
  237. duration: '03:24'
  238. },
  239. {
  240. cover: '/static/默认图片.png',
  241. title: '精讲短文',
  242. grade: '四级',
  243. duration: '03:24'
  244. },
  245. {
  246. cover: '/static/默认图片.png',
  247. title: '精讲短文',
  248. grade: '四级',
  249. duration: '03:24'
  250. }
  251. ],
  252. // 推荐列表数据
  253. recommendList: [
  254. ]
  255. }
  256. },
  257. methods: {
  258. // 切换Tab
  259. switchTab(index) {
  260. this.activeTab = index
  261. },
  262. // 轮播图点击事件
  263. onBannerClick(index) {
  264. console.log('点击轮播图:', index)
  265. // 这里可以添加跳转逻辑
  266. },
  267. // 跳转计划定制
  268. goPlan(id, type) {
  269. uni.navigateTo({
  270. url: '/subPages/home/plan?id=' + id + '&type=' + type
  271. })
  272. },
  273. goSearch() {
  274. uni.navigateTo({
  275. url: '/subPages/home/search'
  276. })
  277. },
  278. goBook() {
  279. uni.navigateTo({
  280. url: '/subPages/home/directory'
  281. })
  282. },
  283. async getBanner() {
  284. const bannerRes = await this.$api.home.getBanner()
  285. if (bannerRes.code === 200){
  286. this.bannerList = bannerRes.result.map(item => ({
  287. image: item.img,
  288. title: item.title
  289. }))
  290. }
  291. },
  292. async getSignup() {
  293. const signupRes = await this.$api.home.getLink()
  294. if (signupRes.code === 200){
  295. this.recommendList = signupRes.result.map(item => ({
  296. img: item.img,
  297. id: item.id,
  298. type: item.type
  299. }))
  300. }
  301. }
  302. },
  303. async onShow() {
  304. Promise.all([this.getBanner(), this.getSignup()])
  305. }
  306. }
  307. </script>
  308. <style lang="scss" scoped>
  309. .home-container {
  310. background: #fff;
  311. min-height: 100vh;
  312. padding-bottom: 80rpx;
  313. }
  314. // 顶部搜索栏
  315. .header {
  316. display: flex;
  317. align-items: center;
  318. padding: 6rpx 32rpx;
  319. background: #fff;
  320. .search-container {
  321. flex: 1;
  322. }
  323. }
  324. // Tab栏
  325. .tab-container {
  326. background: #fff;
  327. // border-bottom: 1px solid #f0f0f0;
  328. top: 0;
  329. left: 0;
  330. right: 0;
  331. z-index: 999;
  332. .tab-scroll {
  333. white-space: nowrap;
  334. .tab-list {
  335. display: flex;
  336. padding: 0 20rpx;
  337. .tab-item {
  338. flex-shrink: 0;
  339. padding: 20rpx 20rpx;
  340. font-size: 32rpx;
  341. color: #666;
  342. position: relative;
  343. &.active {
  344. color: $primary-text-color;
  345. font-weight: 700;
  346. &::after {
  347. content: '';
  348. position: absolute;
  349. bottom: 0;
  350. left: 50%;
  351. transform: translateX(-50%);
  352. width: 22rpx;
  353. height: 4rpx;
  354. background: $primary-text-color;
  355. border-radius: 2rpx;
  356. }
  357. }
  358. }
  359. }
  360. }
  361. }
  362. // 轮播图容器
  363. .swiper-container {
  364. margin: 20rpx;
  365. border-radius: 12rpx;
  366. overflow: hidden;
  367. }
  368. // 内容区块
  369. .section {
  370. margin-top: 40rpx;
  371. .section-header {
  372. display: flex;
  373. align-items: center;
  374. justify-content: space-between;
  375. padding: 0 30rpx ;
  376. margin-bottom: 24rpx;
  377. .section-title {
  378. font-size: 36rpx;
  379. // font-weight: 600;
  380. color: $primary-text-color;
  381. }
  382. .section-more {
  383. display: flex;
  384. align-items: center;
  385. gap: 4rpx;
  386. text {
  387. font-size: 24rpx;
  388. color: $secondary-text-color;
  389. }
  390. }
  391. }
  392. .content-scroll {
  393. white-space: nowrap;
  394. }
  395. }
  396. // 今日更新列表
  397. .content-list {
  398. display: flex;
  399. padding: 0 30rpx;
  400. gap: 32rpx;
  401. .content-item {
  402. flex-shrink: 0;
  403. width: 602rpx;
  404. height: 212rpx;
  405. display: flex;
  406. align-items: center;
  407. background: #F8F8F8;
  408. padding: 16rpx;
  409. border-radius: 16rpx;
  410. gap: 16rpx;
  411. .item-cover {
  412. width: 136rpx;
  413. height: 200rpx;
  414. border-radius: 16rpx;
  415. // overflow: hidden;
  416. image {
  417. width: 136rpx;
  418. height: 200rpx;
  419. }
  420. }
  421. .item-info {
  422. // padding-top: 20rpx;
  423. gap: 16rpx;
  424. display: flex;
  425. flex-direction: column;
  426. .item-title {
  427. font-size: 32rpx;
  428. font-weight: 700;
  429. color: $primary-text-color;
  430. letter-spacing: 0;
  431. line-height: 48rpx;
  432. // margin-bottom: 12rpx;
  433. overflow: hidden;
  434. text-overflow: ellipsis;
  435. white-space: nowrap;
  436. }
  437. .item-author {
  438. font-size: 24rpx;
  439. color: $secondary-text-color;
  440. // margin-bottom: 8rpx;
  441. letter-spacing: 0;
  442. overflow: hidden;
  443. text-overflow: ellipsis;
  444. white-space: nowrap;
  445. }
  446. .item-duration {
  447. gap: 12rpx;
  448. display: flex;
  449. align-items: center;
  450. font-size: 22rpx;
  451. letter-spacing: 0;
  452. color: $secondary-text-color;
  453. .item-icon{
  454. width: 22rpx;
  455. height: 25rpx;
  456. }
  457. }
  458. }
  459. }
  460. }
  461. // 推荐书籍列表
  462. .book-list {
  463. display: flex;
  464. padding: 0 30rpx;
  465. gap: 32rpx;
  466. .book-item {
  467. flex-shrink: 0;
  468. width: 270rpx;
  469. // border-radius: 16rpx;
  470. .book-cover {
  471. width: 100%;
  472. height: 360rpx;
  473. border-radius: 16rpx;
  474. overflow: hidden;
  475. position: relative;
  476. image {
  477. width: 100%;
  478. height: 100%;
  479. }
  480. .book-overlay {
  481. position: absolute;
  482. bottom: 0;
  483. left: 0;
  484. right: 0;
  485. width: 100%;
  486. height: 140rpx;
  487. padding-top: 4rpx;
  488. padding-right: 16rpx;
  489. padding-bottom: 8rpx;
  490. padding-left: 16rpx;
  491. backdrop-filter: blur(5px);
  492. box-sizing: border-box;
  493. background: #00000066;
  494. padding: 20rpx 16rpx 8rpx;
  495. // gap: 26rpx;
  496. .book-duration{
  497. display: flex;
  498. gap: 8rpx;
  499. &-icon{
  500. width: 24rpx;
  501. height: 24rpx;
  502. }
  503. &-text{
  504. font-size: 20rpx;
  505. color: #DCDCDC;
  506. }
  507. }
  508. .book-title {
  509. margin-top: 10rpx;
  510. max-width: 220rpx;
  511. font-size: 24rpx;
  512. line-height: 1.4;
  513. color: #fff;
  514. // max-height: 68rpx; /* = line-height * 2(34rpx * 2)作为保险 */
  515. display: -webkit-box;
  516. -webkit-box-orient: vertical;
  517. -webkit-line-clamp: 2; /* 关键:显示两行,超过两行才省略 */
  518. overflow: hidden;
  519. word-break: break-word; /* 长单词也能断行 */
  520. white-space: normal; /* 允许换行 */
  521. }
  522. }
  523. }
  524. }
  525. }
  526. // 书籍网格布局
  527. .book-grid {
  528. display: flex;
  529. flex-wrap: wrap;
  530. padding: 0 30rpx;
  531. gap: 32rpx;
  532. .book-grid-item {
  533. width: 208rpx;
  534. display: flex;
  535. flex-direction: column;
  536. .book-grid-cover {
  537. box-shadow: 0px 4px 4px 0px #C0BCBA75;
  538. width: 100%;
  539. height: 278rpx;
  540. border-radius: 16rpx;
  541. overflow: hidden;
  542. margin-bottom: 16rpx;
  543. image {
  544. width: 100%;
  545. height: 100%;
  546. }
  547. }
  548. .book-grid-info {
  549. padding: 6rpx;
  550. .book-grid-title {
  551. font-size: 28rpx;
  552. font-weight: 700;
  553. color: $primary-text-color;
  554. margin-bottom: 14rpx;
  555. overflow: hidden;
  556. text-overflow: ellipsis;
  557. white-space: nowrap;
  558. }
  559. .book-grid-meta {
  560. display: flex;
  561. align-items: center;
  562. // gap: 16rpx;
  563. .book-grid-duration-icon {
  564. width: 24rpx;
  565. height: 24rpx;
  566. margin-right: 12rpx;
  567. }
  568. .book-grid-grade {
  569. font-size: 24rpx;
  570. color: $secondary-text-color;
  571. margin-right: 8rpx;
  572. }
  573. .book-grid-duration {
  574. font-size: 24rpx;
  575. color: $secondary-text-color;
  576. }
  577. }
  578. }
  579. }
  580. }
  581. // 推荐列表样式
  582. .recommend-list {
  583. padding: 0 30rpx;
  584. .recommend-item {
  585. width: 100%;
  586. height: 200rpx;
  587. margin-bottom: 48rpx;
  588. border-radius: 32rpx;
  589. overflow: hidden;
  590. &:last-child {
  591. margin-bottom: 0;
  592. }
  593. .recommend-image {
  594. width: 100%;
  595. height: 100%;
  596. }
  597. }
  598. }
  599. </style>