ApproveRecord.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. <template>
  2. <!-- 考勤审批列表 -->
  3. <div>
  4. <van-nav-bar title="考勤审批" left-text="返回" left-arrow @click-left="$route_back" />
  5. <div class="approveRecord">
  6. <van-tabs v-model="status" @change="handleClick">
  7. <van-tab name="waiting" :title="'待我审批(' + reviewTotal + ')'"></van-tab>
  8. <van-tab name="dealed" title="我已审批"></van-tab>
  9. <van-tab name="all" title="抄送给我"></van-tab>
  10. </van-tabs>
  11. <div class="head-Nav">
  12. <van-row>
  13. <van-col span="22"><van-search v-model="keyword" class="leftkep" placeholder="搜索审批内容" @input="keyInp()" /></van-col>
  14. <van-col span="2" @click="showFillter"><van-icon name="filter-o" class="rightsx" /></van-col>
  15. </van-row>
  16. </div>
  17. <div style="position: relative;height: calc(100% - 2rem) !important;">
  18. <scroller ref="scroller" :isInitRefresh="false" :onRefresh="refresh" :onInfinite="infinite" noDataText="没有了噢" :list="reviewList">
  19. <div v-for="item of reviewList" :key="item.id" class="item" @click="$router.push({ name: 'RecordDetail', query: { id: item.id } })">
  20. <div class="content">
  21. <div class="title">
  22. <div class="detail">{{ item.employee_name }}提交的{{ filterType(item.type) }}申请</div>
  23. <div :class="{ wait: item.status == 0, refuse: item.status == -1 }" class="status">{{ filterStatus(item.status) }}</div>
  24. </div>
  25. <div v-if="item.type == 5" class="desc">申请类型:{{ item.holiday_name }}</div>
  26. <div class="desc">申请时间:{{ formatTime(item.create_time) }}</div>
  27. <template v-if="item.type == 0">
  28. <div class="desc">补卡时间:{{ item.start_time }}</div>
  29. <!-- <div class="desc">结束时间:{{ item.end_time }}</div> -->
  30. </template>
  31. <template v-else>
  32. <div class="desc">开始时间:{{ item.start_time }}</div>
  33. <div class="desc">结束时间:{{ item.end_time }}</div>
  34. </template>
  35. </div>
  36. </div>
  37. <van-empty description="暂无数据" v-if="reviewList.length == 0" />
  38. <div style="height: 1rem;"></div>
  39. </scroller>
  40. </div>
  41. <!-- 筛选 -->
  42. <div v-show="fillterVisibale" class="fillterWrapper" :style="setNavstyle">
  43. <div class="fillter">
  44. <div class="fillterTitle">申请类型</div>
  45. <div class="fillterItems">
  46. <div :class="{ active: type == -1 }" @click="type = -1" class="fillterItem type">全部</div>
  47. <div :class="{ active: type == 5 }" class="fillterItem type" @click="type = 5">请假</div>
  48. <div :class="{ active: type == 4 }" class="fillterItem type" @click="type = 4">外出</div>
  49. <div :class="{ active: type == 3 }" class="fillterItem type" @click="type = 3">出差</div>
  50. <div :class="{ active: type == 2 }" class="fillterItem type" @click="type = 2">加班</div>
  51. <div :class="{ active: type == 1 }" class="fillterItem type" @click="type = 1">补卡</div>
  52. </div>
  53. </div>
  54. <div @click="getReviewHistroy()" class="confirmBtn">确认</div>
  55. </div>
  56. </div>
  57. </div>
  58. </template>
  59. <script>
  60. import Vue from 'vue';
  61. import { _debounce } from '@/utils/auth';
  62. import { Tab, Tabs, Search } from 'vant';
  63. Vue.use(Tab)
  64. .use(Tabs)
  65. .use(Search);
  66. export default {
  67. data() {
  68. return {
  69. reviewList: [],
  70. keyword: '',
  71. fillterVisibale: false,
  72. status: 'waiting',
  73. type: -1,
  74. page: 1,
  75. reviewTotal: 0,
  76. setNavstyle: '',
  77. };
  78. },
  79. watch: {
  80. '$route.query.goFillter'(val) {
  81. if (!val) {
  82. this.fillterVisibale = false;
  83. }
  84. }
  85. },
  86. created() {
  87. if (this.$route.query.type != undefined) {
  88. this.type = this.$route.query.type;
  89. }
  90. },
  91. mounted() {
  92. this.isApp();
  93. },
  94. activated() {
  95. this.pullDown()
  96. },
  97. methods: {
  98. pullDown(){
  99. setTimeout(() => {
  100. this.$refs.scroller.triggerPullToRefresh();
  101. }, 50);
  102. },
  103. keyInp: _debounce(function() {
  104. // 搜索
  105. this.pullDown()
  106. }),
  107. handleClick(name, title) {
  108. this.pullDown()
  109. },
  110. isApp() {
  111. if (window.plus) {
  112. this.setNavstyle = 'top: calc(0.88rem + 1px + ' + plus.navigator.getStatusbarHeight() + 'px);';
  113. }
  114. },
  115. formatTime(val) {
  116. return this.$moment(val * 1000).format('YYYY-MM-DD HH:mm');
  117. },
  118. // 上拉刷新
  119. refresh (done) {
  120. this.getReviewHistroy(false,done)
  121. },
  122. // 下拉加载
  123. infinite (done) {
  124. this.page++;
  125. this.getReviewHistroy(true,done)
  126. },
  127. filterVacationType(type) {
  128. switch (type) {
  129. case 0:
  130. return '年假';
  131. case 1:
  132. return '事假';
  133. case 2:
  134. return '病假';
  135. case 3:
  136. return '调休';
  137. case 4:
  138. return '产假';
  139. case 5:
  140. return '婚假';
  141. case 6:
  142. return '例假';
  143. case 7:
  144. return '丧假';
  145. }
  146. },
  147. filterStatus(status) {
  148. if (status === 0) {
  149. return '待审批';
  150. }
  151. if (status === 1) {
  152. return '审批通过';
  153. }
  154. if (status === -1) {
  155. return '审批驳回';
  156. }
  157. },
  158. filterType(type) {
  159. switch (type) {
  160. case 0:
  161. return '补卡';
  162. case 1:
  163. return '加班';
  164. case 2:
  165. return '出差';
  166. case 3:
  167. return '外出';
  168. case 4:
  169. return '请假';
  170. }
  171. },
  172. getReviewHistroy(is,callback) {
  173. let hasMore = false
  174. is? '':this.page=1;
  175. if (this.fillterVisibale) {
  176. this.fillterVisibale = false;
  177. }
  178. let params = {
  179. page: this.page,
  180. type: this.type,
  181. status: this.status,
  182. page_size: 10,
  183. keyword: this.keyword,
  184. is_reviewer:this.status=='all'? 2:1,
  185. };
  186. this.$axiosKq('post', '/ad/review', params).then(res => {
  187. if (res.data.code === 1) {
  188. let data = res.data.data;
  189. if (this.status == 'waiting' && this.type == -1) {
  190. this.reviewTotal = data.total;
  191. }
  192. if (this.page === 1) {
  193. this.reviewList = data.review_list
  194. } else {
  195. this.reviewList = this.reviewList.concat(data.review_list)
  196. }
  197. hasMore = data.review_list.length !== 10
  198. callback && callback(hasMore)
  199. }
  200. });
  201. },
  202. showFillter() {
  203. this.fillterVisibale = true;
  204. }
  205. },
  206. };
  207. </script>
  208. <style lang="scss" scoped>
  209. .approveRecord /deep/ .mint-tab-item .mint-tab-item-label {
  210. font-size: 0.32rem;
  211. }
  212. .fillterWrapper {
  213. z-index: 1;
  214. position: fixed;
  215. top: 0.88rem;
  216. .confirmBtn {
  217. position: fixed;
  218. left: 0;
  219. bottom: 0;
  220. height: 1rem;
  221. line-height: 1rem;
  222. text-align: center;
  223. color: #fff;
  224. background: rgb(55, 171, 254);
  225. width: 100%;
  226. }
  227. background-color: #fff;
  228. height: 100%;
  229. .fillterTitle {
  230. line-height: 0.8rem;
  231. position: relative;
  232. padding-left: 0.4rem;
  233. margin-left: 0.15rem;
  234. margin-top: 0.2rem;
  235. font-size: 0.3rem;
  236. &::after {
  237. content: '';
  238. position: absolute;
  239. top: 0.26rem;
  240. left: 0;
  241. width: 0.24rem;
  242. height: 0.24rem;
  243. border-radius: 50%;
  244. background-color: rgb(72, 169, 239);
  245. }
  246. }
  247. .fillter:nth-of-type(2) .fillterTitle::after {
  248. background-color: rgb(22, 195, 149);
  249. }
  250. .fillterItems {
  251. display: flex;
  252. flex-wrap: wrap;
  253. .fillterItem {
  254. width: 2rem;
  255. height: 1rem;
  256. text-align: center;
  257. line-height: 1rem;
  258. background: rgb(243, 243, 243);
  259. border-radius: 0.2rem;
  260. font-size: 0.28rem;
  261. margin-left: 0.36rem;
  262. margin-bottom: 0.36rem;
  263. &.type {
  264. width: 3.2rem;
  265. }
  266. &.active {
  267. background-color: rgb(228, 240, 250);
  268. color: rgb(119, 191, 241);
  269. }
  270. }
  271. }
  272. .fillter:nth-of-type(2) .fillterItems .fillterItem.active {
  273. background-color: rgb(220, 245, 239);
  274. color: rgb(75, 208, 172);
  275. }
  276. }
  277. .searchItems {
  278. display: flex;
  279. padding-top: 0.4rem;
  280. .searchItem {
  281. flex: 1;
  282. font-size: 0.24rem;
  283. color: #909399;
  284. text-align: center;
  285. .searchItemIcon {
  286. width: 0.5rem;
  287. margin-bottom: 0.18rem;
  288. }
  289. }
  290. }
  291. .searchTip {
  292. margin-top: 1.2rem;
  293. padding: 0 0.8rem;
  294. display: flex;
  295. align-items: center;
  296. justify-content: space-between;
  297. font-size: 0.28rem;
  298. color: #909399;
  299. span {
  300. width: 26%;
  301. height: 0.02rem;
  302. background-color: #eee;
  303. }
  304. }
  305. .searchWrapper {
  306. background-color: #fff;
  307. height: 100%;
  308. position: fixed;
  309. top: 0.88rem;
  310. left: 0;
  311. width: 100%;
  312. .search {
  313. flex: 0 0 1rem;
  314. color: #26a2ff;
  315. padding-right: 0.2rem;
  316. text-align: center;
  317. background-color: #f5f7fa;
  318. height: 0.96rem;
  319. line-height: 0.96rem;
  320. font-size: 0.32rem;
  321. }
  322. }
  323. .topBar {
  324. height: 0.88rem;
  325. background-color: #fff;
  326. border-bottom: 0.02rem solid #eee;
  327. display: flex;
  328. align-items: center;
  329. font-size: 0.3rem;
  330. line-height: 0.5rem;
  331. .left {
  332. flex: 1;
  333. text-align: center;
  334. color: #909399;
  335. .searchIcon {
  336. width: 0.4rem;
  337. margin-right: 0.1rem;
  338. }
  339. }
  340. .right {
  341. flex: 1;
  342. text-align: center;
  343. color: #909399;
  344. .fillterIcon {
  345. width: 0.4rem;
  346. margin-right: 0.1rem;
  347. }
  348. }
  349. }
  350. .approveRecord {
  351. background-color: #f5f7fa;
  352. position: relative;
  353. height: calc(100% - 0.92rem) !important;
  354. }
  355. .wraper {
  356. // padding:0 0.32rem;
  357. // background-color: #fff;
  358. }
  359. .item {
  360. display: flex;
  361. padding: 0 0.32rem 0.26rem;
  362. margin-bottom: 0.24rem;
  363. background-color: #fff;
  364. }
  365. .avatar {
  366. width: 0.86rem;
  367. height: 0.86rem;
  368. border-radius: 50%;
  369. margin: 0.4rem 0.2rem 0 0;
  370. flex-shrink: 0;
  371. }
  372. .content {
  373. // padding-top: 0.2rem;
  374. width: 100%;
  375. }
  376. .content .title {
  377. display: flex;
  378. justify-content: space-between;
  379. align-items: center;
  380. // padding-bottom: 0.12rem;
  381. margin: 0.32rem 0 0.16rem 0;
  382. .detail {
  383. font-size: 0.34rem;
  384. flex: 0 0 4.5rem;
  385. overflow: hidden;
  386. text-overflow: ellipsis;
  387. white-space: nowrap;
  388. }
  389. }
  390. .content .desc {
  391. font-size: 0.28rem;
  392. color: #909399;
  393. margin-bottom: 0.08rem;
  394. }
  395. .content .status {
  396. font-size: 0.34rem;
  397. color: rgb(70, 211, 173);
  398. }
  399. .content .status.wait {
  400. color: rgb(235, 179, 102);
  401. }
  402. .content .status.refuse {
  403. color: rgb(246, 138, 119);
  404. }
  405. .content .status.cancel {
  406. color: rgb(101, 101, 101);
  407. }
  408. .title .time {
  409. padding-right: 0.2rem;
  410. font-size: 0.28rem;
  411. color: #909399;
  412. }
  413. .head-Nav {
  414. background-color: #fff;
  415. border-bottom: 1px solid #f1f1f1;
  416. .leftkep {
  417. padding: 0.2rem 0.12rem 0.2rem 0.32rem;
  418. }
  419. .rightsx {
  420. margin: 0.35rem 0 0 0.1rem;
  421. }
  422. }
  423. </style>
  424. <style>
  425. .searchIcon path {
  426. fill: rgb(51, 51, 51);
  427. }
  428. </style>