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

570 lines
13 KiB

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