edit.vue 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998
  1. <template>
  2. <el-dialog
  3. :title="title"
  4. :visible.sync="dialogVisible"
  5. :close-on-click-modal="false"
  6. :close-on-press-escape="false"
  7. append-to-body
  8. width="60%"
  9. class="dialog exam-dialog"
  10. top="6vh"
  11. @close="closeDialog"
  12. @open="getExamData"
  13. >
  14. <el-form
  15. ref="form"
  16. :label-width="formLabelWidth"
  17. :model="form"
  18. :rules="rules"
  19. class="exam-form"
  20. @submit.native.prevent
  21. >
  22. <el-form-item label="考试名称:" prop="kao_shi_ming_chen">
  23. <el-input
  24. v-model="form.kao_shi_ming_chen"
  25. type="text"
  26. :maxlength="256"
  27. placeholder="请输入考试名称"
  28. :disabled="isDisabled"
  29. />
  30. </el-form-item>
  31. <!-- <el-form-item label="考试类型:" prop="kao_shi_lei_xing_">
  32. <el-select
  33. v-model="form.kao_shi_lei_xing_"
  34. filterable
  35. allow-create
  36. width="100%"
  37. placeholder="请选择考试类型"
  38. >
  39. <el-option
  40. v-for="item in examTypeOptions"
  41. :key="item.value"
  42. :label="item.label"
  43. :value="item.value"
  44. />
  45. </el-select>
  46. </el-form-item> -->
  47. <el-form-item label="考试题库:">
  48. <template slot="label">
  49. 考试题库
  50. <el-tooltip
  51. effect="dark"
  52. content="如果选择多个题库或手动添加选题,最终生成的考试将是所选题目的总和,并将自动生成一个组合题库。"
  53. placement="top"
  54. >
  55. <i class="el-icon-question question-icon">:</i>
  56. </el-tooltip>
  57. </template>
  58. <div class="tiku">
  59. <div class="item">
  60. <ibps-custom-dialog
  61. v-model="allQuestions.tiKu"
  62. size="small"
  63. template-key="tkdhk"
  64. :multiple="true"
  65. :disabled="isDisabled"
  66. type="dialog"
  67. class="custom-dialog"
  68. placeholder="请选择考试题库"
  69. style="width:90%"
  70. />
  71. <div class="number">题数:{{ allQuestionsNumber.tiKuNumber }}</div>
  72. </div>
  73. </div>
  74. </el-form-item>
  75. <el-form-item label="手动选题:">
  76. <template slot="label">
  77. 手动选题
  78. <el-tooltip
  79. effect="dark"
  80. content="如果选择多个题库或手动添加选题,最终生成的考试将是所选题目的总和,并将自动生成一个组合题库。"
  81. placement="top"
  82. >
  83. <i class="el-icon-question question-icon">:</i>
  84. </el-tooltip>
  85. </template>
  86. <div class="tiku">
  87. <div class="item">
  88. <ibps-custom-dialog
  89. v-model="allQuestions.handQuestions"
  90. size="small"
  91. template-key="tmlb"
  92. multiple
  93. type="dialog"
  94. class="custom-dialog"
  95. placeholder="请选择考试题目"
  96. style="width:90%"
  97. />
  98. <div class="number">题数:{{ allQuestions.handQuestions?allQuestions.handQuestions.split(',').length:0 }}</div>
  99. <div class="number" style="margin-left:-20px">去重后:{{ allQuestionsNumber.handQuestionsNumber }}</div>
  100. </div>
  101. </div>
  102. </el-form-item>
  103. <el-form-item>
  104. <template slot="label">
  105. 随机抽题
  106. <el-tooltip
  107. effect="dark"
  108. content="是否开启从题库中随机抽题。"
  109. placement="top"
  110. >
  111. <i class="el-icon-question question-icon">:</i>
  112. </el-tooltip>
  113. </template>
  114. <el-radio-group v-model="form.sui_ji_chou_ti_" :disabled="isDisabled">
  115. <el-radio label="0">关闭</el-radio>
  116. <el-radio label="1" :disabled="allQuestionsNumber.tiKuNumber+allQuestionsNumber.handQuestionsNumber==0">开启</el-radio>
  117. </el-radio-group>
  118. </el-form-item>
  119. <el-form-item v-if="form.sui_ji_chou_ti_ === '1'">
  120. <template slot="label">
  121. 抽题方式
  122. <el-tooltip
  123. effect="dark"
  124. content="随机抽题的依据。"
  125. placement="top"
  126. >
  127. <i class="el-icon-question question-icon">:</i>
  128. </el-tooltip>
  129. </template>
  130. <el-radio-group v-model="form.chou_ti_fang_shi_" :disabled="isDisabled">
  131. <el-radio label="1">按照题型分类抽题</el-radio>
  132. <el-radio label="2">按照难度分类抽题</el-radio>
  133. </el-radio-group>
  134. </el-form-item>
  135. <el-form-item v-if="form.sui_ji_chou_ti_ === '1'" class="handrand">
  136. <template slot="label">
  137. 抽题规则
  138. <el-tooltip
  139. effect="dark"
  140. :content="ruleContent"
  141. placement="top"
  142. >
  143. <i class="el-icon-question question-icon">:</i>
  144. </el-tooltip>
  145. </template>
  146. <template v-if="form.chou_ti_fang_shi_==='1'">
  147. <div v-for="item in handList" :key="item.itemType" class="hand-item">
  148. <template v-if="item.list.length>0">
  149. <span>{{ item.itemType }}:</span>
  150. <el-input-number
  151. v-model="item.questionNumber"
  152. style="width:120px"
  153. :min="0"
  154. :max="item.list.length"
  155. :precision="0"
  156. :disabled="form.sui_ji_chou_ti_ === '0' || isDisabled"
  157. placeholder="请输入抽题数量"
  158. :step="item.step"
  159. step-strictly
  160. />
  161. </template>
  162. </div>
  163. </template>
  164. <template v-if="form.chou_ti_fang_shi_==='2'">
  165. <div v-for="item in levelList" :key="item.itemType" class="hand-item">
  166. <template v-if="item.list.length>0">
  167. <span>{{ item.label }}:</span>
  168. <el-input-number
  169. v-model="item.questionNumber"
  170. style="width:120px"
  171. :min="0"
  172. :max="item.list.length"
  173. :precision="0"
  174. :disabled="form.sui_ji_chou_ti_ === '0' || isDisabled"
  175. placeholder="请输入抽题数量"
  176. :step="item.step"
  177. step-strictly
  178. />
  179. </template>
  180. </div>
  181. </template>
  182. </el-form-item>
  183. <el-form-item prop="xian_kao_shi_jian">
  184. <template slot="label">
  185. 限考时间
  186. <el-tooltip
  187. effect="dark"
  188. content="设置该考试的提交截至时间。"
  189. placement="top"
  190. >
  191. <i class="el-icon-question question-icon">:</i>
  192. </el-tooltip>
  193. </template>
  194. <el-radio-group
  195. v-model="form.isDateLimit"
  196. @change="changeLimit(form.isDateLimit, 'xian_kao_shi_jian', null)"
  197. >
  198. <el-radio label="0">不限</el-radio>
  199. <el-radio label="1">限制</el-radio>
  200. </el-radio-group>
  201. <el-date-picker
  202. v-if="form.isDateLimit === '1'"
  203. v-model="form.xian_kao_shi_jian"
  204. type="datetime"
  205. placeholder="请选择考试限制提交时间"
  206. align="right"
  207. default-time="12:00:00"
  208. class="date-picker"
  209. :picker-options="pickerOptions"
  210. />
  211. </el-form-item>
  212. <el-form-item label="参考人员:" prop="can_kao_ren_yuan_">
  213. <ibps-custom-dialog
  214. v-model="form.can_kao_ren_yuan_"
  215. size="small"
  216. template-key="gjxcxryk_copy"
  217. multiple
  218. :disabled="isDisabled"
  219. type="dialog"
  220. class="custom-dialog"
  221. placeholder="请选择需参加考试的人员"
  222. />
  223. </el-form-item>
  224. <el-form-item prop="ping_fen_ren_">
  225. <template slot="label">
  226. 评分人
  227. <el-tooltip effect="dark" content="设置该考试的评分人,选择的评分人与题目评分人都可以进行试题评阅" placement="top">
  228. <i class="el-icon-question question-icon">:</i>
  229. </el-tooltip>
  230. </template>
  231. <!-- <el-cascader
  232. v-model="form.ping_fen_ren_"
  233. :options="getRaterOptions()"
  234. :show-all-levels="false"
  235. collapse-tags
  236. :props="{
  237. value: 'value',
  238. label: 'label',
  239. multiple: true,
  240. checkStrictly: false
  241. }"
  242. /> -->
  243. <el-select
  244. v-model="form.ping_fen_ren_"
  245. filterable
  246. style="width:100%"
  247. clearable
  248. multiple
  249. :multiple-limit="16"
  250. :disabled="isDisabled"
  251. placeholder="请选择评分人"
  252. >
  253. <el-option
  254. v-for="item in userList"
  255. :key="item.userId"
  256. :label="item.userName"
  257. :value="item.userId"
  258. />
  259. </el-select>
  260. </el-form-item>
  261. <el-form-item prop="isCountLimit" class="inline-item">
  262. <template slot="label">
  263. 限考次数
  264. <el-tooltip
  265. effect="dark"
  266. content="限制是否可重复参加,以及可参加考试的最大次数。"
  267. placement="top"
  268. >
  269. <i class="el-icon-question question-icon">:</i>
  270. </el-tooltip>
  271. </template>
  272. <el-radio-group
  273. v-model="form.isCountLimit"
  274. :disabled="isDisabled"
  275. @change="changeLimit(form.isCountLimit, 'xian_kao_ci_shu_', 1)"
  276. >
  277. <el-radio label="0">不限</el-radio>
  278. <el-radio label="1">限制</el-radio>
  279. </el-radio-group>
  280. <div v-if="form.isCountLimit === '1'" class="time">
  281. <el-input-number
  282. v-model="form.xian_kao_ci_shu_"
  283. :min="1"
  284. :precision="0"
  285. :disabled="isDisabled"
  286. placeholder="请输入单个用户最大限考次数"
  287. />
  288. <div class="unit">次</div>
  289. </div>
  290. </el-form-item>
  291. <el-form-item v-if="form.isCountLimit === '0' || form.isCountLimit === '1' && form.xian_kao_ci_shu_ > 1" prop="ji_fen_fang_shi_">
  292. <template slot="label">
  293. 计分方式
  294. <el-tooltip
  295. effect="dark"
  296. content="设置对于可重复参加的考试,最终得分的计算方式(仅限考次数大于1时有效)。"
  297. placement="top"
  298. >
  299. <i class="el-icon-question question-icon">:</i>
  300. </el-tooltip>
  301. </template>
  302. <el-radio-group v-model="form.ji_fen_fang_shi_" :disabled="isDisabled">
  303. <el-radio label="平均分">平均分</el-radio>
  304. <el-radio label="最高分">最高分</el-radio>
  305. <el-radio label="最近得分">最近得分</el-radio>
  306. </el-radio-group>
  307. </el-form-item>
  308. <el-form-item prop="isTimeLimit" class="inline-item">
  309. <template slot="label">
  310. 考试时长
  311. <el-tooltip
  312. effect="dark"
  313. content="设置该考试单次作答的最大时长。"
  314. placement="top"
  315. >
  316. <i class="el-icon-question question-icon">:</i>
  317. </el-tooltip>
  318. </template>
  319. <el-radio-group v-model="form.isTimeLimit" :disabled="isDisabled">
  320. <el-radio label="0">不限</el-radio>
  321. <el-radio label="1">限制</el-radio>
  322. </el-radio-group>
  323. <template v-if="form.isTimeLimit === '1'">
  324. <div class="time">
  325. <el-input-number
  326. v-model="form.hours"
  327. :min="0"
  328. :max="72"
  329. :precision="0"
  330. :disabled="isDisabled"
  331. />
  332. <div class="unit">小时</div>
  333. </div>
  334. <div class="time">
  335. <el-input-number
  336. v-model="form.minutes"
  337. :min="0"
  338. :max="59"
  339. :precision="0"
  340. :disabled="isDisabled"
  341. />
  342. <div class="unit">分钟</div>
  343. </div>
  344. </template>
  345. </el-form-item>
  346. <el-form-item prop="da_biao_zhan_bi_">
  347. <template slot="label">
  348. 达标分值占比
  349. <el-tooltip
  350. effect="dark"
  351. content="设置该考试的达标分数线占试题总分的百分比。"
  352. placement="top"
  353. >
  354. <i class="el-icon-question question-icon">:</i>
  355. </el-tooltip>
  356. </template>
  357. <el-input-number
  358. v-model="form.da_biao_zhan_bi_"
  359. :min="50"
  360. :max="100"
  361. :precision="0"
  362. :disabled="isDisabled"
  363. placeholder="请输入达标分值占比"
  364. />
  365. <div class="unit">%</div>
  366. </el-form-item>
  367. <el-form-item prop="yun_xu_bao_ming_">
  368. <template slot="label">
  369. 允许自主报名
  370. <el-tooltip
  371. effect="dark"
  372. content="限制非本考试的参考人员是否可报名参加该考试。"
  373. placement="top"
  374. >
  375. <i class="el-icon-question question-icon">:</i>
  376. </el-tooltip>
  377. </template>
  378. <el-radio-group v-model="form.yun_xu_bao_ming_" :disabled="isDisabled">
  379. <el-radio label="是">是</el-radio>
  380. <el-radio label="否">否</el-radio>
  381. </el-radio-group>
  382. </el-form-item>
  383. <el-form-item v-if="!isDisabled || form.guan_lian_id_" prop="guan_lian_id_">
  384. <template slot="label">
  385. 关联培训记录
  386. <el-tooltip effect="dark" content="关联培训记录。" placement="top">
  387. <i class="el-icon-question question-icon">:</i>
  388. </el-tooltip>
  389. </template>
  390. <ibps-custom-dialog
  391. v-model="form.guan_lian_id_"
  392. size="small"
  393. template-key="pxjldhk"
  394. :multiple="false"
  395. :disabled="isDisabled"
  396. type="dialog"
  397. class="custom-dialog"
  398. placeholder="请选择培训记录"
  399. />
  400. </el-form-item>
  401. <el-form-item
  402. v-if="!isDisabled || form.kao_shi_miao_shu_"
  403. label="考试描述:"
  404. prop="kao_shi_miao_shu_"
  405. >
  406. <el-input
  407. v-model="form.kao_shi_miao_shu_"
  408. type="textarea"
  409. :rows="4"
  410. :maxlength="512"
  411. placeholder="请输入描述内容"
  412. :disabled="isDisabled"
  413. />
  414. </el-form-item>
  415. </el-form>
  416. <div slot="footer" class="el-dialog--center">
  417. <ibps-toolbar :actions="toolbars" @action-event="handleActionEvent" />
  418. </div>
  419. </el-dialog>
  420. </template>
  421. <script>
  422. import dayjs from 'dayjs'
  423. import ActionUtils from '@/utils/action'
  424. import { examTypeOptions, scoringType } from '../constants'
  425. export default {
  426. components: {
  427. IbpsCustomDialog: () => import('@/business/platform/data/templaterender/custom-dialog')
  428. },
  429. props: {
  430. visible: {
  431. type: Boolean,
  432. default: false
  433. },
  434. id: {
  435. type: String,
  436. default: ''
  437. },
  438. isDisabled: {
  439. type: Boolean,
  440. default: false
  441. },
  442. userIds: {
  443. type: String,
  444. default: ''
  445. }
  446. },
  447. data () {
  448. const {
  449. userList = [],
  450. deptList = [],
  451. userId,
  452. level
  453. } = this.$store.getters || {}
  454. return {
  455. level: level.second || level.first,
  456. userId: userId,
  457. allQuestions: {
  458. handQuestions: '',
  459. tiKu: ''
  460. },
  461. allQuestionsNumber: {
  462. handQuestionsNumber: 0,
  463. tiKuNumber: 0
  464. },
  465. curQuestions: [],
  466. handList: [
  467. { itemType: '单选题', questionNumber: 0, list: [], step: 1 },
  468. { itemType: '多选题', questionNumber: 0, list: [], step: 1 },
  469. { itemType: '判断题', questionNumber: 0, list: [], step: 1 },
  470. { itemType: '填空题', questionNumber: 0, list: [], step: 1 },
  471. { itemType: '简答题', questionNumber: 0, list: [], step: 1 }
  472. ],
  473. levelList: [
  474. { label: '未知', itemType: '0', questionNumber: 0, list: [], step: 1 },
  475. { label: '易', itemType: '1', questionNumber: 0, list: [], step: 1 },
  476. { label: '偏易', itemType: '2', questionNumber: 0, list: [], step: 1 },
  477. { label: '适中', itemType: '3', questionNumber: 0, list: [], step: 1 },
  478. { label: '偏难', itemType: '4', questionNumber: 0, list: [], step: 1 },
  479. { label: '难', itemType: '5', questionNumber: 0, list: [], step: 1 }
  480. ],
  481. userList,
  482. examTypeOptions,
  483. deptList: deptList.filter((i) => i.depth === 4),
  484. title: this.id ? '编辑考试' : '新建考试',
  485. formLabelWidth: '150px',
  486. dialogVisible: this.visible,
  487. dialogLoading: false,
  488. randButtonDisabled: false,
  489. isFirst: true,
  490. form: {
  491. di_dian_: level.second || level.first,
  492. chuang_jian_shi_j: '',
  493. kao_shi_ming_chen: '',
  494. kao_shi_lei_xing_: '常规',
  495. ti_ku_id_: '',
  496. guan_lian_id_: '',
  497. xian_kao_shi_jian: '不限',
  498. xian_kao_ci_shu_: '不限',
  499. can_kao_ren_yuan_: this.userIds || '',
  500. kao_shi_shi_chang: '',
  501. zhuang_tai_: '未发布',
  502. da_biao_zhan_bi_: 60,
  503. ji_fen_fang_shi_: scoringType.length ? scoringType[0].value : '',
  504. kao_shi_miao_shu_: '',
  505. yun_xu_bao_ming_: '否',
  506. isCountLimit: '0',
  507. isTimeLimit: '0',
  508. isDateLimit: '0',
  509. sui_ji_chou_ti_: '0',
  510. chou_ti_zong_fen_: 0,
  511. ti_mu_zong_shu_: 0,
  512. sui_ji_ti_shu_: [],
  513. hours: 2,
  514. minutes: 30,
  515. chou_ti_fang_shi_: '1',
  516. ping_fen_ren_: ''
  517. },
  518. pickerOptions: {
  519. disabledDate (time) {
  520. // 禁用当前日期之前的日期
  521. return time.getTime() < Date.now() - 8.64e7
  522. }
  523. },
  524. toolbars: [
  525. {
  526. key: 'submit',
  527. icon: 'ibps-icon-save',
  528. label: '保存',
  529. hidden: () => {
  530. return this.readonly
  531. }
  532. },
  533. { key: 'cancel', label: '关闭' }
  534. ],
  535. rules: {
  536. kao_shi_ming_chen: [
  537. { required: true, message: this.$t('validate.required') }
  538. ],
  539. // kao_shi_lei_xing_: [{ required: true, message: this.$t('validate.required') }],
  540. ti_ku_id_: [{ required: true, message: this.$t('validate.required') }],
  541. xian_kao_shi_jian: [
  542. { required: true, message: this.$t('validate.required') }
  543. ],
  544. xian_kao_ci_shu_: [
  545. { required: true, message: this.$t('validate.required') }
  546. ],
  547. can_kao_ren_yuan_: [
  548. { required: true, message: this.$t('validate.required') }
  549. ],
  550. kao_shi_shi_chang: [
  551. { required: true, message: this.$t('validate.required') }
  552. ],
  553. da_biao_zhan_bi_: [
  554. { required: true, message: this.$t('validate.required') }
  555. ]
  556. }
  557. }
  558. },
  559. computed: {
  560. ruleContent () {
  561. switch (this.form.chou_ti_fang_shi_) {
  562. case '1':
  563. return '设置每类题型的抽题数量,相同题型相同分值可以自由选择抽题数量,相同题型不同分值只能全抽或不抽。'
  564. case '2':
  565. return '设置每种难度的抽题数量,相同难度相同分值可以自由选择抽题数量,相同难度不同分值只能全抽或不抽。未设置难度的题目会自动过滤。'
  566. }
  567. return '设置每类题型的抽题数量,相同题型相同分值可以自由选择抽题数量,相同题型不同分值只能全抽或不抽。'
  568. }
  569. },
  570. watch: {
  571. visible: {
  572. handler: function (val, oldVal) {
  573. this.dialogVisible = this.visible
  574. }
  575. // immediate: true
  576. },
  577. 'allQuestions': {
  578. handler (val) {
  579. const allRequests = []
  580. const { tiKu, handQuestions } = val
  581. if (tiKu) {
  582. const sql = `select * from t_questions where parent_id_ in (${tiKu.split(',').map(i => `'${i}'`)}) and zhuang_tai_ = '启用' order by field(ti_xing_, '单选题', '多选题', '判断题', '填空题', '简答题')`
  583. allRequests.push(this.$common.request('sql', sql))
  584. }
  585. if (handQuestions) {
  586. let sql = ''
  587. if (tiKu) {
  588. sql = `select * from t_questions where id_ in (${handQuestions.split(',').map(i => `'${i}'`)}) and parent_id_ not in (${tiKu.split(',').map(i => `'${i}'`)}) and zhuang_tai_ = '启用' order by field(ti_xing_, '单选题', '多选题', '判断题', '填空题', '简答题')`
  589. } else {
  590. sql = `select * from t_questions where id_ in (${handQuestions.split(',').map(i => `'${i}'`)}) and zhuang_tai_ = '启用' order by field(ti_xing_, '单选题', '多选题', '判断题', '填空题', '简答题')`
  591. }
  592. allRequests.push(this.$common.request('sql', sql))
  593. }
  594. if (allRequests.length) {
  595. Promise.all(allRequests).then(res => {
  596. const { data: data1 = [] } = res?.[0]?.variables || {}
  597. const { data: data2 = [] } = res?.[1]?.variables || {}
  598. if (!this.allQuestions.tiKu) {
  599. this.allQuestionsNumber.handQuestionsNumber = data1.length
  600. } else if (!this.allQuestions.handQuestions) {
  601. this.allQuestionsNumber.tiKuNumber = data1.length
  602. } else {
  603. this.allQuestionsNumber.tiKuNumber = data1.length
  604. this.allQuestionsNumber.handQuestionsNumber = data2.length
  605. }
  606. this.curQuestions = [...data1, ...data2]
  607. this.getHandList()
  608. }).catch(err => {
  609. console.error(err)
  610. })
  611. } else {
  612. this.allQuestionsNumber.tiKuNumber = 0
  613. this.allQuestionsNumber.handQuestionsNumber = 0
  614. this.form.sui_ji_chou_ti_ = '0'
  615. this.curQuestions = []
  616. this.getHandList()
  617. }
  618. },
  619. deep: true
  620. }
  621. },
  622. mounted () {
  623. this.getExamData()
  624. },
  625. methods: {
  626. // 分类计算
  627. getHandList () {
  628. const data = this.curQuestions
  629. // 确定每种类型的题目
  630. this.handList.forEach(hand => {
  631. hand.list = data.filter(item => item.ti_xing_ === hand.itemType)
  632. })
  633. // 确定每种难度的题目
  634. this.levelList.forEach(level => {
  635. level.list = data.filter(item => item.nan_du_ === level.itemType)
  636. })
  637. if (this.$utils.isEmpty(this.id)) {
  638. // 设置每种类型题目的默认题数
  639. this.handList.forEach(hand => {
  640. hand.questionNumber = hand.list.length
  641. })
  642. // 设置每种难度题目的默认题数
  643. this.levelList.forEach(level => {
  644. level.questionNumber = level.list.length
  645. })
  646. } else {
  647. if (!this.isFirst) {
  648. this.handList.forEach(hand => {
  649. hand.questionNumber = hand.list.length
  650. })
  651. this.levelList.forEach(level => {
  652. level.questionNumber = level.list.length
  653. })
  654. } else {
  655. // 根据当前的抽题方式给另外一种抽题方式填充默认值
  656. this.isFirst = false
  657. if (this.form.chou_ti_fang_shi_ === '1') {
  658. this.levelList.forEach(level => {
  659. level.questionNumber = level.list.length
  660. })
  661. } else if (this.form.chou_ti_fang_shi_ === '2') {
  662. this.handList.forEach(hand => {
  663. hand.questionNumber = hand.list.length
  664. })
  665. }
  666. }
  667. }
  668. // 设置每种类型题目的步数
  669. this.handList.forEach(hand => {
  670. if (hand.list.length > 0) {
  671. const isSame = hand.list.every(item => item.fen_zhi_ === hand.list[0].fen_zhi_)
  672. hand.step = isSame ? 1 : hand.list.length
  673. }
  674. })
  675. // 设置每种难度题目的步数
  676. this.levelList.forEach(level => {
  677. if (level.list.length > 0) {
  678. const isSame = level.list.every(item => item.fen_zhi_ === level.list[0].fen_zhi_)
  679. level.step = isSame ? 1 : level.list.length
  680. }
  681. })
  682. },
  683. changeLimit (e, type, defaultValue) {
  684. this.form[type] = e === '1' ? defaultValue : '不限'
  685. },
  686. handleActionEvent ({ key }) {
  687. switch (key) {
  688. case 'submit':
  689. this.handleSubmit()
  690. break
  691. case 'cancel':
  692. this.closeDialog()
  693. break
  694. default:
  695. break
  696. }
  697. },
  698. // 获取考试数据
  699. getExamData () {
  700. if (this.$utils.isEmpty(this.id)) {
  701. return
  702. }
  703. if (this.isDisabled) {
  704. this.randButtonDisabled = true
  705. this.$message.info('非未发布状态的考试仅可修改限考时间!')
  706. }
  707. const sql = `select id_, create_by_, ti_ku_id_, guan_lian_id_, kao_shi_ming_chen, kao_shi_lei_xing_, chuang_jian_shi_j, fa_bu_shi_jian_, fa_bu_ren_, xian_kao_shi_jian, xian_kao_ci_shu_, kao_shi_shi_chang, can_kao_ren_yuan_, zhuang_tai_, da_biao_zhan_bi_, ji_fen_fang_shi_, kao_shi_miao_shu_, yun_xu_bao_ming_, sui_ji_chou_ti_, sui_ji_ti_shu_,chou_ti_zong_fen_,ti_mu_zong_shu_,chou_ti_fang_shi_,ping_fen_ren_ from t_exams where id_ = '${this.id}'`
  708. this.$common.request('sql', sql).then((res) => {
  709. const { data = [] } = res.variables || {}
  710. if (!data.length) {
  711. this.$message.error('数据不存在')
  712. return
  713. }
  714. data[0].isCountLimit = data[0].xian_kao_ci_shu_ === '不限' ? '0' : '1'
  715. data[0].isDateLimit = data[0].xian_kao_shi_jian === '不限' ? '0' : '1'
  716. if (data[0].kao_shi_shi_chang === '不限') {
  717. data[0].isTimeLimit = '0'
  718. data[0].hours = null
  719. data[0].minutes = null
  720. } else {
  721. data[0].isTimeLimit = '1'
  722. data[0].hours = Math.floor(data[0].kao_shi_shi_chang / (1000 * 60 * 60))
  723. data[0].minutes = (data[0].kao_shi_shi_chang % (1000 * 60 * 60)) / (60 * 1000)
  724. }
  725. if (data[0].ping_fen_ren_) {
  726. data[0].ping_fen_ren_ = data[0].ping_fen_ren_.split(',') || []
  727. }
  728. this.form = data[0]
  729. if (this.form.sui_ji_chou_ti_ === '1') {
  730. this.form.sui_ji_ti_shu_ = this.form.sui_ji_ti_shu_.split(',')
  731. if (this.form.chou_ti_fang_shi_ === '1') {
  732. this.form.sui_ji_ti_shu_.forEach((item, index) => {
  733. this.handList[index].questionNumber = item
  734. })
  735. } else if (this.form.chou_ti_fang_shi_ === '2') {
  736. this.form.sui_ji_ti_shu_.forEach((item, index) => {
  737. this.levelList[index].questionNumber = item
  738. })
  739. }
  740. }
  741. this.allQuestions.tiKu = this.form.ti_ku_id_
  742. })
  743. },
  744. // 随机题库 弃用
  745. randTiku () {
  746. this.randButtonDisabled = true
  747. const sql = `select id_ from t_question_bank where ti_ku_zhuang_tai_='可用'`
  748. this.$common.request('sql', sql).then((res) => {
  749. const { data = [] } = res.variables || {}
  750. const randNumber = Math.floor(Math.random() * data.length)
  751. this.form.ti_ku_id_ = data[randNumber].id_
  752. this.randButtonDisabled = false
  753. })
  754. },
  755. handleSubmit () {
  756. this.$refs.form.validate(async (valid) => {
  757. if (valid) {
  758. if (this.allQuestionsNumber.tiKuNumber + this.allQuestionsNumber.handQuestionsNumber === 0) {
  759. return this.$message.warning('请先选择题目!')
  760. }
  761. this.form.sui_ji_ti_shu_ = []
  762. this.form.chou_ti_zong_fen_ = 0
  763. this.form.ti_mu_zong_shu_ = 0
  764. if (this.form.sui_ji_chou_ti_ === '1') {
  765. // 计算总分 总数量
  766. if (this.form.chou_ti_fang_shi_ === '1') {
  767. this.handList.forEach(item => {
  768. if (item.list.length > 0) {
  769. this.form.sui_ji_ti_shu_.push(item.questionNumber || 0)
  770. this.form.ti_mu_zong_shu_ += item.questionNumber || 0
  771. this.form.chou_ti_zong_fen_ += item.list.slice(0, item.questionNumber || 0).reduce((pre, cur) => {
  772. return pre + +cur.fen_zhi_
  773. }, 0)
  774. } else {
  775. this.form.sui_ji_ti_shu_.push(0)
  776. }
  777. })
  778. } else if (this.form.chou_ti_fang_shi_ === '2') {
  779. this.levelList.forEach(item => {
  780. if (item.list.length > 0) {
  781. this.form.sui_ji_ti_shu_.push(item.questionNumber || 0)
  782. this.form.ti_mu_zong_shu_ += item.questionNumber || 0
  783. this.form.chou_ti_zong_fen_ += item.list.slice(0, item.questionNumber || 0).reduce((pre, cur) => {
  784. return pre + +cur.fen_zhi_
  785. }, 0)
  786. } else {
  787. this.form.sui_ji_ti_shu_.push(0)
  788. }
  789. })
  790. }
  791. if (this.form.ti_mu_zong_shu_ === 0) {
  792. return this.$message.warning('请填写需要抽取的题目数量!')
  793. }
  794. }
  795. this.form.sui_ji_ti_shu_ = this.form.sui_ji_ti_shu_.join(',')
  796. this.form.ping_fen_ren_ = this.form.ping_fen_ren_ ? this.form.ping_fen_ren_.join(',') : ''
  797. const { isTimeLimit, xian_kao_shi_jian = '' } = this.form || {}
  798. // 转换考试时长
  799. if (isTimeLimit === '0') {
  800. this.form.kao_shi_shi_chang = '不限'
  801. } else {
  802. this.form.kao_shi_shi_chang = (this.form.hours * 60 + this.form.minutes) * 60 * 1000
  803. }
  804. delete this.form.isDateLimit
  805. delete this.form.isCountLimit
  806. delete this.form.isTimeLimit
  807. delete this.form.hours
  808. delete this.form.minutes
  809. this.form.chuang_jian_shi_j = this.$common.getDateNow(19)
  810. this.form.xian_kao_shi_jian = xian_kao_shi_jian !== '不限' ? this.$common.getFormatDate('string', 16, xian_kao_shi_jian) : xian_kao_shi_jian
  811. // 这里表示为组合题 需要生成一个新的题库
  812. if (this.allQuestions.tiKu.indexOf(',') !== -1 || this.allQuestions.handQuestions) {
  813. const tiKuId = await this.createBank()
  814. console.log(tiKuId)
  815. this.form.ti_ku_id_ = tiKuId
  816. } else {
  817. this.form.ti_ku_id_ = this.allQuestions.tiKu
  818. }
  819. // 表单验证通过,提交表单
  820. this.submitForm()
  821. } else {
  822. ActionUtils.saveErrorMessage()
  823. }
  824. })
  825. },
  826. async createBank () {
  827. // 1. 新建题库
  828. const addParams = {
  829. tableName: 't_question_bank',
  830. paramWhere: [{
  831. ti_ku_ming_cheng_: '组合题库' + dayjs().format('YYYYMMDDHHmmss'),
  832. shi_fou_gong_kai_: '是',
  833. bian_zhi_ren_: this.userId,
  834. bian_zhi_shi_jian: this.$common.getDateNow(19),
  835. ti_ku_fen_lei_: '专业组考试',
  836. suo_shu_fan_wei_: '科级',
  837. ti_ku_zhuang_tai_: '可用',
  838. xian_kao_ci_shu_: this.form.xian_kao_ci_shu_,
  839. da_biao_zhan_bi_: this.form.da_biao_zhan_bi_,
  840. miao_shu_: this.form.kao_shi_miao_shu_,
  841. ping_fen_ren_: '',
  842. di_dian_: this.level,
  843. bian_zhi_bu_men_: '',
  844. kao_shi_shi_chang: this.form.kao_shi_shi_chang,
  845. ti_shu_: this.curQuestions.length,
  846. zong_fen_: this.curQuestions.reduce((sum, item) => sum + parseInt(item.fen_zhi_), 0)
  847. }]
  848. }
  849. const { variables: { cont }} = await this.$common.request('add', addParams)
  850. if (cont.length > 0) {
  851. const addParams = {
  852. tableName: 't_questions',
  853. paramWhere: this.curQuestions.map(item => ({
  854. di_dian_: this.level,
  855. parent_id_: cont[0].id_,
  856. bu_men_: item.bu_men_ || '',
  857. chu_ti_ren_: item.chu_ti_ren_,
  858. chu_ti_shi_jian_: item.chu_ti_shi_jian_,
  859. xu_hao_: item.xu_hao_ || '',
  860. ti_gan_: item.ti_gan_,
  861. ti_xing_: item.ti_xing_,
  862. fu_tu_: item.fu_tu_ || '',
  863. xuan_xiang_lei_xi: item.xuan_xiang_lei_xi || '',
  864. da_an_: item.da_an_ || '',
  865. fen_zhi_: item.fen_zhi_,
  866. xuan_xiang_shu_: item.xuan_xiang_shu_ || '',
  867. zheng_que_da_an_: item.zheng_que_da_an_,
  868. ping_fen_fang_shi: item.ping_fen_fang_shi || '',
  869. ping_fen_ren_: item.ping_fen_ren_ || '',
  870. bei_zhu_: item.bei_zhu_ || '',
  871. zhuang_tai_: item.zhuang_tai_,
  872. biao_qian_: item.biao_qian_ || '',
  873. nan_du_: item.nan_du_ || 0,
  874. da_an_jie_xi_: item.da_an_jie_xi_ || ''
  875. }))
  876. }
  877. await this.$common.request('add', addParams)
  878. return cont[0].id_
  879. }
  880. // 2.新建题目
  881. },
  882. submitForm () {
  883. const addParams = {
  884. tableName: 't_exams',
  885. paramWhere: [this.form]
  886. }
  887. const updateParams = {
  888. tableName: 't_exams',
  889. updList: [
  890. {
  891. where: {
  892. id_: this.id
  893. },
  894. param: this.form
  895. }
  896. ]
  897. }
  898. const type = this.id ? 'update' : 'add'
  899. const params = type === 'add' ? addParams : updateParams
  900. this.$common.request(type, params).then(() => {
  901. this.$message.success(this.id ? '修改考试成功' : '新建考试成功')
  902. this.closeDialog(true)
  903. })
  904. },
  905. // 关闭当前窗口
  906. closeDialog (refresh) {
  907. this.$emit('close', false, refresh)
  908. }
  909. }
  910. }
  911. </script>
  912. <style lang="scss" scoped>
  913. .exam-dialog {
  914. ::v-deep {
  915. .el-dialog {
  916. max-width: 1080px;
  917. }
  918. .el-dialog__body {
  919. height: calc(88vh - 150px);
  920. }
  921. .el-form-item {
  922. margin-bottom: 14px !important;
  923. &:last-child {
  924. margin-bottom: 0 !important;
  925. }
  926. .el-form-item__label {
  927. font-size: 14px !important;
  928. }
  929. }
  930. .el-form-item--small .el-form-item__error {
  931. padding-top: 6px;
  932. }
  933. }
  934. .exam-form {
  935. padding: 20px;
  936. .question-icon {
  937. font-size: 13px;
  938. color: #606060;
  939. }
  940. .date-picker {
  941. margin-left: 20px;
  942. }
  943. .custom-dialog {
  944. ::v-deep {
  945. .el-input--prefix .el-input__inner {
  946. padding-left: 15px;
  947. }
  948. }
  949. }
  950. }
  951. .inline-item {
  952. ::v-deep {
  953. .el-radio-group {
  954. margin-right: 20px;
  955. }
  956. }
  957. .time {
  958. display: inline-block;
  959. }
  960. }
  961. .unit {
  962. display: inline-block;
  963. margin: 0 20px 0 5px;
  964. }
  965. .handrand{
  966. ::v-deep .el-form-item__content{
  967. display: flex;
  968. flex-wrap: wrap;
  969. }
  970. .hand-item{
  971. display: flex;
  972. margin-right: 20px;
  973. margin-bottom: 10px;
  974. }
  975. }
  976. }
  977. .tiku {
  978. .el-button {
  979. margin-left: 20px;
  980. }
  981. .item{
  982. display: flex;
  983. gap: 20px;
  984. .number{
  985. width: 100px;
  986. }
  987. }
  988. }
  989. </style>