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

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