batchDistribution.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704
  1. <template>
  2. <view class="allocationPerson-page">
  3. <scroll-view class="scroll-y" scroll-y="true">
  4. <template>
  5. <view class="blockTitle">计划时间</view>
  6. <div class="date-view">
  7. <view class="row">
  8. <!-- 已经分配过的病区,再次修改禁止修改时间 -->
  9. <text class="label">开始时间</text>
  10. <view class="date-box">
  11. <date-time-picker :disabled="details.isDistribution" :height="100"
  12. :start="details.startDate" :end="details.planEndDate" :defaultValue="details.startDate"
  13. placeholder="请选择起始时间" pickType="startDate" @change="changeDateTime" />
  14. </view>
  15. </view>
  16. <view class="row">
  17. <text class="label">结束时间</text>
  18. <view class="date-box">
  19. <date-time-picker :disabled="details.isDistribution" :height="100"
  20. :start="details.planStartDate" :end="details.planEndDate"
  21. :defaultValue="details.endDate" placeholder="请选择结束时间" pickType="endDate"
  22. @change="changeDateTime" />
  23. </view>
  24. </view>
  25. </div>
  26. <view class="tabWrap" v-if="checkPointList.length >0">
  27. <view :class="[currentSelectedTab==0?'on tab':'tab']" @click="tabChangeHandle(0)" >{{`查核人(${checkPresonList.length})`}}</view>
  28. <view :class="[currentSelectedTab==1?'on tab':'tab']" @click="tabChangeHandle(1)">{{`要点分类(${checkedPointList.length})`}}</view>
  29. </view>
  30. <view class="blockTitle noBottomBlockTitle" v-if="checkPointList.length == 0">查核人<text>{{`已选择${checkPresonList.length}人`}}</text></view>
  31. <view v-if="currentSelectedTab==0">
  32. <view class="filter">
  33. <view class="selecter" @click="selecterHandle">
  34. <text>{{selectedDeptStr}}</text>
  35. <image src="../../static/fillBlackArrow.png" mode=""></image>
  36. </view>
  37. <view class="searchBar">
  38. <image class="serachIcon" src="../../static/searchIcon.png" mode=""></image>
  39. <tm-input class="searchVal" :clear="ifclearSearch" @onChange="searchInputHandle"
  40. placeholder="请输入搜索姓名"></tm-input>
  41. <view class="searchBtn" @click="searchHandle">搜索</view>
  42. </view>
  43. </view>
  44. <view class="empListWrapper" v-if="empList.length>0" :style="{height:empListWrapperH}">
  45. <tm-checked-group :list="empList" :defaultValue='checkPresonList' :setting="{
  46. value: 'employeeId',
  47. name: 'label'
  48. }" :openkeys="[0]" @change="onCheckPerosonChanged" />
  49. </view>
  50. <view class="empty" v-if="empList.length==0">
  51. <image src="../../static/no-data.png" mode=""></image>
  52. <text>暂无内容</text>
  53. </view>
  54. </view>
  55. <tm-checked-group v-if="details.situationType == 3&&currentSelectedTab==1" :list="checkPointList"
  56. :defaultValue='checkedPointList' :setting="{
  57. value: 'categoryId',
  58. name: 'categoryName'
  59. }" :openkeys="[0]" @change="checkChanged" />
  60. </template>
  61. </scroll-view>
  62. <view class="fixed-buttom-btn" @click="sure">
  63. <text class="btn-text">确定</text>
  64. </view>
  65. <uni-popup ref="popup" type="bottom" :maskClick="true">
  66. <view class="selectableList">
  67. <scroll-view scroll-y="true" class="listWrap">
  68. <view :class="getClass(v.id)" v-for="(v,i) in departments" @click="listClickHandle(v)">{{v.name}}
  69. </view>
  70. </scroll-view>
  71. <!-- <view class="listWrap">
  72. <view :class="getClass(v.id)" v-for="(v,i) in departments" @click="listClickHandle(v)">{{v.name}}
  73. </view>
  74. </view> -->
  75. <view class="btnGroup">
  76. <view class="cancelBtn btn" @click="btnGroupClickHandle(false)">取消</view>
  77. <view class="confirmBtn btn" @click="btnGroupClickHandle(true)">确定</view>
  78. </view>
  79. </view>
  80. </uni-popup>
  81. </view>
  82. </template>
  83. <script>
  84. // 查核列表编辑 查核人和计划时间
  85. import {
  86. mapState
  87. } from "vuex";
  88. import moment from 'moment';
  89. export default {
  90. computed: {
  91. selectedDeptStr() {
  92. const {
  93. deptIdStr
  94. } = this.filter;
  95. return (deptIdStr.map(t => t.name)).join(',')
  96. },
  97. empListWrapperH(){
  98. if(this.checkPointList.length >0){
  99. return 'calc(100vh - 485rpx)'
  100. }else{
  101. return 'calc(100vh - 460rpx)'
  102. }
  103. },
  104. ifclearSearch() {
  105. return this.filter.keyword.length == 0
  106. },
  107. },
  108. watch: {
  109. filter(val, oldVal) {
  110. if (val.keyword.length == 0) {
  111. this.searchHandle();
  112. }
  113. }
  114. },
  115. data() {
  116. return {
  117. title: '', // 导航标题
  118. // 查核组员列表
  119. empList: [],
  120. // 组件信息
  121. details: {},
  122. //选中的查核人
  123. checkPresonList: [],
  124. //查核要点列表
  125. checkPointList: [],
  126. // 服务器时间
  127. dateStr: '',
  128. timer: null,
  129. // 点击确定按钮是否直接保存
  130. isSubmit: false,
  131. //选中的查核要点
  132. checkedPointList: [],
  133. //可选单位列表
  134. departments: [],
  135. currentSelectedTab:0,//0 查核人 1 要点分类
  136. //筛选条件
  137. filter: {
  138. keyword: '',
  139. deptIdStr: [{
  140. name: '全部',
  141. id: 0
  142. }], //单位
  143. },
  144. }
  145. },
  146. onLoad({
  147. details
  148. }) {
  149. const _details = details ? JSON.parse(details) : {};
  150. //初始化默认时间
  151. const currentDate = new Date();
  152. _details.startDate = `${currentDate.getFullYear()}-${currentDate.getMonth()+1}-${currentDate.getDate()} 00:00`;
  153. _details.endDate = _details.planEndDate;
  154. // 强制刷新返回查核列表页面
  155. if (getCurrentPages().length === 1) {
  156. const {
  157. situationId,
  158. checkId,
  159. checkGroupId,
  160. planStartDate,
  161. planEndDate
  162. } = _details;
  163. uni.redirectTo({
  164. url: `/pages/editCheckList/editCheckList?situationId=${situationId}&checkId=${checkId}&checkGroupId=${checkGroupId}&startDate=${planStartDate}&endDate=${planEndDate}`
  165. });
  166. }
  167. this.pageQueryParams = _details;
  168. this.getComponentInfo(_details);
  169. },
  170. destroyed() {
  171. this.clearTimer();
  172. },
  173. methods: {
  174. tabChangeHandle(num){
  175. this.currentSelectedTab = num;
  176. },
  177. getClass(id) {
  178. const index = this.filter.deptIdStr.findIndex(t => t.id == id)
  179. if (index != -1) {
  180. return "list on"
  181. }
  182. return "list"
  183. },
  184. searchHandle() {
  185. const {
  186. checkGroupId,
  187. situationType,
  188. checkedList,
  189. } = this.details;
  190. const deptId = checkedList.join(',');
  191. this.getEmpDeptTree(checkGroupId, situationType, deptId)
  192. },
  193. /**
  194. * @param {boolean} flag true确定按钮点击,false取消按钮
  195. */
  196. btnGroupClickHandle(flag) {
  197. this.$refs.popup.close();
  198. //清空搜索
  199. this.filter = {
  200. ...this.filter,
  201. keyword: ''
  202. }
  203. },
  204. listClickHandle(item) {
  205. const _filter = this.filter;
  206. const {
  207. deptIdStr
  208. } = _filter;
  209. const index = _filter.deptIdStr.findIndex(t => t.id == item.id);
  210. if (item.id == 0) {
  211. //全部
  212. this.filter = {
  213. ...this.filter,
  214. deptIdStr: [{
  215. name: '全部',
  216. id: 0
  217. }]
  218. };
  219. return;
  220. }
  221. //去除全部选项选中
  222. deptIdStr.splice(_filter.deptIdStr.findIndex(t => t.id == 0), 1);
  223. if (index != -1) {
  224. deptIdStr.splice(index, 1)
  225. } else {
  226. deptIdStr.push({
  227. name: item.name,
  228. id: item.id
  229. })
  230. }
  231. this.filter = _filter;
  232. },
  233. selecterHandle() {
  234. this.$refs.popup.open();
  235. },
  236. /**
  237. * @param {string} val
  238. */
  239. searchInputHandle(val) {
  240. this.filter = {
  241. ...this.filter,
  242. keyword: val
  243. };
  244. },
  245. getComponentInfo(details) {
  246. const {
  247. checkGroupId,
  248. situationType,
  249. checkId,
  250. // deptId,
  251. checkedList,
  252. empId,
  253. empName,
  254. categoryId
  255. } = details;
  256. this.details = details;
  257. const deptId = checkedList.join(',');
  258. this.getEmpDeptTree(checkGroupId, situationType, deptId);
  259. //查核人回显
  260. if (empId && empName) {
  261. const empIdArr = empId.split(',');
  262. const empNameArr = empName.split(',');
  263. this.checkPresonList = empIdArr.map((item, index) => ({
  264. employeeId: Number(item),
  265. employeeName: empNameArr[index]
  266. }));
  267. }
  268. //查核要点回显
  269. if (categoryId) {
  270. this.checkedPointList = categoryId.map((item) => ({
  271. categoryId: Number(item),
  272. }));
  273. }
  274. },
  275. // 查询部门人员树
  276. getEmpDeptTree(checkGroupId, situationType, deptId) {
  277. this.$store.dispatch({
  278. type: 'allocationPerson/commActions',
  279. key: "getGroupEmpList",
  280. data: {
  281. checkGroupId,
  282. situationType,
  283. deptId,
  284. name: this.filter.keyword,
  285. deptIdStr: (this.filter.deptIdStr.map(t => t.id == 0 ? '' : t.id)).join(',')
  286. }
  287. }).then(data => {
  288. if (data) {
  289. let empList = [];
  290. if (data.sysCheckGroupEmployees) {
  291. empList = data.sysCheckGroupEmployees.map(t => ({
  292. ...t,
  293. label: `${t.employeeName} | ${t.code} | ${t.deptName}`
  294. }))
  295. } else {
  296. empList = [];
  297. }
  298. this.empList = empList;
  299. this.departments = [{
  300. name: '全部',
  301. id: 0
  302. }, ...data.departments] || [];
  303. if (situationType == 3) this.checkPointList = data.pointCategoryBOs || [];
  304. }
  305. });
  306. },
  307. //查核要点选择回调
  308. checkChanged(data) {
  309. const {
  310. checkedList
  311. } = data;
  312. this.checkedPointList = checkedList;
  313. },
  314. //查核人选择回调
  315. onCheckPerosonChanged(data) {
  316. const {
  317. checkedList
  318. } = data;
  319. this.checkPresonList = checkedList;
  320. },
  321. // 指派查核人员改变
  322. changeDetails(selectVal, selectData, index) {
  323. this.details = {
  324. ...this.details,
  325. empId: selectData.employeeId,
  326. empName: selectData.employeeName
  327. }
  328. },
  329. // 时间变化
  330. changeDateTime(dateObj, pickType) {
  331. if (pickType === 'startDate') { // 开始时间变化
  332. this.diffDateTime(dateObj.f3, this.details.endDate);
  333. } else {
  334. this.diffDateTime(this.details.startDate, dateObj.f3);
  335. }
  336. this.details = {
  337. ...this.details,
  338. [pickType]: dateObj.f3
  339. };
  340. },
  341. // 开始时间和结束时间对比
  342. diffDateTime(startTime, endTime) {
  343. if (moment(startTime).valueOf() > moment(endTime).valueOf()) {
  344. this.showModal('开始时间不能大于结束时间');
  345. }
  346. },
  347. // 点击确定
  348. sure() {
  349. const {
  350. startDate,
  351. endDate
  352. } = this.details;
  353. const empId = (this.checkPresonList.map(item => item.employeeId)).join(',');
  354. const empName = (this.checkPresonList.map(item => item.employeeName)).join(',');
  355. if (!empId) {
  356. return this.showModal('请选择查核人');
  357. }
  358. if (!startDate) {
  359. return this.showModal('请选择开始时间');
  360. }
  361. if (!endDate) {
  362. return this.showModal('请选择结束时间');
  363. }
  364. if (this.checkPointList.length>0&&this.checkedPointList.length==0) {
  365. //当未选择要点分类时
  366. return this.showModal('请选择要点分类!');
  367. }
  368. const {
  369. checkId,
  370. checkedList,
  371. checkNo,
  372. situationType
  373. } = this.details;
  374. const categoryIds = this.checkedPointList.map(item => item.categoryId);
  375. const data = {
  376. "checkId": checkId, // 计划id
  377. "deptId": JSON.parse(JSON.stringify(checkedList)), // 多个单位id列表
  378. "empId": empId, // 查核者id
  379. "empName": empName, // 查核者名字
  380. "startDate": startDate, // 开始时间
  381. "endDate": endDate, // 结束时间
  382. "checkNo": checkNo,
  383. "situationType": Number(situationType),
  384. "categoryIds": categoryIds
  385. }
  386. this.$store.dispatch({
  387. type: 'batchDistribution/commActions',
  388. key: 'batchCheckEmp',
  389. data: {
  390. ...data
  391. }
  392. }).then(data => {
  393. if (data) {
  394. uni.showModal({
  395. title: '分配成功!',
  396. content: '',
  397. showCancel: false,
  398. success: function(res) {
  399. if (res.confirm) {
  400. // console.log('用户点击确定');
  401. let pages = getCurrentPages(); // 获取当前页面栈
  402. let prePage = pages[pages.length - 2]; // 上一个页面
  403. prePage.ifInit = true;
  404. uni.navigateBack({
  405. delta: 1
  406. });
  407. }
  408. }
  409. });
  410. }
  411. });
  412. },
  413. // 获取当前时间
  414. getDateStr() {
  415. this.$store.dispatch({
  416. type: "commActions",
  417. key: "getDateStr",
  418. }).then((data) => {
  419. if (data) {
  420. this.dateStr = data;
  421. }
  422. });
  423. },
  424. showModal(content) {
  425. uni.showModal({
  426. content,
  427. showCancel: false
  428. });
  429. },
  430. // 清除定时器
  431. clearTimer() {
  432. if (this.timer) {
  433. clearInterval(this.timer);
  434. this.timer = null;
  435. }
  436. }
  437. },
  438. }
  439. </script>
  440. <style lang="less" scoped>
  441. .allocationPerson-page {
  442. height: 100%;
  443. .selectableList {
  444. display: flex;
  445. width: 100%;
  446. flex-direction: column;
  447. height: 50vh;
  448. padding-top: 50rpx;
  449. box-sizing: border-box;
  450. border-radius: 25rpx 25rpx 0px 0px;
  451. background-color: #FFFFFF;
  452. .listWrap {
  453. height: calc(50vh - 75rpx);
  454. overflow-y: scroll;
  455. .list {
  456. height: 87.5rpx;
  457. line-height: 87.5rpx;
  458. text-align: center;
  459. font-size: 30rpx;
  460. font-family: SourceHanSansCN-Normal, SourceHanSansCN;
  461. font-weight: 400;
  462. color: #8A8F99;
  463. &.on {
  464. font-weight: 500;
  465. color: #3377FF;
  466. }
  467. }
  468. }
  469. .btnGroup {
  470. display: flex;
  471. width: 100%;
  472. flex-direction: row;
  473. justify-content: center;
  474. align-items: center;
  475. .btn {
  476. width: 50%;
  477. height: 75rpx;
  478. line-height: 75rpx;
  479. text-align: center;
  480. font-size: 22.5rpx;
  481. font-family: SourceHanSansCN-Normal, SourceHanSansCN;
  482. font-weight: 400;
  483. color: #3377FF;
  484. }
  485. .cancelBtn {
  486. border-top: 0.62rpx solid #DADEE6;
  487. }
  488. .confirmBtn {
  489. color: #FFFFFF;
  490. background: #3377FF;
  491. }
  492. }
  493. }
  494. .scroll-y {
  495. height: calc(100% - 87.5rpx);
  496. padding-top: 15rpx;
  497. .blockTitle {
  498. display: flex;
  499. flex-direction: row;
  500. justify-content: space-between;
  501. align-items: center;
  502. font-size: 22.5rpx;
  503. font-family: SourceHanSansCN-Normal, SourceHanSansCN;
  504. font-weight: 400;
  505. color: #666F80;
  506. padding: 15rpx 25rpx;
  507. border-bottom: 0.62rpx solid #DADEE6;
  508. &.noBottomBlockTitle {
  509. border-bottom: none;
  510. }
  511. }
  512. .tabWrap {
  513. display: flex;
  514. flex-direction: row;
  515. justify-content: space-around;
  516. align-items: center;
  517. padding: 25rpx 0;
  518. padding-top: 12.5rpx;
  519. .tab {
  520. width: 250rpx;
  521. height: 50rpx;
  522. background: #FFFFFF;
  523. border-radius: 25rpx;
  524. font-size: 22.5rpx;
  525. font-family: SourceHanSansCN-Normal, SourceHanSansCN;
  526. font-weight: 400;
  527. text-align: center;
  528. line-height:50rpx;;
  529. color: #525866;
  530. &.on {
  531. color: #FFFFFF;
  532. background: #3377FF;
  533. }
  534. }
  535. }
  536. .filter {
  537. display: flex;
  538. flex-direction: row;
  539. justify-content: space-between;
  540. align-items: center;
  541. margin-bottom: 15rpx;
  542. padding: 0 25rpx;
  543. background: #FFFFFF;
  544. .selecter {
  545. display: flex;
  546. width: 25%;
  547. height: 87.5rpx;
  548. flex-direction: row;
  549. justify-content: space-between;
  550. align-items: center;
  551. padding-right: 25rpx;
  552. border-right: 0.62rpx solid #DADEE6;
  553. &>text {
  554. width: 112.5rpx;
  555. font-size: 25rpx;
  556. font-family: SourceHanSansCN-Medium, SourceHanSansCN;
  557. font-weight: 500;
  558. color: #292C33;
  559. text-overflow: ellipsis;
  560. overflow: hidden;
  561. white-space: nowrap;
  562. }
  563. &>image {
  564. width: 11.25rpx;
  565. height: 7.5rpx;
  566. }
  567. }
  568. .searchBar {
  569. display: flex;
  570. width: 75%;
  571. flex-direction: row;
  572. align-items: center;
  573. height: 87.5rpx;
  574. padding-left: 25rpx;
  575. .serachIcon {
  576. width: 30rpx;
  577. height: 30rpx;
  578. }
  579. .searchVal {
  580. width: 79%;
  581. padding-left: 25rpx;
  582. font-size: 25rpx;
  583. font-family: SourceHanSansCN-Normal, SourceHanSansCN;
  584. font-weight: 400;
  585. color: #292C33;
  586. }
  587. .searchBtn {
  588. padding-left: 25rpx;
  589. font-size: 25rpx;
  590. font-family: SourceHanSansCN-Normal, SourceHanSansCN;
  591. font-weight: 400;
  592. color: #3377FF;
  593. white-space: nowrap;
  594. border-left: 1rpx solid #DADEE6;
  595. }
  596. }
  597. }
  598. .empListWrapper {
  599. // height: 40vh;
  600. overflow-y: scroll;
  601. margin-bottom: 25rpx;
  602. background-color: #FFFFFF;
  603. }
  604. .empty {
  605. display: flex;
  606. height: 40vh;
  607. flex-direction: column;
  608. justify-content: center;
  609. align-items: center;
  610. margin-bottom: 25rpx;
  611. background-color: #FFFFFF;
  612. &>image {
  613. width: 175rpx;
  614. height: 190rpx;
  615. margin-bottom: 40rpx;
  616. }
  617. &>text {
  618. font-size: 22.5rpx;
  619. font-family: SourceHanSansCN-Normal, SourceHanSansCN;
  620. font-weight: 400;
  621. color: #828899;
  622. }
  623. }
  624. .date-view {
  625. padding: 0 25rpx;
  626. background: #fff;
  627. margin-bottom: 12.5rpx;
  628. border-bottom: 0.62rpx solid #DADEE6;
  629. .row {
  630. display: flex;
  631. align-items: center;
  632. height: 62.5rpx;
  633. border-bottom: 0.62rpx solid #DADEE6;
  634. .label {
  635. width: 112.5rpx;
  636. font-size: 22.5rpx;
  637. color: #292C33;
  638. }
  639. .date-box {
  640. padding-left: 25rpx;
  641. flex: 1;
  642. }
  643. &:last-child {
  644. border-bottom: 0;
  645. }
  646. }
  647. }
  648. }
  649. }
  650. </style>