chartList.vue 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. <template>
  2. <view class="chart-list-wrap">
  3. <scroll-view
  4. id="scrollView"
  5. :scroll-y="true"
  6. :style="{'height': ListHeight+'px'}"
  7. :scroll-top="scrollViewTop"
  8. @scrolltolower="scrolltolower"
  9. @scroll="drag.scroll"
  10. :scroll-with-animation="false"
  11. >
  12. <!-- 两个list列表 拖拽完直接切换list 避免闪烁 -->
  13. <block v-for="(tmplist,listType) in dragList" :key="listType">
  14. <view
  15. class="chart-list"
  16. :class="[listType=='A'?(listSwitch?'show':'hide'):(listSwitch?'hide':'show')]"
  17. >
  18. <block v-for="(item,index) in tmplist" :key="index">
  19. <view class="rowBox chart-item" :id="'rowBox'+listType+index">
  20. <view class="row" :id="'row'+listType+index">
  21. <!-- 拖动按钮 -->
  22. <image
  23. class="drag-icon"
  24. src="../../static/chart/drag-icon.png"
  25. mode="aspectFill"
  26. :style="{'height': rowHeight+'px'}"
  27. :data-index="index"
  28. :data-type="listType"
  29. @touchstart="drag.touchstart"
  30. @touchmove="drag.touchmove"
  31. @touchend="drag.touchend"
  32. <!-- #ifdef MP-WEIXIN -->
  33. @longpress="drag.longpress"
  34. <!-- #endif -->
  35. />
  36. <!-- 内容区域 -->
  37. <view>标题{{item.title}}</view>
  38. <image lazy-load class="img" src="" mode="aspectFill"/>
  39. </view>
  40. </view>
  41. </block>
  42. </view>
  43. </block>
  44. </scroll-view>
  45. <!-- 拖动的盒子 -->
  46. <view id="shadowRowBox" class="shadowRowBox">
  47. <view id="shadowRow">
  48. <image class="drag-icon" src="../../static/chart/drag-icon.png" mode="aspectFill"/>
  49. <!-- 内容区域 -->
  50. <view>标题{{shadowRow.title}}</view>
  51. <image lazy-load class="img" src="" mode="aspectFill"/>
  52. </view>
  53. </view>
  54. <view :data-isapph5="isAppH5" :data-islongtouch="isLongTouch" :data-longtouchtime="longTouchTime" :data-listheight="ListHeight"
  55. :data-rownum="list.length" id="dataView" style="display: none !important;">存放数据给wxs读取</view>
  56. </view>
  57. </template>
  58. <script src="./drag.wxs" module="drag" lang="wxs"></script>
  59. <script>
  60. /**
  61. * 拖拽排序组件 HM-dragSort
  62. * @description 拖拽排序组件 HM-dragSort
  63. * @property {ObjectArray} list = [] 列表数据,自定义数据,会传递到name="rowContent"插槽
  64. * @property {Boolean} isLongTouch = [true|false] 是否开启长按拖动
  65. * @property {Number} longTouchTime = [] 选填,触发长按时长,单位:ms,默认350ms,不支持微信小程序
  66. * @property {Number} listHeight = [] 选填,可拖动列表整体的高度,单位:px,默认等于窗口高度
  67. * @property {Number} rowHeight = [] 必填,行高,单位:px,默认44px
  68. * @event {Function} change 行位置发生改变时触发事件 返回值:{index:'原始下标',moveTo:'被拖动到的下标',moveRow:'拖动行数据'}
  69. * @event {Function} confirm 拖拽结束且行位置发生了改变触发事件 返回值:{index:'原始下标',moveTo:'被拖动到的下标',moveRow:'拖动行数据',list:'整个列表拖动后的数据'}
  70. * @event {Function} onclick 点击行触发事件 返回值:{index:'被点击行下标',value:'被点击行数据'}
  71. */
  72. export default {
  73. name: 'chart-list',
  74. data() {
  75. return {
  76. // #ifdef APP-PLUS || H5
  77. isAppH5: true,
  78. // #endif
  79. // #ifdef MP-WEIXIN
  80. isAppH5: false,
  81. // #endif
  82. shadowRow: {}, // 存放被拖拽行数据
  83. // 列表数据 分A和B两个列表 互相切换 避免闪烁
  84. dragList: {
  85. "A": [],
  86. "B": []
  87. },
  88. ListHeight: this.listHeight,
  89. listSwitch: true, // 控制切换列表
  90. // 控制滑动
  91. scrollViewTop: 0, // 滚动条位置
  92. scrollCommand: 1, //传递renderjs数据
  93. isHoldTouch: false, //是否正在拖拽
  94. isScrolling: false, //是否正在滚动视图
  95. scrollTimer: null, //定时器-控制滚动 微信小程序端使用 实现类似requestAnimationFrame效果
  96. }
  97. },
  98. props: {
  99. // 是否开启长按拖动
  100. isLongTouch: {
  101. value: Boolean,
  102. default: true
  103. },
  104. longTouchTime: {
  105. value: Number,
  106. default: 300
  107. },
  108. // 列表数据
  109. list: {
  110. value: Array,
  111. default: []
  112. },
  113. // 行高度 默认44行高
  114. rowHeight: {
  115. value: Number,
  116. default: 44
  117. },
  118. // 组件高度 默认windowHeight满屏
  119. listHeight: {
  120. value: Number,
  121. default: 0
  122. }
  123. },
  124. watch: {
  125. list: {
  126. handler(val) {
  127. this.initList(); //数据变化重新初始化list
  128. },
  129. immediate: true
  130. }
  131. },
  132. mounted() {
  133. if (this.listHeight == 0) {
  134. this.ListHeight = uni.getSystemInfoSync().windowHeight;
  135. }
  136. },
  137. methods: {
  138. // 触底
  139. scrolltolower(){
  140. this.$emit('scrolltolower')
  141. },
  142. loadShadowRow(e) {
  143. this.shadowRow = JSON.parse(JSON.stringify(this.dragList[this.listSwitch ? "A" : "B"][e.rowIndex]));
  144. },
  145. initList() {
  146. if (this.dragList.A.length > 0) {
  147. setTimeout(() => {
  148. this.dragList.A = JSON.parse(JSON.stringify(this.list));
  149. this.dragList.B = JSON.parse(JSON.stringify(this.list));
  150. }, 50)
  151. } else {
  152. this.dragList.A = JSON.parse(JSON.stringify(this.list));
  153. this.dragList.B = JSON.parse(JSON.stringify(this.list));
  154. }
  155. },
  156. triggerClick(index, row) {
  157. this.$emit('onclick', {
  158. index: index,
  159. value: JSON.parse(JSON.stringify(row))
  160. });
  161. },
  162. //兼容微信小程序震动
  163. vibrate() {
  164. uni.vibrateShort()
  165. },
  166. // 控制自动滚动视图
  167. pageScroll(e) {
  168. // 滚动
  169. if (e.command == "up" || e.command == "down") {
  170. if (!this.isHoldTouch) {
  171. this.isHoldTouch = true;
  172. this.scrollViewTop = e.scrollTop;
  173. }
  174. if (this.isScrolling) {
  175. return;
  176. };
  177. this.isScrolling = true;
  178. // APP端和H5端 执行renderjs的滚动
  179. // #ifdef APP-PLUS || H5
  180. e.ListHeight = this.ListHeight;
  181. e.rowHeight = this.rowHeight;
  182. e.rowLength = this.list.length;
  183. this.scrollCommand = e;
  184. return;
  185. // #endif
  186. // 微信小程序执行以下逻辑
  187. this.scrollTimer != null && clearInterval(this.scrollTimer);
  188. let maxheight = this.rowHeight * this.list.length + 1 - this.ListHeight;
  189. // 16.6ms毫秒执行一次,接近60HZ
  190. this.scrollTimer = setInterval(() => {
  191. if (e.command == "up") {
  192. this.scrollViewTop -= 3
  193. }
  194. if (e.command == "down") {
  195. this.scrollViewTop += 3;
  196. }
  197. if (this.scrollViewTop < 0) {
  198. this.scrollViewTop = 0;
  199. clearInterval(this.scrollTimer);
  200. }
  201. if (this.scrollViewTop > maxheight) {
  202. this.scrollViewTop = maxheight;
  203. clearInterval(this.scrollTimer);
  204. }
  205. }, 16.6)
  206. }
  207. // 停止滚动
  208. if (e.command == "stop") {
  209. // #ifdef APP-PLUS || H5
  210. this.scrollCommand = e;
  211. // #endif
  212. this.isScrolling && this.stopScroll();
  213. }
  214. },
  215. stopScroll() {
  216. this.scrollTimer != null && clearInterval(this.scrollTimer);
  217. this.isScrolling = false;
  218. this.scrollingtop = 0;
  219. },
  220. change(e) {
  221. e.moveRow = JSON.parse(JSON.stringify(this.dragList.A[e.index]))
  222. this.$emit('change', e);
  223. },
  224. sort(e) {
  225. this.stopScroll();
  226. this.isHoldTouch = false;
  227. let tmpList = JSON.parse(JSON.stringify(this.dragList.A));
  228. tmpList.splice(e.offset, 0, tmpList.splice(e.index, 1)[0]);
  229. let listType = "A"
  230. if (this.listSwitch) {
  231. this.dragList.B = [];
  232. this.dragList.B = tmpList;
  233. } else {
  234. this.dragList.A = [];
  235. this.dragList.A = tmpList;
  236. listType = "B";
  237. }
  238. setTimeout(() => {
  239. this.resetList(listType, tmpList)
  240. }, 50)
  241. this.$emit('confirm', {
  242. list: tmpList,
  243. index: e.index,
  244. moveTo: e.offset,
  245. moveRow: JSON.parse(JSON.stringify(this.dragList.A[e.index]))
  246. });
  247. },
  248. resetList(listType, tmpList) {
  249. this.listSwitch = !this.listSwitch;
  250. this.$nextTick(() => {
  251. this.dragList[listType] = [];
  252. this.dragList[listType] = tmpList;
  253. })
  254. }
  255. }
  256. }
  257. </script>
  258. <style lang="scss" scoped>
  259. .chart-list-wrap{
  260. .hide{
  261. display: none;
  262. }
  263. .show{
  264. }
  265. }
  266. .chart-list{
  267. padding: 24rpx 25rpx;
  268. width: 100%;
  269. box-sizing: border-box;
  270. display: flex;
  271. justify-content: space-between;
  272. flex-wrap: wrap;
  273. .chart-item{
  274. width: 48.5%;
  275. &.show{
  276. display: block;
  277. }
  278. &.hide{
  279. display: none;
  280. }
  281. .row{
  282. background: #FFFFFF;
  283. box-shadow: 0px 0px 12rpx rgba(154, 141, 123, 0.16);
  284. border-radius: 8rpx;
  285. margin-bottom: 20rpx;
  286. padding: 20rpx 20rpx 33rpx 20rpx;
  287. position: relative;
  288. }
  289. .title{
  290. font-size: 26rpx;
  291. }
  292. .img{
  293. margin-top: 10rpx;
  294. width: 100%;
  295. height: 261rpx;
  296. display: block;
  297. margin-left: auto;
  298. margin-right: auto;
  299. background-color: #f6f6f6;
  300. }
  301. .drag-icon{
  302. position: absolute;
  303. top: 0;
  304. right: 0;
  305. width: 40rpx !important;
  306. height: 40rpx !important;
  307. }
  308. }
  309. }
  310. .shadowRowBox{
  311. &.show{
  312. display: block;
  313. opacity: 0.7;
  314. }
  315. width: 48vw;
  316. background: #FFFFFF;
  317. box-shadow: 0px 0px 12rpx rgba(154, 141, 123, 0.16);
  318. border-radius: 8rpx;
  319. margin-bottom: 20rpx;
  320. padding: 20rpx 20rpx 33rpx 20rpx;
  321. position: absolute;
  322. z-index: 100;
  323. display: none;
  324. .title{
  325. font-size: 26rpx;
  326. }
  327. .img{
  328. margin-top: 10rpx;
  329. width: 100%;
  330. height: 261rpx;
  331. display: block;
  332. margin-left: auto;
  333. margin-right: auto;
  334. background-color: #f6f6f6;
  335. }
  336. .drag-icon{
  337. position: absolute;
  338. top: 0;
  339. right: 0;
  340. width: 40rpx;
  341. height: 40rpx;
  342. }
  343. }
  344. </style>