WaterfallsFlow.vue 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. <template>
  2. <view class="wf-page">
  3. <!--left-->
  4. <view>
  5. <view id="left" v-if="leftList.length">
  6. <view v-for="(item,index) in leftList" :key="index"
  7. class="wf-item" @tap="itemTap(item)">
  8. <WaterfallsFlowItem :item="item" :isAuth="isAuth" :tab="tab" @likeToggle="(item)=>likeToggle(false, index, item)"/>
  9. </view>
  10. </view>
  11. </view>
  12. <!--right-->
  13. <view>
  14. <view id="right" v-if="rightList.length">
  15. <view v-for="(item,index) in rightList" :key="index"
  16. class="wf-item" @tap="itemTap(item)">
  17. <WaterfallsFlowItem :item="item" :isAuth="isAuth" :tab="tab" @likeToggle="(item)=>likeToggle(true, index, item)"/>
  18. </view>
  19. </view>
  20. </view>
  21. <authorize @onLoadFun="onLoadFun" :isAuto="isAuto" :isShowAuth="isShowAuth" @authColse="authColse"></authorize>
  22. </view>
  23. </template>
  24. <script>
  25. import WaterfallsFlowItem from '../plantWaterfallsFlowItem/WaterfallsFlowItem.vue'
  26. import { graphicStartApi } from '@/api/community.js';
  27. import authorize from '@/components/Authorize';
  28. import { mapGetters } from "vuex";
  29. export default {
  30. components: {
  31. WaterfallsFlowItem,
  32. authorize,
  33. },
  34. props: {
  35. // 瀑布流列表
  36. wfList: {
  37. type: Array,
  38. require: true
  39. },
  40. updateNum: {
  41. type: Number,
  42. default: 10
  43. },
  44. isAuth: {
  45. type: Boolean,
  46. default: false
  47. },
  48. tab: {
  49. type: Number,
  50. default: 1
  51. },
  52. },
  53. data() {
  54. return {
  55. allList: [], // 全部列表
  56. leftList: [], // 左边列表
  57. rightList: [], // 右边列表
  58. mark: 0, // 列表标记
  59. boxHeight: [], // 下标0和1分别为左列和右列高度
  60. isShowAuth: false,
  61. isAuto: false
  62. };
  63. },
  64. watch: {
  65. // 监听列表数据变化
  66. 'wfList.length': {
  67. handler(nVal,oVal){
  68. // 如果数据为空或新的列表数据少于旧的列表数据(通常为下拉刷新或切换排序或使用筛选器),初始化变量
  69. if (!this.wfList.length ||
  70. (this.wfList.length === this.updateNum && this.wfList.length <= this.allList.length)) {
  71. this.allList = [];
  72. this.leftList = [];
  73. this.rightList = [];
  74. this.boxHeight = [];
  75. this.mark = 0;
  76. }
  77. // 如果列表有值,调用waterfall方法
  78. if (this.wfList.length) {
  79. this.allList = this.wfList;
  80. this.leftList = [];
  81. this.rightList = [];
  82. this.boxHeight = [];
  83. this.allList.forEach((v, i) => {
  84. if(this.allList.length < 3 || (this.allList.length <= 7 && this.allList.length - i > 1) || (this.allList.length > 7 && this.allList.length - i > 2)) {
  85. if(i % 2){
  86. this.rightList.push(v);
  87. }else{
  88. this.leftList.push(v);
  89. }
  90. }
  91. });
  92. if(this.allList.length < 3){
  93. this.mark = this.allList.length+1;
  94. }else if(this.allList.length <= 7){
  95. this.mark = this.allList.length - 1;
  96. }else{
  97. this.mark = this.allList.length - 2;
  98. }
  99. if(this.mark < this.allList.length){
  100. this.waterFall()
  101. }
  102. }
  103. },
  104. immediate: true,
  105. deep:true
  106. },
  107. mounted(){
  108. },
  109. // 监听标记,当标记发生变化,则执行下一个item排序
  110. mark() {
  111. const len = this.allList.length;
  112. if (this.mark < len && this.mark !== 0 && this.boxHeight.length) {
  113. this.waterFall();
  114. }
  115. }
  116. },
  117. computed: {
  118. ...mapGetters(['isLogin']),
  119. },
  120. methods: {
  121. // 瀑布流排序
  122. waterFall() {
  123. const i = this.mark;
  124. if(!this.allList[i]) return ;
  125. if (i == 0) {
  126. // 初始化,从左边开始插入
  127. this.leftList.push(this.allList[i]);
  128. // 更新左边列表高度
  129. this.getViewHeight(0);
  130. } else if (i == 1) {
  131. // 第二个item插入,默认为右边插入
  132. this.rightList.push(this.allList[i]);
  133. // 更新右边列表高度
  134. this.getViewHeight(1);
  135. } else {
  136. // 根据左右列表高度判断下一个item应该插入哪边
  137. if(!this.boxHeight.length){
  138. this.rightList.length < this.leftList.length
  139. ? this.rightList.push(this.allList[i])
  140. : this.leftList.push(this.allList[i]);
  141. } else {
  142. const leftOrRight = this.boxHeight[0] > this.boxHeight[1] ? 1 : 0;
  143. if (leftOrRight) {
  144. this.rightList.push(this.allList[i])
  145. } else {
  146. this.leftList.push(this.allList[i])
  147. }
  148. }
  149. // 更新插入列表高度
  150. this.getViewHeight();
  151. }
  152. },
  153. // 获取列表高度
  154. getViewHeight() {
  155. // 使用nextTick,确保页面更新结束后,再请求高度
  156. this.$nextTick(() => {
  157. setTimeout(()=>{
  158. uni.createSelectorQuery().in(this).select('#right').boundingClientRect(res => {
  159. res ? this.boxHeight[1] = res.height : '';
  160. uni.createSelectorQuery().in(this).select('#left').boundingClientRect(res => {
  161. res ? this.boxHeight[0] = res.height : '';
  162. this.mark = this.mark + 1;
  163. }).exec();
  164. }).exec();
  165. },100)
  166. })
  167. },
  168. // item点击
  169. itemTap(item) {
  170. this.$emit('itemTap', item)
  171. },
  172. giveStart(item){
  173. let status = item.relevance_id ? 0 : 1
  174. graphicStartApi(item.community_id,{status: status}).then(res => {
  175. if(item.relevance_id){
  176. item.relevance_id = !item.relevance_id;
  177. item.count_start--;
  178. item.count_start = item.count_start == 0 ? 0 : item.count_start
  179. }else{
  180. item.relevance_id = !item.relevance_id;
  181. item.count_start++;
  182. }
  183. }).catch(err => {
  184. uni.showToast({
  185. title: err,
  186. icon: 'none'
  187. })
  188. });
  189. },
  190. // 授权回调
  191. onLoadFun() {
  192. this.isShowAuth = false
  193. },
  194. // 授权关闭
  195. authColse: function(e) {
  196. this.isShowAuth = e
  197. },
  198. // 打开授权
  199. authOpen: function() {
  200. let that = this;
  201. if (that.isLogin === false) {
  202. this.isAuto = true;
  203. this.isShowAuth = true
  204. }
  205. },
  206. likeToggle(type, index){
  207. if(this.isLogin == true){
  208. if(type){
  209. this.giveStart(this.rightList[index])
  210. }else{
  211. this.giveStart(this.leftList[index])
  212. }
  213. }else{
  214. this.authOpen();
  215. }
  216. },
  217. }
  218. }
  219. </script>
  220. <style lang="scss" scoped>
  221. $page-padding: 20rpx;
  222. $grid-gap: 20rpx;
  223. .wf-page {
  224. display: grid;
  225. grid-template-columns: 1fr 1fr;
  226. grid-gap: $grid-gap;
  227. }
  228. .wf-item {
  229. width: calc((100vw - 2 * #{$page-padding} - #{$grid-gap}) / 2);
  230. margin-bottom: $grid-gap;
  231. background: #fff;
  232. border-radius: 16rpx;
  233. }
  234. .wf-item-page{
  235. padding-bottom: 20rpx;
  236. }
  237. </style>