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

548 lines
12 KiB

6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 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. if(banner.appPath){
  137. uni.navigateTo({
  138. url: banner.appPath
  139. })
  140. }
  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 30rpx 20rpx;
  188. padding-top: calc(var(--status-bar-height) + 50rpx);
  189. background-color: #001351; /* 深蓝色背景 */
  190. box-sizing: border-box;
  191. position: sticky;
  192. top: 0;
  193. z-index: 99;
  194. .navbar-left {
  195. width: 80rpx;
  196. display: flex;
  197. justify-content: center;
  198. .calendar-icon {
  199. width: 50rpx;
  200. height: 50rpx;
  201. display: flex;
  202. align-items: center;
  203. justify-content: center;
  204. }
  205. }
  206. .navbar-center {
  207. flex: 1;
  208. margin: 0 20rpx;
  209. .search-box {
  210. width: 420rpx;
  211. display: flex;
  212. align-items: center;
  213. background-color: rgba(255, 255, 255, 0.2);
  214. border-radius: 40rpx;
  215. padding: 0 30rpx;
  216. height: 60rpx;
  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>