dropdownPanel.vue 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. <template>
  2. <view class="filter-wrapper" :style="{ height: height + 'px'}" @touchmove.stop.prevent="discard">
  3. <view class="inner-wrapper">
  4. <view class="mask" :class="showMask ? 'show' : 'hide'" :style="{top: top}" @tap="tapMask"></view>
  5. <view class="navs">
  6. <view class="c-flex-center" :class="{ 'c-flex-center': index > 0, actNav: index === actNav }" v-for="(item, index) in navData" :key="index" @click="navClick(index)">
  7. <view v-if="item.special&&item.name=='批量'" class="x-f" style="align-items: end;">
  8. <u-icon name="file-text" :color="index === actNav ?'#2979ff':'#222'" size="20"></u-icon>
  9. {{index === actNav ? '取消批量':'批量'}}
  10. </view>
  11. <template v-else>
  12. <text>{{item.name}}</text>
  13. <image src="https://i.loli.net/2020/07/15/QsHxlr1gbSImvWt.png" mode="" class="icon-triangle" v-if="index === actNav"></image>
  14. <image src="https://i.loli.net/2020/07/15/xjVSvzWcH9NO7al.png" mode="" class="icon-triangle" v-else></image>
  15. </template>
  16. </view>
  17. </view>
  18. <view scroll-y="true" class="popup" :class="popupShow ? 'popupShow' : ''">
  19. <scroll-view scroll-y="true" style="height: 30vh;"><slot></slot></scroll-view>
  20. <view class="footer x-bc">
  21. <view class="footer-btn" @click="reset">重置</view>
  22. <view class="footer-btn footer-blue" @click="confirm">确认</view>
  23. </view>
  24. </view>
  25. </view>
  26. </view>
  27. </template>
  28. <script>
  29. // import { getCurDateTime } from '@/libs/utils.js';
  30. export default {
  31. props: {
  32. height: {
  33. type: Number,
  34. default: 40
  35. },
  36. // top: {
  37. // type: String,
  38. // default: 'calc(var(--window-statsu-bar) + 44px)'
  39. // },
  40. border: {
  41. type: Boolean,
  42. default: false
  43. },
  44. filterData: {
  45. //必填
  46. type: Array,
  47. default: () => {
  48. return []
  49. }
  50. },
  51. defaultIndex: {
  52. //默认选中条件索引,超出一类时必填
  53. type: Array,
  54. default: () => {
  55. return [0];
  56. }
  57. }
  58. },
  59. data() {
  60. return {
  61. top: 0,
  62. navData: [],
  63. popupShow: false,
  64. showMask: false,
  65. actNav: null,
  66. selIndex: [] //选中条件索引
  67. };
  68. },
  69. created() {
  70. this.navData = this.filterData;
  71. this.selIndex = this.defaultIndex;
  72. // this.keepStatus();
  73. },
  74. mounted() {
  75. const query = uni.createSelectorQuery().in(this);
  76. query
  77. .select(".filter-wrapper")
  78. .boundingClientRect((data) => {
  79. console.log(data)
  80. this.top = data.top + 'px'
  81. })
  82. .exec();
  83. },
  84. methods: {
  85. reset() {
  86. this.$emit('reset');
  87. },
  88. confirm() {
  89. this.showMask = false;
  90. this.popupShow = false;
  91. this.$emit('confirm');
  92. },
  93. keepStatus() {
  94. // this.navData.forEach(itemnavData => {
  95. // itemnavData.map(child => {
  96. // child.select = false;
  97. // });
  98. // return itemnavData;
  99. // });
  100. // for (let i = 0; i < this.selIndex.length; i++) {
  101. // let selindex = this.selIndex[i];
  102. // this.navData[i][selindex].select = true;
  103. // }
  104. },
  105. navClick(index) {
  106. if (index === this.actNav) {
  107. this.tapMask();
  108. return;
  109. }
  110. this.popupShow = true;
  111. this.showMask = true;
  112. this.actNav = index;
  113. this.$emit('onChange', this.actNav);
  114. },
  115. handleOpt(index) {
  116. // this.selIndex[this.actNav] = index;
  117. // this.keepStatus();
  118. // setTimeout(() => {
  119. // this.tapMask();
  120. // }, 100);
  121. // let data = [];
  122. // let res = this.navData.forEach(item => {
  123. // let sel = item.filter(child => child.select);
  124. // data.push(sel);
  125. // });
  126. // console.log(data);
  127. // this.$emit('onSelected', data);
  128. },
  129. tapMask() {
  130. this.showMask = false;
  131. this.popupShow = false;
  132. this.actNav = null;
  133. },
  134. discard() {}
  135. }
  136. };
  137. </script>
  138. <style lang="scss" scoped>
  139. .c-flex-align {
  140. display: flex;
  141. align-items: center;
  142. }
  143. .c-flex-center {
  144. display: flex;
  145. align-items: center;
  146. justify-content: center;
  147. flex-direction: column;
  148. }
  149. .footer {
  150. font-family: PingFang SC, PingFang SC;
  151. font-weight: 400;
  152. font-size: 14px;
  153. color: #222;
  154. padding: 10px;
  155. &-btn {
  156. flex: 1;
  157. text-align: center;
  158. background-color: #fff;
  159. border: 1px solid #999;
  160. border-radius: 50px;
  161. padding: 10px 0;
  162. }
  163. &-blue {
  164. background-color: #1677ff;
  165. border: 1px solid #1677ff;
  166. color: #fff;
  167. margin-left: 10px;
  168. }
  169. }
  170. .filter-wrapper {
  171. // position: fixed;
  172. // left: 0;
  173. // width: 750rpx;
  174. // z-index: 999;
  175. .inner-wrapper {
  176. // position: relative;
  177. .navs {
  178. position: relative;
  179. font-family: PingFang SC, PingFang SC;
  180. font-weight: 400;
  181. font-size: 14px;
  182. color: #222;
  183. padding: 10px;
  184. display: flex;
  185. align-items: center;
  186. justify-content: space-between;
  187. background-color: #fff;
  188. z-index: 999;
  189. box-sizing: border-box;
  190. & > view {
  191. flex: 1;
  192. height: 100%;
  193. flex-direction: row;
  194. z-index: 999;
  195. }
  196. .date {
  197. justify-content: flex-end;
  198. }
  199. .actNav {
  200. color: #1677ff;
  201. font-weight: bold;
  202. }
  203. }
  204. .mask {
  205. z-index: 666;
  206. position: fixed;
  207. top:0;
  208. left: 0;
  209. right: 0;
  210. bottom: 0;
  211. background-color: rgba(0, 0, 0, 0);
  212. transition: background-color 0.15s linear;
  213. &.show {
  214. background-color: rgba(0, 0, 0, 0.4);
  215. }
  216. &.hide {
  217. display: none;
  218. }
  219. }
  220. .popup {
  221. position: relative;
  222. // max-height: 500rpx;
  223. background-color: #fff;
  224. border-bottom-left-radius: 20rpx;
  225. border-bottom-right-radius: 20rpx;
  226. overflow: scroll;
  227. z-index: 999;
  228. transition: all 1s linear;
  229. opacity: 0;
  230. display: none;
  231. .item-opt {
  232. height: 100rpx;
  233. padding: 0 40rpx;
  234. color: #8b9aae;
  235. border-bottom: 2rpx solid #f5f6f9;
  236. }
  237. .actOpt {
  238. color: #1677ff;
  239. font-weight: bold;
  240. position: relative;
  241. &::after {
  242. content: '✓';
  243. font-weight: bold;
  244. font-size: 36rpx;
  245. position: absolute;
  246. right: 40rpx;
  247. }
  248. }
  249. }
  250. .popupShow {
  251. display: block;
  252. opacity: 1;
  253. }
  254. }
  255. .icon-triangle {
  256. width: 16rpx;
  257. height: 16rpx;
  258. margin-left: 10rpx;
  259. }
  260. }
  261. </style>