appoint.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809
  1. <template>
  2. <div class="pages">
  3. <div class="as">
  4. <img src="../static/images/main/banner.png" width="100%"/>
  5. <!--<mu-tabs :value.sync="active" color="#F2F2F2" indicator-color="#ffffff" @change="getIndex" v-if="reFresh">-->
  6. <!--<mu-tab v-for="day in weeks">{{ day.data }} <br> <em>{{ day.name }}</em></mu-tab>-->
  7. <!--</mu-tabs>-->
  8. <div class="tabs">
  9. <div :class="[{'tab':true},{'activeTab':i == active}]" v-for="(day,i) in weeks" @click="changeActive(i)">
  10. {{ day.name }} <br> <em>{{ day.data }}</em>
  11. </div>
  12. </div>
  13. <span class="sum">
  14. {{ today }} 预约名额剩余
  15. <em class="green" v-if="num > 0">{{ num }}</em>
  16. <em class="red" v-else>{{ num }}</em>
  17. </span>
  18. </div>
  19. <div class="context">
  20. <ul class="list">
  21. <li v-for="l in list"
  22. :class="[{'greenLi':l.remain > 0},{'redLi':l.Status == 1},{'yellowLi':l.remain == 0},{'whiteLi':l.WxOrder == 0},{'whiteLi':l.IsAllowSelect == 0}]">
  23. <div class="dotContainer">
  24. <div v-if="l.IsAllowSelect > 0">
  25. <!--正常-->
  26. <i class="dot" v-if="l.remain>0 && l.WxOrder != 0"></i>
  27. <i class="cubes" v-if="l.Status==1"></i>
  28. <!--满员-->
  29. <i class="tri" v-if="l.remain == 0 && l.remain == 0"></i>
  30. <!--不可约-->
  31. <i class="x" v-if="l.WxOrder==0"></i>
  32. </div>
  33. <!-- 不可匹配课程 -->
  34. <div v-else>
  35. <i class="x" v-if="l.OrderId == 0"></i>
  36. </div>
  37. </div>
  38. <div class="title">
  39. <h5><span class="lessons" :style="{ background:l.ClassColor }">{{ l.ClassName }}</span></h5>
  40. <span>{{ l.BeginStr }} - {{ l.EndStr }}</span>
  41. </div>
  42. <div class="current">
  43. <h5>剩余
  44. <em class="green" v-if="l.remain > 0">{{ l.remain }}</em>
  45. <em class="red" v-else>{{ l.remain }}</em>
  46. </h5>
  47. <span>总名额 {{ l.OrderToplimit }} 人</span>
  48. </div>
  49. <!-- 可匹配课程 -->
  50. <div v-if="l.IsAllowSelect > 0">
  51. <mu-button class="appointBtn greenBtn" v-if="l.remain > 0 && l.OrderId == 0 && l.WxOrder != 0"
  52. @click="appointNow(l)">
  53. 预约
  54. </mu-button>
  55. <mu-button class="appointBtn redBtn" v-if="l.remain == 0 && l.OrderId == 0" @click="isFulled">满员
  56. </mu-button>
  57. <mu-button class="appointBtn yellowBtn" v-if="l.OrderId != 0" @click="isAppointed(l)">已约</mu-button>
  58. <mu-button class="appointBtn disableBtn" v-if="l.WxOrder == 0 && l.OrderId == 0" @click="isDisable">不可约</mu-button>
  59. </div>
  60. <!-- 不可匹配课程 -->
  61. <div v-else>
  62. <mu-button class="appointBtn disableBtn" @click="isDisable" v-if="l.OrderId == 0">不可约</mu-button>
  63. </div>
  64. </li>
  65. <div class="tips" v-if="list == ''">
  66. <p style="text-align: center">
  67. 暂无可预约的课程
  68. </p>
  69. </div>
  70. </ul>
  71. <mu-avatar color="rgb(231, 82, 150)" @click.native="goPage('lesson')">
  72. <mu-icon value="reorder"></mu-icon>
  73. </mu-avatar>
  74. </div>
  75. <bottomTab :curTab="thisTab"></bottomTab>
  76. <div class="doalog">
  77. <mu-dialog title="预约课程" width="600" max-width="80%" :esc-press-close="false" :overlay-close="false"
  78. :open.sync="openAlert">
  79. <p>
  80. 是否预约 课程:{{ dialog.ClassName }} ,时间:{{ dialog.BeginStr }} - {{ dialog.EndStr }}
  81. <br>
  82. </p>
  83. <mu-button slot="actions" flat color="primary" @click="closeAlertDialog">取消</mu-button>
  84. <mu-button slot="actions" flat color="primary" @click="confirmAppoint">确定</mu-button>
  85. </mu-dialog>
  86. </div>
  87. <alert ref="alertPart"></alert>
  88. </div>
  89. </template>
  90. <script>
  91. import axios from 'axios';
  92. import bottomTab from '../components/bottomTab'
  93. import {
  94. CanOrderSchoolTimeTableListQuery,
  95. OderAddByVipUser,
  96. OderCancelByVipUser,
  97. QueryNextWeek,
  98. testSelect,
  99. testTable,
  100. } from '../api/getApiRes.js'
  101. import alert from '../components/alert'
  102. let qs = require('qs');
  103. import Global from '../Global.js'
  104. export default {
  105. data() {
  106. return {
  107. num: 0,
  108. thisTab: '预约课程',
  109. active: 0,
  110. sum: 0,
  111. HaveDays: 0,
  112. openAlert: false,
  113. reFresh: true,
  114. list: [],
  115. weeks: [],
  116. today: '',
  117. dialog: {
  118. id: '',
  119. name: '',
  120. timeLong: '',
  121. },
  122. }
  123. },
  124. mounted() {
  125. this.getQueryNextWeek();
  126. // this.alertInfo(document.body.clientWidth);
  127. // this.alertInfo( window.screen.height);
  128. },
  129. watch: {
  130. '$route'(to) {
  131. if (to.name == 'appoint') {
  132. this.getList();
  133. }
  134. },
  135. 'active'(to) {
  136. this.getList();
  137. }
  138. },
  139. activated() {
  140. this.active = 0;
  141. this.reFresh = false;
  142. this.$nextTick(() => {
  143. this.reFresh = true;
  144. this.getQueryNextWeek();
  145. });
  146. },
  147. methods: {
  148. changeActive(i) {
  149. this.active = i;
  150. },
  151. getIndex(val) {
  152. console.log(val);
  153. },
  154. getQueryNextWeek() {
  155. let that = this;
  156. let param = {
  157. token: localStorage.token,
  158. shopId: this.$route.query.shopId,
  159. };
  160. let postdata = qs.stringify(param);
  161. this.weeks = [];
  162. QueryNextWeek(postdata).then(res => {
  163. let json = res;
  164. if (json.Code == 0) {
  165. this.HaveDays = json.Rs;
  166. this.getFurtherDays(this.HaveDays);
  167. } else {
  168. that.list = [];
  169. that.$message.error(json.Memo);
  170. }
  171. })
  172. },
  173. alertInfo(info) {
  174. this.$refs.alertPart.openSimpleDialog(info);
  175. },
  176. goPage(url) {
  177. this.$router.push({
  178. path: '/' + url, query: {
  179. shopId: this.$route.query.shopId
  180. }
  181. });
  182. },
  183. // 获取未来7天的
  184. getFurtherDays(HaveDays) {
  185. let now = new Date();
  186. let nowTime = now.getTime();
  187. let oneDayTime = 24 * 60 * 60 * 1000;
  188. let days = '';
  189. let item = [];
  190. let month = 0;
  191. let day = 0;
  192. this.weeks = [];
  193. for (let i = 0; i < HaveDays; i++) {
  194. days = new Date(nowTime + (i) * oneDayTime);//显示周日
  195. month = days.getMonth() + 1;
  196. day = days.getDate();
  197. month = month < 10 ? '0' + month : month;
  198. day = day < 10 ? '0' + day : day;
  199. item = {
  200. name: this.numberToWeek(days.getDay()),
  201. data: days.getMonth() + 1 + '月' + days.getDate() + '日',
  202. orderDate: days.getFullYear() + '-' + month + '-' + day
  203. };
  204. this.weeks.push(item);
  205. }
  206. this.today = this.weeks[0].name;
  207. this.getList();
  208. },
  209. numberToWeek(val) {
  210. switch (parseInt(val)) {
  211. case 1:
  212. return '星期一';
  213. break;
  214. case 2:
  215. return '星期二';
  216. break;
  217. case 3:
  218. return '星期三';
  219. break;
  220. case 4:
  221. return '星期四';
  222. break;
  223. case 5:
  224. return '星期五';
  225. break;
  226. case 6:
  227. return '星期六';
  228. break;
  229. case 0:
  230. return '星期天';
  231. break;
  232. }
  233. },
  234. confirmAppoint() {
  235. let that = this;
  236. that.openAlert = false;
  237. let param = {
  238. token: localStorage.token,
  239. stdId: that.dialog.StdId
  240. };
  241. let postdata = qs.stringify(param);
  242. OderAddByVipUser(postdata).then(res => {
  243. let json = res;
  244. if (json.Code == 0) {
  245. that.alertInfo('已成功预约', 'success');
  246. that.getList();
  247. } else {
  248. that.alertInfo(json.Memo + ' 错误码:' + json.Code);
  249. }
  250. })
  251. },
  252. closeAlertDialog() {
  253. this.openAlert = false;
  254. },
  255. appointNow(row) {
  256. this.dialog = row;
  257. this.openAlert = true;
  258. },
  259. isFulled() {
  260. let that = this;
  261. that.$alert('当前课程满员,请选择其他课程或其他时间预约', '提示', {
  262. okLabel: '知道了'
  263. }).then(() => {
  264. that.getList();
  265. });
  266. },
  267. isAppointed(row) {
  268. let that = this;
  269. this.$confirm('是否取消前课程预约?', '提示', {
  270. type: 'warning'
  271. }).then(({ result }) => {
  272. if (result) {
  273. let param = {
  274. token: localStorage.token,
  275. orderId: row.OrderId,
  276. };
  277. let postdata = qs.stringify(param);
  278. OderCancelByVipUser(postdata).then(res => {
  279. let json = res;
  280. if (json.Code == 0) {
  281. that.alertInfo('当前课程已取消预约', 'success');
  282. that.getList();
  283. } else {
  284. that.alertInfo(json.Memo + ' 错误码:' + json.Code);
  285. }
  286. })
  287. } else {
  288. this.alertInfo('点击了取消');
  289. }
  290. });
  291. },
  292. isDisable(row) {
  293. this.alertInfo('课程不可预约,请选择其他课程或其他时间预约', 'info');
  294. },
  295. getList() {
  296. let that = this;
  297. this.today = this.weeks[this.active].name;
  298. let curDay = this.weeks[this.active].orderDate;
  299. let param = {
  300. token: localStorage.token,
  301. orderDate: curDay,
  302. shopId: this.$route.query.shopId,
  303. };
  304. let postdata = qs.stringify(param);
  305. that.list = [];
  306. that.num = 0;
  307. CanOrderSchoolTimeTableListQuery(postdata).then(res => {
  308. let json = res;
  309. if (json.Code == 0) {
  310. that.list = json.Rs;
  311. if (that.list) {
  312. // 计算剩余
  313. that.num = 0;
  314. that.list.map(function (item) {
  315. item.remain = parseInt(item.OrderToplimit) - parseInt(item.OrderCount);
  316. that.num = that.num + item.remain
  317. console.log(that.num);
  318. })
  319. }
  320. } else {
  321. that.alertInfo(json.Memo + ' 错误码:' + json.Code);
  322. }
  323. })
  324. },
  325. },
  326. components: {
  327. bottomTab, alert
  328. }
  329. }
  330. </script>
  331. <style scoped>
  332. .pages {
  333. overflow: hidden;
  334. display: block;
  335. margin: 0 auto;
  336. }
  337. /*mu-header*/
  338. .mu-primary-color {
  339. line-height: 60px;
  340. height: 60px;
  341. background: url("../static/images/comm/headerBg.png") top center no-repeat;
  342. background-size: 100%;
  343. }
  344. /deep/ .mu-appbar-left {
  345. padding-top: 15px;
  346. }
  347. /deep/ .material-icons {
  348. color: #fff;
  349. }
  350. /deep/ .mu-appbar-title {
  351. text-align: center;
  352. }
  353. /deep/ .mu-tabs {
  354. /*display: flex;*/
  355. /*width: 414px;*/
  356. overflow-x: scroll;
  357. overflow-y: hidden;
  358. /*display:inline;*/
  359. /*float: left;*/
  360. }
  361. /deep/ .mu-tab {
  362. width: 85px;
  363. min-width: 85px;
  364. float: left;
  365. height: 51px;
  366. margin-right: 6px;
  367. }
  368. /*/deep/ .mu-tab:nth-child(5) {*/
  369. /* margin-right: 0px;*/
  370. /*}*/
  371. /deep/ .mu-tab-wrapper {
  372. height: 51px;
  373. background: #f4f4f4;
  374. color: #363636;
  375. box-shadow: 1px 0px 6px rgba(0, 0, 0, 0.16);
  376. border-radius: 8px 8px 0px 0px;
  377. font-size: 14px;
  378. }
  379. /deep/ .mu-tab-active .mu-tab-wrapper {
  380. height: 56px;
  381. border-radius: 8px 8px 0px 0px;
  382. background: #ffffff;
  383. box-shadow: 1px 0px 6px rgba(0, 0, 0, 0.16);
  384. color: #000;
  385. }
  386. /deep/ .mu-tab-wrapper em {
  387. font-size: 12px;
  388. }
  389. .sum {
  390. width: 100%;
  391. height: 55px;
  392. line-height: 55px;
  393. background: #fff;
  394. font-family: "PingFang SC";
  395. font-weight: 300;
  396. font-size: 16px;
  397. text-align: center;
  398. color: #909090;
  399. overflow: hidden;
  400. display: block;
  401. margin: 0 auto;
  402. }
  403. .green {
  404. color: #37CB00;
  405. }
  406. .red {
  407. color: #F8847F;
  408. }
  409. .list {
  410. width: 100%;
  411. overflow: hidden;
  412. display: block;
  413. margin: 0 auto;
  414. margin-top: 8px;
  415. padding-bottom: 30px;
  416. }
  417. .list li {
  418. width: 100%;
  419. height: 70px;
  420. margin-bottom: 8px;
  421. padding-top: 16px;
  422. padding-bottom: 16px;
  423. }
  424. .list .dotContainer {
  425. width: 50px;
  426. float: left;
  427. height: 60px;
  428. padding-left: 22px;
  429. padding-top: 10px;
  430. }
  431. .dotContainer .dot {
  432. width: 12px;
  433. height: 12px;
  434. background: #37cb00;
  435. border-radius: 250px;
  436. float: left;
  437. }
  438. .cubes {
  439. width: 12px;
  440. height: 12px;
  441. background: #f8847f;
  442. float: left;
  443. }
  444. .tri {
  445. width: 12px;
  446. height: 12px;
  447. background: url("../static/images/appoint/tri.png") top center no-repeat;
  448. background-size: 100% 100%;
  449. float: left;
  450. }
  451. .x {
  452. width: 12px;
  453. height: 12px;
  454. background: url("../static/images/appoint/x.png") top center no-repeat;
  455. background-size: 100% 100%;
  456. float: left;
  457. }
  458. .yellowLi {
  459. background: #FFFBED;
  460. }
  461. .redLi {
  462. background: #FFF7F7;
  463. }
  464. .greenLi {
  465. background: #F7FFF4;
  466. }
  467. .whiteLi {
  468. background: #fff;
  469. }
  470. .list li .title {
  471. /*width: 90px;*/
  472. width: 27%;
  473. height: 60px;
  474. float: left;
  475. }
  476. li .title h5 {
  477. width: 100%;
  478. overflow: hidden;
  479. display: block;
  480. margin: 0 auto;
  481. font-weight: normal;
  482. font-size: 14px;
  483. text-align: left;
  484. color: #3b3b3b;
  485. }
  486. li .title span {
  487. width: 100%;
  488. overflow: hidden;
  489. display: block;
  490. margin: 0 auto;
  491. font-weight: normal;
  492. font-size: 12px;
  493. text-align: left;
  494. color: #909090;
  495. }
  496. .list li .current {
  497. width: 120px;
  498. height: 60px;
  499. float: left;
  500. }
  501. li .current h5 {
  502. width: 100%;
  503. overflow: hidden;
  504. display: block;
  505. margin: 0 auto;
  506. font-family: "PingFang SC";
  507. font-weight: normal;
  508. font-size: 14px;
  509. text-align: left;
  510. color: #3b3b3b;
  511. }
  512. .current h5 em {
  513. font-family: "PingFang SC";
  514. font-weight: normal;
  515. font-size: 14px;
  516. text-align: left;
  517. }
  518. .current span {
  519. font-family: "PingFang SC";
  520. font-weight: normal;
  521. font-size: 12px;
  522. text-align: left;
  523. color: #909090;
  524. }
  525. .appointBtn {
  526. width: 79px;
  527. height: 37px;
  528. border-radius: 18.5px;
  529. background: #fff;
  530. float: right;
  531. font-family: "PingFang SC";
  532. font-weight: normal;
  533. font-size: 18px;
  534. margin-right: 2%;
  535. }
  536. .greenBtn {
  537. border: 1px solid #37cb00;
  538. color: #37cb00;
  539. }
  540. .redBtn {
  541. border: 1px solid #F8847F;
  542. color: #F8847F;
  543. }
  544. .yellowBtn {
  545. border: 1px solid #FFB43C;
  546. color: #fff;
  547. background: #FFB43C;
  548. }
  549. .disableBtn {
  550. border: 1px solid #C9C9C9;
  551. color: #C9C9C9;
  552. }
  553. /deep/ .mu-tabs-center {
  554. display: flex;
  555. overflow-x: auto;
  556. overflow-y: hidden;
  557. white-space: nowrap;
  558. }
  559. /deep/ .mu-tabs-center::-webkit-scrollbar {
  560. display: none;
  561. }
  562. /deep/ .mu-modal-inner {
  563. width: 90%;
  564. float: left;
  565. }
  566. /deep/ .mu-tab-link-highlight {
  567. display: none !important;
  568. }
  569. li .title span.lessons {
  570. width: auto;
  571. padding: 1px 11px;
  572. border-radius: 250px;
  573. float: left;
  574. text-align: center;
  575. color: #000;
  576. font-size: 14px;
  577. }
  578. /deep/ .mu-avatar {
  579. position: fixed;
  580. bottom: 9%;
  581. float: left;
  582. left: 1%;
  583. }
  584. .context {
  585. position: absolute;
  586. left: 0;
  587. right: 0;
  588. top: 30%;
  589. bottom: 0;
  590. overflow-y: scroll;
  591. padding-bottom: 50px;
  592. }
  593. .as {
  594. position: fixed;
  595. width: 100%;
  596. overflow: hidden;
  597. display: block;
  598. margin: 0 auto;
  599. z-index: 222;
  600. background: #F2F2F2;
  601. }
  602. /deep/ .mu-raised-button {
  603. box-shadow: none;
  604. }
  605. .tabs {
  606. width: 100%;
  607. justify-content: space-between;
  608. white-space: nowrap;
  609. overflow-y: hidden;
  610. overflow-x: scroll;
  611. display: flex;
  612. border-bottom: 1px solid #ccc;
  613. }
  614. .tab {
  615. font-size: 14px;
  616. min-width: 72px;
  617. max-width: 264px;
  618. background: none;
  619. -webkit-appearance: none;
  620. -moz-appearance: none;
  621. appearance: none;
  622. text-decoration: none;
  623. border: none;
  624. outline: none;
  625. color: inherit;
  626. position: relative;
  627. line-height: normal;
  628. -webkit-transition: all .45s cubic-bezier(.445, .05, .55, .95);
  629. transition: all .45s cubic-bezier(.445, .05, .55, .95);
  630. width: 85px;
  631. float: left;
  632. height: 51px;
  633. margin-right: 6px;
  634. cursor: pointer;
  635. line-height: 20px;
  636. padding-top: 4px;
  637. text-align: center;
  638. border-top-left-radius: 5px;
  639. border-top-right-radius: 5px;
  640. border: 1px solid #ccc;
  641. border-bottom: 0;
  642. }
  643. .tab.activeTab {
  644. color: #fff;
  645. background-color: #2196f3;
  646. color: hsla(0, 0%, 100%, .7);
  647. }
  648. /*响应式调整*/
  649. @media only screen and (max-width: 320px) {
  650. .list .dotContainer {
  651. width: 20px;
  652. padding-left: 5px;
  653. }
  654. .list li .title {
  655. width: 30%;
  656. }
  657. .list li .current {
  658. width: 29%;
  659. }
  660. .context {
  661. top: 227px;
  662. }
  663. }
  664. @media (min-width: 321px) and (max-width: 344px) {
  665. .list li .current {
  666. width: 28%;
  667. }
  668. .context {
  669. top: 227px;
  670. }
  671. }
  672. @media (min-width: 345px) and (max-width: 360px) {
  673. .list li .current {
  674. width: 30%;
  675. }
  676. .context {
  677. top: 230px;
  678. }
  679. }
  680. @media (min-width: 361px) and (max-width: 375px) {
  681. .list li .current {
  682. width: 30%;
  683. }
  684. .context {
  685. top: 230px;
  686. }
  687. }
  688. @media (min-width: 376px) and (max-width: 396px) {
  689. .list li .current {
  690. width: 30%;
  691. }
  692. .context {
  693. top: 230px;
  694. }
  695. }
  696. @media (min-width: 397px) and (max-width: 414px) {
  697. .list li .current {
  698. width: 30%;
  699. }
  700. .context {
  701. top: 230px;
  702. }
  703. }
  704. @media (min-width: 415px) and (max-width: 480px) {
  705. .list li .current {
  706. width: 30%;
  707. }
  708. .context {
  709. top: 230px;
  710. }
  711. }
  712. @media (min-width: 481px) and (max-width: 640px) {
  713. .context {
  714. position: fixed;
  715. /*top: 230px;*/
  716. }
  717. }
  718. @media (min-width: 641px) and (max-width: 2481px) {
  719. .context {
  720. position: fixed;
  721. top: 38%;
  722. /*top: 230px;*/
  723. }
  724. }
  725. @media (min-width: 2482px) and (max-width: 3841px) {
  726. .context {
  727. position: fixed;
  728. top: 60%;
  729. /*top: 230px;*/
  730. }
  731. }
  732. </style>