StudyTables.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607
  1. <template>
  2. <div class="studyRecordTable">
  3. <div style="height: 50px" class="fixeBox">
  4. <div
  5. class="studyStyle"
  6. :class="fixeStatus ? 'isFixed' : null"
  7. :style="{ left: left }"
  8. >
  9. <div class="a_style">
  10. <i></i>
  11. <span>视频审核进度</span>
  12. <div class="flex_style_study">
  13. <div class="num_style" style="color: #0047d0">
  14. 待审:{{ userData.pending }}节
  15. </div>
  16. <div class="num_style" style="color: #e53935">
  17. 作弊:{{ userData.cheat }}节
  18. </div>
  19. <div class="num_style" style="color: #43a047">
  20. 通过:{{ userData.pass }}节
  21. </div>
  22. <div style="clear: both"></div>
  23. </div>
  24. </div>
  25. <div class="a_style">
  26. <i></i>
  27. <span>做题审核进度</span>
  28. <div class="flex_style_study">
  29. <div class="num_style" style="color: #0047d0">
  30. 待审:{{ userData.examPending }}节
  31. </div>
  32. <div class="num_style" style="color: #e53935">
  33. 作弊:{{ userData.examCheat }}节
  34. </div>
  35. <div class="num_style" style="color: #43a047">
  36. 通过:{{ userData.examPass }}节
  37. </div>
  38. <div style="clear: both"></div>
  39. </div>
  40. </div>
  41. <div class="a_style" style="width: 280px">
  42. <i></i>
  43. <span>学时审批状态</span>
  44. <div class="flex_style_study">
  45. <div class="num_style" style="color: #0047d0">
  46. {{
  47. ["不可审核", "未通过", "通过审核", "待审核", "审核中"][
  48. periodStatus + 1
  49. ]
  50. }}
  51. </div>
  52. <div style="clear: both"></div>
  53. </div>
  54. </div>
  55. <div class="s_sd">
  56. <template v-if="periodStatus === 2">
  57. <el-checkbox
  58. :disabled="!allIds.length"
  59. :indeterminate="isIndeterminate"
  60. v-model="checkAll"
  61. @change="handleCheckAllChange"
  62. >待审全选</el-checkbox
  63. >
  64. <el-button
  65. style="margin-left: 10px"
  66. size="mini"
  67. type="success"
  68. @click="getChangeStatus(1)"
  69. >勾选通过</el-button
  70. >
  71. <el-button size="mini" type="danger" @click="getChangeStatus(2)"
  72. >勾选作弊</el-button
  73. >
  74. </template>
  75. <template v-if="periodStatus === 3">
  76. <el-button style="margin-left: 10px" size="mini" @click="checkBack"
  77. >勾选数据,打回待审核状态</el-button
  78. >
  79. <el-button size="mini" type="warning" @click="approvedOK = true"
  80. >确认审核通过结果</el-button
  81. >
  82. </template>
  83. <el-button
  84. v-if="periodStatus === 3"
  85. style="margin-left: 10px"
  86. size="mini"
  87. type="danger"
  88. @click="backToAudit"
  89. >全部打回重学</el-button
  90. >
  91. </div>
  92. </div>
  93. </div>
  94. <el-checkbox-group v-model="checkList" @change="handleCheckedCitiesChange">
  95. <component
  96. :is="keys[key]"
  97. v-for="key in Object.keys(tablesData)"
  98. :key="key"
  99. :tabledata="tablesData[key]"
  100. :label="key == 5 ? '卷' : '章'"
  101. :setData="setData"
  102. :erJianErZao="erJianErZao"
  103. ></component>
  104. </el-checkbox-group>
  105. <Cheat-dialog
  106. :disabledBtn="disabledBtn"
  107. :vidBoxHours.sync="vidBoxHours"
  108. @close="loadingClose"
  109. @submit="
  110. (reason) => {
  111. submitOK(2, reason);
  112. }
  113. "
  114. ></Cheat-dialog>
  115. <Base-dialog
  116. title="操作提示:"
  117. :disabledBtn="disabledBtn"
  118. :isShow.sync="through"
  119. @close="loadingClose"
  120. @submit="
  121. () => {
  122. submitOK(1);
  123. }
  124. "
  125. >
  126. <div>
  127. 确定所勾选的内容,审核结果为【通过】?<br />
  128. 确认后,初审不可再修改,请检查清楚再操作!
  129. </div>
  130. </Base-dialog>
  131. <Base-dialog
  132. title="操作提示:"
  133. :disabledBtn="disabledBtn"
  134. :isShow.sync="popback"
  135. @close="loadingClose"
  136. @submit="uploadForm"
  137. >
  138. <div>
  139. <div style="color: red">
  140. <h4 style="margin: 0px">当前勾选了{{ checkList.length }}条数据:</h4>
  141. <ul style="margin: 0px 0px 6px; max-height: 500px; overflow: auto">
  142. <li v-for="(item, index) in checkList" :key="index">
  143. {{ index + 1 }}.{{ getSecName(item) }}
  144. </li>
  145. </ul>
  146. </div>
  147. <div style="text-align: center; font-weight: bold">
  148. 所选数据,确定要打回待审核状态吗?<br />
  149. 打回后,重新走审核流程,请慎重操作。
  150. </div>
  151. </div>
  152. </Base-dialog>
  153. <Base-dialog
  154. title="操作提示:"
  155. :disabledBtn="disabledBtn"
  156. :isShow.sync="approvedOK"
  157. @close="loadingClose"
  158. @submit="approvedOKFunc"
  159. >
  160. <div>
  161. <div style="color: red">
  162. <h4 style="margin: 0px">确认审核通过结果后:</h4>
  163. <ul style="margin: 0px 0px 6px">
  164. <li>
  165. (1)有做官方接口的,自动触发【学时官方推送】<br />
  166. (2)公开【学习学时记录-学时记录】按钮,权限人可查看【审核结果】<br />
  167. (3)有匹配的预约考试,可走预约流程
  168. </li>
  169. </ul>
  170. </div>
  171. <div style="font-weight: bold; margin-top: 20px">
  172. 确认提交审核通过结果?<br />
  173. 确认后,不能再修改,请慎重操作。
  174. </div>
  175. </div>
  176. </Base-dialog>
  177. </div>
  178. </template>
  179. <script>
  180. import ModulTable from "./ModulTable.vue";
  181. import ChapterTable from "./ChapterTable.vue";
  182. import LessonTable from "./LessonTable.vue";
  183. import CheatDialog from "./CheatDialog.vue";
  184. import { rollBackPeriod } from "@/api/education/classManageMent";
  185. import { mapGetters } from "vuex";
  186. export default {
  187. props: {
  188. tablesData: {
  189. type: Object,
  190. default: () => {
  191. return {};
  192. },
  193. },
  194. userData: {
  195. type: Object,
  196. default: () => {
  197. return {};
  198. },
  199. },
  200. setData: {
  201. type: Object,
  202. default: () => {
  203. return {};
  204. },
  205. },
  206. getUserInfo: {
  207. type: Function,
  208. default: () => {},
  209. },
  210. erJianErZao:{
  211. type:Boolean,
  212. default:()=>{
  213. return false
  214. }
  215. }
  216. },
  217. provide() {
  218. return {
  219. getPeriodStatus: () => this.periodStatus,
  220. getUserInfo: this.getUserInfo,
  221. getAllIds: () => this.allIds,
  222. };
  223. },
  224. data() {
  225. return {
  226. checkList: [],
  227. allIds: [],
  228. checkAll: false,
  229. isIndeterminate: false,
  230. vidBoxHours: false,
  231. through: false,
  232. popback: false,
  233. approvedOK: false,
  234. disabledBtn: false,
  235. formData: {
  236. cheating_reason: "",
  237. },
  238. statusPop: "", //1单个2批量
  239. rules: {
  240. cheating_reason: [
  241. {
  242. required: true,
  243. message: "请填写作弊原因",
  244. trigger: ["blur", "change"],
  245. },
  246. ],
  247. },
  248. msgTitle: [
  249. { label: "学习拍照异常", value: 1 },
  250. {
  251. label: "学习拍照太黑无法识别人像,请确保拍照光线充足并拍到全脸",
  252. value: 2,
  253. },
  254. {
  255. label: "学习拍照太模糊无法识别人像,请确保拍照光线充足并拍到全脸",
  256. value: 3,
  257. },
  258. {
  259. label: "学习拍照人像不全无法识别,请确保拍照光线充足并拍到全脸",
  260. value: 4,
  261. },
  262. ],
  263. allType3List: [],
  264. fixeStatus: false,
  265. };
  266. },
  267. methods: {
  268. submitAllSlect(reason) {
  269. this.submitOK(2, reason);
  270. },
  271. handleCheckedCitiesChange(value) {
  272. let checkedCount = value.length;
  273. if (checkedCount) {
  274. this.checkAll = checkedCount === this.allIds.length;
  275. } else {
  276. this.checkAll = false;
  277. }
  278. this.isIndeterminate =
  279. checkedCount > 0 && checkedCount < this.allIds.length;
  280. },
  281. handleCheckAllChange(val) {
  282. this.checkList = val ? this.allIds : [];
  283. this.isIndeterminate = false;
  284. },
  285. getAllId(data) {
  286. if (!data || !data.length) {
  287. return;
  288. }
  289. data.forEach((ele) => {
  290. if (ele.type == 3 || ele.type == 4) {
  291. this.allType3List.push(ele);
  292. ele.status === 2 && this.allIds.push(ele.periodStatusId);
  293. } else {
  294. if (ele.type == 1 && ele.arr) {
  295. let item = ele.arr[0];
  296. this.allType3List.push(item);
  297. item.status === 2 && this.allIds.push(item.periodStatusId);
  298. }
  299. this.getAllId(
  300. ele.type == 1 ? ele.classPeriods : ele.classPeriodSectionList
  301. );
  302. }
  303. });
  304. },
  305. getChangeStatus(int) {
  306. if (!this.checkList.length) {
  307. this.$message.warning("请勾选需要操作的待审核数据");
  308. return;
  309. }
  310. var data = {
  311. gradeId: Number(this.setData.id),
  312. userId: Number(this.setData.userId),
  313. goodsId: Number(this.setData.goodsId),
  314. };
  315. if (int === 1) {
  316. data.status = 1;
  317. this.through = true;
  318. }
  319. if (int === 2) {
  320. data.status = 0;
  321. this.statusPop = 2;
  322. this.formData.cheating_reason = "";
  323. this.vidBoxHours = true;
  324. }
  325. },
  326. loadingClose() {
  327. this.disabledBtn = false;
  328. },
  329. submitOK(int, msg) {
  330. this.disabledBtn = true;
  331. var data = {
  332. gradeId: Number(this.setData.id),
  333. userId: Number(this.setData.userId),
  334. goodsId: Number(this.setData.goodsId),
  335. ids: this.checkList,
  336. };
  337. if (int === 1) {
  338. data.status = 1;
  339. }
  340. if (int === 2) {
  341. data.auditReason = msg;
  342. data.status = 0;
  343. }
  344. this.$api
  345. .editGradeUsereditPeriodeAll(data)
  346. .then((res) => {
  347. if (int === 1) {
  348. this.$message.success("状态全部通过修改成功");
  349. this.through = false;
  350. this.checkAll && this.goReview();
  351. }
  352. if (int === 2) {
  353. this.$message.success("状态全部作弊修改成功");
  354. this.vidBoxHours = false;
  355. }
  356. this.checkList = [];
  357. this.isIndeterminate = false;
  358. this.checkAll = false;
  359. this.getUserInfo(true);
  360. })
  361. .catch(() => {
  362. this.disabledBtn = false;
  363. });
  364. },
  365. getSecName(id) {
  366. try {
  367. return this.allType3List.find((e) => e.periodStatusId == id).typeName;
  368. } catch (error) {
  369. return "";
  370. }
  371. },
  372. uploadText(msg) {
  373. this.formData.cheating_reason = msg;
  374. },
  375. checkBack() {
  376. if (!this.checkList.length) {
  377. this.$confirm("您还未勾选数据,是否勾选全部数据?", "提示", {
  378. confirmButtonText: "是",
  379. cancelButtonText: "否",
  380. type: "warning",
  381. })
  382. .then(() => {
  383. this.checkList = this.allType3List.map((i) => {
  384. if (
  385. this.periodStatus === 3 &&
  386. i.periodStatus === 1 &&
  387. i.status !== 2
  388. ) {
  389. return i.periodStatusId;
  390. }
  391. });
  392. })
  393. .catch(() => {});
  394. return;
  395. }
  396. this.popback = true;
  397. },
  398. // 打回审核状态
  399. uploadForm() {
  400. this.disabledBtn = true;
  401. let data = {
  402. gradeId: Number(this.setData.id),
  403. userId: Number(this.setData.userId),
  404. goodsId: Number(this.setData.goodsId),
  405. orderGoodsId: Number(this.setData.orderGoodsId),
  406. ids: this.checkList,
  407. };
  408. this.$api
  409. .editGradeUsereditrollbackPeriod(data)
  410. .then((res) => {
  411. this.checkList = []; //勾选列表
  412. this.isIndeterminate = false; //待审半选
  413. this.checkAll = false; //全选状态
  414. this.getUserInfo(true);
  415. this.$message.success("已打回待审核状态");
  416. this.popback = false;
  417. this.goReview();
  418. })
  419. .catch(() => {
  420. this.disabledBtn = false;
  421. });
  422. },
  423. // 确认审核结果
  424. approvedOKFunc() {
  425. this.disabledBtn = true;
  426. let data = {
  427. gradeId: Number(this.setData.id),
  428. userId: Number(this.setData.userId),
  429. goodsId: Number(this.setData.goodsId),
  430. orderGoodsId: Number(this.setData.orderGoodsId),
  431. };
  432. this.$api
  433. .editGradeUsereditrollconfirmPeriod(data)
  434. .then((res) => {
  435. this.getUserInfo(true);
  436. this.$message.success("审核通过");
  437. this.approvedOK = false;
  438. this.goReview();
  439. })
  440. .catch(() => {
  441. this.disabledBtn = false;
  442. });
  443. },
  444. backToAudit() {
  445. this.$prompt("是否全部打回重学", "提示", {
  446. confirmButtonText: "确定",
  447. cancelButtonText: "取消",
  448. inputPattern: /^.+$/,
  449. inputErrorMessage: "请输入审核不通过原因",
  450. beforeClose: (action, instance, done) => {
  451. if (action === "confirm") {
  452. instance.confirmButtonLoading = true;
  453. instance.confirmButtonText = '执行中...';
  454. rollBackPeriod({
  455. orderGoodsId: this.userData.orderGoodsId,
  456. allReStudyReason: instance.inputValue,
  457. allReStudy: 1,
  458. })
  459. .then((res) => {
  460. done();
  461. })
  462. .catch(() => {
  463. this.$message.error("接口提交失败");
  464. return;
  465. }).finally(()=>{
  466. instance.confirmButtonText = '确定';
  467. instance.confirmButtonLoading = false;
  468. })
  469. } else {
  470. done();
  471. }
  472. },
  473. })
  474. .then(({ value }) => {
  475. this.getUserInfo(true);
  476. this.$message.success("已全部打回重学");
  477. })
  478. .catch(() => {});
  479. },
  480. goReview() {
  481. this.$store.dispatch("tagsView/delView", this.$route).then((res) => {
  482. this.$router.push({
  483. name: "ListOfhoursToBeReviewed",
  484. });
  485. });
  486. },
  487. scrollFunc() {
  488. this.fixeStatus =
  489. document.getElementsByClassName("fixeBox")[0].getBoundingClientRect()
  490. .top <= 83
  491. ? true
  492. : false;
  493. console.log(this.userData.examPending, "fixed");
  494. },
  495. },
  496. created() {
  497. this.keys = {
  498. 1: "ModulTable",
  499. 2: "ChapterTable",
  500. 5: "ChapterTable",
  501. 6: "LessonTable",
  502. };
  503. },
  504. components: { ModulTable, LessonTable, ChapterTable, CheatDialog },
  505. watch: {
  506. tablesData: {
  507. handler() {
  508. this.allIds = [];
  509. for (const key in this.tablesData) {
  510. this.getAllId(this.tablesData[key]);
  511. }
  512. },
  513. immediate: true,
  514. deep: true,
  515. },
  516. },
  517. computed: {
  518. periodStatus() {
  519. return this.userData.periodStatus;
  520. },
  521. ...mapGetters(["sidebar"]),
  522. left() {
  523. return this.sidebar.opened ? "226px" : "60px";
  524. },
  525. },
  526. mounted() {
  527. // window.addEventListener("scroll", this.scrollFunc,false);
  528. },
  529. };
  530. </script>
  531. <style lang="scss" scoped>
  532. .studyRecordTable {
  533. .studyStyle {
  534. display: flex;
  535. align-items: center;
  536. height: 50px;
  537. & > .a_style {
  538. display: flex;
  539. align-items: center;
  540. margin-right: 16px;
  541. padding: 11px 16px;
  542. box-shadow: 0px 0px 8px 0px rgba(217, 217, 217, 0.8);
  543. border-radius: 4px;
  544. height: 40px;
  545. width: 440px;
  546. user-select: none;
  547. i {
  548. width: 2px;
  549. height: 18px;
  550. display: inline-block;
  551. background-color: #0047d0;
  552. margin-right: 8px;
  553. }
  554. span {
  555. color: #666;
  556. font-weight: bold;
  557. }
  558. .flex_style_study {
  559. flex: 1;
  560. }
  561. .num_style {
  562. float: right;
  563. font-size: 14px;
  564. margin-left: 14px;
  565. }
  566. }
  567. .s_sd {
  568. flex: 1;
  569. justify-content: flex-end;
  570. display: flex;
  571. align-items: center;
  572. flex-shrink: 0;
  573. .dis_colu {
  574. height: 55px;
  575. margin-right: 14px;
  576. display: flex;
  577. flex-direction: column;
  578. justify-content: space-around;
  579. font-size: 14px;
  580. }
  581. }
  582. }
  583. .isFixed {
  584. position: fixed;
  585. top: 84px;
  586. right: 0;
  587. z-index: 10;
  588. background: #fff;
  589. padding: 0 20px;
  590. margin: 0;
  591. }
  592. }
  593. </style>