onlineHomework.vue 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151
  1. <template>
  2. <div>
  3. <LinkTitlesCustom
  4. :current-paths="['考试管理', '考试信息', '在线作业设置']"
  5. />
  6. <section class="content">
  7. <div class="box box-info">
  8. <!-- 正文信息 -->
  9. <div class="box-body">
  10. <el-form
  11. ref="form"
  12. :inline="true"
  13. :rules="rules"
  14. :model="form"
  15. inline-message
  16. label-position="right"
  17. >
  18. <div style="margin-bottom: 10px">
  19. <el-button type="primary" size="small" @click="saveExam"
  20. >保 存</el-button
  21. >
  22. <el-button
  23. type="primary"
  24. size="small"
  25. icon="el-icon-arrow-left"
  26. @click="back"
  27. >返 回</el-button
  28. >
  29. </div>
  30. <el-tabs ref="tabs" v-model="activeName" type="border-card">
  31. <!-- 基础信息 -->
  32. <el-tab-pane label="基础信息" name="tab1">
  33. <el-row v-if="examId != 'add'">
  34. <el-form-item
  35. label="ID"
  36. prop="id"
  37. :label-width="style.label_width_tab1"
  38. >
  39. <el-input
  40. v-model="form.id"
  41. class="input"
  42. :disabled="true"
  43. maxlength="20"
  44. ></el-input>
  45. </el-form-item>
  46. </el-row>
  47. <el-row v-if="examId != 'add'">
  48. <el-form-item
  49. label="考试编码"
  50. placeholder="请输入考试编码"
  51. prop="code"
  52. :label-width="style.label_width_tab1"
  53. >
  54. <el-input
  55. v-model="form.code"
  56. class="input"
  57. :disabled="true"
  58. maxlength="20"
  59. ></el-input>
  60. </el-form-item>
  61. </el-row>
  62. <el-row v-else>
  63. <el-form-item
  64. label="考试编码"
  65. placeholder="请输入考试编码"
  66. prop="code"
  67. :label-width="style.label_width_tab1"
  68. >
  69. <el-input
  70. v-model="form.name"
  71. class="input"
  72. :disabled="true"
  73. maxlength="20"
  74. ></el-input>
  75. </el-form-item>
  76. </el-row>
  77. <el-row>
  78. <el-form-item
  79. label="考试名称"
  80. placeholder="请输入考试名称"
  81. prop="name"
  82. :label-width="style.label_width_tab1"
  83. >
  84. <el-input
  85. v-model="form.name"
  86. class="input"
  87. maxlength="20"
  88. ></el-input>
  89. </el-form-item>
  90. </el-row>
  91. <el-row>
  92. <el-form-item
  93. label="考试类型"
  94. :label-width="style.label_width_tab1"
  95. >
  96. <el-select
  97. v-model="form.examType"
  98. class="input"
  99. :disabled="true"
  100. placeholder="请选择"
  101. >
  102. <el-option
  103. v-for="item in examTypeList"
  104. :key="item.value"
  105. :label="item.label"
  106. :value="item.value"
  107. ></el-option>
  108. </el-select>
  109. </el-form-item>
  110. </el-row>
  111. <el-row>
  112. <el-form-item
  113. label="状态"
  114. :label-width="style.label_width_tab1"
  115. >
  116. <el-radio-group v-model="form.enable" class="input">
  117. <el-radio label="true">启用</el-radio>
  118. <el-radio label="false">禁用</el-radio>
  119. </el-radio-group>
  120. </el-form-item>
  121. </el-row>
  122. <el-row v-if="1 == 2">
  123. <el-form-item
  124. label="是否可以考试"
  125. :label-width="style.label_width_tab1"
  126. >
  127. <el-radio-group v-model="form.examLimit" class="input">
  128. <el-radio label="true">否</el-radio>
  129. <el-radio label="false">是</el-radio>
  130. </el-radio-group>
  131. </el-form-item>
  132. </el-row>
  133. <el-row>
  134. <el-form-item
  135. label="考试时间"
  136. prop="examDatetimeRange"
  137. :label-width="style.label_width_tab1"
  138. >
  139. <el-date-picker
  140. v-model="examDatetimeRange"
  141. class="input"
  142. type="datetimerange"
  143. range-separator="至"
  144. start-placeholder="开始日期"
  145. end-placeholder="结束日期"
  146. value-format="yyyy-MM-dd HH:mm:ss"
  147. :clearable="false"
  148. ></el-date-picker>
  149. </el-form-item>
  150. </el-row>
  151. <el-row>
  152. <el-form-item
  153. label="开启环境检测"
  154. :label-width="style.label_width_tab1"
  155. >
  156. <el-switch
  157. v-model="form.properties.CHECK_ENVIRONMENT"
  158. on-text="是"
  159. off-text="否"
  160. ></el-switch>
  161. </el-form-item>
  162. </el-row>
  163. <el-row>
  164. <el-form-item
  165. label="开放微信小程序作答"
  166. :label-width="style.label_width_tab1"
  167. >
  168. <el-switch
  169. v-model="form.properties.WEIXIN_ANSWER_ENABLED"
  170. :disabled="!rootOrgWenXinAnswerEnabled"
  171. on-text="是"
  172. off-text="否"
  173. ></el-switch>
  174. </el-form-item>
  175. </el-row>
  176. <el-row v-show="false">
  177. <el-form-item
  178. label="开启特殊设置"
  179. :label-width="style.label_width_tab1"
  180. >
  181. <el-switch
  182. v-model="form.specialSettingsEnabled"
  183. on-text="是"
  184. off-text="否"
  185. ></el-switch>
  186. </el-form-item>
  187. </el-row>
  188. <el-row>
  189. <el-form-item
  190. v-show="form.specialSettingsEnabled"
  191. label="特殊设置方式"
  192. :label-width="style.label_width_tab1"
  193. >
  194. <el-radio-group
  195. v-model="form.specialSettingsType"
  196. class="input"
  197. >
  198. <el-radio label="ORG_BASED">机构特殊设置</el-radio>
  199. <el-radio label="STAGE_BASED">场次特殊设置</el-radio>
  200. </el-radio-group>
  201. </el-form-item>
  202. </el-row>
  203. <el-row>
  204. <el-form-item
  205. v-show="form.specialSettingsEnabled"
  206. label="无特殊设置时禁止考试"
  207. :label-width="style.label_width_tab1"
  208. >
  209. <el-switch
  210. v-model="form.properties.LIMITED_IF_NO_SPECIAL_SETTINGS"
  211. on-text="是"
  212. off-text="否"
  213. ></el-switch>
  214. </el-form-item>
  215. </el-row>
  216. </el-tab-pane>
  217. <!-- 周期设置 -->
  218. <el-tab-pane label="周期设置" name="tab8">
  219. <el-row>
  220. <el-form-item
  221. label="是否开启周期设置"
  222. :label-width="style.label_width_tab4"
  223. >
  224. <el-radio-group
  225. v-model="form.properties.EXAM_CYCLE_ENABLED"
  226. class="input"
  227. @change="examCycleEnabledChange"
  228. >
  229. <el-radio label="true">开启</el-radio>
  230. <el-radio label="false">不开启</el-radio>
  231. </el-radio-group></el-form-item
  232. >
  233. </el-row>
  234. <el-row v-if="form.properties.EXAM_CYCLE_ENABLED == 'true'">
  235. <el-form-item
  236. label="日期循环设置"
  237. prop="examCycleWeekArr"
  238. :label-width="style.label_width_tab4"
  239. >
  240. <el-checkbox-group
  241. v-model="examCycleWeekArr"
  242. style="width: 680px; display: -webkit-inline-box"
  243. >
  244. <el-checkbox :label="1">星期一</el-checkbox>
  245. <el-checkbox :label="2">星期二</el-checkbox>
  246. <el-checkbox :label="3">星期三</el-checkbox>
  247. <el-checkbox :label="4">星期四</el-checkbox>
  248. <el-checkbox :label="5">星期五</el-checkbox>
  249. <el-checkbox :label="6">星期六</el-checkbox>
  250. <el-checkbox :label="7">星期日</el-checkbox>
  251. </el-checkbox-group></el-form-item
  252. >
  253. </el-row>
  254. <template v-if="form.properties.EXAM_CYCLE_ENABLED == 'true'">
  255. <el-row>
  256. <el-col :span="14">
  257. <el-form-item
  258. label="时间分段设置"
  259. :label-width="style.label_width_tab4"
  260. prop="examCycleTimeRangeArr"
  261. >
  262. </el-form-item>
  263. </el-col>
  264. <el-col :span="10" style="line-height: 48px; height: 40px">
  265. <i
  266. class="el-icon-circle-plus"
  267. style="color: #00a4ff; font-size: 24px"
  268. @click="addCycleTimeRange"
  269. ></i>
  270. </el-col>
  271. </el-row>
  272. <el-row
  273. v-for="(item, index) in examCycleTimeRangeArr"
  274. :key="'tr' + index"
  275. >
  276. <el-col :span="14">
  277. <el-form-item
  278. :label-width="style.label_width_tab4"
  279. :label="index + 1 + '.'"
  280. >
  281. <el-time-picker
  282. v-model="item.timeRange"
  283. class="input"
  284. style="width: 100%"
  285. is-range
  286. start-placeholder="开始时间"
  287. range-separator="至"
  288. end-placeholder="结束时间"
  289. format="HH:mm"
  290. value-format="HH:mm"
  291. :clearable="false"
  292. size="small"
  293. ></el-time-picker>
  294. </el-form-item>
  295. </el-col>
  296. <el-col :span="10" style="line-height: 48px; height: 40px">
  297. <i
  298. class="el-icon-remove"
  299. style="color: #00a4ff; font-size: 24px"
  300. @click="removeExamCycleTimeRange(index)"
  301. ></i>
  302. </el-col>
  303. </el-row>
  304. </template>
  305. </el-tab-pane>
  306. <!-- 控制设置 -->
  307. <el-tab-pane label="控制设置" name="tab2">
  308. <el-row>
  309. <el-form-item
  310. label="考试时长"
  311. prop="duration"
  312. :label-width="style.label_width_tab2"
  313. >
  314. <el-input
  315. v-model.trim.number="form.duration"
  316. maxlength="5"
  317. auto-complete="off"
  318. class="input"
  319. >
  320. <template slot="append">分钟</template>
  321. </el-input>
  322. </el-form-item>
  323. </el-row>
  324. <el-row>
  325. <el-form-item
  326. label="考试次数"
  327. prop="examTimes"
  328. :label-width="style.label_width_tab2"
  329. >
  330. <el-input
  331. v-model.trim.number="form.examTimes"
  332. maxlength="5"
  333. auto-complete="off"
  334. class="input"
  335. >
  336. <template slot="append">次</template>
  337. </el-input>
  338. </el-form-item>
  339. </el-row>
  340. <el-row>
  341. <el-form-item
  342. label="交卷冻结时间"
  343. prop="FREEZE_TIME"
  344. :label-width="style.label_width_tab2"
  345. >
  346. <el-input
  347. v-model.trim.number="form.properties.FREEZE_TIME"
  348. maxlength="5"
  349. auto-complete="off"
  350. class="input"
  351. >
  352. <template slot="append">分钟</template>
  353. </el-input>
  354. </el-form-item>
  355. </el-row>
  356. <el-row>
  357. <el-form-item
  358. label="断点续考时间"
  359. prop="EXAM_RECONNECT_TIME"
  360. :label-width="style.label_width_tab2"
  361. >
  362. <el-input
  363. v-model.trim.number="form.properties.EXAM_RECONNECT_TIME"
  364. maxlength="5"
  365. auto-complete="off"
  366. class="input"
  367. >
  368. <template slot="append">分钟</template>
  369. </el-input>
  370. </el-form-item>
  371. </el-row>
  372. <el-row>
  373. <el-form-item
  374. label="断点续考次数"
  375. prop="MAX_INTERRUPT_NUM"
  376. :label-width="style.label_width_tab2"
  377. >
  378. <el-input
  379. v-model.trim.number="form.properties.MAX_INTERRUPT_NUM"
  380. maxlength="5"
  381. auto-complete="off"
  382. class="input"
  383. >
  384. <template slot="append">次</template>
  385. </el-input>
  386. </el-form-item>
  387. </el-row>
  388. </el-tab-pane>
  389. <el-tab-pane label="显示设置" name="tab3">
  390. <el-row v-if="show_ckeditor">
  391. <el-form-item
  392. label="考前说明"
  393. :label-width="style.label_width_tab3"
  394. >
  395. <ckeditor
  396. v-model="form.properties.BEFORE_EXAM_REMARK"
  397. ></ckeditor>
  398. </el-form-item>
  399. </el-row>
  400. <el-row v-if="show_ckeditor">
  401. <el-form-item
  402. label="考后说明"
  403. :label-width="style.label_width_tab3"
  404. >
  405. <ckeditor
  406. v-model="form.properties.AFTER_EXAM_REMARK"
  407. ></ckeditor>
  408. </el-form-item>
  409. </el-row>
  410. <el-row>
  411. <el-form-item
  412. label="展示作弊说明"
  413. :label-width="style.label_width_tab3"
  414. >
  415. <el-radio-group
  416. v-model="form.properties.SHOW_CHEATING_REMARK"
  417. class="input"
  418. >
  419. <el-radio label="true">开启</el-radio>
  420. <el-radio label="false">关闭</el-radio>
  421. </el-radio-group>
  422. </el-form-item>
  423. </el-row>
  424. <el-row v-if="show_ckeditor">
  425. <el-form-item
  426. label="作弊说明"
  427. :label-width="style.label_width_tab3"
  428. >
  429. <ckeditor
  430. v-model="form.properties.CHEATING_REMARK"
  431. ></ckeditor>
  432. </el-form-item>
  433. </el-row>
  434. <el-row>
  435. <el-form-item
  436. label="单选题补充说明"
  437. :label-width="style.label_width_tab3"
  438. >
  439. <el-input
  440. v-model="form.properties.SINGLE_ANSWER_REMARK"
  441. maxlength="20"
  442. :disabled="!form.properties.SINGLE_EDIT"
  443. auto-complete="off"
  444. class="input"
  445. ></el-input>
  446. </el-form-item>
  447. <el-form-item label>
  448. <el-switch
  449. v-model="form.properties.SINGLE_EDIT"
  450. on-text="启用"
  451. off-text="禁用"
  452. ></el-switch>
  453. </el-form-item>
  454. </el-row>
  455. <el-row>
  456. <el-form-item
  457. label="多选题补充说明"
  458. :label-width="style.label_width_tab3"
  459. >
  460. <el-input
  461. v-model="form.properties.MUTIPLE_ANSWER_REMARK"
  462. maxlength="20"
  463. :disabled="!form.properties.MUTIPLE_EDIT"
  464. auto-complete="off"
  465. class="input"
  466. ></el-input>
  467. </el-form-item>
  468. <el-form-item label>
  469. <el-switch
  470. v-model="form.properties.MUTIPLE_EDIT"
  471. on-text="启用"
  472. off-text="禁用"
  473. ></el-switch>
  474. </el-form-item>
  475. </el-row>
  476. <el-row>
  477. <el-form-item
  478. label="判断题补充说明"
  479. :label-width="style.label_width_tab3"
  480. >
  481. <el-input
  482. v-model="form.properties.BOOL_ANSWER_REMARK"
  483. maxlength="20"
  484. :disabled="!form.properties.BOOL_EDIT"
  485. class="input"
  486. auto-complete="off"
  487. ></el-input>
  488. </el-form-item>
  489. <el-form-item label>
  490. <el-switch
  491. v-model="form.properties.BOOL_EDIT"
  492. on-text="启用"
  493. off-text="禁用"
  494. ></el-switch>
  495. </el-form-item>
  496. </el-row>
  497. <el-row>
  498. <el-form-item
  499. label="填空题补充说明"
  500. :label-width="style.label_width_tab3"
  501. >
  502. <el-input
  503. v-model="form.properties.FILL_BLANK_REMARK"
  504. maxlength="20"
  505. :disabled="!form.properties.FILL_BLANK_EDIT"
  506. class="input"
  507. auto-complete="off"
  508. ></el-input>
  509. </el-form-item>
  510. <el-form-item label>
  511. <el-switch
  512. v-model="form.properties.FILL_BLANK_EDIT"
  513. on-text="启用"
  514. off-text="禁用"
  515. ></el-switch>
  516. </el-form-item>
  517. </el-row>
  518. <el-row>
  519. <el-form-item
  520. label="客观题成绩显示"
  521. :label-width="style.label_width_tab3"
  522. >
  523. <el-radio-group
  524. v-model="form.properties.IS_OBJ_SCORE_VIEW"
  525. class="input"
  526. >
  527. <el-radio label="true">开启</el-radio>
  528. <el-radio label="false">关闭</el-radio>
  529. </el-radio-group>
  530. </el-form-item>
  531. </el-row>
  532. </el-tab-pane>
  533. <el-tab-pane label="阅卷设置" name="tab5">
  534. <el-row>
  535. <el-form-item
  536. label="阅卷方式"
  537. :label-width="style.label_width_tab5"
  538. >
  539. <el-radio-group
  540. v-model="form.properties.MARKING_TYPE"
  541. :disabled="form.started"
  542. class="input"
  543. >
  544. <el-radio label="ALL">全部评阅</el-radio>
  545. <el-radio label="OBJECT_SCORE_MAX">客观分最高</el-radio>
  546. <el-radio label="LAST_SUBMIT">最后一次提交</el-radio>
  547. </el-radio-group>
  548. </el-form-item>
  549. </el-row>
  550. </el-tab-pane>
  551. <el-tab-pane label="网络设置" name="tab6">
  552. <el-row>
  553. <el-form-item
  554. label="IP限制"
  555. :label-width="style.label_width_tab6"
  556. >
  557. <el-radio-group v-model="form.properties.IP_LIMIT">
  558. <el-radio label="true">开启</el-radio>
  559. <el-radio label="false">关闭</el-radio>
  560. </el-radio-group>
  561. </el-form-item>
  562. </el-row>
  563. <el-row>
  564. <el-form-item
  565. label="IP段( *表示任意 )"
  566. :label-width="style.label_width_tab6"
  567. >
  568. <el-input
  569. v-model="form.properties.IP_ADDRESSES"
  570. maxlength="2000"
  571. class="input"
  572. type="textarea"
  573. rows="6"
  574. ></el-input>
  575. </el-form-item>
  576. </el-row>
  577. </el-tab-pane>
  578. <el-tab-pane label="其它" name="tab7">
  579. <el-row>
  580. <el-form-item
  581. label="是否推送成绩"
  582. :label-width="style.label_width_tab7"
  583. >
  584. <el-radio-group v-model="form.properties.PUSH_SCORE">
  585. <el-radio label="true">是</el-radio>
  586. <el-radio label="false">否</el-radio>
  587. </el-radio-group>
  588. </el-form-item>
  589. </el-row>
  590. </el-tab-pane>
  591. </el-tabs>
  592. </el-form>
  593. </div>
  594. </div>
  595. </section>
  596. </div>
  597. </template>
  598. <script>
  599. import { mapState } from "vuex";
  600. import { EXAM_TYPE, EXAM_WORK_API, CORE_API } from "@/constants/constants.js";
  601. import moment from "moment";
  602. import ckeditor from "@/components/ckeditor.vue";
  603. import LinkTitlesCustom from "@/components/LinkTitlesCustom.vue";
  604. let _this = null;
  605. let validateExamCycleTimeRange = (rule, value, callback) => {
  606. if (_this.examCycleTimeRangeArr.length == 0) {
  607. callback(new Error("请至少设置一个时间段"));
  608. } else {
  609. callback();
  610. }
  611. };
  612. let validateExamCycleWeek = (rule, value, callback) => {
  613. if (_this.examCycleWeekArr.length == 0) {
  614. callback(new Error("请至少勾选一个日期"));
  615. } else {
  616. callback();
  617. }
  618. };
  619. let validateCode = (rule, value, callback) => {
  620. if (_this.examId == "add") {
  621. _this.form.code = _this.form.name;
  622. }
  623. let code = _this.form.code;
  624. if (code == "") {
  625. callback(new Error("请输入考试编码"));
  626. if (!_this.toActiveName) {
  627. _this.toActiveName = "tab1";
  628. _this.activeName = "tab1";
  629. }
  630. } else {
  631. callback();
  632. }
  633. };
  634. let validateName = (rule, value, callback) => {
  635. let name = _this.form.name;
  636. if (name == "") {
  637. callback(new Error("请输入考试名称"));
  638. if (!_this.toActiveName) {
  639. _this.toActiveName = "tab1";
  640. _this.activeName = "tab1";
  641. }
  642. } else {
  643. callback();
  644. }
  645. };
  646. let validateExamDatetimeRange = (rule, value, callback) => {
  647. let examDatetimeRange = _this.examDatetimeRange;
  648. if (!examDatetimeRange) {
  649. callback(new Error("请输入考试时间"));
  650. if (!_this.toActiveName) {
  651. _this.toActiveName = "tab1";
  652. _this.activeName = "tab1";
  653. }
  654. } else {
  655. callback();
  656. }
  657. };
  658. let validateDuration = (rule, value, callback) => {
  659. let duration = _this.form.duration;
  660. if (duration === "") {
  661. callback(new Error("请输入考试时长"));
  662. if (!_this.toActiveName) {
  663. _this.toActiveName = "tab2";
  664. _this.activeName = "tab2";
  665. }
  666. } else if (!duration.toString().match(/^[1-9]\d*|0$/)) {
  667. callback(new Error("只能是非负整数"));
  668. if (!_this.toActiveName) {
  669. _this.toActiveName = "tab2";
  670. _this.activeName = "tab2";
  671. }
  672. } else {
  673. callback();
  674. }
  675. };
  676. let validateExamTimes = (rule, value, callback) => {
  677. let examTimes = _this.form.examTimes;
  678. if (examTimes === "") {
  679. callback(new Error("请输入考试次数"));
  680. if (!_this.toActiveName) {
  681. _this.toActiveName = "tab2";
  682. _this.activeName = "tab2";
  683. }
  684. } else if (!examTimes.toString().match(/^[1-9]\d*$/)) {
  685. callback(new Error("只能是正整数"));
  686. if (!_this.toActiveName) {
  687. _this.toActiveName = "tab2";
  688. _this.activeName = "tab2";
  689. }
  690. } else {
  691. callback();
  692. }
  693. };
  694. let validateFreezeTime = (rule, value, callback) => {
  695. let freezeTime = _this.form.properties.FREEZE_TIME;
  696. let duration = _this.form.duration;
  697. if (freezeTime === "") {
  698. callback(new Error("请输入交卷冻结时长"));
  699. if (!_this.toActiveName) {
  700. _this.toActiveName = "tab2";
  701. _this.activeName = "tab2";
  702. }
  703. } else if (!freezeTime.toString().match(/^[1-9]\d*|0$/)) {
  704. callback(new Error("只能是非负整数"));
  705. if (!_this.toActiveName) {
  706. _this.toActiveName = "tab2";
  707. _this.activeName = "tab2";
  708. }
  709. } else if (duration != "" && parseInt(freezeTime) > parseInt(duration)) {
  710. callback(new Error("交卷冻结时长不能大于考试时长"));
  711. if (!_this.toActiveName) {
  712. _this.toActiveName = "tab2";
  713. _this.activeName = "tab2";
  714. }
  715. } else {
  716. callback();
  717. }
  718. };
  719. let validateExamReconnectTime = (rule, value, callback) => {
  720. let examReconnectTime = _this.form.properties.EXAM_RECONNECT_TIME;
  721. if (examReconnectTime === "") {
  722. callback(new Error("请输入断点续考时间"));
  723. if (!_this.toActiveName) {
  724. _this.toActiveName = "tab2";
  725. _this.activeName = "tab2";
  726. }
  727. } else if (!examReconnectTime.toString().match(/^[1-9]\d*$/)) {
  728. callback(new Error("只能是正整数"));
  729. if (!_this.toActiveName) {
  730. _this.toActiveName = "tab2";
  731. _this.activeName = "tab2";
  732. }
  733. } else if (examReconnectTime < 3) {
  734. callback(new Error("最小设置值为3"));
  735. if (!_this.toActiveName) {
  736. _this.toActiveName = "tab2";
  737. _this.activeName = "tab2";
  738. }
  739. } else {
  740. callback();
  741. }
  742. };
  743. let validateMaxInterruptNum = (rule, value, callback) => {
  744. let examReconnectTime = _this.form.properties.MAX_INTERRUPT_NUM;
  745. if (examReconnectTime === "") {
  746. callback();
  747. } else if (!examReconnectTime.toString().match(/^[0-9]\d*$/)) {
  748. callback(new Error("只能是非负整数"));
  749. if (!_this.toActiveName) {
  750. _this.toActiveName = "tab2";
  751. _this.activeName = "tab2";
  752. }
  753. } else {
  754. callback();
  755. }
  756. };
  757. export default {
  758. components: {
  759. ckeditor,
  760. LinkTitlesCustom,
  761. },
  762. data() {
  763. return {
  764. style: {
  765. label_width_tab1: "160px",
  766. label_width_tab2: "110px",
  767. label_width_tab3: "120px",
  768. label_width_tab4: "170px",
  769. label_width_tab5: "80px",
  770. label_width_tab6: "120px",
  771. label_width_tab7: "150px",
  772. },
  773. examCycleTimeRangeArr: [],
  774. examCycleWeekArr: [1, 2, 3, 4, 5, 6, 7],
  775. activeName: "tab1",
  776. toActiveName: null,
  777. examDatetimeRange: [],
  778. show_ckeditor: false,
  779. is_face_verify_diabled: true,
  780. is_face_enable_diabled: true,
  781. rootOrgWenXinAnswerEnabled: false,
  782. IDENTIFICATION_OF_LIVING_BODY_SCHEME: "S1",
  783. form: {
  784. started: false,
  785. name: "",
  786. code: "",
  787. examType: "ONLINE_HOMEWORK",
  788. examTimes: 1,
  789. beginTime: null,
  790. endTime: null,
  791. duration: 120,
  792. enable: "true",
  793. examLimit: "false",
  794. specialSettingsEnabled: false,
  795. specialSettingsType: "ORG_BASED",
  796. properties: {
  797. IS_OBJ_SCORE_VIEW: "true",
  798. IS_STRANGER_ENABLE: "false",
  799. MAX_INTERRUPT_NUM: "",
  800. EXAM_RECONNECT_TIME: 30,
  801. FREEZE_TIME: 0,
  802. BEFORE_EXAM_REMARK: "",
  803. AFTER_EXAM_REMARK: "",
  804. SHOW_CHEATING_REMARK: "true",
  805. CHEATING_REMARK: "",
  806. SINGLE_EDIT: "false",
  807. MUTIPLE_EDIT: "false",
  808. BOOL_EDIT: "false",
  809. FILL_BLANK_EDIT: "false",
  810. SINGLE_ANSWER_REMARK: "",
  811. MUTIPLE_ANSWER_REMARK: "",
  812. FILL_BLANK_REMARK: "",
  813. BOOL_ANSWER_REMARK: "",
  814. IS_FACE_ENABLE: "false",
  815. IS_FACE_CHECK: "false",
  816. SNAPSHOT_INTERVAL: 30,
  817. WARN_THRESHOLD: 50,
  818. MARKING_TYPE: "ALL",
  819. IP_LIMIT: "false",
  820. IP_ADDRESSES: null,
  821. LIVING_WARN_THRESHOLD: 50,
  822. IS_FACE_VERIFY: "false",
  823. FACE_VERIFY_START_MINUTE: 5,
  824. FACE_VERIFY_END_MINUTE: 10,
  825. PUSH_SCORE: "false",
  826. CHECK_ENVIRONMENT: "false",
  827. WEIXIN_ANSWER_ENABLED: "false",
  828. ADD_FACE_VERIFY_OUT_FREEZE_TIME: "false",
  829. OUT_FREEZE_TIME_FACE_VERIFY_START_MINUTE: 10,
  830. OUT_FREEZE_TIME_FACE_VERIFY_END_MINUTE: 30,
  831. LIMITED_IF_NO_SPECIAL_SETTINGS: "false",
  832. EXAM_CYCLE_ENABLED: "false",
  833. EXAM_CYCLE_WEEK: "",
  834. EXAM_CYCLE_TIME_RANGE: "",
  835. },
  836. },
  837. examTypeList: EXAM_TYPE,
  838. examId: "",
  839. rootOrgId: null,
  840. rules: {
  841. code: [{ required: true, validator: validateCode, trigger: "blur" }],
  842. name: [{ required: true, validator: validateName, trigger: "blur" }],
  843. examDatetimeRange: [
  844. {
  845. required: true,
  846. validator: validateExamDatetimeRange,
  847. trigger: "blur",
  848. },
  849. ],
  850. duration: [
  851. { required: true, validator: validateDuration, trigger: "blur" },
  852. ],
  853. examTimes: [
  854. { required: true, validator: validateExamTimes, trigger: "blur" },
  855. ],
  856. FREEZE_TIME: [
  857. { required: true, validator: validateFreezeTime, trigger: "blur" },
  858. ],
  859. EXAM_RECONNECT_TIME: [
  860. {
  861. required: true,
  862. validator: validateExamReconnectTime,
  863. trigger: "blur",
  864. },
  865. ],
  866. MAX_INTERRUPT_NUM: [
  867. {
  868. required: false,
  869. validator: validateMaxInterruptNum,
  870. trigger: "blur",
  871. },
  872. ],
  873. examCycleWeekArr: [
  874. {
  875. required: true,
  876. validator: validateExamCycleWeek,
  877. trigger: "change",
  878. },
  879. ],
  880. examCycleTimeRangeArr: [
  881. {
  882. required: true,
  883. validator: validateExamCycleTimeRange,
  884. trigger: "change",
  885. },
  886. ],
  887. },
  888. };
  889. },
  890. computed: {
  891. ...mapState({ user: (state) => state.user }),
  892. },
  893. created() {
  894. _this = this;
  895. this.examId = this.$route.params.id;
  896. this.init();
  897. },
  898. methods: {
  899. examCycleEnabledChange(val) {
  900. if (val == "true") {
  901. this.examCycleWeekArr = [1, 2, 3, 4, 5, 6, 7];
  902. this.addCycleTimeRange();
  903. } else {
  904. this.examCycleTimeRangeArr = [];
  905. this.examCycleWeekArr = [];
  906. }
  907. },
  908. getEndTimeStr() {
  909. return "23:59";
  910. },
  911. getNowTimeStr() {
  912. let now = new Date();
  913. let hour = now.getHours();
  914. if (hour.length < 10) {
  915. hour = "0" + hour;
  916. }
  917. let minute = now.getMinutes();
  918. if (minute < 10) {
  919. minute = "0" + minute;
  920. }
  921. return hour + ":" + minute;
  922. },
  923. removeExamCycleTimeRange(index) {
  924. if (this.examCycleTimeRangeArr.length == 1) {
  925. this.$notify({
  926. type: "warning",
  927. message: "不能删除最后一个分段",
  928. });
  929. return;
  930. }
  931. this.examCycleTimeRangeArr.splice(index, 1);
  932. this.$refs.form.validateField("examCycleTimeRangeArr");
  933. },
  934. addCycleTimeRange() {
  935. if (this.examCycleTimeRangeArr.length >= 12) {
  936. this.$notify({
  937. type: "warning",
  938. message: "时间分段不得超过12条",
  939. });
  940. return;
  941. }
  942. this.examCycleTimeRangeArr.push({
  943. timeRange: [this.getNowTimeStr(), this.getEndTimeStr()],
  944. });
  945. this.$refs.form.validateField("examCycleTimeRangeArr");
  946. },
  947. faceEnableChange() {
  948. if (this.form.properties.IS_FACE_ENABLE == "false") {
  949. this.form.properties.IS_STRANGER_ENABLE = "false";
  950. this.form.properties.IS_FACE_CHECK = "false";
  951. this.form.properties.IS_FACE_VERIFY = "false";
  952. this.form.properties.ADD_FACE_VERIFY_OUT_FREEZE_TIME = "false";
  953. }
  954. },
  955. init() {
  956. if (this.examId != "add") {
  957. let url = EXAM_WORK_API + "/exam/" + this.examId;
  958. this.$httpWithMsg.get(url).then((response) => {
  959. let body = response.data;
  960. this.rootOrgId = body.rootOrgId;
  961. body.properties = this.form.properties;
  962. this.form = Object.assign(this.form, response.data);
  963. this.form.enable = this.form.enable ? "true" : "false";
  964. this.form.examLimit = this.form.examLimit ? "true" : "false";
  965. this.examDatetimeRange = [this.form.beginTime, this.form.endTime];
  966. console.log("getOnlineHomework(); form: ", this.form);
  967. let url = EXAM_WORK_API + "/exam/allProperties/" + this.examId;
  968. this.$httpWithMsg.get(url).then((response) => {
  969. this.form.properties = Object.assign(
  970. this.form.properties,
  971. response.data
  972. );
  973. this.form.properties.SINGLE_EDIT =
  974. this.form.properties.SINGLE_EDIT === "true";
  975. this.form.properties.MUTIPLE_EDIT =
  976. this.form.properties.MUTIPLE_EDIT === "true";
  977. this.form.properties.BOOL_EDIT =
  978. this.form.properties.BOOL_EDIT === "true";
  979. this.form.properties.FILL_BLANK_EDIT =
  980. this.form.properties.FILL_BLANK_EDIT === "true";
  981. this.form.properties.CHECK_ENVIRONMENT =
  982. this.form.properties.CHECK_ENVIRONMENT === "true";
  983. this.form.properties.WEIXIN_ANSWER_ENABLED =
  984. this.form.properties.WEIXIN_ANSWER_ENABLED === "true";
  985. this.form.properties.LIMITED_IF_NO_SPECIAL_SETTINGS =
  986. this.form.properties.LIMITED_IF_NO_SPECIAL_SETTINGS === "true";
  987. if (this.form.properties.EXAM_CYCLE_TIME_RANGE) {
  988. this.examCycleTimeRangeArr = JSON.parse(
  989. this.form.properties.EXAM_CYCLE_TIME_RANGE
  990. );
  991. }
  992. if (this.form.properties.EXAM_CYCLE_WEEK) {
  993. this.examCycleWeekArr = JSON.parse(
  994. this.form.properties.EXAM_CYCLE_WEEK
  995. );
  996. }
  997. this.show_ckeditor = true;
  998. this.checkRootOrgPrivileges();
  999. });
  1000. });
  1001. } else {
  1002. let now = moment().format("YYYY-MM-DD HH:mm:ss");
  1003. this.examDatetimeRange = [now, now];
  1004. this.show_ckeditor = true;
  1005. this.checkRootOrgPrivileges();
  1006. }
  1007. },
  1008. checkRootOrgPrivileges: function () {
  1009. let url =
  1010. CORE_API +
  1011. "/rolePrivilege/checkRootOrgPrivileges?privilegeCodes=FACE_CHECK,IDENTIFICATION_OF_LIVING_BODY";
  1012. this.$httpWithMsg.post(url).then((response) => {
  1013. let res = response.data;
  1014. if (!res.FACE_CHECK) {
  1015. this.form.properties.IS_FACE_ENABLE = "false";
  1016. this.form.properties.IS_STRANGER_ENABLE = "false";
  1017. this.form.properties.IS_FACE_CHECK = "false";
  1018. this.form.properties.IS_FACE_VERIFY = "false";
  1019. this.form.properties.ADD_FACE_VERIFY_OUT_FREEZE_TIME = "false";
  1020. this.is_face_enable_diabled = true;
  1021. } else {
  1022. this.is_face_enable_diabled = false;
  1023. }
  1024. if (!res.IDENTIFICATION_OF_LIVING_BODY) {
  1025. this.is_face_verify_diabled = true;
  1026. this.form.properties.IS_FACE_VERIFY = "false";
  1027. this.form.properties.ADD_FACE_VERIFY_OUT_FREEZE_TIME = "false";
  1028. } else {
  1029. this.is_face_verify_diabled = false;
  1030. }
  1031. });
  1032. let url2 =
  1033. CORE_API +
  1034. "/org/property/" +
  1035. this.user.rootOrgId +
  1036. "/WEIXIN_ANSWER_ENABLED";
  1037. this.$httpWithMsg.get(url2).then((response) => {
  1038. let res = response.data;
  1039. this.rootOrgWenXinAnswerEnabled = res == true;
  1040. if (!this.rootOrgWenXinAnswerEnabled) {
  1041. this.form.properties.WEIXIN_ANSWER_ENABLED = false;
  1042. }
  1043. });
  1044. let that = this;
  1045. this.getOrgProperty(
  1046. "IDENTIFICATION_OF_LIVING_BODY_SCHEME",
  1047. function (res) {
  1048. that.form.IDENTIFICATION_OF_LIVING_BODY_SCHEME = res;
  1049. }
  1050. );
  1051. },
  1052. getOrgProperty: function (propkey, callback) {
  1053. let url =
  1054. CORE_API + "/org/property/" + this.user.rootOrgId + "/" + propkey;
  1055. this.$httpWithMsg.get(url).then((response) => {
  1056. let res = response.data;
  1057. callback(res);
  1058. });
  1059. },
  1060. compare: function (x, y) {
  1061. if (x < y) {
  1062. return -1;
  1063. } else if (x > y) {
  1064. return 1;
  1065. } else {
  1066. return 0;
  1067. }
  1068. },
  1069. saveExam: function () {
  1070. this.toActiveName = null;
  1071. this.form.beginTime = this.examDatetimeRange[0];
  1072. this.form.endTime = this.examDatetimeRange[1];
  1073. this.form.properties.EXAM_CYCLE_TIME_RANGE = JSON.stringify(
  1074. this.examCycleTimeRangeArr
  1075. );
  1076. this.examCycleWeekArr.sort(this.compare);
  1077. this.form.properties.EXAM_CYCLE_WEEK = JSON.stringify(
  1078. this.examCycleWeekArr
  1079. );
  1080. console.log(this.form);
  1081. let url = EXAM_WORK_API + "/exam";
  1082. this.$refs.form.validate((valid) => {
  1083. if (valid) {
  1084. if (this.examId != "add") {
  1085. this.$httpWithMsg.put(url, this.form).then((response) => {
  1086. if (200 != response.status) {
  1087. this.$notify({
  1088. type: "error",
  1089. message: response.body.desc,
  1090. });
  1091. return;
  1092. }
  1093. this.$notify({
  1094. type: "success",
  1095. message: "保存成功",
  1096. });
  1097. });
  1098. } else {
  1099. this.form.code = this.form.name;
  1100. this.$httpWithMsg.post(url, this.form).then((response) => {
  1101. console.log(response);
  1102. this.$notify({
  1103. type: "success",
  1104. message: "新增成功",
  1105. });
  1106. this.examId = response.data.id;
  1107. this.form.id = this.examId;
  1108. this.$router.push({
  1109. path: "/examwork/onlineHomework/" + response.data.id,
  1110. });
  1111. });
  1112. }
  1113. } else {
  1114. return false;
  1115. }
  1116. });
  1117. },
  1118. back() {
  1119. this.$router.push({ path: "/examwork/examInfo" });
  1120. },
  1121. },
  1122. };
  1123. </script>
  1124. <style scoped>
  1125. .input {
  1126. width: 440px;
  1127. }
  1128. .input >>> .el-input__inner {
  1129. -webkit-appearance: button;
  1130. }
  1131. </style>