practiceExam.vue 15 KB

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