小说小程序前端代码仓库(小程序)
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.

547 lines
12 KiB

7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
  1. <template>
  2. <view class="page">
  3. <!-- 自定义导航栏 -->
  4. <view class="custom-navbar">
  5. <view class="navbar-left">
  6. <view class="calendar-icon">
  7. <uv-icon name="calendar" color="#ffffff" size="44rpx"></uv-icon>
  8. </view>
  9. </view>
  10. <view class="navbar-center" @click="toSearch">
  11. <view class="search-box">
  12. <uv-icon name="search" color="#999999" size="32rpx"></uv-icon>
  13. <text class="search-placeholder">请输入搜索内容</text>
  14. </view>
  15. </view>
  16. <view class="navbar-right">
  17. <view class="function-btn">
  18. <uv-icon name="more-dot-fill" color="#ffffff" size="44rpx"></uv-icon>
  19. </view>
  20. <view class="function-btn">
  21. <uv-icon name="chat-fill" color="#ffffff" size="44rpx"></uv-icon>
  22. </view>
  23. </view>
  24. </view>
  25. <view class="content">
  26. <!-- 顶部横幅广告 -->
  27. <view class="banner">
  28. <uv-swiper
  29. :list="bannerList"
  30. keyName="image"
  31. :autoplay="true"
  32. :circular="true"
  33. :interval="3000"
  34. radius="10"
  35. :height="400"
  36. indicatorActiveColor="#ffffff"
  37. indicatorInactiveColor="rgba(255, 255, 255, 0.5)"
  38. @click="clickBanner"
  39. >
  40. <template v-slot:default="{item}">
  41. <view class="swiper-item">
  42. <image class="swiper-image" :src="item.image" mode="aspectFill"></image>
  43. <view class="swiper-content">
  44. <view class="swiper-title">{{item.title}}</view>
  45. <view class="swiper-desc">{{item.desc}}</view>
  46. </view>
  47. </view>
  48. </template>
  49. </uv-swiper>
  50. </view>
  51. <!-- 通知区域 -->
  52. <view class="notice" @click="viewNotice">
  53. <view class="notice-left">
  54. <view class="notice-icon">
  55. <image src="/static/image/home/notice.png" mode="aspectFill"></image>
  56. </view>
  57. <view class="">
  58. 全部共告
  59. </view>
  60. </view>
  61. <view class="notice-center">
  62. <view class="notice-tag">{{noticeList.title}}</view>
  63. <view class="notice-text" @click="viewNotice">
  64. {{ noticeList.titleText }}
  65. </view>
  66. </view>
  67. <view class="notice-right">
  68. <uv-icon name="arrow-right" color="#999" size="24rpx"></uv-icon>
  69. </view>
  70. </view>
  71. <!-- 最近更新 -->
  72. <view class="section">
  73. <view class="section-header">
  74. <text class="section-title">最近更新</text>
  75. </view>
  76. <scroll-view scroll-x style="width: 100%;">
  77. <view class="recommend-list">
  78. <view class="recommend-item"
  79. @click="navigateToDetail(item.id)"
  80. v-for="(item, index) in novelList" :key="index">
  81. <novel-item horizontal :key="index" :book="item" />
  82. </view>
  83. </view>
  84. </scroll-view>
  85. </view>
  86. </view>
  87. <!-- 精品推荐 -->
  88. <view class="section1">
  89. <view class="section-header">
  90. <text class="section-title">精品推荐</text>
  91. <text class="section-more" @click="$utils.navigateTo('/pages/index/category')">查看更多 ></text>
  92. </view>
  93. <view class="novel-list">
  94. <novel-item v-for="(item, index) in list"
  95. @click="navigateToDetail(item.id)"
  96. :key="index" :book="item" />
  97. </view>
  98. </view>
  99. <PrivacyAgreementPoup />
  100. <tabber select="home" />
  101. </view>
  102. </template>
  103. <script>
  104. import PrivacyAgreementPoup from '@/components/config/PrivacyAgreementPoup.vue'
  105. import tabber from '@/components/base/tabbar.vue'
  106. import novelItem from '@/components/novel/novelItem.vue'
  107. import mixinsList from '@/mixins/list.js'
  108. export default {
  109. mixins: [mixinsList],
  110. components: {
  111. tabber,
  112. PrivacyAgreementPoup,
  113. novelItem,
  114. },
  115. data() {
  116. return {
  117. // 轮播图数据
  118. bannerList: [],
  119. // 最近更新小说列表数据
  120. novelList: [],
  121. // 公告数据
  122. noticeList: {},
  123. // 精品小说列表
  124. mixinsListApi : 'getRecommendList',
  125. }
  126. },
  127. computed: {},
  128. onShow() {
  129. this.getBanner()
  130. this.getNotice()
  131. this.getNewList()
  132. },
  133. methods: {
  134. // 跳转到搜索页面
  135. toSearch() {
  136. this.$utils.navigateTo('/pages/search/index')
  137. },
  138. // 点击轮播图
  139. clickBanner(index) {
  140. // const banner = this.bannerList[index];
  141. // console.log('点击了轮播图:', banner.title);
  142. // // 跳转到小说详情页
  143. // uni.showToast({
  144. // title: '正在前往: ' + banner.title,
  145. // icon: 'none'
  146. // })
  147. // setTimeout(() => {
  148. // this.$utils.navigateTo(`/pages_order/book/bookDetail?id=${banner.id}`)
  149. // }, 500)
  150. },
  151. // 查看公告详情
  152. viewNotice() {
  153. uni.navigateTo({
  154. url: '/pages_order/announcement/announcements'
  155. })
  156. },
  157. navigateToDetail(id) {
  158. // 跳转到小说详情页
  159. this.$utils.navigateTo(`/pages_order/novel/novelDetail?id=${id}`)
  160. },
  161. async getBanner() {
  162. const data = await this.$fetch('getBanner')
  163. this.bannerList = data
  164. },
  165. // 获取公告列表
  166. async getNotice() {
  167. const data = await this.$fetch('getNotice')
  168. this.noticeList = data
  169. },
  170. // 获取最近更新小说列表
  171. async getNewList() {
  172. const data = await this.$fetch('getNewList')
  173. this.novelList = data.records
  174. },
  175. }
  176. }
  177. </script>
  178. <style scoped lang="scss">
  179. .page {
  180. background-color: #f5f5f5;
  181. // min-height: 100vh;
  182. /* 自定义导航栏样式 */
  183. .custom-navbar {
  184. display: flex;
  185. align-items: center;
  186. justify-content: space-between;
  187. padding: 0 20rpx 20rpx 20rpx;
  188. background-color: #001351; /* 深蓝色背景 */
  189. height: 160rpx;
  190. box-sizing: border-box;
  191. position: sticky;
  192. top: 0;
  193. z-index: 99;
  194. padding-top: calc(var(--status-bar-height) + 20rpx);
  195. .navbar-left {
  196. width: 80rpx;
  197. display: flex;
  198. justify-content: center;
  199. .calendar-icon {
  200. width: 50rpx;
  201. height: 50rpx;
  202. display: flex;
  203. align-items: center;
  204. justify-content: center;
  205. }
  206. }
  207. .navbar-center {
  208. flex: 1;
  209. margin: 0 20rpx;
  210. .search-box {
  211. display: flex;
  212. align-items: center;
  213. background-color: rgba(255, 255, 255, 0.95);
  214. border-radius: 40rpx;
  215. padding: 0 30rpx;
  216. height: 70rpx;
  217. box-sizing: border-box;
  218. .search-placeholder {
  219. color: #999;
  220. font-size: 28rpx;
  221. margin-left: 16rpx;
  222. }
  223. }
  224. }
  225. .navbar-right {
  226. display: flex;
  227. align-items: center;
  228. .function-btn {
  229. margin-left: 16rpx;
  230. width: 50rpx;
  231. height: 50rpx;
  232. display: flex;
  233. justify-content: center;
  234. align-items: center;
  235. }
  236. }
  237. }
  238. .content {
  239. padding-bottom: 5rpx;
  240. }
  241. .banner {
  242. padding: 0;
  243. margin: 20rpx;
  244. border-radius: 10rpx;
  245. overflow: hidden;
  246. box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.1);
  247. transition: all 0.3s;
  248. &:active {
  249. transform: scale(0.98);
  250. }
  251. .swiper-item {
  252. position: relative;
  253. width: 100%;
  254. height: 100%;
  255. .swiper-image {
  256. width: 100%;
  257. height: 100%;
  258. border-radius: 10rpx;
  259. }
  260. .swiper-content {
  261. position: absolute;
  262. bottom: 0;
  263. left: 0;
  264. width: 100%;
  265. padding: 30rpx;
  266. background: linear-gradient(to top, rgba(0,0,0,0.8), rgba(0,0,0,0.3), transparent);
  267. border-bottom-left-radius: 10rpx;
  268. border-bottom-right-radius: 10rpx;
  269. .swiper-title {
  270. font-size: 36rpx;
  271. color: #fff;
  272. font-weight: bold;
  273. margin-bottom: 10rpx;
  274. text-shadow: 0 2rpx 4rpx rgba(0,0,0,0.5);
  275. }
  276. .swiper-desc {
  277. font-size: 28rpx;
  278. color: rgba(255,255,255,0.9);
  279. line-height: 1.4;
  280. text-shadow: 0 1rpx 3rpx rgba(0,0,0,0.5);
  281. }
  282. }
  283. }
  284. }
  285. .notice {
  286. display: flex;
  287. align-items: center;
  288. background-color: #fff;
  289. margin: 20rpx;
  290. margin-bottom: 0;
  291. padding: 20rpx;
  292. border-radius: 10rpx;
  293. box-shadow: 0 2rpx 10rpx rgba(0,0,0,0.05);
  294. transition: all 0.2s;
  295. &:active {
  296. background-color: #f9f9f9;
  297. }
  298. .notice-left {
  299. display: flex;
  300. align-items: center;
  301. margin-right: 20rpx;
  302. flex-direction: column;
  303. font-size: 22rpx;
  304. width: 90rpx;
  305. justify-content: center;
  306. .notice-icon {
  307. width: 60rpx;
  308. height: 60rpx;
  309. border-radius: 30rpx;
  310. overflow: hidden;
  311. box-shadow: 0 2rpx 6rpx rgba(0,0,0,0.1);
  312. image {
  313. width: 100%;
  314. height: 100%;
  315. }
  316. }
  317. }
  318. .notice-center {
  319. flex: 1;
  320. .notice-tag {
  321. font-size: 22rpx;
  322. color: #666;
  323. background-color: #f5f5f5;
  324. padding: 4rpx 12rpx;
  325. border-radius: 6rpx;
  326. margin-right: 10rpx;
  327. width: fit-content;
  328. margin-bottom: 10rpx;
  329. }
  330. .notice-text {
  331. font-size: 26rpx;
  332. color: #333;
  333. overflow: hidden;
  334. white-space: nowrap;
  335. text-overflow: ellipsis;
  336. }
  337. }
  338. .notice-right {
  339. margin-left: 20rpx;
  340. opacity: 0.6;
  341. }
  342. }
  343. .section {
  344. background-color: #fff;
  345. margin: 30rpx 0 0 0;
  346. padding: 10rpx 30rpx;
  347. border-radius: 0;
  348. .section-header {
  349. display: flex;
  350. justify-content: space-between;
  351. align-items: center;
  352. margin-bottom: 20rpx;
  353. .section-title {
  354. font-size: 32rpx;
  355. font-weight: bold;
  356. color: #333;
  357. }
  358. .section-more {
  359. font-size: 24rpx;
  360. color: #999;
  361. }
  362. }
  363. .novel-list {
  364. .novel-item {
  365. display: flex;
  366. padding: 20rpx 0;
  367. border-bottom: 1px solid #eee;
  368. &:last-child {
  369. border-bottom: none;
  370. }
  371. .novel-cover {
  372. width: 160rpx;
  373. height: 200rpx;
  374. border-radius: 8rpx;
  375. margin-right: 20rpx;
  376. }
  377. .novel-info {
  378. flex: 1;
  379. display: flex;
  380. flex-direction: column;
  381. justify-content: space-between;
  382. .novel-title {
  383. font-size: 28rpx;
  384. font-weight: bold;
  385. color: #333;
  386. margin-bottom: 10rpx;
  387. }
  388. .novel-desc {
  389. font-size: 24rpx;
  390. color: #999;
  391. line-height: 1.5;
  392. display: -webkit-box;
  393. -webkit-box-orient: vertical;
  394. -webkit-line-clamp: 3;
  395. overflow: hidden;
  396. }
  397. }
  398. }
  399. }
  400. .recommend-list {
  401. display: flex;
  402. .recommend-item {
  403. width: fit-content;
  404. }
  405. }
  406. }
  407. .section1 {
  408. background-color: #fff;
  409. margin: 0rpx 0 0 0;
  410. padding: 20rpx 30rpx;
  411. border-radius: 0;
  412. .section-header {
  413. display: flex;
  414. justify-content: space-between;
  415. align-items: center;
  416. margin-bottom: 20rpx;
  417. .section-title {
  418. font-size: 32rpx;
  419. font-weight: bold;
  420. color: #333;
  421. }
  422. .section-more {
  423. font-size: 24rpx;
  424. color: #999;
  425. }
  426. }
  427. .novel-list {
  428. .novel-item {
  429. display: flex;
  430. padding: 20rpx 0;
  431. border-bottom: 1px solid #eee;
  432. &:last-child {
  433. border-bottom: none;
  434. }
  435. .novel-cover {
  436. width: 160rpx;
  437. height: 200rpx;
  438. border-radius: 8rpx;
  439. margin-right: 20rpx;
  440. }
  441. .novel-info {
  442. flex: 1;
  443. display: flex;
  444. flex-direction: column;
  445. justify-content: space-between;
  446. .novel-title {
  447. font-size: 28rpx;
  448. font-weight: bold;
  449. color: #333;
  450. margin-bottom: 10rpx;
  451. }
  452. .novel-desc {
  453. font-size: 24rpx;
  454. color: #999;
  455. line-height: 1.5;
  456. display: -webkit-box;
  457. -webkit-box-orient: vertical;
  458. -webkit-line-clamp: 3;
  459. overflow: hidden;
  460. }
  461. }
  462. }
  463. }
  464. .recommend-list {
  465. display: flex;
  466. flex-wrap: wrap;
  467. justify-content: space-between;
  468. .recommend-item {
  469. width: 30%;
  470. margin-bottom: 20rpx;
  471. .recommend-cover {
  472. width: 100%;
  473. height: 200rpx;
  474. border-radius: 8rpx;
  475. margin-bottom: 10rpx;
  476. }
  477. .recommend-title {
  478. font-size: 24rpx;
  479. color: #333;
  480. overflow: hidden;
  481. white-space: nowrap;
  482. text-overflow: ellipsis;
  483. }
  484. }
  485. }
  486. }
  487. }
  488. </style>