Leave.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  1. <template>
  2. <div class="leave">
  3. <m-header v-if="headerStatus" />
  4. <van-cell-group class="search">
  5. <van-field
  6. label="开始时间"
  7. placeholder="选择开始时间"
  8. input-align="right"
  9. v-model="searchList.startText"
  10. readonly
  11. is-link
  12. @click="startShow = true"
  13. />
  14. <van-field
  15. label="结束时间"
  16. input-align="right"
  17. placeholder="选择结束时间"
  18. v-model="searchList.endText"
  19. readonly
  20. is-link
  21. @click="endShow = true"
  22. />
  23. <!-- <van-field label="请假类型" is-link input-align="right" placeholder="选择请假类型"
  24. v-model="searchList.dealText" readonly clickable
  25. @click="dealShow = true" /> -->
  26. <van-field
  27. type="textarea"
  28. v-model="searchList.remark"
  29. placeholder="请详细说明原因"
  30. rows="4"
  31. autosize
  32. />
  33. </van-cell-group>
  34. <van-panel title="课时安排" v-if="vipList.length > 0 && vipListType">
  35. <template v-for="(item, index) in vipList">
  36. <div class="leaveCell" v-if="item.type == 'VIP'" :key="index">
  37. <div class="leaveCell-l">{{ item.name }}</div>
  38. <div class="leaveCell-r">
  39. <div class="left-wrap">
  40. <p class="classTime">上课时间</p>
  41. <p>{{ item.classDate | getFormatTime(item.startClassTime) }}</p>
  42. <div class="line"></div>
  43. <img src="@/assets/images/switch-icon.png" alt="" class="icon" />
  44. </div>
  45. <div class="left-wrap" v-if="item.changeTime">
  46. <p class="classTime">已调整为</p>
  47. <p>
  48. {{ item.changeTime }}
  49. <van-icon @click="onUpdate(item)" name="edit" />
  50. </p>
  51. </div>
  52. <div class="left-wrap" v-else>
  53. <van-button @click="onAdd(item)" round type="info" size="small"
  54. >调整</van-button
  55. >
  56. </div>
  57. </div>
  58. </div>
  59. </template>
  60. </van-panel>
  61. <div class="button-group">
  62. <van-button type="primary" @click="onSubmit" round size="large"
  63. >确认</van-button
  64. >
  65. </div>
  66. <!-- 开始时间弹窗 -->
  67. <van-popup v-model="startShow" position="bottom" >
  68. <van-datetime-picker
  69. v-model="startDate.currentDate"
  70. type="datetime"
  71. :item-height="40"
  72. title="开始时间"
  73. :min-date="startDate.minDate"
  74. :max-date="startDate.maxDate"
  75. @cancel="startShow = false"
  76. @confirm="onStartConfirm"
  77. :formatter="formatter"
  78. />
  79. </van-popup>
  80. <!-- 结束时间弹窗 -->
  81. <van-popup v-model="endShow" position="bottom">
  82. <van-datetime-picker
  83. v-model="endDate.currentDate"
  84. type="datetime"
  85. :item-height="40"
  86. title="结束时间"
  87. :min-date="endDate.minDate"
  88. :max-date="endDate.maxDate"
  89. @cancel="endShow = false"
  90. @confirm="onEndConfirm"
  91. :formatter="formatter"
  92. />
  93. </van-popup>
  94. <van-action-sheet
  95. v-model="dealShow"
  96. :actions="leaveCategoryList"
  97. cancel-text="取消"
  98. @cancel="dealShow = false"
  99. @select="onDealSelect"
  100. />
  101. <!-- 调整时间 -->
  102. <van-popup v-model="changeShow" position="bottom">
  103. <van-datetime-picker
  104. v-model="changeDate.currentDate"
  105. type="datetime"
  106. :item-height="40"
  107. title="结束时间"
  108. :min-date="changeDate.minDate"
  109. :max-date="changeDate.maxDate"
  110. @cancel="changeShow = false"
  111. @confirm="onChangeConfirm"
  112. :formatter="formatter"
  113. />
  114. </van-popup>
  115. </div>
  116. </template>
  117. <script>
  118. /* eslint-disable */
  119. import MHeader from "@/components/MHeader";
  120. import {
  121. queryVipCourseScheduleList,
  122. leaveCategoryPage,
  123. askForLeave,
  124. } from "@/api/teacher";
  125. import { browser } from "@/common/common";
  126. // let nowTime = new Date()
  127. // let changeTime = new Date(nowTime.setDate(nowTime.getDate() + 1))
  128. export default {
  129. name: "leave",
  130. components: { MHeader },
  131. data() {
  132. return {
  133. headerStatus: false,
  134. startShow: false,
  135. startDate: {
  136. // 开始时间
  137. minDate: new Date(),
  138. maxDate: new Date(2025, 12, 31),
  139. currentDate: new Date(),
  140. },
  141. endShow: false,
  142. endDate: {
  143. // 结束时间
  144. minDate: new Date(),
  145. maxDate: new Date(2025, 12, 31),
  146. currentDate: new Date(),
  147. },
  148. dealShow: false,
  149. searchList: {
  150. startText: null,
  151. endText: null,
  152. dealText: null,
  153. remark: null,
  154. },
  155. vipList: [], // 申请调整的vip列表
  156. vipListType: false, // 判断是否只有乐团课
  157. changeShow: false,
  158. changeDate: {
  159. // 结束时间
  160. minDate: new Date(),
  161. maxDate: new Date(2025, 12, 31),
  162. currentDate: new Date(),
  163. },
  164. leaveCategoryList: [],
  165. changeItem: null,
  166. };
  167. },
  168. mounted() {
  169. let params = this.$route.query;
  170. if (params.Authorization) {
  171. localStorage.setItem("Authorization", params.Authorization);
  172. localStorage.setItem("userInfo", params.Authorization);
  173. }
  174. document.title = "批量调整";
  175. // if(browser().android) {
  176. // this.headerStatus = true
  177. // }
  178. this.__init();
  179. },
  180. methods: {
  181. __init() {
  182. leaveCategoryPage({
  183. rows: 9999,
  184. page: 1,
  185. }).then((res) => {
  186. let result = res.data;
  187. if (result.code == 200) {
  188. result.data.rows.forEach((item) => {
  189. this.leaveCategoryList.push({
  190. name: item.name,
  191. id: item.id,
  192. });
  193. });
  194. }
  195. });
  196. },
  197. getDateInfo(value) {
  198. // 获取时间
  199. let tempValue = value;
  200. if (typeof value !== "object") {
  201. tempValue = value.replace(/-/gi, "/");
  202. }
  203. let d = new Date(tempValue);
  204. let hour = d.getHours() >= 10 ? d.getHours() : "0" + d.getHours();
  205. let minute = d.getMinutes() >= 10 ? d.getMinutes() : "0" + d.getMinutes();
  206. return hour + ":" + minute + ":00";
  207. },
  208. onSubmit() {
  209. let searchList = this.searchList;
  210. if (!searchList.startText || !searchList.endText) {
  211. this.$toast("时间不能为空");
  212. return;
  213. }
  214. // if(!searchList.dealText) {
  215. // this.$toast('请选择请假类型')
  216. // return
  217. // }
  218. if (!searchList.remark) {
  219. this.$toast("请填写原因");
  220. return;
  221. }
  222. let leaveCategoryId;
  223. this.leaveCategoryList.forEach((item) => {
  224. if (item.name == searchList.dealText) {
  225. leaveCategoryId = item.id;
  226. }
  227. });
  228. let coursesScheduleJson = [];
  229. let status = false;
  230. this.vipList.forEach((item) => {
  231. if (!item.changeAllTime && item.type == "VIP") {
  232. this.$toast("操作无效:您还有VIP未调整");
  233. status = true;
  234. }
  235. let tempI = {};
  236. if (item.type == "VIP") {
  237. tempI = Object.assign({}, item);
  238. let startStr = "2019/12/18 " + this.getDateInfo(item.startClassTime),
  239. endStr = "2019/12/18 " + this.getDateInfo(item.endClassTime);
  240. let startDate = new Date(startStr),
  241. endDate = new Date(endStr);
  242. let m = parseInt(
  243. Math.abs(startDate.getTime() - endDate.getTime()) / 1000 / 60
  244. );
  245. tempI.classDate = this.getFormatDate(item.changeAllTime) + ":00";
  246. tempI.startClassTime = this.getFormatDate(item.changeAllTime) + ":00";
  247. let currentDate = new Date(item.changeAllTime);
  248. currentDate.setMinutes(currentDate.getMinutes() + m);
  249. tempI.endClassTime = this.getFormatDate(currentDate) + ":00";
  250. }
  251. coursesScheduleJson.push({
  252. before: item,
  253. after: tempI,
  254. });
  255. });
  256. if (status) return;
  257. askForLeave({
  258. coursesScheduleJson: JSON.stringify(coursesScheduleJson),
  259. startTime: searchList.startText,
  260. endTime: searchList.endText,
  261. leaveCategoryId: leaveCategoryId,
  262. leaveCategoryName: searchList.dealText,
  263. remark: searchList.remark,
  264. }).then((res) => {
  265. let result = res.data;
  266. if (result.code == 200) {
  267. this.$toast("申请成功,请等待审核");
  268. setTimeout(() => {
  269. if (browser().iPhone) {
  270. window.webkit.messageHandlers.DAYA.postMessage(
  271. JSON.stringify({ api: "back" })
  272. );
  273. } else if (browser().android) {
  274. DAYA.postMessage(JSON.stringify({ api: "back" }));
  275. } else {
  276. this.$router.push("/business");
  277. }
  278. }, 500);
  279. } else {
  280. this.$toast(result.msg);
  281. }
  282. });
  283. },
  284. onAdd(item) {
  285. // 调整
  286. this.changeShow = true;
  287. this.changeItem = item;
  288. },
  289. onUpdate(item) {
  290. this.changeDate.currentDate = item.changeAllTime;
  291. this.changeShow = true;
  292. this.changeItem = item;
  293. },
  294. onChangeConfirm(val) {
  295. let tempDate = new Date(val);
  296. let month =
  297. tempDate.getMonth() + 1 >= 10
  298. ? tempDate.getMonth() + 1
  299. : "0" + (tempDate.getMonth() + 1);
  300. let day =
  301. tempDate.getDate() >= 10
  302. ? tempDate.getDate()
  303. : "0" + tempDate.getDate();
  304. let hours =
  305. tempDate.getHours() >= 10
  306. ? tempDate.getHours()
  307. : "0" + tempDate.getHours();
  308. let min =
  309. tempDate.getMinutes() >= 10
  310. ? tempDate.getMinutes()
  311. : "0" + tempDate.getMinutes();
  312. this.changeItem.changeTime = month + "-" + day + " " + hours + ":" + min;
  313. this.changeItem.changeAllTime = val;
  314. this.changeShow = false;
  315. },
  316. onStartConfirm(val) {
  317. // 开始时间
  318. let searchList = this.searchList;
  319. searchList.startText = this.getFormatDate(val);
  320. this.startShow = false;
  321. if (val >= this.endDate.currentDate) {
  322. searchList.endText = null;
  323. this.endDate.currentDate = new Date();
  324. } else {
  325. if (searchList.startText && searchList.endText) {
  326. this.queryVipCourseScheduleList();
  327. }
  328. }
  329. },
  330. onEndConfirm(val) {
  331. // 结束时间
  332. let searchList = this.searchList;
  333. searchList.endText = this.getFormatDate(val);
  334. this.endShow = false;
  335. if (val <= this.startDate.currentDate) {
  336. searchList.startText = null;
  337. this.startDate.currentDate = new Date();
  338. } else {
  339. if (searchList.startText && searchList.endText) {
  340. this.queryVipCourseScheduleList();
  341. }
  342. }
  343. },
  344. queryVipCourseScheduleList() {
  345. // 获取需要调整的VIP课
  346. queryVipCourseScheduleList({
  347. endTime: this.searchList.endText,
  348. startTime: this.searchList.startText,
  349. }).then((res) => {
  350. let result = res.data;
  351. this.vipList = [];
  352. if (result.code == 200 && result.data.length > 0) {
  353. this.vipList = result.data;
  354. result.data.forEach((item) => {
  355. if (item.type == "VIP") {
  356. this.vipListType = true;
  357. }
  358. });
  359. }
  360. });
  361. },
  362. onDealSelect(val) {
  363. // 交易收支
  364. this.searchList.dealText = val.name;
  365. this.dealShow = false;
  366. },
  367. getFormatDate(data) {
  368. let tempDate = new Date(data);
  369. let month =
  370. tempDate.getMonth() + 1 >= 10
  371. ? tempDate.getMonth() + 1
  372. : "0" + (tempDate.getMonth() + 1);
  373. let day =
  374. tempDate.getDate() >= 10
  375. ? tempDate.getDate()
  376. : "0" + tempDate.getDate();
  377. let tDate = tempDate.getFullYear() + "-" + month + "-" + day;
  378. let hours =
  379. tempDate.getHours() >= 10
  380. ? tempDate.getHours()
  381. : "0" + tempDate.getHours();
  382. let min =
  383. tempDate.getMinutes() >= 10
  384. ? tempDate.getMinutes()
  385. : "0" + tempDate.getMinutes();
  386. return tDate + " " + hours + ":" + min;
  387. },
  388. formatter(type, value) {
  389. // 格式化时间
  390. if (type === "year") {
  391. return `${value}年`;
  392. } else if (type === "month") {
  393. return `${value}月`;
  394. } else if (type === "day") {
  395. return `${value}日`;
  396. } else if (type === "hour") {
  397. return `${value}时`;
  398. } else if (type === "minute") {
  399. return `${value}分`;
  400. }
  401. return value;
  402. },
  403. },
  404. filters: {
  405. getFormatTime(tempA, tempB) {
  406. (tempA = new Date(tempA.replace(/-/g, "/"))),
  407. (tempB = new Date(tempB.replace(/-/g, "/")));
  408. let month =
  409. Number(tempA.getMonth() + 1) >= 10
  410. ? Number(tempA.getMonth() + 1)
  411. : "0" + Number(tempA.getMonth() + 1);
  412. let day =
  413. Number(tempA.getDate()) >= 10 ? tempA.getDate() : "0" + tempA.getDate();
  414. let hours =
  415. Number(tempB.getHours()) >= 10
  416. ? tempB.getHours()
  417. : "0" + tempB.getHours();
  418. let min =
  419. Number(tempB.getMinutes()) >= 10
  420. ? tempB.getMinutes()
  421. : "0" + tempB.getMinutes();
  422. return month + "-" + day + " " + hours + ":" + min;
  423. },
  424. },
  425. };
  426. </script>
  427. <style lang='less' scoped>
  428. @import url("../../assets/commonLess/variable.less");
  429. .leave {
  430. min-height: 100vh;
  431. overflow: hidden;
  432. }
  433. .search .van-cell {
  434. padding: 0.13rem 0.16rem;
  435. font-size: 0.14rem;
  436. line-height: 0.24rem;
  437. display: flex;
  438. align-items: center;
  439. }
  440. .result {
  441. margin-top: 0.1rem;
  442. .count {
  443. font-size: 0.12rem;
  444. color: @tFontColor;
  445. }
  446. .add {
  447. color: @orangeColor;
  448. }
  449. }
  450. /deep/.van-panel {
  451. margin-top: 0.1rem;
  452. .van-cell__title {
  453. font-size: 0.16rem;
  454. color: @mFontColor;
  455. }
  456. }
  457. .leaveCell {
  458. position: relative;
  459. display: flex;
  460. flex-direction: row;
  461. // justify-content: space-between;
  462. align-items: center;
  463. padding: 0.15rem;
  464. border-bottom: 1px solid #f3f4f8;
  465. font-size: 0.14rem;
  466. &:last-child {
  467. border-bottom: 0;
  468. }
  469. .leaveCell-l {
  470. word-break: break-all;
  471. flex-basis: 0.8rem;
  472. padding-right: 0.08rem;
  473. }
  474. .leaveCell-r {
  475. display: flex;
  476. flex-direction: row;
  477. justify-content: space-around;
  478. align-items: center;
  479. .left-wrap {
  480. .van-button--info{
  481. width: .72rem;
  482. height: .28rem;
  483. font-size: .14rem;
  484. }
  485. .classTime {
  486. margin-bottom: 0.06rem;
  487. }
  488. min-width: 1rem;
  489. position: relative;
  490. &:first-child {
  491. padding-right: 0.15rem;
  492. }
  493. &:last-child {
  494. padding-left: 0.15rem;
  495. }
  496. .line {
  497. position: absolute;
  498. width: 1px;
  499. height: 0.56rem;
  500. background-color: #f3f3f8;
  501. right: 0;
  502. top: -0.07rem;
  503. }
  504. .icon {
  505. position: absolute;
  506. width: 0.15rem;
  507. height: 0.15rem;
  508. right: -0.07rem;
  509. top: 0.15rem;
  510. }
  511. }
  512. }
  513. }
  514. /deep/.van-field__label {
  515. width: 0.9rem;
  516. }
  517. /deep/.van-icon-edit {
  518. color: @mColor;
  519. font-size: 0.16rem;
  520. vertical-align: text-bottom;
  521. margin-left: 0.08rem;
  522. }
  523. /deep/.van-button--info {
  524. background-color: @mColor;
  525. border: 1px solid @mColor;
  526. }
  527. .button-group {
  528. margin: 0.3rem 0.26rem 0.2rem;
  529. .van-button--primary {
  530. background: @mColor;
  531. font-size: 0.18rem;
  532. height: 0.5rem;
  533. line-height: 0.48rem;
  534. }
  535. }
  536. </style>