news.vue 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. <template>
  2. <gracePage headerBG="#FFFFFF" :isSwitchPage="true">
  3. <view slot="gHeader" style="padding:0 25rpx;">
  4. <graceNavBar :items="tabs" :currentIndex="currentIndex" @change="navChange"></graceNavBar>
  5. </view>
  6. <view slot="gBody" class="grace-flex-v1" id="gBody">
  7. <swiper :style="{height:mainHeight+'px'}" :current="currentIndex" @change="swiperChange">
  8. <swiper-item v-for="(news, newsIndex) in newsAll" :key="newsIndex">
  9. <scroll-view scroll-y="true" :style="{height:mainHeight+'px'}"
  10. @scrolltolower="scrollend" @scroll="scroll"
  11. @touchstart="touchstart" @touchmove="touchmove" @touchend="touchend">
  12. <graceReload ref="graceReload" width="700rpx" marginLeft="25rpx" @reload="reload"></graceReload>
  13. <graceEmpty v-if="news == 'empty'">
  14. <view slot="img" class="empty-view">
  15. <!-- 请根据您的项目要求制作并更换为空图片 -->
  16. <image class="empty-img" mode="widthFix" src="https://staticimgs.oss-cn-beijing.aliyuncs.com/empty.png"></image>
  17. </view>
  18. <text slot="text" class="grace-text-small grace-gray">本栏目暂无新闻</text>
  19. </graceEmpty>
  20. <view style="padding:0 25rpx;">
  21. <block v-for="(item, index) in news" :key="index" v-if="news != 'empty'">
  22. <view class="grace-news-list grace-border-b" v-if="item.imgs.length < 3" @tap="newsinfo">
  23. <view class="grace-news-item">
  24. <view class="grace-news-img grace-news-img-l">
  25. <image :src="item.imgs[0]" mode="widthFix" class="grace-news-img-in"></image>
  26. </view>
  27. <view class="grace-news-body">
  28. <text class="grace-news-title">{{item.title}}</text>
  29. <text class="grace-news-desc">{{item.desc}}</text>
  30. </view>
  31. </view>
  32. <view class="grace-news-info">
  33. <view style="width:500rpx;" class="grace-nowrap">
  34. <text class="grace-icons grace-news-info-text">&#xe609; {{item.viewnum}}</text>
  35. <text class="grace-icons grace-news-info-text" style="margin-left:30rpx;">&#xe69e; {{item.author}} · {{item.catename}}</text>
  36. </view>
  37. <text class="grace-icons grace-news-info-text">&#xe6b8; 208</text>
  38. </view>
  39. </view>
  40. <view class="grace-news-list grace-border-b" v-if="item.imgs.length >= 3" @tap="newsinfo">
  41. <text class="grace-news-title">{{item.title}}</text>
  42. <view class="grace-news-img-list">
  43. <view class="grace-news-imgs" v-for="(img, imgIndex) in item.imgs" :key="imgIndex">
  44. <image :src="img" mode="widthFix" class="grace-news-imgs-img"></image>
  45. </view>
  46. </view>
  47. <view class="grace-news-info">
  48. <view style="width:500rpx;" class="grace-nowrap">
  49. <text class="grace-icons grace-news-info-text">&#xe609; {{item.viewnum}}</text>
  50. <text class="grace-icons grace-news-info-text" style="margin-left:30rpx;">&#xe69e; {{item.author}} · {{item.catename}}</text>
  51. </view>
  52. <text class="grace-icons grace-news-info-text">&#xe6b8; 208</text>
  53. </view>
  54. </view>
  55. </block>
  56. </view>
  57. <graceLoading :loadingType="loadingTypes[newsIndex]"></graceLoading>
  58. </scroll-view>
  59. </swiper-item>
  60. </swiper>
  61. </view>
  62. </gracePage>
  63. </template>
  64. <script>
  65. import gracePage from "../../graceUI/components/gracePage.vue";
  66. import graceNavBar from "../../graceUI/components/graceNavBar.vue";
  67. import graceLoading from "../../graceUI/components/graceLoading.vue";
  68. import graceEmpty from '../../graceUI/components/graceEmptyNew.vue';
  69. import graceReload from '../../graceUI/components/graceReload.vue';
  70. export default {
  71. data() {
  72. return {
  73. currentIndex: 0,
  74. mainHeight : 600,
  75. //分类数据
  76. tabsAll : [],
  77. tabs : [],
  78. // 新闻信息保存数组
  79. newsAll : [],
  80. // 每个选项卡对应的分页
  81. pages : [],
  82. // 加载状态
  83. loadingTypes : [],
  84. // 每个滚动区域的滚动值
  85. scrollTops : []
  86. }
  87. },
  88. onReady:function(){
  89. setTimeout(()=>{
  90. uni.createSelectorQuery().select('#gBody').fields(
  91. {size: true}, (res) => {
  92. this.mainHeight = res.height;
  93. }
  94. ).exec();
  95. },1000);
  96. //加载分类信息 初始化数据
  97. this.getCate();
  98. },
  99. watch:{
  100. currentIndex : function (nVal, oldVal) {
  101. if( this.loadingTypes[this.currentIndex] != 2 || this.loadingTypes[this.currentIndex] != 4){ this.getNews(); }
  102. }
  103. },
  104. methods:{
  105. navChange: function (e) {
  106. this.currentIndex = e;
  107. },
  108. swiperChange: function (e) {
  109. var index = e.detail.current;
  110. this.currentIndex = index;
  111. },
  112. //加载分类信息 初始化数据
  113. getCate : function () {
  114. uni.request({
  115. // 此处可以获取分类 根据分类自己拼接请求地址
  116. // 格式请参考 接口 [ 浏览器运行直接查看 ]
  117. url : 'http://grace.hcoder.net/api/tabs',
  118. method : 'GET',
  119. data : {},
  120. success : res => {
  121. // 初始化新闻列表数组 元素数量与分类匹配
  122. this.tabsAll = res.data.data;
  123. for(var i = 0; i < this.tabsAll.length; i++){
  124. this.newsAll.push([]);
  125. this.tabs.push(this.tabsAll[i].txt);
  126. this.pages.push(1);
  127. this.loadingTypes.push(3);
  128. this.scrollTops.push(0);
  129. }
  130. this.getNews();
  131. }
  132. });
  133. },
  134. // 加载新闻
  135. getNews : function(isReload){
  136. // 当前正在展示的 选项index 为 this.currentIndex
  137. // 那么分类 id 应该为 this.tabsAll[this.currentIndex].id
  138. //console.log('类型 : ' + this.tabs[this.currentIndex] + ' 第'+ this.pages[this.currentIndex] +'页');
  139. if(!isReload){this.loadingTypes.splice(this.currentIndex, 1, 1);}
  140. //console.log('http://grace.hcoder.net/api/news/index/'+this.tabsAll[this.currentIndex].id+'/'+this.pages[this.currentIndex]);
  141. uni.request({
  142. // 此处可以获取分类 根据分类自己拼接请求地址
  143. // 分类 id 、页码 都已经获取到了
  144. url : 'http://grace.hcoder.net/api/news/index/'+this.tabsAll[this.currentIndex].id+'/'+this.pages[this.currentIndex],
  145. method : 'GET',
  146. data : {},
  147. success : res => {
  148. if(res.data.status == 'ok'){
  149. // 第一页
  150. if(this.pages[this.currentIndex] == 1){
  151. this.newsAll.splice(this.currentIndex, 1 , res.data.data);
  152. }
  153. // 之后的加载页
  154. else{
  155. this.newsAll[this.currentIndex] = this.newsAll[this.currentIndex].concat(res.data.data);
  156. }
  157. // 页码增加
  158. this.pages[this.currentIndex]++;
  159. setTimeout(()=>{
  160. this.loadingTypes.splice(this.currentIndex, 1, 3);
  161. },300)
  162. }else if(res.data.status == 'empty'){
  163. console.log('empty');
  164. this.newsAll[this.currentIndex] = 'empty';
  165. this.loadingTypes.splice(this.currentIndex, 1, 4);
  166. }else if(res.data.status == 'nomore'){
  167. console.log('nomore');
  168. this.loadingTypes.splice(this.currentIndex, 1, 2);
  169. }
  170. },
  171. complete: () => {
  172. if(isReload){
  173. setTimeout(()=>{
  174. this.$refs.graceReload[this.currentIndex].endReload();
  175. },300)
  176. }
  177. }
  178. });
  179. },
  180. // 点击新闻列表
  181. newsinfo : function () {
  182. uni.navigateTo({
  183. url:'../artInfo/artInfo'
  184. })
  185. },
  186. // 加载更多
  187. scrollend:function(e){
  188. // 判断加载状态避免多次滚动时有加载尚未完成
  189. if( this.loadingTypes[this.currentIndex] == 2 || this.loadingTypes[this.currentIndex] == 4){ return false; }
  190. console.log('loadmore.....');
  191. this.getNews();
  192. },
  193. scroll:function(e){
  194. this.scrollTops[this.currentIndex] = e.detail.scrollTop;
  195. },
  196. touchstart : function (e){
  197. var touchObj = {scrollTop : this.scrollTops[this.currentIndex], moveY : e.changedTouches[0].pageY};
  198. this.$refs.graceReload[this.currentIndex].touchstart(touchObj);
  199. },
  200. touchmove : function (e) {
  201. var touchObj = {scrollTop : this.scrollTops[this.currentIndex], moveY : e.changedTouches[0].pageY};
  202. this.$refs.graceReload[this.currentIndex].touchmove(touchObj);
  203. },
  204. touchend : function (e) {
  205. var touchObj = {scrollTop : this.scrollTops[this.currentIndex], moveY : e.changedTouches[0].pageY};
  206. this.$refs.graceReload[this.currentIndex].touchend(touchObj);
  207. },
  208. // 下拉刷新
  209. reload:function(){
  210. this.pages[this.currentIndex] = 1;
  211. this.loadingTypes.splice(this.currentIndex, 1, 3);
  212. this.getNews(1);
  213. }
  214. },
  215. components:{gracePage, graceNavBar, graceEmpty, graceLoading, graceReload}
  216. }
  217. </script>
  218. <style>
  219. .grace-news-img{width:220rpx; height:150rpx; overflow:hidden; font-size:0;}
  220. .grace-news-img-in{width:100%;}
  221. .grace-news-imgs-img{width:225rpx; height:380rpx;}
  222. .empty-view{width:280rpx; height:280rpx; border-radius:280rpx; background-color:#F6F7F8; margin-top:300rpx;}
  223. .empty-img{width:220rpx; height:200rpx; margin:40rpx; border-radius:200rpx;}
  224. .grace-text-small{margin-top:10px;}
  225. </style>