Exam-Marking.vue 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. <template>
  2. <div class="exam-train-exam-marking-edit-container layout-padding">
  3. <div class="exam-train-exam-marking-edit-container-box pd20 h100">
  4. <splitpanes :horizontal="false">
  5. <pane min-size="16" max-size="25" size="16" class="left-container">
  6. <p class="border-title mb20">考试人员</p>
  7. <el-scrollbar ref="scrollBarRef" style="height: calc(100% - 55px)" always>
  8. <el-auto-resizer class="table">
  9. <template #default="{ height }">
  10. <el-skeleton :loading="state.userLoading" animated :rows="10">
  11. <template #default>
  12. <el-tree-v2
  13. :data="state.userList"
  14. highlight-current
  15. :expand-on-click-node="false"
  16. node-key="userId"
  17. :props="{ children: 'children', label: 'userName' }"
  18. @node-click="handleNodeClick"
  19. :current-node-key="state.userList[0]?.id"
  20. ref="treeRef"
  21. :item-size="36"
  22. empty-text="暂无数据"
  23. :height="height"
  24. >
  25. <template #default="{ node }">
  26. <span>{{ node.label }}</span>
  27. </template>
  28. </el-tree-v2>
  29. </template>
  30. </el-skeleton>
  31. </template>
  32. </el-auto-resizer>
  33. </el-scrollbar>
  34. </pane>
  35. <pane class="right-container">
  36. <p class="border-title mb20">阅卷试卷</p>
  37. <div style="overflow: hidden; width: 100%; height: 100%; flex: 1">
  38. <el-row v-loading="state.loading" class="h100 w100">
  39. <el-col>
  40. <div class="questionBox" v-if="state.questionDetail">
  41. <p class="questionTitle">题干:{{ state.questionDetail.title }}</p>
  42. <div class="questionAnswer">
  43. <div v-if="[0, 2].includes(state.questionDetail.questionType)">
  44. <el-radio-group style="display: block" v-model="state.selRadioValue">
  45. <el-form-item
  46. :label="item.label + '. '"
  47. v-for="item in state.questionDetail.practiceQuestionOptionsDtos"
  48. style="margin-bottom: 10px"
  49. >
  50. <el-radio :label="item.content" :value="item.questionOptionId" />
  51. </el-form-item>
  52. </el-radio-group>
  53. </div>
  54. <div v-else-if="state.questionDetail.questionType == 1">
  55. <el-checkbox-group v-model="state.selCheckboxValue">
  56. <el-form-item
  57. :label="item.label + '. '"
  58. v-for="item in state.questionDetail.practiceQuestionOptionsDtos"
  59. style="margin-bottom: 10px"
  60. >
  61. <el-checkbox :label="item.content" :value="item.questionOptionId" />
  62. </el-form-item>
  63. </el-checkbox-group>
  64. </div>
  65. <!-- <div v-else-if="state.questionDetail.questionType == 2"></div> -->
  66. <!-- <div v-else-if="state.questionDetail.questionType == 3">
  67. <el-form-item label="答:">
  68. <el-input type="textarea" v-model="state.answerValue" :rows="3" placeholder="请输入答案,如果有多个请依照顺序用英文 , 隔开" clearable></el-input>
  69. </el-form-item>
  70. </div>
  71. <div v-else-if="state.questionDetail.questionType == 4">
  72. <el-form-item label="答:">
  73. <el-input type="textarea" v-model="state.answerValue" :rows="3" placeholder="请输入答案" clearable></el-input>
  74. </el-form-item>
  75. </div> -->
  76. </div>
  77. </div>
  78. </el-col>
  79. </el-row>
  80. </div>
  81. <div style="text-align: center">
  82. <el-button type="primary" @click="onSave(ruleFormRef)" :loading="state.loading">保存</el-button>
  83. <el-button class="default-button" @click="onCancel" :loading="state.loading">关闭 </el-button>
  84. </div>
  85. </pane>
  86. </splitpanes>
  87. </div>
  88. </div>
  89. </template>
  90. <script setup lang="ts" name="examTrainExamMarkingEdit">
  91. import { onMounted, reactive, ref } from 'vue';
  92. import type { FormInstance } from 'element-plus';
  93. import { ElMessage } from 'element-plus';
  94. import mittBus from '@/utils/mitt';
  95. import { useRoute, useRouter } from 'vue-router';
  96. import { Splitpanes, Pane } from 'splitpanes';
  97. import 'splitpanes/dist/splitpanes.css';
  98. import { Local } from '@/utils/storage';
  99. import other from '@/utils/other';
  100. import { throttle, transformFile, guid } from '@/utils/tools';
  101. import { addExamManage, editExamManage, getExamManageDetail, getTestPaperQuestionCount } from '@/api/examTrain/examManage';
  102. import { getMarkingDetailByUser, getMarkingDetailUser } from '@/api/examTrain/marking';
  103. // 定义变量内容
  104. const state = reactive<any>({
  105. loading: false,
  106. userList: [], // 用户列表
  107. queryParams: {},
  108. userLoading: false,
  109. UserId: null, // 用户ID
  110. });
  111. const route = useRoute(); // 获取路由
  112. const router = useRouter(); // 路由跳转
  113. const ruleFormRef = ref<any>(); // 表单ref
  114. // 点击人员查询试卷
  115. const handleNodeClick = (data: any) => {
  116. state.UserId = data.userId;
  117. getExamManageDetailData();
  118. };
  119. // 获取用户列表
  120. const routeParams = route.params;
  121. const getUserList = async () => {
  122. state.userLoading = true;
  123. try {
  124. const { result } = await getMarkingDetailUser({ ExamId: route.params.examId });
  125. state.userList = result ?? [];
  126. state.userLoading = false;
  127. state.UserId = result[0]?.userId;
  128. await getExamManageDetailData();
  129. } catch (error) {
  130. console.error(error);
  131. state.userLoading = false;
  132. }
  133. };
  134. // 获取试卷内容
  135. const getExamManageDetailData = async () => {
  136. state.loading = true;
  137. try {
  138. const { result } = await getMarkingDetailByUser({ ExamId: route.params.examId, UserId: state.UserId });
  139. console.log(result);
  140. state.loading = false;
  141. } catch (error) {
  142. console.error(error);
  143. state.loading = false;
  144. }
  145. };
  146. // 保存提交
  147. const onSave = throttle(async (formEl: FormInstance | undefined) => {
  148. if (!formEl) return;
  149. await formEl.validate((valid: boolean) => {
  150. if (!valid) return;
  151. state.loading = true;
  152. const submitObj = other.deepClone(state.ruleForm);
  153. if (submitObj.examType == 0) {
  154. submitObj.startTime = submitObj.rangeTime[0];
  155. submitObj.endTime = submitObj.rangeTime[1];
  156. Reflect.deleteProperty(submitObj, 'rangeTime');
  157. } else if (submitObj.examType == 1) {
  158. Reflect.deleteProperty(submitObj, 'rangeTime');
  159. Reflect.deleteProperty(submitObj, 'startTime');
  160. Reflect.deleteProperty(submitObj, 'endTime');
  161. Reflect.deleteProperty(submitObj, 'count');
  162. Reflect.deleteProperty(submitObj, 'timeSpan');
  163. }
  164. if (submitObj.mode == 1) {
  165. Reflect.deleteProperty(submitObj, 'questionSort');
  166. }
  167. console.log(submitObj);
  168. if (route.params.id) {
  169. editExamManage(submitObj)
  170. .then(handleSuccess)
  171. .catch(() => {
  172. state.loading = false;
  173. });
  174. } else {
  175. // 新增
  176. addExamManage(submitObj)
  177. .then(handleSuccess)
  178. .catch(() => {
  179. state.loading = false;
  180. });
  181. }
  182. });
  183. }, 300);
  184. // 取消
  185. const onCancel = () => {
  186. state.loading = true;
  187. mittBus.emit('onCurrentContextmenuClick', Object.assign({}, { contextMenuClickId: 1, ...route }));
  188. mittBus.emit('clearCache', 'examTrainExamMarking');
  189. router.push({
  190. path: '/examTrain/exam/marking',
  191. });
  192. state.loading = false;
  193. };
  194. const handleSuccess = () => {
  195. state.loading = false;
  196. ElMessage.success('操作成功');
  197. // 关闭当前 tagsView
  198. mittBus.emit('onCurrentContextmenuClick', Object.assign({}, { contextMenuClickId: 1, ...route }));
  199. mittBus.emit('clearCache', 'examTrainExamMarking');
  200. router.push({
  201. path: '/examTrain/exam/marking',
  202. });
  203. };
  204. onMounted(() => {
  205. state.queryParams.ExamId = routeParams.examId;
  206. getUserList();
  207. });
  208. </script>
  209. <style lang="scss" scoped>
  210. .exam-train-exam-marking-edit-container {
  211. .exam-train-exam-marking-edit-container-box {
  212. background-color: var(--el-color-white);
  213. overflow: hidden;
  214. }
  215. .right-container {
  216. height: 100%;
  217. display: flex;
  218. flex-direction: column;
  219. }
  220. }
  221. :deep(.el-tree-node__content) {
  222. height: 40px;
  223. }
  224. </style>