You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

210 lines
5.7 KiB

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