news.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. <template>
  2. <view class="container-news">
  3. <view class="nav" v-if="isStick"></view>
  4. <view class="msg" @click="goToMsg">
  5. <text class="iconfont3 msgCenter">&#xe62a;</text>
  6. <text>消息</text>
  7. <text class="msgTxt" v-if="msgCenter==0?false:msgCenter">{{msgCenter}}</text>
  8. </view>
  9. <view id="header" v-if="swiperlist.length || bannerList.length">
  10. <view class="top" v-if="swiperlist.length > 0">
  11. <template>
  12. <swiper class="swiper" circular :autoplay="true" :interval="10000" :indicator-dots="true">
  13. <swiper-item v-for="(item, index) in swiperlist" :key="item.id">
  14. <view class="swiper-item" @click="$mUtil.imgLink(item.model_type, item.model_id, item.url, item.shop_id)">
  15. <image :src="item.cover" mode="widthFix"></image>
  16. </view>
  17. </swiper-item>
  18. </swiper>
  19. </template>
  20. </view>
  21. <view class="banner" v-if="bannerList.length > 0">
  22. <image :src="bannerList[0].cover" mode="widthFix"
  23. @click="$mUtil.imgLink(bannerList[0].model_type, bannerList[0].model_id, bannerList[0].url, bannerList[0].shop_id)">
  24. </image>
  25. </view>
  26. </view>
  27. <view class="main" :class="{'stickMain': isStick}">
  28. <view class="tabs" :class="{'stickTabs': isStick}">
  29. <scroll-view scroll-x class="scorll-x" :scroll-left="scrollLeft" :show-scrollbar="false">
  30. <view class="tab" :class="{'active': current == index}" v-for="(item, index) in list" :key="item.id"
  31. :id="'item'+index" @click="tabsChange(index)">
  32. <view class="">{{item.name}}</view>
  33. </view>
  34. </scroll-view>
  35. </view>
  36. <swiper class="list-swiper" :style="{height: tabHeight[current]+'px'}" :current="tabIndex" @change="swiperChange">
  37. <swiper-item class="swiper-item" v-for="(item, index) in list" :key="index">
  38. <!-- <scroll-view scroll-y style="height: 100%;width: 100%;" @scrolltoupper="topScroll" @scrolltolower="loadMore"
  39. :refresher-enabled="true" :refresher-triggered="triggered" :refresher-threshold="100"
  40. refresher-background="white" @refresherpulling="onPulling" @refresherrefresh="onRefresh"
  41. @refresherrestore="onRestore" @refresherabort="onAbort"> -->
  42. <news :classify_id="item.id" :ref="'page' + index" :id="'page' + index" @getSwiperHeight="getSwiperHeight">
  43. </news>
  44. <!-- </scroll-view> -->
  45. </swiper-item>
  46. </swiper>
  47. </view>
  48. </view>
  49. </template>
  50. <script>
  51. import news from '@/components/news';
  52. export default {
  53. components: {
  54. news
  55. },
  56. data() {
  57. return {
  58. swiperlist: [],
  59. msgCenter: null,
  60. headerHeight: 0,
  61. isStick: false,
  62. list: [],
  63. scrollLeft: 0,
  64. totalCount: 0,
  65. current: 0,
  66. tabIndex: 0,
  67. pageList: [],
  68. triggered: false,
  69. tabHeight: [],
  70. systemInfo: {},
  71. tabScrollTop: [],
  72. scrollTop: 0,
  73. bannerList: []
  74. }
  75. },
  76. onLoad() {
  77. this.freshing = false;
  78. setTimeout(() => {
  79. this.triggered = true;
  80. }, 1000)
  81. uni.getSystemInfo({
  82. success: res => {
  83. this.systemInfo = res
  84. }
  85. })
  86. this.getLocation()
  87. this.getSwiperList()
  88. this.getBanner()
  89. this.getClassify()
  90. },
  91. onShow() {
  92. this.getmessageNum()
  93. },
  94. onPageScroll(e) {
  95. if (e) {
  96. if (e.scrollTop >= this.headerHeight) {
  97. this.isStick = true
  98. } else {
  99. this.isStick = false
  100. }
  101. this.scrollTop = e.scrollTop
  102. this.getSwiperHeight()
  103. }
  104. },
  105. onReachBottom() {
  106. this.loadMore()
  107. },
  108. onPullDownRefresh() {
  109. this.tabScrollTop = []
  110. this.getmessageNum()
  111. this.getSwiperList()
  112. this.getBanner()
  113. this.getClassify(true)
  114. // this.getSwiperList()
  115. setTimeout(() => {
  116. uni.stopPullDownRefresh();
  117. }, 300)
  118. },
  119. methods: {
  120. // 获取经纬度
  121. getLocation() {
  122. uni.getLocation({
  123. type: 'wgs84',
  124. geocode: true,
  125. success: (res) => {
  126. uni.setStorageSync('locationObj', res)
  127. }
  128. });
  129. },
  130. // 获取轮播
  131. getSwiperList() {
  132. this.$http.get('/ad/ad/getShopAdByAdL/0/news-swiper').then(res => {
  133. if (res.code == 200) {
  134. this.swiperlist = res.list.slice(0, 6)
  135. this.$nextTick(() => {
  136. this.getDomHeight()
  137. })
  138. }
  139. })
  140. },
  141. // 获取banner
  142. getBanner() {
  143. this.$http.get('/ad/ad/getShopAdByAdL/0/news-banner').then(res => {
  144. if (res.code == 200) {
  145. this.bannerList = res.list
  146. this.$nextTick(() => {
  147. this.getDomHeight()
  148. })
  149. }
  150. })
  151. },
  152. async getSwiperHeight() {
  153. let minHeight = this.systemInfo.windowHeight - 44;
  154. let rect = await this.getGoodDom();
  155. if (rect && rect.height !== 0 && rect.height > minHeight) {
  156. this.tabHeight[this.current] = rect.height
  157. this.$forceUpdate()
  158. }
  159. },
  160. getGoodDom() {
  161. let self = this;
  162. return new Promise(resolve => {
  163. this.$nextTick(() => {
  164. let query = uni.createSelectorQuery();
  165. // #ifndef MP-ALIPAY
  166. query = query.in(this)
  167. // #endif
  168. query.select('#page' + this.current).boundingClientRect(data => {
  169. if (!data)
  170. return
  171. resolve(data)
  172. }).exec();
  173. })
  174. })
  175. },
  176. // 获取头部高度
  177. getDomHeight() {
  178. this.$u.getRect('#header').then(res => {
  179. this.headerHeight = res.height
  180. })
  181. },
  182. setScrollLeft(i) {
  183. let winWidth = uni.getSystemInfoSync().windowWidth - uni.upx2px(30)
  184. this.scrollLeft = this.tabarr[i].left + (this.tabarr[i].width / 2) - (winWidth / 2)
  185. },
  186. getWidth() { //得到元素的宽高
  187. let view = uni.createSelectorQuery().in(this);
  188. for (let i = 0; i < this.list.length; i++) {
  189. view.select('#item' + i).boundingClientRect();
  190. }
  191. view.exec(res => {
  192. this.tabarr = res
  193. })
  194. },
  195. /**获得消息数量 */
  196. getmessageNum() {
  197. let token = uni.getStorageSync("apiToken")
  198. if (token) {
  199. this.$http.get("/private/message/unread-num").then(res => {
  200. if (res && res.code == 200) {
  201. this.msgCenter = res.data
  202. }
  203. })
  204. } else {
  205. this.msgCenter = 0
  206. }
  207. },
  208. goToMsg() {
  209. let token = uni.getStorageSync("apiToken")
  210. if (!token) {
  211. uni.navigateTo({
  212. url: "/pages/login/index"
  213. })
  214. } else {
  215. uni.navigateTo({
  216. url: "/pages/research/setup/myMsg"
  217. })
  218. }
  219. },
  220. // 获取资讯分类
  221. getClassify(refresh) {
  222. this.$http.get('/information/classify/list').then(res => {
  223. if (res && res.code == 200) {
  224. this.list = [...[{
  225. id: '',
  226. name: '推荐'
  227. }], ...res.list]
  228. setTimeout(() => {
  229. this.$nextTick(() => {
  230. this.getWidth()
  231. for (let i = 0; i < this.list.length; i++) {
  232. let item = this.$refs['page' + i]
  233. if (Array.isArray(item)) {
  234. this.pageList.push(item[0])
  235. } else {
  236. this.pageList.push(item)
  237. }
  238. }
  239. this.switchTab(this.tabIndex, refresh);
  240. })
  241. }, 300)
  242. }
  243. })
  244. },
  245. switchTab(index, refresh) {
  246. this.$nextTick(() => {
  247. this.getSwiperHeight()
  248. })
  249. if (refresh) {
  250. this.pageList.map(item => {
  251. item.dataList = []
  252. })
  253. // this.pageList[index].dataList = []
  254. this.$forceUpdate()
  255. }
  256. if (this.pageList[index].dataList.length === 0) {
  257. this.loadTabData(index, refresh ? 'refresh' : '');
  258. }
  259. if (this.tabIndex === index) {
  260. return;
  261. }
  262. },
  263. loadTabData(index, refresh) {
  264. this.pageList[index].loadData(index, refresh);
  265. },
  266. // tabs通知swiper切换
  267. tabsChange(index) {
  268. this.tabIndex = index;
  269. this.current = index
  270. },
  271. swiperChange(e) {
  272. let tabTop = e.currentTarget.offsetTop; //tab距离顶部的距离
  273. let swiperTop = tabTop - uni.upx2px(100) - 44 - this.systemInfo.statusBarHeight;
  274. if (e.detail.source) {
  275. this.tabScrollTop[this.current] = this.scrollTop < swiperTop ? swiperTop : this.scrollTop; //给之前的tab赋值
  276. }
  277. this.tabIndex = e.detail.current;
  278. this.current = e.detail.current
  279. this.switchTab(this.current)
  280. this.setScrollLeft(this.current)
  281. if (this.scrollTop < swiperTop) return;
  282. if (this.tabScrollTop[this.current] < swiperTop) {
  283. this.tabScrollTop[this.current] = swiperTop //给当前的tab赋值
  284. }
  285. uni.pageScrollTo({
  286. scrollTop: this.tabScrollTop[this.current],
  287. duration: 0
  288. })
  289. },
  290. // topScroll() {
  291. // // this.pageList[this.current].loadData(this.current, 'refresh');
  292. // },
  293. loadMore() {
  294. this.pageList[this.current].loadData(this.current, 'more');
  295. },
  296. // onPulling(e) {
  297. // console.log("onpulling", e);
  298. // },
  299. // onRefresh() {
  300. // if (this.freshing) return;
  301. // this.freshing = true;
  302. // this.pageList[this.current].loadData(this.current, 'refresh');
  303. // setTimeout(() => {
  304. // this.triggered = false;
  305. // this.freshing = false;
  306. // }, 500)
  307. // },
  308. // onRestore() {
  309. // this.triggered = 'restore'; // 需要重置
  310. // console.log("onRestore");
  311. // },
  312. // onAbort() {
  313. // this.triggered = 'restore'; // 需要重置
  314. // console.log("onAbort");
  315. // }
  316. }
  317. }
  318. </script>
  319. <style lang="scss" scoped>
  320. .container-news {
  321. .msg {
  322. display: flex;
  323. flex-direction: column;
  324. align-items: center;
  325. position: fixed;
  326. // top: 36rpx;
  327. top: 88rpx;
  328. right: 25rpx;
  329. z-index: 3;
  330. color: #fff;
  331. font-size: 24rpx;
  332. z-index: 7;
  333. .msgCenter {
  334. font-size: 40rpx;
  335. }
  336. .msgTxt {
  337. position: absolute;
  338. top: -25%;
  339. left: -30%;
  340. padding: 0 6rpx;
  341. font-size: 20rpx;
  342. background: #ff0000;
  343. border-radius: 13rpx;
  344. }
  345. }
  346. .swiper {
  347. /deep/ .uni-swiper-dot {
  348. width: 15rpx !important;
  349. height: 15rpx;
  350. border-radius: 50% !important;
  351. background-color: #ffffff !important;
  352. opacity: 0.5;
  353. }
  354. /deep/ .uni-swiper-dot-active {
  355. width: 20rpx !important;
  356. height: 20rpx;
  357. border-radius: 50% !important;
  358. background-color: #ffffff !important;
  359. opacity: 1;
  360. }
  361. }
  362. .nav {
  363. position: fixed;
  364. top: 0;
  365. width: 100%;
  366. height: 80rpx;
  367. background-color: #FA6138;
  368. z-index: 9;
  369. }
  370. .top {
  371. position: relative;
  372. width: 100%;
  373. height: 880rpx;
  374. .swiper,
  375. .swiper-item {
  376. width: 100%;
  377. height: 100%;
  378. image {
  379. width: 100%;
  380. height: 100% !important;
  381. vertical-align: middle;
  382. }
  383. }
  384. }
  385. .banner {
  386. width: 100%;
  387. height: 160rpx;
  388. image {
  389. width: 100%;
  390. height: 100%;
  391. vertical-align: middle;
  392. }
  393. }
  394. .stickMain {
  395. margin-top: calc(100rpx + 100rpx);
  396. }
  397. .tabs {
  398. width: 100%;
  399. height: 95rpx;
  400. padding: 0 30rpx;
  401. border-bottom: 1rpx solid #e6e6e6;
  402. font-size: 30rpx;
  403. font-family: PingFang SC, PingFang SC-Regular;
  404. font-weight: 400;
  405. color: #1a1a1a;
  406. background: #fff;
  407. .scorll-x {
  408. width: 100%;
  409. height: 100%;
  410. white-space: nowrap;
  411. }
  412. .tab {
  413. display: inline-block;
  414. height: 100%;
  415. line-height: 95rpx;
  416. margin-right: 44rpx;
  417. }
  418. .active {
  419. position: relative;
  420. font-family: PingFang SC, PingFang SC-Bold;
  421. font-weight: 700;
  422. color: #FA6138;
  423. &::after {
  424. position: absolute;
  425. bottom: 0;
  426. display: block;
  427. content: '';
  428. width: 100%;
  429. height: 4rpx;
  430. background: #FA6138;
  431. border-radius: 2rpx;
  432. z-index: 3;
  433. }
  434. }
  435. }
  436. .stickTabs {
  437. position: fixed;
  438. top: 80rpx;
  439. z-index: 9;
  440. }
  441. .list-swiper {
  442. width: 100%;
  443. height: calc(100vh - 100rpx);
  444. .swiper-item {
  445. width: 100%;
  446. height: 100%;
  447. }
  448. }
  449. }
  450. </style>