filtrate.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. <template>
  2. <view class="filtrate-box">
  3. <view :style="{ position: 'absolute', zIndex: index }">
  4. <u-transition :show="show">
  5. <view class="shade" catchtouchmove="true" @touchmove.stop.prevent="() => { }" @click="changeShow">
  6. <view @click.stop="">
  7. <scroll-view :style="{ maxHeight: tovw(maxHeight) }" class="scroll-view" scroll-y>
  8. <block v-for="(item, index) in list" :key="item.key">
  9. <block v-if="item.type == 'dateRange'">
  10. <view class="date-label">
  11. {{ item.title || '时间区间' }}
  12. </view>
  13. <view class="date-box">
  14. <scroll-view :scroll-x="true">
  15. <view class="options">
  16. <view class="item" hover-class="navigator-hover"
  17. :class="item.day == 1 ? 'active' : ''" @click="fast(1, index)">
  18. 今天
  19. </view>
  20. <view class="item" hover-class="navigator-hover"
  21. :class="item.day == 7 ? 'active' : ''" @click="fast(7, index)">
  22. 7天
  23. </view>
  24. <view class="item" hover-class="navigator-hover"
  25. :class="item.day == 30 ? 'active' : ''" @click="fast(30, index)">
  26. 30天
  27. </view>
  28. <view style="width: 10px;" />
  29. <u-number-box :value="item.day || 1" @change="valChange($event, index)" />
  30. </view>
  31. </scroll-view>
  32. <view class="row" style="margin-top: 20px">
  33. <picker mode="date" class="date-box"
  34. :style="{ color: item.begindate ? '#333' : '#ddd' }" :value="item.begindate"
  35. data-name="begindate" :end="enddate" @change="onDateChange($event, index)">
  36. {{ item.begindate || '开始日期' }}
  37. </picker>
  38. <view style="padding: 0 10px;">
  39. -
  40. </view>
  41. <picker mode="date" class="date-box"
  42. :style="{ color: item.enddate ? '#333' : '#ddd' }" :value="item.enddate"
  43. data-name="enddate" @change="onDateChange($event, index)" :start="enddate">
  44. {{ item.enddate || '结束日期' }}
  45. </picker>
  46. </view>
  47. </view>
  48. </block>
  49. <group v-else :ref="'group' + index" :item="item" :rowIndex="index" @onChange="onChange" />
  50. </block>
  51. </scroll-view>
  52. <view class="but-box">
  53. <view class="reset" hover-class="navigator-hover" @click="onReset">
  54. 重置
  55. </view>
  56. <view class="confirm" hover-class="navigator-hover" @click="onConfirm">
  57. 确定
  58. </view>
  59. </view>
  60. </view>
  61. </view>
  62. </u-transition>
  63. </view>
  64. </view>
  65. </template>
  66. <script>
  67. import group from "./filtrate-group.vue"
  68. export default {
  69. components: { group },
  70. props: {
  71. zIndex: {
  72. type: [String, Number],
  73. default: 9
  74. },
  75. filtrateList: {
  76. type: Array,
  77. default: [{
  78. title: "",//组名称
  79. key: 'id',//提交时返回的Key
  80. showKey: "",//显示的key
  81. selected: "",//选择时选择的字段
  82. isAll: false,//true 返回整个对象 false 返回selected选中的value
  83. value: "",//提交时选中的value
  84. defaultVal: "",//默认值
  85. rang: "",//选择的范围
  86. interrupt: false,//中断
  87. }]
  88. },
  89. onFiltration: {
  90. type: Function
  91. },
  92. onInterrupt: {
  93. type: Function
  94. }
  95. },
  96. watch: {
  97. filtrateList: {
  98. handler: function (newVal) {
  99. if (newVal) {
  100. this.list = JSON.parse(JSON.stringify(newVal));
  101. }
  102. },
  103. immediate: true,
  104. }
  105. },
  106. data() {
  107. return {
  108. show: false,
  109. maxHeight: 0,
  110. index: -99,
  111. list: [],
  112. }
  113. },
  114. methods: {
  115. changeShow() {
  116. this.show = !this.show;
  117. if (this.show) {
  118. this.index = this.zIndex
  119. setTimeout(this.setHeight, 10);
  120. } else {
  121. setTimeout(() => { this.index = -99 }, 150)
  122. }
  123. },
  124. setHeight() {
  125. this.getHeight(".filtrate-box", this).then(res => {
  126. this.maxHeight = res - 300;
  127. });
  128. },
  129. onChange(option, index) {
  130. let item = this.list[index];
  131. this.$set(item, 'value', item.selected ? option[item.selected] : option);
  132. try {
  133. if (item.isAll) item.selectObj = option;
  134. } catch (error) { }
  135. this.$set(this.list, index, item);
  136. if (item.interrupt) this.$emit("onInterrupt", { item, index, option })
  137. },
  138. onReset() {
  139. this.list = JSON.parse(JSON.stringify(this.filtrateList));
  140. },
  141. fast(num, index) {
  142. return new Promise((resolve) => {
  143. let now = new Date().getTime() - 0,
  144. end = now + 86400000,
  145. beg = end - (num * 86400000);
  146. this.list[index].begindate = this.formatTime(new Date(beg)).split(' ')[0];
  147. this.list[index].enddate = this.formatTime(new Date(end)).split(' ')[0];
  148. this.list[index].day = num;
  149. resolve()
  150. })
  151. },
  152. valChange(e, index) {
  153. this.fast(e.value, index)
  154. },
  155. onDateChange(e, index) {
  156. this[e.target.dataset.name] = e.detail.value;
  157. let item = this.list[index];
  158. if (item.begindate && item.enddate) {
  159. let end = new Date(item.enddate).getTime(),
  160. beg = new Date(item.begindate).getTime();
  161. item.day = (end - beg) / 86400000;
  162. }
  163. this.list[index] = item;
  164. },
  165. onConfirm() {
  166. let obj = {};
  167. this.list.forEach(v => {
  168. if (v.type == "dateRange") {
  169. obj[v.key] = {
  170. begindate: v.begindate,
  171. enddate: v.enddate,
  172. };
  173. } else {
  174. if (v.value || v.defaultVal) {
  175. if (v.isAll) {
  176. obj[v.key] = v.rang.find(s => s[v.selected] == v.value) || v.rang.find(s => s[v.selected] == v.defaultVal);
  177. } else {
  178. obj[v.key] = v.value || v.defaultVal;
  179. }
  180. } else {
  181. obj[v.key] = '';
  182. }
  183. }
  184. })
  185. this.$emit("onFiltration", obj)
  186. this.changeShow();
  187. },
  188. },
  189. }
  190. </script>
  191. <style lang="scss">
  192. .filtrate-box {
  193. position: relative;
  194. .scroll-view {
  195. width: 100vw;
  196. background: #fff;
  197. }
  198. .but-box {
  199. display: flex;
  200. justify-content: space-between;
  201. width: 100vw;
  202. padding: 10px;
  203. background: #fff;
  204. box-sizing: border-box;
  205. .reset {
  206. width: 82px;
  207. height: 45px;
  208. line-height: 45px;
  209. text-align: center;
  210. background: #FFFFFF;
  211. border-radius: 5px;
  212. border: 1px solid #999999;
  213. }
  214. .confirm {
  215. width: 263px;
  216. height: 45px;
  217. text-align: center;
  218. line-height: 45px;
  219. background: #C30D23;
  220. border-radius: 5px;
  221. font-size: 16px;
  222. color: #FFFFFF;
  223. }
  224. }
  225. .shade {
  226. position: absolute;
  227. top: 0;
  228. width: 100vw;
  229. height: 9999px;
  230. background: rgba($color: #000000, $alpha: .7);
  231. }
  232. }
  233. .date-label {
  234. line-height: 22px;
  235. font-family: PingFang SC, PingFang SC;
  236. font-weight: bold;
  237. font-size: 16px;
  238. color: #333333;
  239. padding: 10px;
  240. }
  241. .date-box {
  242. .active {
  243. background: #C30D23 !important;
  244. color: #FFFFFF !important;
  245. }
  246. .options {
  247. display: flex;
  248. .item {
  249. display: flex;
  250. align-items: center;
  251. justify-content: center;
  252. background: #F5F5F5;
  253. border-radius: 4px;
  254. margin-left: 10px;
  255. font-size: 14px;
  256. color: #333333;
  257. overflow: hidden;
  258. box-sizing: border-box;
  259. padding: 6px 12px;
  260. flex-shrink: 0;
  261. }
  262. /deep/ .u-number-box__minus,
  263. /deep/.u-number-box__input,
  264. /deep/.u-number-box__plus {
  265. height: 30px !important;
  266. }
  267. /deep/ .u-number-box__input {
  268. width: 35px !important;
  269. }
  270. }
  271. .row {
  272. display: flex;
  273. align-items: center;
  274. font-size: 14px;
  275. color: #646566;
  276. padding: 10px;
  277. padding-top: 0;
  278. border-bottom: 1px solid #ddd;
  279. box-sizing: border-box;
  280. .date-box {
  281. flex: 1;
  282. height: 35px;
  283. line-height: 35px;
  284. background: #FFFFFF;
  285. border-radius: 4px;
  286. border: 1px solid #CCCCCC;
  287. font-size: 14px;
  288. padding-left: 10px;
  289. }
  290. }
  291. }
  292. </style>