MarkParamStructure.vue 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. <template>
  2. <div class="mark-param-structure">
  3. <div class="mark-body" v-if="dataReady">
  4. <component
  5. :is="currentComponent"
  6. :ref="currentComponent"
  7. :datas="infos"
  8. @next-step="toNext"
  9. @on-ready="compReady"
  10. @data-change="dataChange"
  11. ></component>
  12. </div>
  13. <div class="text-center">
  14. <el-button
  15. v-if="!isFirstStep"
  16. type="primary"
  17. :disabled="loading"
  18. @click="prevStep"
  19. >上一步</el-button
  20. >
  21. <el-button
  22. v-if="isLastStep"
  23. type="primary"
  24. :disabled="loading"
  25. @click="nextStep"
  26. >提交</el-button
  27. >
  28. <el-button v-else type="primary" @click="nextStep" :disabled="loading"
  29. >下一步</el-button
  30. >
  31. <el-button @click="cancel">取消</el-button>
  32. </div>
  33. <div slot="footer"></div>
  34. </div>
  35. </template>
  36. <script>
  37. import { mapState, mapMutations } from "vuex";
  38. import MarkPaperGroup from "./MarkPaperGroup.vue";
  39. import MarkPaperStructure from "./MarkPaperStructure.vue";
  40. import { examStructureSubmit } from "../../api";
  41. import { calcSum, deepCopy } from "@/plugins/utils";
  42. const STEPS_LIST = [
  43. {
  44. name: "structure",
  45. title: "试卷结构",
  46. desc: "请按试卷填写相应试卷结构信息",
  47. },
  48. {
  49. name: "group",
  50. title: "评卷分组",
  51. desc: "请设置评卷分组",
  52. },
  53. ];
  54. export default {
  55. name: "mark-param-structure",
  56. components: { MarkPaperGroup, MarkPaperStructure },
  57. data() {
  58. return {
  59. infos: {
  60. basicPaperInfo: {},
  61. paperStructureInfo: [],
  62. groupInfo: [],
  63. paperStat: {},
  64. structureCanEdit: true,
  65. },
  66. // step
  67. steps: STEPS_LIST,
  68. current: 0,
  69. loading: false,
  70. dataReady: false,
  71. };
  72. },
  73. computed: {
  74. ...mapState("markParam", ["markParamInfos", "objectiveStructure"]),
  75. currentComponent() {
  76. return `mark-paper-${this.steps[this.current].name}`;
  77. },
  78. isFirstStep() {
  79. return this.current === 0;
  80. },
  81. isLastStep() {
  82. return this.current === this.lastStep;
  83. },
  84. lastStep() {
  85. return this.steps.length - 1;
  86. },
  87. },
  88. mounted() {
  89. this.initData();
  90. },
  91. methods: {
  92. ...mapMutations("markParam", [
  93. "setMarkParamInfos",
  94. "setObjectiveStructure",
  95. ]),
  96. async initData() {
  97. this.current = 0;
  98. this.loading = false;
  99. const {
  100. structureCanEdit,
  101. paperStructureInfo,
  102. groupInfo,
  103. classInfo,
  104. basicPaperInfo,
  105. } = this.markParamInfos;
  106. this.infos = {
  107. structureCanEdit,
  108. paperStructureInfo: deepCopy(paperStructureInfo),
  109. groupInfo: deepCopy(groupInfo),
  110. classInfo: deepCopy(classInfo),
  111. basicPaperInfo: this.getBaseInfo(basicPaperInfo),
  112. paperStat: this.statPaperStructure(paperStructureInfo),
  113. };
  114. this.dataReady = true;
  115. },
  116. getBaseInfo(baseInfo) {
  117. return this.$objAssign(
  118. {
  119. id: null,
  120. examPaperStructureId: baseInfo.id,
  121. examId: null,
  122. cardId: null,
  123. thirdRelateId: null,
  124. thirdRelateName: "",
  125. courseName: "",
  126. courseId: "",
  127. paperNumber: null,
  128. paperType: "",
  129. sequence: null,
  130. openClassReading: null,
  131. status: "",
  132. },
  133. baseInfo
  134. );
  135. },
  136. statPaperStructure(paperStructureInfo) {
  137. const questionCount = paperStructureInfo.length;
  138. const subjectiveQuestionCount = paperStructureInfo.filter(
  139. (item) => item.qType === "subjective"
  140. ).length;
  141. return {
  142. questionCount,
  143. paperTotalScore: calcSum(
  144. paperStructureInfo.map((item) => item.totalScore || 0)
  145. ),
  146. subjectiveQuestionCount,
  147. objectiveQuestionCount: questionCount - subjectiveQuestionCount,
  148. structChanged: false,
  149. };
  150. },
  151. prevStep() {
  152. if (this.isFirstStep) return;
  153. this.$refs[this.currentComponent].updateData();
  154. this.current -= 1;
  155. if (this.steps[this.current].name === "structure") {
  156. this.$notify({
  157. title: "警告",
  158. message: "修改试卷结构会清空已经设置的评卷员,需要重新设置!",
  159. type: "warning",
  160. duration: 5000,
  161. });
  162. }
  163. },
  164. nextStep() {
  165. this.$refs[this.currentComponent].checkData();
  166. },
  167. toNext() {
  168. if (this.isLastStep) {
  169. this.submit();
  170. } else {
  171. const paperStat = this.infos.paperStat;
  172. let tipsContent = `本试卷共${paperStat.questionCount}道小题,客观题${paperStat.objectiveQuestionCount}道,主观题${paperStat.subjectiveQuestionCount}道,总分为${paperStat.paperTotalScore}分。`;
  173. if (paperStat.structChanged) {
  174. tipsContent += "试卷结构有变动,评卷员将被清空。";
  175. }
  176. if (paperStat.subjectiveQuestionCount) {
  177. this.$confirm(`${tipsContent}确定要下一步吗?`, "提示", {
  178. type: "warning",
  179. })
  180. .then(() => {
  181. this.current += 1;
  182. })
  183. .catch(() => {});
  184. } else {
  185. // 没有主观题,可以直接提交,不需要设置评卷员分组
  186. this.$confirm(`${tipsContent}, 是否立即提交?`, "提示", {
  187. type: "warning",
  188. })
  189. .then(() => {
  190. this.submit();
  191. })
  192. .catch(() => {});
  193. }
  194. }
  195. },
  196. getPaperStructData(paperStructureInfo) {
  197. let originStruct = [];
  198. let group = [];
  199. let curMainId = null;
  200. let curQType = null;
  201. paperStructureInfo.forEach((item) => {
  202. if (curMainId !== item.mainId) {
  203. curMainId = item.mainId;
  204. curQType = item.qType[0];
  205. if (group.length) originStruct.push(`${curQType}${group.length}`);
  206. group = [];
  207. }
  208. group.push(item);
  209. });
  210. if (group.length) originStruct.push(`${curQType}${group.length}`);
  211. return originStruct;
  212. },
  213. dataChange(data) {
  214. if (data.paperStructureInfo) {
  215. data.paperStat = this.statPaperStructure(data.paperStructureInfo);
  216. }
  217. if (data.paperStructureInfo && this.infos.paperStructureInfo.length) {
  218. // 检验试卷结构是否有变化
  219. const originStruct = this.getPaperStructData(
  220. this.infos.paperStructureInfo
  221. );
  222. const curStruct = this.getPaperStructData(data.paperStructureInfo);
  223. if (curStruct.join("") !== originStruct.join("")) {
  224. data.groupInfo = [];
  225. data.classInfo = [];
  226. data.paperStat.structChanged = true;
  227. } else {
  228. // 更新分组中的试题信息
  229. const paperMap = {};
  230. data.paperStructureInfo.forEach((item) => {
  231. paperMap[`${item.mainNumber}-${item.subNumber}`] = item;
  232. });
  233. const groupInfo = this.infos.groupInfo.map((group) => {
  234. let ngroup = { ...group };
  235. ngroup.questions = ngroup.questions.map((q) => {
  236. return { ...paperMap[`${q.mainNumber}-${q.subNumber}`] };
  237. });
  238. return ngroup;
  239. });
  240. data.groupInfo = groupInfo;
  241. }
  242. }
  243. Object.entries(data).forEach(([key, val]) => {
  244. this.infos[key] = val;
  245. });
  246. },
  247. compReady(type = false) {
  248. this.loading = type;
  249. },
  250. async submit() {
  251. if (this.loading) return;
  252. const hasGroupNoPic = this.infos.groupInfo.some(
  253. (item) => !item.pictureConfigList.length
  254. );
  255. if (hasGroupNoPic) {
  256. const confirm = await this.$confirm(
  257. `当前评卷员分组中存在没有设置评卷区的分组, 确定要提交吗?`,
  258. "提示",
  259. {
  260. type: "warning",
  261. }
  262. ).catch(() => {});
  263. if (confirm !== "confirm") return;
  264. }
  265. this.loading = true;
  266. const datas = {
  267. structureCanEdit: this.infos.structureCanEdit,
  268. basicPaperInfo: this.infos.basicPaperInfo,
  269. paperStructureInfo: {
  270. objectiveQuestionList: this.infos.paperStructureInfo.filter(
  271. (item) => item.qType === "objective"
  272. ),
  273. subjectiveQuestionList: this.infos.paperStructureInfo.filter(
  274. (item) => item.qType === "subjective"
  275. ),
  276. },
  277. groupInfo: this.infos.groupInfo,
  278. classInfo: this.infos.classInfo,
  279. };
  280. const res = await examStructureSubmit(datas).catch(() => false);
  281. this.loading = false;
  282. if (!res) return;
  283. // 判断客观题数据结构是否变化
  284. const cacheStruct = this.getPaperStructData(this.objectiveStructure);
  285. const curStruct = this.getPaperStructData(
  286. datas.paperStructureInfo.objectiveQuestionList
  287. );
  288. if (curStruct.join("") !== cacheStruct.join("")) {
  289. this.setObjectiveStructure([]);
  290. }
  291. this.infos.basicPaperInfo.id = res;
  292. const infos = {
  293. ...this.infos,
  294. basicPaperInfo: Object.assign(
  295. this.markParamInfos.basicPaperInfo,
  296. this.infos.basicPaperInfo
  297. ),
  298. };
  299. this.setMarkParamInfos(infos);
  300. this.$message.success("提交成功!");
  301. this.$emit("confirm");
  302. },
  303. cancel() {
  304. this.$emit("cancel");
  305. },
  306. },
  307. };
  308. </script>