WaterfallsFlow.vue 6.5 KB

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