index.vue 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. <template>
  2. <view class="infoBox">
  3. <view class="headerBox">
  4. <view :style="{height: statusBarHeight + 'px'}"></view>
  5. <!-- 头部 -->
  6. <Header />
  7. <!-- 搜索框 -->
  8. <Search />
  9. <!-- 头部导航 -- tab标签 -->
  10. <MenuTab :typeList="typeList" @changeTab="handleSelectTab" />
  11. </view>
  12. <!-- 内容列表 -->
  13. <view class="content">
  14. <scroll-view style="height:100%" :scroll-y="true" :refresher-enabled="true" :refresher-triggered="triggered"
  15. @scrolltolower="scrolltolower" @refresherrefresh="onRefresh" refresher-default-style="black">
  16. <!-- 需要滚动的区域 -<strong></strong>->
  17. <!-- 主资讯 -->
  18. <view class="firstInfo" @click="goDetail" v-if="mainInfo && mainInfo.id">
  19. <!-- <image src="@/static/2.jpg" alt=""></image> -->
  20. <!-- <image :src="getUrl(mainInfo.banner)" alt=""></image> -->
  21. <view class="left">
  22. <view class="time">
  23. {{mainInfo.updateTime ? parseTime(mainInfo.updateTime, '{y}/{m}/{d}'): ''}}
  24. </view>
  25. <view class="title">{{mainInfo.title}}</view>
  26. <!-- <view class="subTitle">副标题副标题副标题</view> -->
  27. </view>
  28. <view>
  29. <i class="custom-icon custom-icon-collect"></i>
  30. </view>
  31. </view>
  32. <!-- <template v-for="(item, index) in infoList"> -->
  33. <view class="info" v-for="(item, index) in infoList" :key="index" @click="goDetail(item)">
  34. <view class="leftBox">
  35. <view class="title">
  36. {{item.title}}
  37. </view>
  38. <view class="attentionSituation">
  39. <view class="collectCount">
  40. <i class="custom-icon custom-icon-collected"></i>
  41. 2145
  42. </view>
  43. <!-- <view class="commentCount">
  44. <i class="custom-icon custom-icon-comment"></i>
  45. 543
  46. </view> -->
  47. <view class="time">
  48. {{item.updateTime ? formatDate(Date.parse(item.updateTime)): ""}}
  49. </view>
  50. </view>
  51. </view>
  52. <image :src="getUrl(item.banner)" alt="图片走丢啦" />
  53. </view>
  54. <!-- </template> -->
  55. <!-- 上拉Loading -->
  56. <u-loadmore :status="loadingStatus" marginTop="50px" loadmoreText="没有更多了" line
  57. v-if="showTip && infoList.length" />
  58. <!-- 上拉Loading -->
  59. <u-empty mode="data" text="列表暂无数据" v-if="!mainInfo.id">
  60. </u-empty>
  61. </scroll-view>
  62. </view>
  63. <!-- 底部导航 -->
  64. <Tabbar :current-page="0" />
  65. </view>
  66. </template>
  67. <script>
  68. import Header from "@/components/Header/index.vue";
  69. import Search from "@/components/Search/index.vue";
  70. import MenuTab from "@/components/MenuTab/index.vue";
  71. import Tabbar from "@/components/Tabbar/index.vue";
  72. import {
  73. getInfoList,
  74. getInfoType
  75. } from '@/api/info.js'
  76. import {
  77. baseUrl
  78. } from "@/utils/apiconfig.js";
  79. import {
  80. parseTime,
  81. formatDate
  82. } from '@/utils/util.js'
  83. export default {
  84. components: {
  85. Header,
  86. Search,
  87. MenuTab,
  88. Tabbar
  89. },
  90. data() {
  91. return {
  92. typeList: [], // 分类
  93. triggered: false, // 下拉是否激活
  94. loadingStatus: 'loadmore', // 上拉loading
  95. showTip: false, // 是否展示上拉loading
  96. mainInfo: {}, // 主资讯(资讯列表的第一条数据)
  97. infoList: [], // 资讯列表(除资讯列表第一条数据的)
  98. total: 0, // 数据总量
  99. infoParams: {
  100. pageNum: 1,
  101. pageSize: 10,
  102. checkStatus: '5', // 已发布的数据
  103. categoryId: '', // 分类
  104. },
  105. statusBarHeight: getApp().globalData.statusBarHeight,
  106. isRequesting: false, // 是否正在请求,如果是则返回,用于节流
  107. }
  108. },
  109. onLoad() {
  110. this.getType();
  111. this.getList();
  112. },
  113. // 监控滚动(可用于判断是否展示返回顶部)
  114. // onPageScroll(e) {
  115. // },
  116. methods: {
  117. parseTime,
  118. formatDate,
  119. // 获取图片完整地址
  120. getUrl(url) {
  121. return baseUrl + url
  122. },
  123. // 获取资讯分类
  124. getType() {
  125. let params = {
  126. status: '0',
  127. pageNum: 1,
  128. pageSize: 9999,
  129. }
  130. getInfoType(params).then(res => {
  131. console.log(res)
  132. let obj = {
  133. id: -1,
  134. name: '全部'
  135. }
  136. this.typeList = [obj, ...res.rows]
  137. })
  138. },
  139. // 上拉加载
  140. scrolltolower() {
  141. this.showTip = true
  142. if (this.infoList.length < this.total) {
  143. this.pageNum += 1;
  144. // 继续请求下一页,记得保留原先数组
  145. this.getList();
  146. } else {
  147. uni.showToast({
  148. title: "没有更多了",
  149. icon: "none",
  150. duration: 2000,
  151. });
  152. return;
  153. }
  154. },
  155. // 自定义下拉刷新被触发
  156. onRefresh() {
  157. // 开启下拉自定义样式
  158. this.triggered = true;
  159. // 清空原本的列表数据。不然会叠加
  160. this.infoList = [];
  161. // 重新调用
  162. this.getList();
  163. // 1秒之后复位
  164. setTimeout(() => {
  165. this.triggered = false;
  166. }, 1000);
  167. },
  168. // 获取资讯列表
  169. getList() {
  170. this.isRequesting = true
  171. getInfoList(this.infoParams).then(res => {
  172. // console.log("res:", res)
  173. // this.infoList = [...this.infoList, ...res.rows]
  174. // 如果是第一页的数据,需要将第一条数据单独拿出来
  175. if (this.infoParams.pageNum === 1) {
  176. console.log('触发第一页的数据啦')
  177. this.mainInfo = res.rows[0] || {}
  178. this.infoList = res.rows.filter((item, index) => index !== 0)
  179. } else {
  180. console.log('触发其余页码的数据啦')
  181. this.infoList = [...this.infoList, ...res.rows]
  182. }
  183. // console.log('infoList', this.infoList)
  184. this.total = res.total - 1
  185. this.loadingStatus = this.infoList.length >= this.total - 1 ? 'nomore' : 'loading'
  186. }).finally(() => this.isRequesting = false)
  187. },
  188. // 切换tab
  189. handleSelectTab(val) {
  190. // 切换tab时页面要回到顶部
  191. uni.pageScrollTo({
  192. scrollTop: 0,
  193. duration: 0, // 直接跳转到顶部,不需要动画
  194. })
  195. this.infoParams = {
  196. ...this.infoParams,
  197. pageNum: 1,
  198. categoryId: val.id === -1 ? '' : val.id,
  199. }
  200. this.getList()
  201. },
  202. // 点击资讯跳转详情
  203. goDetail(val) {
  204. console.log('跳转')
  205. uni.setStorageSync('infoDetail', val)
  206. uni.navigateTo({
  207. url: `/pages/index/detail`
  208. });
  209. },
  210. }
  211. }
  212. </script>
  213. <style lang="scss" scoped>
  214. page {
  215. background-color: #f9f9f9;
  216. font-size: 28rpx;
  217. height: 100%;
  218. // background-color: yellow;
  219. }
  220. .infoBox {
  221. height: 100vh;
  222. padding-top: 20rpx;
  223. display: flex;
  224. flex-direction: column;
  225. /deep/ .Search {
  226. margin: 20rpx 0;
  227. }
  228. .content {
  229. min-height: 0;
  230. flex: 1;
  231. box-sizing: border-box;
  232. // background-color: yellow;
  233. overflow-y: auto;
  234. position: relative;
  235. /deep/ .u-loadmore {
  236. padding-bottom: 200rpx;
  237. }
  238. /deep/ .u-empty {
  239. position: absolute;
  240. left: 50%;
  241. transform: translate(-50%, 50%);
  242. }
  243. }
  244. .firstInfo {
  245. margin: 20rpx auto;
  246. width: 90%;
  247. height: 320rpx;
  248. // background-image: url(../../static/2.jpg);
  249. // background-repeat: no-repeat;
  250. // background-size: 100% 100%;
  251. // border-radius: 30rpx;
  252. // background-color: red;
  253. display: flex;
  254. justify-content: space-between;
  255. padding: 40rpx;
  256. // color: #fff;
  257. color: #000;
  258. font-size: 32rpx;
  259. position: relative;
  260. z-index: 0;
  261. image {
  262. position: absolute;
  263. top: 0;
  264. left: 0;
  265. width: 100%;
  266. height: 320rpx;
  267. border-radius: 30rpx;
  268. z-index: -1;
  269. }
  270. .time {
  271. opacity: 0.8;
  272. font-size: 24rpx;
  273. }
  274. .title {
  275. margin: 10rpx 0;
  276. }
  277. .custom-icon-collect {
  278. font-size: 40rpx;
  279. }
  280. }
  281. .info {
  282. width: 90%;
  283. background-color: #fff;
  284. display: flex;
  285. padding: 20rpx;
  286. height: 260rpx;
  287. margin: 10rpx auto;
  288. border-radius: 24rpx;
  289. box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.2);
  290. .leftBox {
  291. width: 66%;
  292. display: flex;
  293. flex-direction: column;
  294. justify-content: space-between;
  295. }
  296. .title {
  297. overflow: hidden;
  298. text-overflow: ellipsis;
  299. display: -webkit-box;
  300. -webkit-line-clamp: 3;
  301. -webkit-box-orient: vertical;
  302. }
  303. .attentionSituation {
  304. font-size: 24rpx;
  305. display: flex;
  306. align-items: center;
  307. .collectCount,
  308. .commentCount {
  309. display: flex;
  310. align-items: center;
  311. }
  312. .custom-icon {
  313. margin-right: 10rpx;
  314. &::before {
  315. background: -webkit-linear-gradient(left, #f84a1a, #ffa53e);
  316. -webkit-background-clip: text;
  317. -webkit-text-fill-color: transparent;
  318. font-weight: bold;
  319. }
  320. }
  321. .collectCount {
  322. margin-right: 30rpx;
  323. }
  324. .time {
  325. color: #aaa;
  326. }
  327. }
  328. image {
  329. flex: 1;
  330. width: 100%;
  331. height: 100%;
  332. border-radius: 20rpx;
  333. }
  334. .rightBox {
  335. width: 100%;
  336. height: 100%;
  337. // background-color: yellow;
  338. image {
  339. width: 100%;
  340. height: 100%;
  341. }
  342. }
  343. }
  344. }
  345. </style>