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

578 lines
13 KiB

3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 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">通讯</view>
  63. <view class="notice-text" @click="viewNotice">
  64. 2025年2月平台福利活动截稿作品公示
  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 novelList"
  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 {
  108. mapGetters
  109. } from 'vuex'
  110. export default {
  111. components: {
  112. tabber,
  113. PrivacyAgreementPoup,
  114. novelItem,
  115. },
  116. data() {
  117. return {
  118. // 轮播图数据
  119. bannerList: [
  120. {
  121. id: '3',
  122. image: 'https://img95.699pic.com/photo/50055/5909.jpg_wh300.jpg',
  123. title: '我有一座妖怪城',
  124. desc: '妖怪横行,一座神秘古城,藏着千年秘密'
  125. }
  126. ],
  127. // 小说列表数据
  128. novelList: [
  129. {
  130. id: '1',
  131. title: '我是半妖',
  132. cover: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain',
  133. author: '东方不败',
  134. desc: '都市玄幻小说,主角获得半妖化能力,通过吸收妖气不断变强...',
  135. tags: ['玄幻', '都市', '热血'],
  136. status: '连载中'
  137. },
  138. {
  139. id: '2',
  140. title: '兽王进化',
  141. cover: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain',
  142. author: '天下霸唱',
  143. desc: '一场意外让主角获得兽王血脉,开始了进化之路...',
  144. tags: ['奇幻', '冒险'],
  145. status: '连载中'
  146. },
  147. {
  148. id: '3',
  149. title: '魔法少女纯爷们',
  150. cover: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain',
  151. author: '南派三叔',
  152. desc: '一个普通男孩意外获得魔法少女的力量,开始了奇妙冒险...',
  153. tags: ['搞笑', '奇幻'],
  154. status: '已完结'
  155. },
  156. {
  157. id: '4',
  158. title: '我是一条小青龙',
  159. cover: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain',
  160. author: '辰东',
  161. desc: '重生为一条小青龙,主角在修仙世界中成长的故事...',
  162. tags: ['仙侠', '修真'],
  163. status: '连载中'
  164. },
  165. {
  166. id: '5',
  167. title: '女帝归来',
  168. cover: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.iUyxJ_fxLjjX3kEBjteXWwAAAA?rs=1&pid=ImgDetMain',
  169. author: '猫腻',
  170. desc: '曾经的女帝重生归来,开始了复仇之路...',
  171. tags: ['古代', '女强'],
  172. status: '连载中'
  173. }
  174. ]
  175. }
  176. },
  177. computed: {},
  178. methods: {
  179. // 跳转到搜索页面
  180. toSearch() {
  181. this.$utils.navigateTo('/pages/search/index')
  182. },
  183. // 点击轮播图
  184. clickBanner(index) {
  185. // const banner = this.bannerList[index];
  186. // console.log('点击了轮播图:', banner.title);
  187. // // 跳转到小说详情页
  188. // uni.showToast({
  189. // title: '正在前往: ' + banner.title,
  190. // icon: 'none'
  191. // })
  192. // setTimeout(() => {
  193. // this.$utils.navigateTo(`/pages_order/book/bookDetail?id=${banner.id}`)
  194. // }, 500)
  195. },
  196. // 查看公告详情
  197. viewNotice() {
  198. uni.navigateTo({
  199. url: '/pages_order/announcement/announcements'
  200. })
  201. },
  202. navigateToDetail(id) {
  203. // 跳转到小说详情页
  204. this.$utils.navigateTo(`/pages_order/novel/novelDetail?id=${id}`)
  205. },
  206. }
  207. }
  208. </script>
  209. <style scoped lang="scss">
  210. .page {
  211. background-color: #f5f5f5;
  212. // min-height: 100vh;
  213. /* 自定义导航栏样式 */
  214. .custom-navbar {
  215. display: flex;
  216. align-items: center;
  217. justify-content: space-between;
  218. padding: 0 20rpx 20rpx 20rpx;
  219. background-color: #001351; /* 深蓝色背景 */
  220. height: 160rpx;
  221. box-sizing: border-box;
  222. position: sticky;
  223. top: 0;
  224. z-index: 99;
  225. padding-top: calc(var(--status-bar-height) + 20rpx);
  226. .navbar-left {
  227. width: 80rpx;
  228. display: flex;
  229. justify-content: center;
  230. .calendar-icon {
  231. width: 50rpx;
  232. height: 50rpx;
  233. display: flex;
  234. align-items: center;
  235. justify-content: center;
  236. }
  237. }
  238. .navbar-center {
  239. flex: 1;
  240. margin: 0 20rpx;
  241. .search-box {
  242. display: flex;
  243. align-items: center;
  244. background-color: rgba(255, 255, 255, 0.95);
  245. border-radius: 40rpx;
  246. padding: 0 30rpx;
  247. height: 70rpx;
  248. box-sizing: border-box;
  249. .search-placeholder {
  250. color: #999;
  251. font-size: 28rpx;
  252. margin-left: 16rpx;
  253. }
  254. }
  255. }
  256. .navbar-right {
  257. display: flex;
  258. align-items: center;
  259. .function-btn {
  260. margin-left: 16rpx;
  261. width: 50rpx;
  262. height: 50rpx;
  263. display: flex;
  264. justify-content: center;
  265. align-items: center;
  266. }
  267. }
  268. }
  269. .content {
  270. padding-bottom: 5rpx;
  271. }
  272. .banner {
  273. padding: 0;
  274. margin: 20rpx;
  275. border-radius: 10rpx;
  276. overflow: hidden;
  277. box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.1);
  278. transition: all 0.3s;
  279. &:active {
  280. transform: scale(0.98);
  281. }
  282. .swiper-item {
  283. position: relative;
  284. width: 100%;
  285. height: 100%;
  286. .swiper-image {
  287. width: 100%;
  288. height: 100%;
  289. border-radius: 10rpx;
  290. }
  291. .swiper-content {
  292. position: absolute;
  293. bottom: 0;
  294. left: 0;
  295. width: 100%;
  296. padding: 30rpx;
  297. background: linear-gradient(to top, rgba(0,0,0,0.8), rgba(0,0,0,0.3), transparent);
  298. border-bottom-left-radius: 10rpx;
  299. border-bottom-right-radius: 10rpx;
  300. .swiper-title {
  301. font-size: 36rpx;
  302. color: #fff;
  303. font-weight: bold;
  304. margin-bottom: 10rpx;
  305. text-shadow: 0 2rpx 4rpx rgba(0,0,0,0.5);
  306. }
  307. .swiper-desc {
  308. font-size: 28rpx;
  309. color: rgba(255,255,255,0.9);
  310. line-height: 1.4;
  311. text-shadow: 0 1rpx 3rpx rgba(0,0,0,0.5);
  312. }
  313. }
  314. }
  315. }
  316. .notice {
  317. display: flex;
  318. align-items: center;
  319. background-color: #fff;
  320. margin: 20rpx;
  321. margin-bottom: 0;
  322. padding: 20rpx;
  323. border-radius: 10rpx;
  324. box-shadow: 0 2rpx 10rpx rgba(0,0,0,0.05);
  325. transition: all 0.2s;
  326. &:active {
  327. background-color: #f9f9f9;
  328. }
  329. .notice-left {
  330. display: flex;
  331. align-items: center;
  332. margin-right: 20rpx;
  333. flex-direction: column;
  334. font-size: 22rpx;
  335. width: 90rpx;
  336. justify-content: center;
  337. .notice-icon {
  338. width: 60rpx;
  339. height: 60rpx;
  340. border-radius: 30rpx;
  341. overflow: hidden;
  342. box-shadow: 0 2rpx 6rpx rgba(0,0,0,0.1);
  343. image {
  344. width: 100%;
  345. height: 100%;
  346. }
  347. }
  348. }
  349. .notice-center {
  350. flex: 1;
  351. .notice-tag {
  352. font-size: 22rpx;
  353. color: #666;
  354. background-color: #f5f5f5;
  355. padding: 4rpx 12rpx;
  356. border-radius: 6rpx;
  357. margin-right: 10rpx;
  358. width: fit-content;
  359. margin-bottom: 10rpx;
  360. }
  361. .notice-text {
  362. font-size: 26rpx;
  363. color: #333;
  364. overflow: hidden;
  365. white-space: nowrap;
  366. text-overflow: ellipsis;
  367. }
  368. }
  369. .notice-right {
  370. margin-left: 20rpx;
  371. opacity: 0.6;
  372. }
  373. }
  374. .section {
  375. background-color: #fff;
  376. margin: 30rpx 0 0 0;
  377. padding: 10rpx 30rpx;
  378. border-radius: 0;
  379. .section-header {
  380. display: flex;
  381. justify-content: space-between;
  382. align-items: center;
  383. margin-bottom: 20rpx;
  384. .section-title {
  385. font-size: 32rpx;
  386. font-weight: bold;
  387. color: #333;
  388. }
  389. .section-more {
  390. font-size: 24rpx;
  391. color: #999;
  392. }
  393. }
  394. .novel-list {
  395. .novel-item {
  396. display: flex;
  397. padding: 20rpx 0;
  398. border-bottom: 1px solid #eee;
  399. &:last-child {
  400. border-bottom: none;
  401. }
  402. .novel-cover {
  403. width: 160rpx;
  404. height: 200rpx;
  405. border-radius: 8rpx;
  406. margin-right: 20rpx;
  407. }
  408. .novel-info {
  409. flex: 1;
  410. display: flex;
  411. flex-direction: column;
  412. justify-content: space-between;
  413. .novel-title {
  414. font-size: 28rpx;
  415. font-weight: bold;
  416. color: #333;
  417. margin-bottom: 10rpx;
  418. }
  419. .novel-desc {
  420. font-size: 24rpx;
  421. color: #999;
  422. line-height: 1.5;
  423. display: -webkit-box;
  424. -webkit-box-orient: vertical;
  425. -webkit-line-clamp: 3;
  426. overflow: hidden;
  427. }
  428. }
  429. }
  430. }
  431. .recommend-list {
  432. display: flex;
  433. .recommend-item {
  434. width: fit-content;
  435. }
  436. }
  437. }
  438. .section1 {
  439. background-color: #fff;
  440. margin: 0rpx 0 0 0;
  441. padding: 20rpx 30rpx;
  442. border-radius: 0;
  443. .section-header {
  444. display: flex;
  445. justify-content: space-between;
  446. align-items: center;
  447. margin-bottom: 20rpx;
  448. .section-title {
  449. font-size: 32rpx;
  450. font-weight: bold;
  451. color: #333;
  452. }
  453. .section-more {
  454. font-size: 24rpx;
  455. color: #999;
  456. }
  457. }
  458. .novel-list {
  459. .novel-item {
  460. display: flex;
  461. padding: 20rpx 0;
  462. border-bottom: 1px solid #eee;
  463. &:last-child {
  464. border-bottom: none;
  465. }
  466. .novel-cover {
  467. width: 160rpx;
  468. height: 200rpx;
  469. border-radius: 8rpx;
  470. margin-right: 20rpx;
  471. }
  472. .novel-info {
  473. flex: 1;
  474. display: flex;
  475. flex-direction: column;
  476. justify-content: space-between;
  477. .novel-title {
  478. font-size: 28rpx;
  479. font-weight: bold;
  480. color: #333;
  481. margin-bottom: 10rpx;
  482. }
  483. .novel-desc {
  484. font-size: 24rpx;
  485. color: #999;
  486. line-height: 1.5;
  487. display: -webkit-box;
  488. -webkit-box-orient: vertical;
  489. -webkit-line-clamp: 3;
  490. overflow: hidden;
  491. }
  492. }
  493. }
  494. }
  495. .recommend-list {
  496. display: flex;
  497. flex-wrap: wrap;
  498. justify-content: space-between;
  499. .recommend-item {
  500. width: 30%;
  501. margin-bottom: 20rpx;
  502. .recommend-cover {
  503. width: 100%;
  504. height: 200rpx;
  505. border-radius: 8rpx;
  506. margin-bottom: 10rpx;
  507. }
  508. .recommend-title {
  509. font-size: 24rpx;
  510. color: #333;
  511. overflow: hidden;
  512. white-space: nowrap;
  513. text-overflow: ellipsis;
  514. }
  515. }
  516. }
  517. }
  518. }
  519. </style>