workbench-filter.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. <template>
  2. <view class="filter-popup">
  3. <view class="popup-header">
  4. <!-- <view class="text">筛选</view> -->
  5. <text class="wk wk-close icon" @click="handleCloseFilter" />
  6. <view class="wk-tabs">
  7. <view
  8. v-for="(tab, index) in tabs"
  9. :key="index"
  10. :class="{active: activeTab === tab.value}"
  11. class="wk-tab-item"
  12. @click="handleToggleTabs(tab.value)">
  13. {{ tab.label }}
  14. </view>
  15. </view>
  16. </view>
  17. <view class="popup-content">
  18. <view
  19. v-if="activeTab === 'userOrDept'"
  20. class="filter-user-dept">
  21. <view
  22. v-for="item in filterDataTypeOptions"
  23. :key="item.value"
  24. :class="{active: filterObj.dataType === item.value}"
  25. class="data-range-item"
  26. @click="handleDataRangeChange(item)">
  27. <text class="text">
  28. {{ item.label }}
  29. </text>
  30. <text v-if="filterObj.dataType === item.value && !item.value !== 0" class="wk wk-check icon" />
  31. <text v-if="item.value === 0" class="wk wk-arrow-right icon" />
  32. </view>
  33. </view>
  34. <view
  35. v-if="activeTab === 'time'"
  36. class="filter-time">
  37. <view class="title">
  38. 时间
  39. </view>
  40. <view class="time-container">
  41. <view
  42. v-for="(item, index) in timeOptions"
  43. :key="index"
  44. :class="{ active: filterObj.dateFilter === item.value }"
  45. class="box-item"
  46. @click="handleTimeRange(item)">
  47. {{ item.label }}
  48. </view>
  49. <view class="box-item empty" />
  50. </view>
  51. <view
  52. v-if="filterObj.dateFilter === 'custom'"
  53. class="defined-filter">
  54. <view
  55. class="start time-box"
  56. @click="handleChooseDate('startDate')">
  57. <image
  58. :src="$static('images/icon/calendar_gray.png')"
  59. class="calendar-icon" />
  60. <text v-if="filterObj.startDate">
  61. {{ filterObj.startDate }}
  62. </text>
  63. <text v-else class="wk-placeholder">
  64. 开始时间
  65. </text>
  66. </view>
  67. <text class="ident">
  68. --
  69. </text>
  70. <view
  71. :class="{ active: !!filterObj.endDate }"
  72. class="end time-box"
  73. @click="handleChooseDate('endDate')">
  74. <image
  75. :src="$static('images/icon/calendar_gray.png')"
  76. class="calendar-icon" />
  77. <text v-if="filterObj.endDate">
  78. {{ filterObj.endDate }}
  79. </text>
  80. <text v-else class="wk-placeholder">
  81. 结束时间
  82. </text>
  83. </view>
  84. </view>
  85. </view>
  86. <view
  87. class="btn-group">
  88. <button class="button reset-btn" @click="handleReset">
  89. <image
  90. :src="$static('images/icon/delete_besom.png')"
  91. class="icon" />
  92. 重置
  93. </button>
  94. <button class="button" @click="emitFilterData">
  95. 确定
  96. </button>
  97. </view>
  98. </view>
  99. <uni-popup ref="popup" type="picker" @change="childPopupChange">
  100. <wk-date-picker
  101. v-model="timeValue"
  102. type="date"
  103. @select="handleSelectTime" />
  104. </uni-popup>
  105. </view>
  106. </template>
  107. <script>
  108. import { timeOptions } from '@/utils/data.js'
  109. import { deepCopy } from '@/utils/lib.js'
  110. import moment from 'moment'
  111. export default {
  112. name: 'WorkbenchFilter',
  113. props: {
  114. filterData: {
  115. type: Object,
  116. default: () => {}
  117. },
  118. defaultTab: {
  119. type: String,
  120. default: 'userOrDept'
  121. }
  122. },
  123. data() {
  124. return {
  125. guid: null,
  126. tabs: [
  127. { label: '员工与部门', value: 'userOrDept' },
  128. { label: '时间筛选', value: 'time' },
  129. ],
  130. activeTab: 'userOrDept',
  131. filterDataTypeOptions: [
  132. { label: '仅本人', value: 1 },
  133. { label: '本人及下属', value: 2 },
  134. { label: '仅本部门', value: 3 },
  135. { label: '本部门及下属部门', value: 4 },
  136. { label: '自定义', value: 0 }
  137. ],
  138. timeOptions: timeOptions,
  139. timeValue: '',
  140. dateField: null,
  141. filterObj: {
  142. dataType: 2,
  143. dateFilter: 'month',
  144. startDate: '',
  145. endDate: '',
  146. userList: [],
  147. deptList: []
  148. }
  149. }
  150. },
  151. watch: {
  152. defaultTab: {
  153. handler() {
  154. this.activeTab = this.defaultTab
  155. },
  156. immediate: true
  157. },
  158. filterData: {
  159. handler(val) {
  160. const data = deepCopy(val || {})
  161. this.filterObj = {
  162. dataType: !this.filterData ? 2 : this.filterData.dataType,
  163. dateFilter: !this.filterData ? 'month' : this.filterData.dateFilter,
  164. startDate: !this.filterData ? null : this.filterData.startDate,
  165. endDate: !this.filterData ? null : this.filterData.endDate,
  166. userList: !this.filterData ? [] : this.filterData.userList,
  167. userListObj: [],
  168. deptList: !this.filterData ? [] : this.filterData.deptList,
  169. deptListObj: []
  170. }
  171. },
  172. deep: true,
  173. immediate: true
  174. }
  175. },
  176. created() {
  177. this.guid = this.$guid()
  178. },
  179. methods: {
  180. /**
  181. * 切换tab
  182. * @param {String} tab
  183. */
  184. handleToggleTabs(tab) {
  185. this.activeTab = tab
  186. },
  187. childPopupChange(evt) {
  188. this.$emit('popup-change', evt.show)
  189. },
  190. closeChildPopup() {
  191. this.$refs.popup.close()
  192. },
  193. /**
  194. * 修改数据范围
  195. * @param {Object} item
  196. */
  197. handleDataRangeChange(item) {
  198. this.filterObj.dataType = item.value
  199. if (item.value === 0) {
  200. getApp().globalData.selectedValBridge.userAndDept = {
  201. guid: this.guid,
  202. defaultVal: {
  203. userList: this.filterObj.userListObj,
  204. deptList: this.filterObj.deptListObj
  205. }
  206. }
  207. uni.$on('selected-user-and-dept', this.selectedUserOrDept)
  208. this.$Router.navigateTo({
  209. url: '/pages_common/selectList/userAndDept'
  210. })
  211. } else {
  212. this.filterObj.userList = []
  213. this.filterObj.userListObj = []
  214. this.filterObj.deptList = []
  215. this.filterObj.deptListObj = []
  216. // this.emitFilterData()
  217. }
  218. },
  219. /**
  220. * 选择员工部门回调
  221. * @param {Object} data
  222. */
  223. selectedUserOrDept(data) {
  224. if (data.guid === this.guid) {
  225. uni.$off('selected-user-and-dept')
  226. let {deptList = [], userList = []} = data.data
  227. this.filterObj.deptList = deptList.map((item, index) => {
  228. return item.deptId
  229. })
  230. this.filterObj.userList = userList.map((item, index) => {
  231. return item.userId
  232. })
  233. if (deptList.length === 0 && userList === 0) {
  234. setTimeout(() => {
  235. this.$toast('请选择员工或部门')
  236. }, 200)
  237. } else {
  238. this.emitFilterData()
  239. }
  240. }
  241. },
  242. /**
  243. * 修改时间区间
  244. * @param {Object} item
  245. */
  246. handleTimeRange(item) {
  247. if (item.value === 'custom') {
  248. this.filterObj.startDate = null
  249. this.filterObj.endDate = null
  250. }
  251. this.filterObj.dateFilter = item.value
  252. },
  253. /**
  254. * 去自定义选择时间
  255. * @param {Object} field
  256. */
  257. handleChooseDate(field) {
  258. this.timeValue = this.filterObj[field]
  259. this.dateField = field
  260. this.$refs.popup.open()
  261. },
  262. /**
  263. * 选择时间回调
  264. * @param {Object} date
  265. * @param {Object} next
  266. */
  267. handleSelectTime(date, next) {
  268. next()
  269. this.filterObj[this.dateField] = date
  270. let start = this.filterObj.startDate || null
  271. let end = this.filterObj.endDate || null
  272. if (start && end) {
  273. if (start > end) {
  274. this.filterObj[this.dateField] = ''
  275. this.$toast('开始时间不能大于结束时间')
  276. }
  277. }
  278. },
  279. /**
  280. * 重置时间区间
  281. */
  282. handleReset() {
  283. this.filterObj = {
  284. dataType: 2,
  285. dateFilter: 'month',
  286. startDate: null,
  287. endDate: null,
  288. userList: [],
  289. userListObj: [],
  290. deptList: [],
  291. deptListObj: []
  292. }
  293. },
  294. /**
  295. * 派发关闭事件
  296. */
  297. handleCloseFilter() {
  298. this.$emit('close')
  299. },
  300. /**
  301. * 派发筛选条件
  302. */
  303. emitFilterData() {
  304. if (this.filterObj.dataType === 0) {
  305. if (
  306. this.$isEmpty(this.filterObj.userList) &&
  307. this.$isEmpty(this.filterObj.deptList)
  308. ) {
  309. this.$toast('请选择员工或部门')
  310. return
  311. }
  312. }
  313. if (this.filterObj.dateFilter === 'custom') {
  314. const start = this.filterObj.startDate || null
  315. const end = this.filterObj.endDate || null
  316. if (!start || !end) {
  317. this.$toast('请选择筛选时间段')
  318. return
  319. }
  320. }
  321. this.$emit('change', this.filterObj)
  322. this.handleCloseFilter()
  323. }
  324. }
  325. }
  326. </script>
  327. <style scoped lang="scss">
  328. .wk-tabs {
  329. .wk-tab-item {
  330. padding: 15rpx 0;
  331. // &::after {
  332. // width: 50%;
  333. // }
  334. &.active {
  335. color: $theme-color;
  336. }
  337. }
  338. }
  339. .filter-popup {
  340. padding: 10rpx 36rpx 20rpx 36rpx;
  341. position: relative;
  342. .popup-header {
  343. position: relative;
  344. @include center;
  345. .text {
  346. font-size: $wk-font-large;
  347. }
  348. .icon {
  349. position: absolute;
  350. left: -20rpx;
  351. top: 50%;
  352. transform: translateY(-50%);
  353. color: $gray;
  354. font-size: $wk-font-medium;
  355. padding: 20rpx;
  356. }
  357. }
  358. .popup-content {
  359. width: 100%;
  360. height: 750rpx;
  361. margin-top: 20rpx;
  362. overflow: auto;
  363. display: flex;
  364. align-items: flex-start;
  365. justify-content: flex-start;
  366. flex-direction: column;
  367. padding-bottom: 100rpx;
  368. .filter-user-dept {
  369. width: 100%;
  370. .data-range-item {
  371. color: $dark;
  372. font-size: $wk-font-base;
  373. border-bottom: 1rpx solid $border-color;
  374. padding: 22rpx 0;
  375. @include left;
  376. .text {
  377. flex: 1;
  378. }
  379. .icon {
  380. font-size: $wk-font-medium;
  381. color: inherit;
  382. line-height: 1;
  383. }
  384. &.active {
  385. color: $theme-color;
  386. }
  387. }
  388. }
  389. .filter-time {
  390. flex: 1;
  391. width: 100%;
  392. .title {
  393. font-size: $wk-font-base;
  394. font-weight: bold;
  395. color: $dark;
  396. }
  397. .time-container {
  398. width: 100%;
  399. display: flex;
  400. justify-content: space-between;
  401. flex-wrap: wrap;
  402. .box-item {
  403. width: 32%;
  404. height: 60rpx;
  405. color: #666;
  406. font-size: $wk-font-base;
  407. background-color: #f4f4f4;
  408. border-radius: 10rpx;
  409. margin-top: 20rpx;
  410. @include center;
  411. &.active {
  412. color: $theme-color;
  413. background-color: #E7F0FF;
  414. }
  415. &.empty {
  416. visibility: hidden;
  417. }
  418. }
  419. }
  420. .defined-filter {
  421. font-size: $wk-font-base;
  422. margin-top: 25rpx;
  423. @include left;
  424. .time-box {
  425. flex: 1;
  426. text-align: center;
  427. border: 1rpx solid #E1E1E1;
  428. border-radius: 6rpx;
  429. padding: 10rpx 15rpx;
  430. @include left;
  431. &.active {
  432. color: #333;
  433. }
  434. .calendar-icon {
  435. width: 38rpx;
  436. height: 38rpx;
  437. margin-right: 10rpx;
  438. }
  439. .wk-placeholder {
  440. font-size: inherit;
  441. }
  442. }
  443. .ident {
  444. color: #CDCDCD;
  445. padding: 0 30rpx;
  446. }
  447. }
  448. }
  449. .btn-group {
  450. width: 100%;
  451. @include center;
  452. position: absolute;
  453. bottom: 0rpx;
  454. left: 0;
  455. right: 0;
  456. padding:0 38rpx 30rpx;
  457. background: white;
  458. border-top: 1px solid white;
  459. .button {
  460. flex: 1;
  461. height: 80rpx;
  462. color: white;
  463. font-size: $wk-font-base;
  464. background-color: $theme-color;
  465. border-radius: 12rpx;
  466. @include center;
  467. }
  468. .reset-btn {
  469. width: 180rpx;
  470. flex-shrink: 0;
  471. flex: unset;
  472. color: $dark;
  473. background-color: #F5F5F5;
  474. margin-right: 30rpx;
  475. .icon {
  476. width: 32rpx;
  477. height: 32rpx;
  478. vertical-align: baseline;
  479. margin-right: 10rpx;
  480. }
  481. }
  482. }
  483. }
  484. }
  485. </style>