index.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. <template>
  2. <!-- 习题练习 -->
  3. <Basic>
  4. <div class="exam">
  5. <p>正在考试>>><span>{{name}}</span> <i
  6. title="反馈"
  7. class="el-icon-question error"
  8. @click="ErrorFunc"
  9. >反馈</i></p>
  10. <TestPaper
  11. :Data="listData"
  12. :State="state"
  13. :StateData='stateData'
  14. :Total="total"
  15. :Unselected="Unselected"
  16. :Timer='timer'
  17. @Func="Success"
  18. />
  19. </div>
  20. <el-dialog
  21. title="反馈"
  22. :visible.sync="dialogTableVisible"
  23. >
  24. <el-form
  25. ref="form"
  26. :rules="rules"
  27. :model="form"
  28. label-width="80px"
  29. >
  30. <el-form-item
  31. label="错误类型"
  32. prop="type"
  33. >
  34. <el-radio-group v-model="form.type">
  35. <el-radio label="题目类型"></el-radio>
  36. <el-radio label="题目答案"></el-radio>
  37. <el-radio label="题目解析"></el-radio>
  38. <el-radio label="其他"></el-radio>
  39. </el-radio-group>
  40. </el-form-item>
  41. <el-form-item label="错误描述">
  42. <el-input
  43. type="textarea"
  44. v-model="form.desc"
  45. ></el-input>
  46. </el-form-item>
  47. <el-form-item>
  48. <el-button
  49. type="primary"
  50. @click="onSubmit('form')"
  51. >提交</el-button>
  52. </el-form-item>
  53. </el-form>
  54. </el-dialog>
  55. </Basic>
  56. </template>
  57. <script>
  58. const Basic = () => import("@/components/Basic/index");
  59. const TestPaper = () => import("@/components/TestPaper");
  60. import Exam from '@/api/exam';
  61. import { ABC } from '@/utils/index';
  62. export default {
  63. components: {
  64. Basic, TestPaper
  65. },
  66. data () {
  67. return {
  68. form: { desc: '', type: '' },
  69. rules: {
  70. type: [{ required: true, message: '请选择错误类型!', trigger: 'change' }]
  71. },
  72. dialogTableVisible: false,//反馈
  73. practise: null,//请求题目套卷的唯一表示
  74. name: "",//考卷的名字
  75. state: false, //false stateData必须 做题状态
  76. timer: 0,//计时器
  77. Unselected: 0,//未做的题
  78. total: 0,//总共题数
  79. stateData: [],
  80. // stateData: [
  81. // {
  82. // type: "单选题",
  83. // data: [{ id: 1, state: true }, { id: 2, state: true }, { id: 3, state: true }, { id: 4, state: false }, { id: 5, state: false }, { id: 6, state: false }]
  84. // }, {
  85. // type: "多选题",
  86. // data: [{ id: 7, state: false }, { id: 8, state: false }, { id: 9, state: false }]
  87. // }, {
  88. // type: "填空题",
  89. // data: [{ id: 10, state: false }, { id: 11, state: false }, { id: 12, state: false }, { id: 13, state: false }, { id: 14, state: false }]
  90. // }, {
  91. // type: '判断题',
  92. // data: [{ id: 15, state: false }, { id: 16, state: false }, { id: 17, state: false }, { id: 18, state: false }, { id: 19, state: false }]
  93. // }
  94. // ],
  95. // 本题
  96. listData: {},
  97. // 模拟数据 样板 使用时删除
  98. // list: [{
  99. // id: 1,
  100. // type: "radio",
  101. // content: "<p>结合xxx特征<p>",
  102. // value: [{ key: "A", label: '公园' }, { key: "B", label: '大陵园' }, { key: "C", label: '天坛' }, { key: "D", label: '清明园' }],
  103. // result: {
  104. // yes: ["公园"],
  105. // no: ["广场"]
  106. // },
  107. // }, {
  108. // id: 2,
  109. // type: "checkbox",
  110. // content: "<p>结合xxx特征<p>",
  111. // value: [{ key: "A", label: '公园' }, { key: "B", label: '大陵园' }, { key: "C", label: '天坛' }, { key: "D", label: '清明园' }],
  112. // result: {
  113. // yes: ["公园", "农田"],
  114. // no: ["公园", "农田", "车站"]
  115. // }
  116. // }, {
  117. // id: 3,
  118. // type: "input",
  119. // content: "<p>结合xxx特征<p>",
  120. // value: ['', ''],
  121. // result: {
  122. // yes: ["正确答案", "正确答案"],
  123. // no: ["错误答案", "错误答案"],
  124. // }
  125. // },
  126. // {
  127. // id: 4,
  128. // type: "bool",
  129. // content: "<p>结合xxx特征<p>",
  130. // result: {
  131. // yes: true,
  132. // no: false,
  133. // }
  134. // }]
  135. }
  136. },
  137. methods: {
  138. // 反馈
  139. ErrorFunc () {
  140. this.dialogTableVisible = true;
  141. },
  142. onSubmit (formName) {
  143. this.$refs[formName].validate((valid) => {
  144. if (valid) {
  145. let { type, desc } = this.form;
  146. let arr = [{ id: 1, name: '题目类型' }, { id: 2, name: '题目答案' }, { id: 3, name: "题目解析" }, { id: 4, name: "其他" }];
  147. let obj = arr.filter(item => item.name == type);
  148. Exam.exam_error({ type: obj[0].id, desc, main: this.listData.question_id }).then(res => { this.dialogTableVisible = false, this.form = { desc: '', type: '' } })
  149. }
  150. });
  151. },
  152. // 请求题目函数
  153. Subject (practise, query) {
  154. !this.practise ? this.practise = practise : '';
  155. return new Promise(resolve => {
  156. Exam.subject({ practise, query: { ...query, answers: JSON.stringify(query.answers) } }).then(res => {
  157. this.SubjectHandle(res.data)
  158. resolve();
  159. })
  160. })
  161. },
  162. // 处理路由参数
  163. Router () {
  164. let query = this.$route.query;
  165. this.timer = !query.timer ? 0 : query.timer;
  166. let next_practise = !query.next_practise ? 0 : query.next_practise;
  167. this.Subject(query.practise, { now_practise: '', answers: [], next_number: 0, next_type: 1, button_type: "next", next_practise });
  168. },
  169. // 处理每次题目以及答题卡的数据
  170. SubjectHandle (data) {
  171. try {
  172. // 答题卡 数据处理
  173. let { single_questions_list, multiple_questions_list, fill_questions_list, judgment_questions_list } = data,
  174. total = 1,//共几道题,题目标识
  175. total_question = [],//总题目id储存
  176. Unselected = 0//几道题未做
  177. ;
  178. this.name = data.question_data.exam_title;
  179. // 解决排序跳转问题
  180. let show_question_id = data.question_data.id, next_question_id = null, top_question_id = null, show_question_li = null, i = null;
  181. function mapfunc (data) {
  182. data = data.map((item, index) => {
  183. if (item.question_id == show_question_id) {
  184. show_question_li = total;
  185. i = total - 1;
  186. }
  187. let obj = { id: total, question_id: item.question_id, state: item.complete };
  188. total++;
  189. !item.complete ? Unselected++ : "";
  190. total_question.push(obj);
  191. return obj
  192. })
  193. return data;
  194. }
  195. let stateData = [];
  196. if (single_questions_list.length != 0) {
  197. stateData.push({ type: "单选题", data: mapfunc(single_questions_list) })
  198. }
  199. if (multiple_questions_list.length != 0) {
  200. stateData.push({ type: "多选题", data: mapfunc(multiple_questions_list) })
  201. }
  202. if (fill_questions_list.length != 0) {
  203. stateData.push({ type: "填空题", data: mapfunc(fill_questions_list) })
  204. }
  205. if (judgment_questions_list.length != 0) {
  206. stateData.push({ type: "判断题", data: mapfunc(judgment_questions_list) })
  207. }
  208. this.Unselected = Unselected;
  209. this.total = total - 1;
  210. // 处理相邻题目问题
  211. if (i != null) {
  212. next_question_id = total_question[i + 1];
  213. top_question_id = total_question[i - 1];
  214. }
  215. this.stateData = stateData;
  216. this.total_question = total_question;
  217. // 题目数据
  218. let { id, next_type, title: content, option: value, next_number, previous_practise } = data.question_data;
  219. value = value.map((item, index) => {
  220. let obj = next_type != 3 ? { id: item.id, label: item.content, key: ABC[index], state: item.answer } : { id: item.id, label: item.content };
  221. return obj
  222. })
  223. let listData = {
  224. question_id: id,
  225. id: show_question_li, //题目序号
  226. next_question_id,//下一题的
  227. top_question_id,//上一题的
  228. next_type,
  229. next_number,
  230. previous_practise,
  231. content,
  232. value,
  233. type: next_type == 1 ? 'radio' : next_type == 2 ? 'checkbox' : next_type == 3 ? 'input' : 'bool',
  234. }
  235. this.listData = listData;
  236. } catch (err) {
  237. console.error(`数据处理错误:${err}`)
  238. }
  239. },
  240. // 页内提示 答题状态
  241. Notify () {
  242. this.$notify.error({
  243. title: '监考的关爱:',
  244. message: '请完成当前页面的考试内容!再继续答题!',
  245. duration: 3000
  246. });
  247. },
  248. // 功能
  249. Success (data) {
  250. return new Promise(resolve => {
  251. let { practise, listData } = this;
  252. // 判断 处理 字段
  253. let button_type = null, answers = [], next_practise = null;
  254. // 判断按钮格式
  255. if (data.data.tag == 'btn' && data.data.type == "+") {
  256. button_type = "next";
  257. next_practise = listData.next_question_id.question_id;
  258. } else if (data.data.tag == 'btn' && data.data.type == "-") {
  259. button_type = "previous";
  260. next_practise = listData.top_question_id.question_id
  261. } else if (data.data.tag == 'btns') {
  262. next_practise = listData.question_id
  263. }
  264. else {
  265. button_type = "previous";
  266. next_practise = data.data.data.question_id;
  267. }
  268. // 单选题数据处理
  269. if (listData.next_type == 1 && data.value.length != 0) {
  270. answers = [data.value[0]['id']];
  271. }
  272. // 多选题
  273. if (listData.next_type == 2 && data.value.length != 0) {
  274. data.value.forEach(item => {
  275. answers.push(item.id)
  276. })
  277. }
  278. // 填空题
  279. if (listData.next_type == 3 && data.value.length != 0) {
  280. answers = [...data.value];
  281. answers = answers.map(item => (item == null ? '' : item))
  282. }
  283. // 判断题
  284. if (listData.next_type == 4 && data.value.length != 0) {
  285. answers = [...data.value];
  286. }
  287. this.Subject(practise, { next_practise, now_practise: listData.question_id, answers, next_number: listData.next_number, next_type: listData.next_type, button_type }).then(res => {
  288. if (data.data.tag == 'btns') {
  289. Exam.submit(practise).then(res => this.$router.push({ path: "/practice", query: { tabs: "2" } }))
  290. }
  291. })
  292. })
  293. },
  294. },
  295. created () {
  296. this.Router();
  297. },
  298. }
  299. </script>
  300. <style lang="less" scoped>
  301. .exam {
  302. p {
  303. font-size: 14px;
  304. span {
  305. color: #777;
  306. }
  307. position: relative;
  308. .error {
  309. position: absolute;
  310. line-height: 19px;
  311. right: 0;
  312. }
  313. }
  314. }
  315. </style>