onlineExam.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535
  1. <template>
  2. <div>
  3. <section class="content" style="margin-top: -10px;">
  4. <div class="box box-info">
  5. <!-- 正文信息 -->
  6. <div class="box-body">
  7. <el-form
  8. :inline="true"
  9. :rules="rules"
  10. ref="form"
  11. :model="form"
  12. label-position="right"
  13. >
  14. <div style="margin-bottom: 10px">
  15. <el-button-group>
  16. <el-button type="primary" @click="saveOnlineExam"
  17. >保 存</el-button
  18. >
  19. <el-button @click="back">返 回</el-button>
  20. </el-button-group>
  21. </div>
  22. <el-tabs type="border-card" v-model="activeName">
  23. <!-- 基础信息 -->
  24. <el-tab-pane label="基础信息" name="tab1">
  25. <el-row>
  26. <el-form-item
  27. label="考试名称"
  28. placeholder="请输入考试名称"
  29. prop="name"
  30. >
  31. <el-input v-model="form.name"></el-input>
  32. </el-form-item>
  33. </el-row>
  34. <el-row>
  35. <el-form-item label="考试类型">
  36. <el-select
  37. style="width:205px"
  38. :disabled="true"
  39. v-model="form.examType"
  40. placeholder="请选择"
  41. >
  42. <el-option
  43. v-for="item in examTypeList"
  44. :key="item.value"
  45. :label="item.label"
  46. :value="item.value"
  47. >
  48. </el-option>
  49. </el-select>
  50. </el-form-item>
  51. </el-row>
  52. <el-row>
  53. <el-form-item label="是否开启">
  54. <el-radio-group
  55. v-model="form.enable"
  56. style="margin-left: 15px"
  57. >
  58. <el-radio label="true">开启</el-radio>
  59. <el-radio label="false">关闭</el-radio>
  60. </el-radio-group>
  61. </el-form-item>
  62. </el-row>
  63. <el-row>
  64. <el-form-item label="考试时间" prop="examDatetimeRange">
  65. <el-date-picker
  66. style="margin-left: 10px"
  67. v-model="examDatetimeRange"
  68. type="datetimerange"
  69. range-separator="至"
  70. start-placeholder="开始日期"
  71. end-placeholder="结束日期"
  72. value-format="yyyy-MM-dd HH:mm:ss"
  73. :clearable="false"
  74. >
  75. </el-date-picker>
  76. </el-form-item>
  77. </el-row>
  78. </el-tab-pane>
  79. <!-- 控制设置 -->
  80. <el-tab-pane label="控制设置" name="tab2">
  81. <el-row>
  82. <el-form-item label="考试时长" prop="duration">
  83. <el-input
  84. v-model.trim.number="form.duration"
  85. auto-complete="off"
  86. ></el-input>
  87. </el-form-item>
  88. <el-form-item label="分钟"></el-form-item>
  89. </el-row>
  90. <el-row>
  91. <el-form-item label="考试次数" prop="examTimes">
  92. <el-input
  93. v-model.trim.number="form.examTimes"
  94. auto-complete="off"
  95. ></el-input>
  96. </el-form-item>
  97. </el-row>
  98. <el-row>
  99. <el-form-item label="交卷冻结时间" prop="FREEZE_TIME">
  100. <el-input
  101. v-model.trim.number="form.properties.FREEZE_TIME"
  102. auto-complete="off"
  103. ></el-input>
  104. </el-form-item>
  105. <el-form-item label="分钟"></el-form-item>
  106. </el-row>
  107. <el-row>
  108. <el-form-item label="断点续考时间" prop="EXAM_RECONNECT_TIME">
  109. <el-input
  110. v-model.trim.number="form.properties.EXAM_RECONNECT_TIME"
  111. auto-complete="off"
  112. ></el-input>
  113. </el-form-item>
  114. <el-form-item label="分钟"></el-form-item>
  115. </el-row>
  116. </el-tab-pane>
  117. <el-tab-pane label="显示设置" name="tab3">
  118. <el-row>
  119. <el-form-item label="考前说明">
  120. <el-input
  121. v-model="form.properties.BEFORE_EXAM_REMARK"
  122. auto-complete="off"
  123. ></el-input>
  124. </el-form-item>
  125. </el-row>
  126. <el-row>
  127. <el-form-item label="考后说明">
  128. <el-input
  129. v-model="form.properties.AFTER_EXAM_REMARK"
  130. auto-complete="off"
  131. ></el-input>
  132. </el-form-item>
  133. </el-row>
  134. <el-row>
  135. <el-form-item label="展示作弊说明">
  136. <el-radio-group
  137. v-model="form.properties.SHOW_CHEATING_REMARK"
  138. >
  139. <el-radio label="true">开启</el-radio>
  140. <el-radio label="false">关闭</el-radio>
  141. </el-radio-group>
  142. </el-form-item>
  143. </el-row>
  144. <el-row>
  145. <el-form-item label="作弊说明">
  146. <el-input
  147. v-model="form.properties.CHEATING_REMARK"
  148. auto-complete="off"
  149. ></el-input>
  150. </el-form-item>
  151. </el-row>
  152. <el-row>
  153. <el-form-item label="单选题补充说明">
  154. <el-input
  155. :disabled="!form.properties.SINGLE_EDIT"
  156. v-model="form.properties.SINGLE_ANSWER_REMARK"
  157. auto-complete="off"
  158. ></el-input>
  159. </el-form-item>
  160. <el-form-item label="">
  161. <el-switch
  162. v-model="form.properties.SINGLE_EDIT"
  163. on-text="启用"
  164. off-text="禁用"
  165. ></el-switch>
  166. </el-form-item>
  167. </el-row>
  168. <el-row>
  169. <el-form-item label="多选题补充说明">
  170. <el-input
  171. :disabled="!form.properties.MUTIPLE_EDIT"
  172. v-model="form.properties.MUTIPLE_ANSWER_REMARK"
  173. auto-complete="off"
  174. ></el-input>
  175. </el-form-item>
  176. <el-form-item label="">
  177. <el-switch
  178. v-model="form.properties.MUTIPLE_EDIT"
  179. on-text="启用"
  180. off-text="禁用"
  181. ></el-switch>
  182. </el-form-item>
  183. </el-row>
  184. <el-row>
  185. <el-form-item label="判断题补充说明">
  186. <el-input
  187. :disabled="!form.properties.BOOL_EDIT"
  188. v-model="form.properties.BOOL_ANSWER_REMARK"
  189. auto-complete="off"
  190. ></el-input>
  191. </el-form-item>
  192. <el-form-item label="">
  193. <el-switch
  194. v-model="form.properties.BOOL_EDIT"
  195. on-text="启用"
  196. off-text="禁用"
  197. ></el-switch>
  198. </el-form-item>
  199. </el-row>
  200. <el-row>
  201. <el-form-item label="填空题补充说明">
  202. <el-input
  203. :disabled="!form.properties.FILL_BLANK_EDIT"
  204. v-model="form.properties.FILL_BLANK_REMARK"
  205. auto-complete="off"
  206. ></el-input>
  207. </el-form-item>
  208. <el-form-item label="">
  209. <el-switch
  210. v-model="form.properties.FILL_BLANK_EDIT"
  211. on-text="启用"
  212. off-text="禁用"
  213. ></el-switch>
  214. </el-form-item>
  215. </el-row>
  216. <el-row>
  217. <el-form-item label="客观题成绩显示">
  218. <el-radio-group v-model="form.properties.IS_OBJ_SCORE_VIEW">
  219. <el-radio label="true">开启</el-radio>
  220. <el-radio label="false">关闭</el-radio>
  221. </el-radio-group>
  222. </el-form-item>
  223. </el-row>
  224. </el-tab-pane>
  225. <el-tab-pane label="人脸识别设置" name="tab4">
  226. <el-row>
  227. <el-form-item label="是否开启">
  228. <el-radio-group
  229. v-model="form.properties.IS_FACE_ENABLE"
  230. @change="faceChange"
  231. >
  232. <el-radio label="true">开启</el-radio>
  233. <el-radio label="false">关闭</el-radio>
  234. </el-radio-group>
  235. </el-form-item>
  236. </el-row>
  237. <el-row v-show="form.properties.IS_FACE_ENABLE == 'true'">
  238. <el-form-item label="考试强制使用">
  239. <el-radio-group v-model="form.properties.IS_FACE_CHECK">
  240. <el-radio label="true">强制</el-radio>
  241. <el-radio label="false">非强制</el-radio>
  242. </el-radio-group>
  243. </el-form-item>
  244. </el-row>
  245. <el-row v-show="form.properties.IS_FACE_ENABLE == 'true'">
  246. <el-form-item label="抓拍间隔">
  247. <el-input
  248. v-model.number="form.properties.SNAPSHOT_INTERVAL"
  249. auto-complete="off"
  250. ></el-input>
  251. </el-form-item>
  252. <el-form-item label="分钟"></el-form-item>
  253. </el-row>
  254. <el-row v-show="form.properties.IS_FACE_ENABLE == 'true'">
  255. <el-form-item label="预警阀值">
  256. <el-input
  257. v-model.number="form.properties.WARN_THRESHOLD"
  258. auto-complete="off"
  259. ></el-input>
  260. </el-form-item>
  261. <el-form-item label="%"></el-form-item>
  262. </el-row>
  263. <el-row v-show="form.properties.IS_FACE_ENABLE == 'true'">
  264. <el-form-item label="真实性预警阀值">
  265. <el-input
  266. v-model.number="form.properties.LIVING_WARN_THRESHOLD"
  267. auto-complete="off"
  268. ></el-input>
  269. </el-form-item>
  270. <el-form-item label="%"></el-form-item>
  271. </el-row>
  272. </el-tab-pane>
  273. <el-tab-pane label="阅卷设置" name="tab5">
  274. <el-row>
  275. <el-form-item label="阅卷方式">
  276. <el-radio-group
  277. :disabled="form.started"
  278. v-model="form.properties.MARKING_TYPE"
  279. >
  280. <el-radio label="ALL">全部评阅</el-radio>
  281. <el-radio label="OBJECT_SCORE_MAX">客观分最高</el-radio>
  282. <el-radio label="LAST_SUBMIT">最后一次提交</el-radio>
  283. </el-radio-group>
  284. </el-form-item>
  285. </el-row>
  286. </el-tab-pane>
  287. <el-tab-pane label="网络设置" name="tab6">
  288. <el-row>
  289. <el-form-item label="IP限制">
  290. <el-radio-group v-model="form.properties.IP_LIMIT">
  291. <el-radio label="true">开启</el-radio>
  292. <el-radio label="false">关闭</el-radio>
  293. </el-radio-group>
  294. </el-form-item>
  295. </el-row>
  296. <el-row>
  297. <el-form-item label="IP段( *表示任意 )">
  298. <el-input v-model="form.properties.IP_ADDRESSES"></el-input>
  299. </el-form-item>
  300. </el-row>
  301. </el-tab-pane>
  302. </el-tabs>
  303. </el-form>
  304. </div>
  305. </div>
  306. </section>
  307. </div>
  308. </template>
  309. <script>
  310. import { EXAM_TYPE, EXAM_WORK_API } from "@/constants/constants.js";
  311. import moment from "moment";
  312. let _this = null;
  313. let validateName = (rule, value, callback) => {
  314. let name = _this.form.name;
  315. if (name == "") {
  316. callback(new Error("请输入考试名称"));
  317. _this.activeName = "tab1";
  318. } else {
  319. callback();
  320. }
  321. };
  322. let validateDuration = (rule, value, callback) => {
  323. let duration = _this.form.duration;
  324. if (duration == "") {
  325. callback(new Error("请输入考试时长"));
  326. _this.activeName = "tab2";
  327. } else if (!duration.toString().match(/^[1-9]\d*|0$/)) {
  328. callback(new Error("只能是非负整数"));
  329. _this.activeName = "tab2";
  330. } else {
  331. callback();
  332. }
  333. };
  334. let validateExamTimes = (rule, value, callback) => {
  335. let examTimes = _this.form.examTimes;
  336. if (examTimes == "") {
  337. callback(new Error("请输入考试次数"));
  338. _this.activeName = "tab2";
  339. } else if (!examTimes.toString().match(/^[1-9]\d*$/)) {
  340. callback(new Error("只能是正整数"));
  341. _this.activeName = "tab2";
  342. } else {
  343. callback();
  344. }
  345. };
  346. let validateFreezeTime = (rule, value, callback) => {
  347. let freezeTime = _this.form.properties.FREEZE_TIME;
  348. let duration = _this.form.duration;
  349. if (freezeTime == "") {
  350. callback(new Error("请输入交卷冻结时长"));
  351. _this.activeName = "tab2";
  352. } else if (!freezeTime.toString().match(/^[1-9]\d*|0$/)) {
  353. callback(new Error("只能是非负整数"));
  354. _this.activeName = "tab2";
  355. } else if (freezeTime > duration) {
  356. callback(new Error("交卷冻结时长不能大于考试时长"));
  357. _this.activeName = "tab2";
  358. } else {
  359. callback();
  360. }
  361. };
  362. let validateExamReconnectTime = (rule, value, callback) => {
  363. let examReconnectTime = _this.form.properties.EXAM_RECONNECT_TIME;
  364. if (examReconnectTime == "") {
  365. callback(new Error("请输入断点续考时间"));
  366. _this.activeName = "tab2";
  367. } else if (!examReconnectTime.toString().match(/^[1-9]\d*$/)) {
  368. callback(new Error("只能是正整数"));
  369. _this.activeName = "tab2";
  370. } else {
  371. callback();
  372. }
  373. };
  374. export default {
  375. data() {
  376. return {
  377. activeName: "tab1",
  378. examDatetimeRange: [],
  379. show_ckeditor: false,
  380. form: {
  381. started: false,
  382. name: "",
  383. examType: "ONLINE",
  384. examTimes: 1,
  385. beginTime: null,
  386. endTime: null,
  387. duration: 120,
  388. enable: "true",
  389. properties: {
  390. IS_OBJ_SCORE_VIEW: "true",
  391. EXAM_RECONNECT_TIME: 30,
  392. FREEZE_TIME: 0,
  393. BEFORE_EXAM_REMARK: "",
  394. AFTER_EXAM_REMARK: "",
  395. SHOW_CHEATING_REMARK: "true",
  396. CHEATING_REMARK: "",
  397. SINGLE_EDIT: "false",
  398. MUTIPLE_EDIT: "false",
  399. BOOL_EDIT: "false",
  400. FILL_BLANK_EDIT: "false",
  401. SINGLE_ANSWER_REMARK: "",
  402. MUTIPLE_ANSWER_REMARK: "",
  403. FILL_BLANK_REMARK: "",
  404. BOOL_ANSWER_REMARK: "",
  405. IS_FACE_ENABLE: "false",
  406. IS_FACE_CHECK: "false",
  407. SNAPSHOT_INTERVAL: 30,
  408. WARN_THRESHOLD: 50,
  409. MARKING_TYPE: "ALL",
  410. IP_LIMIT: "false",
  411. IP_ADDRESSES: null,
  412. LIVING_WARN_THRESHOLD: 50
  413. }
  414. },
  415. examTypeList: EXAM_TYPE,
  416. examId: "",
  417. rules: {
  418. name: [{ required: true, validator: validateName, trigger: "blur" }],
  419. duration: [
  420. { required: true, validator: validateDuration, trigger: "blur" }
  421. ],
  422. examTimes: [
  423. { required: true, validator: validateExamTimes, trigger: "blur" }
  424. ],
  425. FREEZE_TIME: [
  426. { required: true, validator: validateFreezeTime, trigger: "blur" }
  427. ],
  428. EXAM_RECONNECT_TIME: [
  429. {
  430. required: true,
  431. validator: validateExamReconnectTime,
  432. trigger: "blur"
  433. }
  434. ]
  435. }
  436. };
  437. },
  438. methods: {
  439. faceChange() {
  440. if (this.form.properties.IS_FACE_ENABLE == "false") {
  441. this.form.properties.SNAPSHOT_INTERVAL = 30;
  442. this.form.properties.WARN_THRESHOLD = 50;
  443. }
  444. },
  445. init() {
  446. if (this.examId != "add") {
  447. let url = EXAM_WORK_API + "/exam/" + this.examId;
  448. this.$http.get(url).then(response => {
  449. let body = response.data;
  450. body.properties = this.form.properties;
  451. this.form = Object.assign(this.form, response.data);
  452. this.form.enable = this.form.enable ? "true" : "false";
  453. this.examDatetimeRange = [this.form.beginTime, this.form.endTime];
  454. console.log("getOnlineExam(); form: ", this.form);
  455. let url = EXAM_WORK_API + "/exam/allProperties/" + this.examId;
  456. this.$http.get(url).then(response => {
  457. this.form.properties = Object.assign(
  458. this.form.properties,
  459. response.data
  460. );
  461. this.form.properties.SINGLE_EDIT =
  462. this.form.properties.SINGLE_EDIT == "true" ? true : false;
  463. this.form.properties.MUTIPLE_EDIT =
  464. this.form.properties.MUTIPLE_EDIT == "true" ? true : false;
  465. this.form.properties.BOOL_EDIT =
  466. this.form.properties.BOOL_EDIT == "true" ? true : false;
  467. this.form.properties.FILL_BLANK_EDIT =
  468. this.form.properties.FILL_BLANK_EDIT == "true" ? true : false;
  469. this.show_ckeditor = true;
  470. });
  471. });
  472. } else {
  473. let now = moment().format("YYYY-MM-DD HH:mm:ss");
  474. this.examDatetimeRange = [now, now];
  475. this.show_ckeditor = true;
  476. }
  477. },
  478. saveOnlineExam: function() {
  479. this.form.beginTime = this.examDatetimeRange[0];
  480. this.form.endTime = this.examDatetimeRange[1];
  481. console.log(this.form);
  482. let url = EXAM_WORK_API + "/exam";
  483. this.$refs.form.validate(valid => {
  484. if (valid) {
  485. if (this.examId != "add") {
  486. this.$http.put(url, this.form).then(response => {
  487. if (200 != response.status) {
  488. this.$notify({
  489. type: "error",
  490. message: response.body.desc
  491. });
  492. return;
  493. }
  494. this.$notify({
  495. type: "success",
  496. message: "保存成功"
  497. });
  498. });
  499. } else {
  500. this.$http.post(url, this.form).then(response => {
  501. console.log(response);
  502. this.$notify({
  503. type: "success",
  504. message: "新增成功"
  505. });
  506. this.back();
  507. });
  508. }
  509. } else {
  510. return false;
  511. }
  512. });
  513. },
  514. back() {
  515. this.$router.push({ path: "/examwork/examInfo" });
  516. }
  517. },
  518. created() {
  519. _this = this;
  520. this.examId = this.$route.params.id;
  521. this.init();
  522. }
  523. };
  524. </script>
  525. <style scoped></style>