index.vue 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802
  1. <template>
  2. <view>
  3. <nav-bar title="模考预约" class="nav"></nav-bar>
  4. <view class="tabs">
  5. <view
  6. class="tab"
  7. :class="{ active: param.mockStatus == 0 }"
  8. data-index="1"
  9. @click="tab(0)"
  10. >
  11. <view>未考试</view>
  12. </view>
  13. <view
  14. class="tab"
  15. :class="{ active: param.mockStatus == 1 }"
  16. data-index="2"
  17. @click="tab(1)"
  18. >
  19. <view>已结束</view>
  20. </view>
  21. <view class="sort" @click="showSort = true"> 筛选 </view>
  22. </view>
  23. <view class="record">
  24. <template v-if="param.mockStatus == 0">
  25. <view v-if="recordList.length">
  26. <view
  27. class="examList"
  28. v-for="(item, index) in recordList"
  29. :key="index"
  30. >
  31. <view class="main">
  32. <view class="top" @click="showDetails(item)">
  33. <view class="subject">{{ item.applyName }}</view>
  34. </view>
  35. <view class="item">
  36. <view class="left">项目</view>
  37. <view class="right"
  38. >{{ item.businessName }} {{ item.projectName }}</view
  39. >
  40. </view>
  41. <view class="item">
  42. <view class="left">专业</view>
  43. <view class="right">{{ item.categoryName }}</view>
  44. </view>
  45. <view class="item">
  46. <view class="left">科目</view>
  47. <view class="right">{{ item.subjectName }}</view>
  48. </view>
  49. <view class="item" v-if="item.mockActivity !== 1">
  50. <view class="left">考试时间</view>
  51. <view class="right">
  52. {{ $method.timestampToTime(item.applySiteExamTime) }}
  53. {{ item.applySiteStartTime }} - {{ item.applySiteEndTime }}
  54. </view>
  55. </view>
  56. <view class="btn-wrap">
  57. <view class="btn-line">
  58. <!-- mockActivity 1是活动模考,0否 && (!item.handStatus || item.handStatus == 0)-->
  59. <view
  60. v-if="
  61. item.mockActivity == 1 &&
  62. (!item.handStatus || item.handStatus == 0)
  63. "
  64. class="btn"
  65. :class="{
  66. 'test-disabled': !(item.activityStartTime < nowTime),
  67. }"
  68. @click="goExamCount(item, index)"
  69. >去考试</view
  70. >
  71. <view v-else>
  72. <view
  73. class="btn test-disabled"
  74. v-if="goTest(item)"
  75. @click="goExamCount(item, index)"
  76. >去考试</view
  77. >
  78. <view class="btn test-disabled" v-else-if="item.handStatus"
  79. >已考试</view
  80. >
  81. <view class="btn" v-else @click="goExamCount(item, index)"
  82. >去考试</view
  83. >
  84. </view>
  85. </view>
  86. </view>
  87. </view>
  88. </view>
  89. </view>
  90. <view v-else class="nodata">暂无相关数据</view>
  91. </template>
  92. <template v-if="param.mockStatus == 1">
  93. <view v-if="recordList.length">
  94. <view
  95. class="examList"
  96. v-for="(item, index) in recordList"
  97. :key="index"
  98. >
  99. <view class="main">
  100. <view class="top" @click="showDetails(item)">
  101. <view class="subject">{{ item.applyName }}</view>
  102. </view>
  103. <view class="item">
  104. <view class="left">项目</view>
  105. <view class="right"
  106. >{{ item.businessName }} {{ item.projectName }}</view
  107. >
  108. </view>
  109. <view class="item">
  110. <view class="left">专业</view>
  111. <view class="right">{{ item.categoryName }}</view>
  112. </view>
  113. <view class="item">
  114. <view class="left">科目</view>
  115. <view class="right">{{ item.subjectName }}</view>
  116. </view>
  117. <view class="item">
  118. <view class="left">考试时间</view>
  119. <view class="right">
  120. {{ $method.timestampToTime(item.applySiteExamTime) }}
  121. {{ item.applySiteStartTime }} - {{ item.applySiteEndTime }}
  122. </view>
  123. </view>
  124. <view class="btn-wrap">
  125. <view class="btn-line" v-if="item.reSubscribe == 1">
  126. <view class="btn border" @click="reApply(item)"
  127. >重新预约</view
  128. >
  129. </view>
  130. <template v-else>
  131. <view class="btn-line">
  132. <view class="text" v-if="item.handStatus"
  133. >当前报告含主观题需人工阅卷,阅卷完成后显示完整报告</view
  134. >
  135. <view class="text" v-if="!item.handStatus"
  136. >由于未按时参加考试,主观题将不会提交至后台进行人工阅卷</view
  137. >
  138. <view
  139. class="btn border"
  140. :class="{
  141. disabled: item.canDo === 0,
  142. 'btn--half': item.handStatus,
  143. }"
  144. @click="doQuestion(item)"
  145. >去做题</view
  146. >
  147. <view
  148. class="btn btn--half border"
  149. @click="report(item)"
  150. v-if="item.handStatus"
  151. >查看报告</view
  152. >
  153. </view>
  154. <view
  155. class="btn-line"
  156. v-if="
  157. item.liveEndTime && item.liveStartTime && item.liveUrl
  158. "
  159. >
  160. <view class="text-half">
  161. <view>模考讲解直播时间</view>
  162. <view
  163. >{{
  164. $method.timestampToTime(item.liveStartTime, false)
  165. }}
  166. -
  167. {{
  168. $method.timestampToTime(item.liveEndTime, false)
  169. }}</view
  170. >
  171. </view>
  172. <view class="btn btn--half border" @click="goLive(item)"
  173. >去查看</view
  174. >
  175. </view>
  176. </template>
  177. </view>
  178. </view>
  179. </view>
  180. </view>
  181. <view v-else class="nodata">暂无相关数据</view>
  182. </template>
  183. </view>
  184. <view class="modal" :style="{ top: modalTop + 'px' }" v-if="showSort">
  185. <view class="content">
  186. <view class="item">
  187. <view class="item__title">考试时间</view>
  188. <view class="item__box">
  189. <view class="text">
  190. <picker
  191. mode="date"
  192. :value="param.startTime"
  193. :end="endDate"
  194. @change="bindDateFromChange"
  195. >
  196. <view class="uni-input">{{
  197. param.startTime || "开始时间"
  198. }}</view>
  199. </picker>
  200. -
  201. <picker
  202. mode="date"
  203. :value="param.endTime"
  204. :end="endDate"
  205. @change="bindDateToChange"
  206. >
  207. <view class="uni-input">{{ param.endTime || "结束时间" }}</view>
  208. </picker>
  209. </view>
  210. <u-icon class="icon" name="calendar"></u-icon>
  211. </view>
  212. </view>
  213. <view class="item">
  214. <view class="item__title">考试标题</view>
  215. <view class="item__box">
  216. <picker
  217. class="picker"
  218. mode="selector"
  219. :range="listApplyName"
  220. range-key="applyName"
  221. :value="param.applyName"
  222. @change="bindTitleChange"
  223. >
  224. <view style="width: 650rpx; height: 40rpx">{{
  225. param.applyName
  226. }}</view>
  227. </picker>
  228. <u-icon class="icon" name="arrow-down"></u-icon>
  229. </view>
  230. </view>
  231. </view>
  232. <view class="modal_wrap" @click="showSort = false"></view>
  233. </view>
  234. </view>
  235. </template>
  236. <script>
  237. import { mapGetters } from "vuex";
  238. export default {
  239. data() {
  240. return {
  241. showSort: false,
  242. index: 0,
  243. list: [],
  244. list1: [],
  245. recordList: [],
  246. goodsData: {},
  247. param: {
  248. pageNum: 1,
  249. pageSize: 10,
  250. mockStatus: 0,
  251. endTime: "",
  252. startTime: "",
  253. applyName: "",
  254. },
  255. nowTime: 0,
  256. sysTime: Date.now(),
  257. dateFrom: "",
  258. dateTo: "",
  259. isRepeat: false,
  260. total: 0,
  261. activeIndex: 0,
  262. typeIndex: 0,
  263. itemIndex: "",
  264. modalTop: 0,
  265. endDate: "",
  266. titleName: 3,
  267. listApplyName: [],
  268. };
  269. },
  270. computed: {
  271. ...mapGetters(["userInfo", "other"]),
  272. },
  273. onLoad(option) {
  274. this.param.mockStatus = option.state || 0;
  275. this.endDate = this.$method
  276. .timestampToTime(new Date().getTime() / 1000)
  277. .replace(/-/g, "/");
  278. // this.mockSubscribeListSubscribe();
  279. uni.getSystemInfo({
  280. success: (e) => {
  281. let info = uni.createSelectorQuery().select(".nav");
  282. info
  283. .boundingClientRect((navData) => {
  284. //data - 各种参数
  285. let info = uni.createSelectorQuery().select(".tabs");
  286. info
  287. .boundingClientRect((tabData) => {
  288. //data - 各种参数
  289. this.modalTop = navData.height + tabData.height;
  290. console.log(navData); // 获取元素宽度
  291. console.log(tabData); // 获取元素宽度
  292. })
  293. .exec();
  294. })
  295. .exec();
  296. },
  297. });
  298. },
  299. onPullDownRefresh() {
  300. let that = this;
  301. this.param.pageNum = 1;
  302. this.mockSubscribeListSubscribe();
  303. setTimeout(function () {
  304. uni.stopPullDownRefresh();
  305. }, 500);
  306. },
  307. onReachBottom() {
  308. console.log(this.total, "total");
  309. console.log(this.recordList.length, "length");
  310. if (this.recordList.length < this.total) {
  311. this.param.pageNum++;
  312. this.mockSubscribeListSubscribe();
  313. }
  314. },
  315. onShow() {
  316. this.nowTime = +this.$method.timest();
  317. // if(this.itemIndex !== '') {
  318. // this.refreshByIndex();
  319. // }
  320. this.recordList = [];
  321. this.mockSubscribeListSubscribe();
  322. },
  323. methods: {
  324. mockApplyListApplyName() {
  325. let param = JSON.parse(JSON.stringify(this.param));
  326. if (param.endTime) {
  327. param.endTime = this.$method.TimeTotimestamp(param.endTime);
  328. }
  329. if (param.startTime) {
  330. param.startTime = this.$method.TimeTotimestamp(param.startTime);
  331. }
  332. console.log(param, "param");
  333. this.$api.mockApplyListApplyName(param).then((res) => {
  334. this.listApplyName = res.data.rows;
  335. console.log(this.listApplyName, "listApplyName");
  336. this.param.applyName = "";
  337. this.mockSubscribeListSubscribe();
  338. });
  339. },
  340. reApply(item) {
  341. uni.redirectTo({
  342. url: "/pages5/examAppointList/index",
  343. });
  344. },
  345. report(item) {
  346. uni.navigateTo({
  347. url:
  348. "/pages5/examReport/index?&examId=" +
  349. item.examId +
  350. "&id=" +
  351. item.recordId +
  352. "&eachExamId=" +
  353. item.eachExamId +
  354. "&subscribeId=" +
  355. item.subscribeId,
  356. });
  357. },
  358. doQuestion(item) {
  359. if (item.canDo === 0) {
  360. uni.showToast({
  361. icon: "none",
  362. msg: "请等待所有科目考试结束后再进入刷题",
  363. });
  364. return;
  365. }
  366. uni.navigateTo({
  367. url:
  368. "../examBank/index?examId=" +
  369. item.examId +
  370. "&eachExamId=" +
  371. item.eachExamId +
  372. "&subscribeId=" +
  373. item.subscribeId,
  374. });
  375. },
  376. goTest(item) {
  377. if (item.mockActivity && item.mockActivity == 1) {
  378. return false;
  379. }
  380. let startTime = this.$method.TimeTotimestamp(
  381. this.$method.timestampToTime(item.applySiteExamTime) +
  382. " " +
  383. item.applySiteStartTime
  384. );
  385. let canGo =
  386. startTime - this.nowTime <= 600 &&
  387. startTime - this.nowTime >= (-(item.timeLimit * 60) || 0);
  388. return !canGo;
  389. },
  390. isStart(item) {
  391. let startTime = this.$method.TimeTotimestamp(
  392. this.$method.timestampToTime(item.applySiteExamTime) +
  393. " " +
  394. item.applySiteStartTime
  395. );
  396. return startTime - this.nowTime <= 600;
  397. },
  398. mockSubscribeListSubscribe() {
  399. let param = JSON.parse(JSON.stringify(this.param));
  400. if (param.endTime) {
  401. param.endTime = this.$method.TimeTotimestamp(param.endTime);
  402. }
  403. if (param.startTime) {
  404. param.startTime = this.$method.TimeTotimestamp(param.startTime);
  405. }
  406. // mock/subscribe/listSubscribe
  407. this.$api.mockSubscribeListSubscribe(param).then((res) => {
  408. this.recordList.push(...res.data.rows);
  409. this.total = res.data.total;
  410. });
  411. },
  412. refreshByIndex() {
  413. let param = JSON.parse(JSON.stringify(this.param));
  414. if (param.endTime) {
  415. param.endTime = this.$method.TimeTotimestamp(param.endTime);
  416. }
  417. if (param.startTime) {
  418. param.startTime = this.$method.TimeTotimestamp(param.startTime);
  419. }
  420. param.pageNum = this.itemIndex + 1;
  421. param.pageSize = 1;
  422. this.$api.mockSubscribeListSubscribe(param).then((res) => {
  423. console.log("res.data.rows[0]", res.data.rows[0]);
  424. this.$set(this.recordList, this.itemIndex, res.data.rows[0]);
  425. this.itemIndex = "";
  426. });
  427. },
  428. goLive(item) {
  429. let uuid = new Date().valueOf() + "";
  430. // buyCourse 是否购买课程:1是 0否
  431. let encode = encodeURIComponent(
  432. this.other.hostLive +
  433. "/pages/live/index?token=" +
  434. uni.getStorageSync("token") +
  435. "&userInfo=" +
  436. JSON.stringify(this.userInfo) +
  437. "&channelId=" +
  438. item.liveUrl +
  439. "&buyCourse=1" +
  440. "&ident=" +
  441. uuid
  442. );
  443. uni.navigateTo({
  444. url: `/pages5/webview/index?url=` + encode,
  445. });
  446. },
  447. async goExamCount(item, index) {
  448. if (item.mockActivity && item.mockActivity == 1) {
  449. if (!(item.activityStartTime < this.nowTime)) {
  450. return;
  451. }
  452. await this.$http({
  453. url: "/mock/apply/addMockTime",
  454. method: "post",
  455. data: {
  456. applyId: item.applyId,
  457. duration: item.duration,
  458. majorId: item.majorId,
  459. subjectId: item.subjectId,
  460. mockMajorSubjectId: item.mockMajorSubjectId,
  461. },
  462. }).then((res) => {
  463. if (res.data.code == 200) {
  464. const { examTime, startTime, endTime, eachExamId, mockActivity } =
  465. res.data.data;
  466. let o_item = {
  467. ...item,
  468. applySiteExamTime: examTime,
  469. applySiteStartTime: startTime,
  470. applySiteEndTime: endTime,
  471. eachExamId: eachExamId,
  472. mockActivity: mockActivity,
  473. };
  474. // item.applySiteExamTime = examTime // 当前时间的时间戳
  475. // item.applySiteStartTime = startTime
  476. // item.applySiteEndTime = endTime
  477. // item.eachExamId = eachExamId
  478. this.toJump(o_item, index);
  479. } else {
  480. this.$u.toast(res.data.msg);
  481. return;
  482. }
  483. });
  484. } else {
  485. this.toJump(item, index);
  486. }
  487. },
  488. toJump(item, index) {
  489. if (this.goTest(item)) {
  490. uni.showToast({
  491. icon: "none",
  492. title: "不在考试时间",
  493. });
  494. return;
  495. }
  496. this.itemIndex = index;
  497. uni.navigateTo({
  498. url:
  499. "../examCount/index?start=" +
  500. this.$method.TimeTotimestamp(
  501. this.$method.timestampToTime(item.applySiteExamTime) +
  502. " " +
  503. item.applySiteStartTime
  504. ) +
  505. "&limit=" +
  506. item.timeLimit +
  507. "&examId=" +
  508. item.examId +
  509. "&eachExamId=" +
  510. item.eachExamId +
  511. "&subscribeId=" +
  512. item.subscribeId +
  513. "&mockName=" +
  514. item.applyName +
  515. "&examEndTime=" +
  516. this.$method.TimeTotimestamp(
  517. this.$method.timestampToTime(item.applySiteExamTime) +
  518. " " +
  519. item.applySiteEndTime
  520. ) +
  521. "&mockActivity=" +
  522. item.mockActivity +
  523. "&goodsId=" +
  524. (item.goodsId || "") +
  525. "&orderGoodsId=" +
  526. (item.orderGoodsId || ""),
  527. });
  528. },
  529. sort() {},
  530. appoint(item) {
  531. this.appointModal = true;
  532. },
  533. tab(state) {
  534. if (this.param.mockStatus == state) {
  535. return;
  536. }
  537. this.recordList = [];
  538. this.param.endTime = "";
  539. this.param.startTime = "";
  540. this.param.applyName = "";
  541. this.param.pageNum = 1;
  542. this.param.mockStatus = state;
  543. this.mockSubscribeListSubscribe();
  544. },
  545. bindDateFromChange(e) {
  546. this.param.startTime = e.detail.value;
  547. this.param.pageNum = 1;
  548. this.param.applyName = "";
  549. this.recordList = [];
  550. this.mockApplyListApplyName();
  551. },
  552. bindDateToChange(e) {
  553. this.param.endTime = e.detail.value;
  554. this.param.pageNum = 1;
  555. this.param.applyName = "";
  556. this.recordList = [];
  557. this.mockApplyListApplyName();
  558. },
  559. bindTitleChange(e) {
  560. if (this.listApplyName.length) {
  561. let index = e.detail.value;
  562. this.param.applyName = this.listApplyName[index].applyName;
  563. } else {
  564. this.param.applyName = "";
  565. }
  566. this.param.pageNum = 1;
  567. this.recordList = [];
  568. this.mockSubscribeListSubscribe();
  569. },
  570. },
  571. };
  572. </script>
  573. <style>
  574. page {
  575. background: #eaeef1;
  576. }
  577. </style>
  578. <style lang="scss" scope>
  579. .animals {
  580. transition: all 0.3s;
  581. transform: rotate(180deg);
  582. }
  583. .tabs {
  584. position: fixed;
  585. left: 0;
  586. width: 100%;
  587. display: flex;
  588. z-index: 10;
  589. background: #ffffff;
  590. padding: 18rpx 0;
  591. border-bottom: 1px solid #eee;
  592. .tab {
  593. padding: 0 18rpx;
  594. flex: 1;
  595. background: #ffffff;
  596. font-size: 32rpx;
  597. color: #999999;
  598. text-align: center;
  599. position: relative;
  600. &:nth-of-type(2) {
  601. border-right: 1px solid #eeeeee;
  602. }
  603. &.active {
  604. color: #333333;
  605. &::before {
  606. content: "";
  607. position: absolute;
  608. width: 24px;
  609. height: 4px;
  610. background: #007aff;
  611. border-radius: 2px;
  612. left: 50%;
  613. margin-left: -12px;
  614. bottom: -18rpx;
  615. }
  616. }
  617. }
  618. .sort {
  619. width: 160rpx;
  620. text-align: center;
  621. font-size: 32rpx;
  622. font-weight: 500;
  623. color: #999999;
  624. }
  625. }
  626. .record {
  627. margin-top: 80rpx;
  628. padding: 16rpx 16rpx;
  629. .examList {
  630. .main {
  631. background: #ffffff;
  632. border-radius: 16rpx;
  633. margin: 20rpx 0;
  634. }
  635. .top {
  636. height: 80rpx;
  637. text-align: center;
  638. line-height: 80rpx;
  639. font-size: 30rpx;
  640. color: #333333;
  641. font-weight: bold;
  642. border-bottom: 1px solid #eeeeee;
  643. }
  644. .item {
  645. display: flex;
  646. justify-content: space-between;
  647. align-items: center;
  648. margin-left: 31rpx;
  649. height: 80rpx;
  650. padding-right: 24rpx;
  651. border-bottom: 1px solid #eeeeee;
  652. font-size: 24rpx;
  653. color: #666666;
  654. .right {
  655. font-size: 28rpx;
  656. }
  657. }
  658. .btn-wrap {
  659. padding: 24rpx 16rpx;
  660. border-bottom: 1px solid #eeeeee;
  661. .btn-line {
  662. display: flex;
  663. align-items: center;
  664. justify-content: center;
  665. flex-wrap: wrap;
  666. }
  667. .text {
  668. width: 100%;
  669. color: #f5222d;
  670. font-size: 24rpx;
  671. text-align: center;
  672. }
  673. .text-half {
  674. color: #666666;
  675. font-size: 24rpx;
  676. width: 320rpx;
  677. margin: 8rpx;
  678. }
  679. .btn {
  680. margin: 8rpx;
  681. width: 528rpx;
  682. height: 64rpx;
  683. background: #007aff;
  684. border-radius: 16rpx;
  685. text-align: center;
  686. line-height: 64rpx;
  687. color: #fff;
  688. &--half {
  689. width: 320rpx;
  690. }
  691. &.border {
  692. background: #fff;
  693. color: #007aff;
  694. border: 1px solid #007aff;
  695. }
  696. &.disabled {
  697. color: #d9d9d9;
  698. border-color: #d9d9d9;
  699. }
  700. &.test-disabled {
  701. color: #fff;
  702. background: #d9d9d9;
  703. }
  704. }
  705. }
  706. }
  707. }
  708. .modal {
  709. bottom: 0;
  710. z-index: 199999999;
  711. position: fixed;
  712. left: 0;
  713. width: 100%;
  714. .content {
  715. overflow: hidden;
  716. position: relative;
  717. z-index: 10;
  718. background: #fff;
  719. padding: 20rpx 12rpx 16rpx;
  720. .item {
  721. &__title {
  722. padding: 16rpx 0;
  723. font-size: 28rpx;
  724. color: #999999;
  725. }
  726. &__box {
  727. padding: 0 16rpx;
  728. display: flex;
  729. width: 718rpx;
  730. height: 80rpx;
  731. background: #ffffff;
  732. border: 1px solid #eeeeee;
  733. border-radius: 16rpx;
  734. align-items: center;
  735. .text {
  736. flex: 1;
  737. display: flex;
  738. align-items: center;
  739. }
  740. }
  741. }
  742. }
  743. .modal_wrap {
  744. position: absolute;
  745. left: 0;
  746. width: 100%;
  747. top: 0;
  748. height: 100%;
  749. background: rgba(0, 0, 0, 0.3);
  750. }
  751. }
  752. .activesty {
  753. background: #007aff !important;
  754. color: #fff !important;
  755. }
  756. .nodata {
  757. text-align: center;
  758. margin-top: 100rpx;
  759. font-size: 32rpx;
  760. color: #222;
  761. }
  762. </style>