examManualVolumeFormation.vue 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285
  1. <template>
  2. <div class="app-container">
  3. <a-spin :spinning="loading">
  4. <!-- 基础信息 -->
  5. <div class="common-card basic-information-box">
  6. <div class="basic-information-title">基本信息</div>
  7. <a-form
  8. :form="loginForm"
  9. @submit="handleSubmitFun"
  10. style="width: 515px;"
  11. :loading="loading"
  12. >
  13. <a-form-item
  14. label="考试名称"
  15. :label-col="labelCol"
  16. :wrapper-col="wrapperCol"
  17. >
  18. <a-input
  19. placeholder="请输入考试标题"
  20. :maxLength="100"
  21. v-decorator="[
  22. 'name',
  23. {
  24. initialValue: examDetailData.name,
  25. rules: [{ required: true, message: '请输入考试名称!' }],
  26. },
  27. ]"
  28. />
  29. </a-form-item>
  30. <a-form-item
  31. label="考试时间"
  32. :label-col="labelCol"
  33. :wrapper-col="wrapperCol"
  34. >
  35. <!-- <ExamDateTime
  36. v-decorator="[
  37. 'examDateTime',
  38. {
  39. initialValue: { dateTime: examDateTime },
  40. rules: [
  41. {
  42. required: true,
  43. validator: checkExamDateTime,
  44. },
  45. ],
  46. },
  47. ]"
  48. />-->
  49. <a-date-picker
  50. showTime
  51. placeholder="请选择日期 + 时间"
  52. @change="onDateChange"
  53. v-decorator="[
  54. 'examDateTime',
  55. {
  56. initialValue: examDetailData.startTime,
  57. rules: [
  58. { required: true, message: '请选择考试日期 + 时间!' },
  59. ],
  60. },
  61. ]"
  62. style="width:100%;"
  63. />
  64. </a-form-item>
  65. <a-form-item
  66. label="考试时长"
  67. :label-col="labelCol"
  68. :wrapper-col="wrapperCol"
  69. >
  70. <ExamTimeLong
  71. v-decorator="[
  72. 'examTimeLong',
  73. {
  74. initialValue: {
  75. hours: examDetailData.examLongTimeHours,
  76. minutes: examDetailData.examLongTimeMinutes,
  77. },
  78. rules: [
  79. {
  80. required: true,
  81. validator: checkExamTimeLong,
  82. },
  83. ],
  84. },
  85. ]"
  86. />
  87. </a-form-item>
  88. <a-form-item
  89. label="考试描述"
  90. :label-col="labelCol"
  91. :wrapper-col="wrapperCol"
  92. >
  93. <a-textarea
  94. placeholder="请输入考试描述"
  95. :auto-size="{ minRows: 3, maxRows: 5 }"
  96. :maxLength="200"
  97. v-decorator="[
  98. 'content',
  99. {
  100. initialValue: examDetailData.description,
  101. rules: [
  102. {
  103. required: true,
  104. message: '请输入考试描述!',
  105. },
  106. ],
  107. },
  108. ]"
  109. />
  110. </a-form-item>
  111. <a-form-item
  112. label="考试类别"
  113. :label-col="labelCol"
  114. :wrapper-col="wrapperCol"
  115. >
  116. <a-select
  117. v-decorator="[
  118. 'examTypeChooseValue',
  119. {
  120. rules: [{ required: true, message: '请选择考试类别!' }],
  121. initialValue: examDetailData.examCategory,
  122. },
  123. ]"
  124. >
  125. <a-select-option
  126. :value="item.code"
  127. v-for="(item, index) in examTypeList"
  128. :key="index"
  129. >{{ item.name }}</a-select-option
  130. >
  131. </a-select>
  132. </a-form-item>
  133. <a-form-item
  134. label="工种类别"
  135. :label-col="labelCol"
  136. :wrapper-col="wrapperCol"
  137. >
  138. <a-select
  139. v-decorator="[
  140. 'engineeringWorkChooseValue',
  141. {
  142. rules: [
  143. {
  144. required: true,
  145. message: '请选择工种类别!',
  146. },
  147. ],
  148. initialValue: examDetailData.engineeringWork,
  149. },
  150. ]"
  151. >
  152. <a-select-option
  153. :value="item.id"
  154. v-for="(item, index) in engineeringWorkList"
  155. :key="index"
  156. >{{ item.name }}</a-select-option
  157. >
  158. </a-select>
  159. </a-form-item>
  160. <a-form-item v-show="false">
  161. <a-button
  162. id="examManualVolumeFormationSubmit"
  163. type="primary"
  164. html-type="submit"
  165. >提交</a-button
  166. >
  167. </a-form-item>
  168. </a-form>
  169. <div></div>
  170. </div>
  171. <!-- 当前试题列表 -->
  172. <div class="common-card a-card-margin-top">
  173. <div class="flex-between">
  174. <div class="current-table-title">当前试题</div>
  175. <div class="current-table-title">
  176. 总分:{{ current_tableGradesCount }}
  177. </div>
  178. </div>
  179. <!-- 清空、批量删除 -->
  180. <div class="exam-question-edit-row a-card-margin-top">
  181. <a-button
  182. type="primary"
  183. :disabled="!currentHasSelected"
  184. @click="clearCurrentTableSelectDataFun"
  185. >清空所选</a-button
  186. >
  187. <span
  188. v-if="currentHasSelected"
  189. class="exam-question-edit-checkedtxt"
  190. >{{ `已选择 ${current_selectedRowKeys.length} 项` }}</span
  191. >
  192. <a-button
  193. class="exam-question-edit-delete"
  194. type="primary"
  195. :disabled="!currentHasSelected"
  196. @click="deleteCurrentTableSelectDataFun"
  197. >批量删除</a-button
  198. >
  199. </div>
  200. <!-- 表单 -->
  201. <a-table
  202. :columns="current_columns"
  203. :data-source="current_tableData"
  204. :row-key="(record) => record.id"
  205. :row-selection="{
  206. selectedRowKeys: current_selectedRowKeys,
  207. onChange: onCurrentTableSelectChange,
  208. }"
  209. :loading="loading"
  210. :pagination="current_pagination"
  211. @change="handleCurrentTableChangePage"
  212. >
  213. <template slot="grade" slot-scope="text, record">
  214. <a-input
  215. :value="record.grade"
  216. type="number"
  217. placeholder="输入分值"
  218. :maxLength="3"
  219. @change="
  220. (e) => {
  221. handleCurrentGradeChange(e, record);
  222. }
  223. "
  224. />
  225. </template>
  226. <template slot="action" slot-scope="text, record">
  227. <a @click="toQuestionDetailFun(record)">详情</a>
  228. <a-divider type="vertical" />
  229. <a @click="deleteCurrentTableQuestionFun(record)">删除</a>
  230. </template>
  231. </a-table>
  232. <!-- 分页 -->
  233. <!-- <div class="a-pagination-display">
  234. <a-pagination
  235. v-model="current_pagination.current"
  236. :pageSize="current_pagination.pageSize"
  237. :total.sync="current_pagination.total"
  238. show-less-items
  239. show-quick-jumper
  240. @change="getCurrentQusetionsListFun"
  241. />
  242. </div> -->
  243. </div>
  244. <!-- 题库试题列表 -->
  245. <div class="common-card a-card-margin-top">
  246. <!-- 过滤条件栏目 -->
  247. <div>
  248. <div class="filter-condition-box">
  249. <span>所属类别:</span>
  250. <ul>
  251. <li
  252. :class="{
  253. checkedExamQuestionType:
  254. bank_checkedQuestionType === item.code,
  255. }"
  256. v-for="(item, index) in bank_questionType"
  257. :key="index"
  258. @click="handleExamQuestionTypeFun(item)"
  259. >
  260. {{ item.name }}
  261. </li>
  262. </ul>
  263. </div>
  264. <div class="filter-condition-box a-card-margin-top flexCenter">
  265. <span>所属类型:</span>
  266. <div class="create-select-row">
  267. <div class="create-select-item">
  268. <span>父类</span>
  269. <a-select
  270. v-model="bank_checkedQuestionTypeConditionParent"
  271. @change="selectTypeConditionParent"
  272. >
  273. <a-select-option
  274. v-for="(item, index) in bank_questionTypeConditionParent"
  275. :key="index"
  276. :value="item.id"
  277. >
  278. {{ item.name }}
  279. </a-select-option>
  280. </a-select>
  281. </div>
  282. <div class="create-select-item">
  283. <span>子类</span>
  284. <a-select
  285. v-model="bank_checkedQuestionTypeConditionChildren"
  286. :disabled="!bank_checkedQuestionTypeConditionParent"
  287. @change="selectTypeConditionChildren"
  288. >
  289. <a-select-option
  290. v-for="(item, index) in bank_questionTypeConditionChildren"
  291. :key="index"
  292. :value="item.id"
  293. >
  294. {{ item.name }}
  295. </a-select-option>
  296. </a-select>
  297. </div>
  298. </div>
  299. </div>
  300. <div class="border-line"></div>
  301. <div class="filter-other-box">
  302. <span class="filter-other-title">其它选项:</span>
  303. <span class="filter-other-item-title">工种:</span>
  304. <a-select
  305. v-model="bank_engineeringWorkChooseValue"
  306. @change="handleChangeEngineeringWorkValue"
  307. >
  308. <a-select-option
  309. v-for="(item, index) in bank_engineeringWorkList"
  310. :key="index"
  311. :value="item.id"
  312. >{{ item.name }}</a-select-option
  313. >
  314. </a-select>
  315. </div>
  316. </div>
  317. <!-- 表单 -->
  318. <div class="a-card-margin-top">
  319. <!-- 清空、批量添加 -->
  320. <div class="exam-question-edit-row">
  321. <a-button
  322. type="primary"
  323. :disabled="!bankHasSelected"
  324. @click="clearBankTableSelect"
  325. >清空所选</a-button
  326. >
  327. <span
  328. v-if="bankHasSelected"
  329. class="exam-question-edit-checkedtxt"
  330. >{{ `已选择 ${bank_selectedRowKeys.length} 项` }}</span
  331. >
  332. <a-button
  333. class="exam-question-edit-delete"
  334. type="primary"
  335. :disabled="!bankHasSelected"
  336. @click="bankTableAddSelectData"
  337. >批量添加</a-button
  338. >
  339. </div>
  340. <!-- 表单 -->
  341. <a-table
  342. :columns="bank_columns"
  343. :data-source="bank_tableData"
  344. :row-key="(record) => record.id"
  345. :row-selection="{
  346. selectedRowKeys: bank_selectedRowKeys,
  347. onChange: onBankTableSelectChange,
  348. getCheckboxProps: (record) => ({
  349. props: {
  350. disabled: record.disabled,
  351. },
  352. }),
  353. }"
  354. :loading="loading"
  355. :pagination="false"
  356. >
  357. <template slot="action" slot-scope="text, record">
  358. <a @click="toQuestionDetailFun(record)">详情</a>
  359. <a-divider type="vertical" />
  360. <a
  361. :class="{ disabledBtn: record.disabled }"
  362. @click="bankTableAddQuestion(record)"
  363. >添加</a
  364. >
  365. </template>
  366. </a-table>
  367. <!-- 分页 -->
  368. <div class="a-pagination-display">
  369. <a-pagination
  370. v-model="bank_pagination.current"
  371. :pageSize="bank_pagination.pageSize"
  372. :total.sync="bank_pagination.total"
  373. show-less-items
  374. show-quick-jumper
  375. @change="getBankQusetionsListFun"
  376. />
  377. </div>
  378. </div>
  379. <div class="submit-row">
  380. <a-button type="primary" @click="handleSubmitBtnFun">组卷</a-button>
  381. </div>
  382. </div>
  383. </a-spin>
  384. <div class="company-info">
  385. <span>
  386. copyright © 浮游科技有限公司出品
  387. </span>
  388. </div>
  389. </div>
  390. </template>
  391. <script>
  392. import { EXAM_TYPE, EXAM_QUESTION_TYPE } from '@/common/Constant';
  393. import {
  394. formateSeconds,
  395. formateUrlParams,
  396. formatePathParams,
  397. formateDateTimeToAfter,
  398. formatTimeHoursMinuteSecondsFun,
  399. } from '@/filters';
  400. import { mapGetters } from 'vuex';
  401. // const ExamDateTime = {
  402. // props: ['value'],
  403. // template: `
  404. // <span>
  405. // <a-date-picker
  406. // placeholder="请选择日期"
  407. // showTime
  408. // @change="handleDateChange"
  409. // style="width:100%;"
  410. // />
  411. // </span>
  412. // `,
  413. // data() {
  414. // const value = this.value || {};
  415. // return {
  416. // dateTime: value.dateTime || null,
  417. // };
  418. // },
  419. // methods: {
  420. // handleDateChange(dates, datesString) {
  421. // if (dates) {
  422. // this.dateTime = datesString;
  423. // } else {
  424. // this.dateTime = null;
  425. // }
  426. // this.triggerChange({ dateTime: this.dateTime });
  427. // },
  428. // triggerChange(changedValue) {
  429. // // Should provide an event to pass value to Form.
  430. // this.$emit('change', Object.assign({}, this.$data, changedValue));
  431. // },
  432. // },
  433. // };
  434. const ExamTimeLong = {
  435. props: ['value'],
  436. template: `
  437. <span>
  438. <a-input
  439. type='number'
  440. :value="hours"
  441. :maxLength="2"
  442. @change="handleNumberChange"
  443. style="width: 35%; margin-right: 2%;"
  444. />
  445. <span style="margin-right: 2%;">小时</span>
  446. <a-input
  447. type='number'
  448. :value="minutes"
  449. :maxLength="2"
  450. @change="handleCurrencyChange"
  451. style="width: 35%; margin-right: 2%;"
  452. />
  453. <span>分钟</span>
  454. </span>
  455. `,
  456. data() {
  457. const value = this.value || {};
  458. return {
  459. hours: value.hours || '',
  460. minutes: value.minutes || '',
  461. };
  462. },
  463. watch: {
  464. value(val = {}) {
  465. this.hours = val.hours || '';
  466. this.minutes = val.minutes || '';
  467. },
  468. },
  469. methods: {
  470. handleNumberChange(e) {
  471. const hours = parseInt(e.target.value);
  472. if (isNaN(hours)) {
  473. return;
  474. }
  475. this.triggerChange({ hours });
  476. },
  477. handleCurrencyChange(e) {
  478. const minutes = parseInt(e.target.value);
  479. if (isNaN(minutes)) {
  480. return;
  481. }
  482. this.triggerChange({ minutes });
  483. },
  484. triggerChange(changedValue) {
  485. // Should provide an event to pass value to Form.
  486. this.$emit('change', Object.assign({}, this.$data, changedValue));
  487. },
  488. },
  489. };
  490. export default {
  491. name: 'examManualVolumeFormation',
  492. props: {},
  493. components: {
  494. ExamTimeLong,
  495. // ExamDateTime,
  496. },
  497. data() {
  498. return {
  499. loading: false, // 是否展示加载动画
  500. // 基础信息的表单
  501. labelCol: { span: 6 }, // 表单行中label的占位
  502. wrapperCol: { span: 18 }, // 表单行中内容的占位
  503. loginForm: this.$form.createForm(this, {
  504. name: 'examManualVolumeFormation',
  505. }),
  506. engineeringWorkList: [], // 工种数据列表
  507. examTypeList: [], // 考试类型列表
  508. examDateTime: '', // 考试时间
  509. examDetailData: {
  510. id: '',
  511. name: '', // 考试名称
  512. startTime: '', // 考试开始日期时间
  513. examLongTimeHours: '', // 考试时长:小时
  514. examLongTimeMinutes: '', // 考试时长:分钟
  515. description: '', // 考试描述
  516. examCategory: '', // 考试类型
  517. engineeringWork: '', // 工种类别
  518. }, // 考试详情
  519. // 当前试题列表
  520. current_columns: [], // form表单的列参数
  521. current_tableData: [], // 表单数据
  522. current_pagination: {
  523. pageSize: 7,
  524. current: 1,
  525. total: 0,
  526. }, // 分页参数
  527. current_selectedRowKeys: [], // 多选的结果
  528. // 题库列表
  529. bank_questionType: [], // 试题类别列表
  530. bank_checkedQuestionType: '', // 所选试题类别
  531. bank_questionTypeConditionParent: [], // 试题类型列表-父类
  532. bank_checkedQuestionTypeConditionParent: '', // 所选试题类型-父类
  533. bank_questionTypeConditionChildren: [], // 试题类型列表-子类
  534. bank_checkedQuestionTypeConditionChildren: '', // 所选试题类型-子类
  535. bank_engineeringWorkList: [], // 工种数据列表
  536. bank_engineeringWorkChooseValue: '', // 所选工种
  537. bank_columns: [], // form表单的列参数
  538. bank_tableData: [], // 表单数据
  539. bank_pagination: {
  540. pageSize: 7,
  541. current: 1,
  542. total: 0,
  543. }, // 分页参数
  544. bank_selectedRowKeys: [], // 多选的结果
  545. disabledIdArr: [], // 当前试题中已有的试题ID(即题库列表中不可选取的行数据Id)
  546. };
  547. },
  548. created() {
  549. this.initDataFun(); //初始化数据
  550. },
  551. mounted() {},
  552. beforeDestroy() {},
  553. watch: {},
  554. computed: {
  555. ...mapGetters([
  556. 'GET_ENGINEERING_WORK_LIST',
  557. 'GET_EXAM_QUESTION_TYPE_CONDITION_PARENT',
  558. ]),
  559. // 判断 当前试题 列表中是否有行被选择
  560. currentHasSelected() {
  561. return this.current_selectedRowKeys.length > 0;
  562. },
  563. // 判断 题库试题 列表中是否有行被选择
  564. bankHasSelected() {
  565. return this.bank_selectedRowKeys.length > 0;
  566. },
  567. // 计算:当前题目列表的总分
  568. current_tableGradesCount() {
  569. let that = this;
  570. let totalGrades = 0;
  571. that.current_tableData.forEach((item) => {
  572. if (item.grade) {
  573. totalGrades = totalGrades + item.grade;
  574. }
  575. });
  576. return totalGrades;
  577. },
  578. },
  579. methods: {
  580. //初始化数据
  581. initDataFun() {
  582. // 考试类型
  583. this.examTypeList = [...EXAM_TYPE];
  584. this.examDetailData.examCategory = this.examTypeList[0].code;
  585. // 工种类别
  586. this.engineeringWorkList = this.GET_ENGINEERING_WORK_LIST;
  587. this.examDetailData.engineeringWork = this.engineeringWorkList[0].id;
  588. this.initCurrentTableFun(); // 初始化当前试题列表相关数据
  589. this.initBankTableFun(); // 初始化题库试题列表相关数据
  590. },
  591. // #region 当前试题列表
  592. // 初始化当前试题列表
  593. initCurrentTableFun() {
  594. // 表单的列的配置参数
  595. this.current_columns = [
  596. {
  597. title: '试题编号',
  598. dataIndex: 'id',
  599. key: 'id',
  600. width: 240,
  601. },
  602. {
  603. title: '试题',
  604. dataIndex: 'content',
  605. key: 'content',
  606. },
  607. {
  608. title: '试题类别',
  609. dataIndex: 'typeTxt',
  610. key: 'typeTxt',
  611. scopedSlots: { customRender: 'typeTxt' },
  612. width: 100,
  613. },
  614. {
  615. title: '试题父类',
  616. dataIndex: 'parentId',
  617. key: 'parentId',
  618. scopedSlots: { customRender: 'parentId' },
  619. width: 150,
  620. },
  621. {
  622. title: '试题子类',
  623. dataIndex: 'categoryid',
  624. key: 'categoryid',
  625. scopedSlots: { customRender: 'categoryid' },
  626. width: 150,
  627. },
  628. {
  629. title: '工种',
  630. dataIndex: 'engineerTypeTxt',
  631. key: 'engineerTypeTxt',
  632. scopedSlots: { customRender: 'engineerTypeTxt' },
  633. width: 100,
  634. },
  635. {
  636. title: '分值',
  637. dataIndex: 'grade',
  638. key: 'grade',
  639. scopedSlots: { customRender: 'grade' },
  640. width: 150,
  641. },
  642. {
  643. title: '操作',
  644. dataIndex: 'action',
  645. key: 'action',
  646. scopedSlots: { customRender: 'action' },
  647. width: 150,
  648. },
  649. ];
  650. // // 参数存在即编辑
  651. // if (this.$route.query.id) {
  652. // this.getExamDetailFun(this.$route.query.id);
  653. // this.getCurrentQusetionsListFun(
  654. // this.$route.query.id,
  655. // this.$route.query.questionNum
  656. // ); // 查询:当前试题列表数据
  657. // }
  658. },
  659. // 查询:考试详情
  660. getExamDetailFun(examId) {
  661. this.loading = true;
  662. let params = {
  663. examId: examId,
  664. };
  665. this.$_http
  666. .get(formatePathParams(this.$_API.INTERFACE_GET_EXAM_DETAIL, params))
  667. .then((res) => {
  668. let resData = res.data;
  669. // 考试时长
  670. let tarTime = formatTimeHoursMinuteSecondsFun(resData.duration);
  671. // 工种
  672. if (
  673. resData.engineerTypes &&
  674. resData.engineerTypes[0] &&
  675. resData.engineerTypes[0].id
  676. ) {
  677. resData.engineeringWork = resData.engineerTypes[0].id;
  678. } else {
  679. resData.engineerTypeTxt = '不限';
  680. }
  681. this.examDetailData = {
  682. id: resData.id || '',
  683. name: resData.name || '', // 考试名称
  684. startTime: resData.startTime || '', // 考试开始日期时间
  685. examLongTimeHours: tarTime.hours || '', // 考试时长:小时
  686. examLongTimeMinutes: tarTime.minutes || '', // 考试时长:分钟
  687. description: resData.description || '', // 考试描述
  688. examCategory:
  689. resData.examCategory || this.engineeringWorkList[0].id, // 考试类型
  690. engineeringWork:
  691. resData.engineeringWork || this.examTypeList[0].code, // 工种类别
  692. };
  693. this.loading = false;
  694. })
  695. .catch(() => {
  696. this.loading = false;
  697. });
  698. },
  699. // 查询:试题列表数据
  700. getCurrentQusetionsListFun(id, questionNum) {
  701. if (!id || !questionNum) {
  702. this.$message.error('数据异常,请重新进入当前页面');
  703. return;
  704. }
  705. this.loading = true;
  706. let paramsPath = {
  707. examId: id,
  708. };
  709. let params = {
  710. page: 0,
  711. size: questionNum,
  712. };
  713. this.$_http
  714. .get(
  715. formatePathParams(
  716. this.$_API.INTERFACE_GET_EXAM_QUESTIONS_LIST,
  717. paramsPath
  718. ),
  719. { params }
  720. )
  721. .then((res) => {
  722. let resData = res.data.content;
  723. resData.forEach((item) => {
  724. // 试题类别
  725. this.bank_questionType.forEach((it) => {
  726. if (item.type === it.code) {
  727. item.typeTxt = it.name;
  728. }
  729. });
  730. // 工种
  731. if (
  732. item.engineerTypes &&
  733. item.engineerTypes[0] &&
  734. item.engineerTypes[0].id
  735. ) {
  736. item.engineerTypeTxt = item.engineerTypes[0].name;
  737. } else {
  738. item.engineerTypeTxt = '不限';
  739. }
  740. });
  741. this.current_tableData = resData;
  742. this.current_pagination.total = res.data.totalElements; // 总条数
  743. this.loading = false;
  744. })
  745. .catch(() => {
  746. this.loading = false;
  747. });
  748. },
  749. // 切换:表格页码
  750. handleCurrentTableChangePage(pagination) {
  751. const pager = { ...this.current_pagination };
  752. pager.current = pagination.current;
  753. this.current_pagination = pager;
  754. },
  755. // 操作:修改分值
  756. handleCurrentGradeChange(e, record) {
  757. for (let i = 0; i < this.current_tableData.length; i++) {
  758. if (this.current_tableData[i].id === record.id) {
  759. this.$set(this.current_tableData[i], 'grade', Number(e.target.value));
  760. break;
  761. }
  762. }
  763. },
  764. // 操作:删除
  765. deleteCurrentTableQuestionFun(record) {
  766. let that = this;
  767. this.$confirm({
  768. title: '删除',
  769. content: `确认删除编号为 ${record.questionCode} 的试题吗?`,
  770. okText: '确认',
  771. cancelText: '取消',
  772. onOk() {
  773. that.loading = true;
  774. that.removeDataFromCurrentTable([record.id], that);
  775. that.current_selectedRowKeys = that.current_selectedRowKeys.filter(
  776. (id) => {
  777. if (id !== record.id) {
  778. return id;
  779. }
  780. }
  781. );
  782. that.loading = false;
  783. },
  784. onCancel() {},
  785. });
  786. },
  787. // 操作:清空选择
  788. clearCurrentTableSelectDataFun() {
  789. this.current_selectedRowKeys = [];
  790. },
  791. // 操作:多选变化时
  792. onCurrentTableSelectChange(selectedRowKeys) {
  793. this.current_selectedRowKeys = selectedRowKeys;
  794. },
  795. // 操作:批量删除
  796. deleteCurrentTableSelectDataFun() {
  797. let that = this;
  798. this.$confirm({
  799. title: '批量删除',
  800. content: `确认批量删除吗?`,
  801. okText: '确认',
  802. cancelText: '取消',
  803. onOk() {
  804. that.loading = true;
  805. that.removeDataFromCurrentTable(that.current_selectedRowKeys, that);
  806. // 置空选择结果
  807. that.current_selectedRowKeys = [];
  808. that.loading = false;
  809. },
  810. onCancel() {},
  811. });
  812. },
  813. // 移除当前试题列表中要删除的数据
  814. removeDataFromCurrentTable(ids = [], that) {
  815. // 移出当前试题
  816. that.current_tableData = that.current_tableData.filter((currentItem) => {
  817. if (!ids.includes(currentItem.id)) {
  818. return currentItem;
  819. }
  820. });
  821. // 禁用状态去除
  822. that.bank_tableData.forEach((banItem) => {
  823. if (ids.includes(banItem.id)) {
  824. banItem.disabled = false;
  825. }
  826. });
  827. that.bank_tableData = [...that.bank_tableData];
  828. },
  829. // #endregion
  830. //#region 题库试题列表
  831. initBankTableFun() {
  832. // 试题类别
  833. this.bank_questionType = [
  834. { name: '全部', code: '' },
  835. ...EXAM_QUESTION_TYPE,
  836. ];
  837. // 试题类型
  838. this.bank_questionTypeConditionParent = [
  839. { name: '全部', id: '' },
  840. ...this.GET_EXAM_QUESTION_TYPE_CONDITION_PARENT,
  841. ];
  842. // 工种类别
  843. this.bank_engineeringWorkList = [
  844. { name: '全部', id: '' },
  845. ...this.GET_ENGINEERING_WORK_LIST,
  846. ];
  847. // 表单的列的配置参数
  848. this.bank_columns = [
  849. {
  850. title: '试题编号',
  851. dataIndex: 'id',
  852. key: 'id',
  853. width: 240,
  854. },
  855. {
  856. title: '试题',
  857. dataIndex: 'content',
  858. key: 'content',
  859. },
  860. {
  861. title: '试题类别',
  862. dataIndex: 'typeTxt',
  863. key: 'typeTxt',
  864. scopedSlots: { customRender: 'typeTxt' },
  865. width: 100,
  866. },
  867. {
  868. title: '试题父类',
  869. dataIndex: 'parentId',
  870. key: 'parentId',
  871. scopedSlots: { customRender: 'parentId' },
  872. width: 150,
  873. },
  874. {
  875. title: '试题子类',
  876. dataIndex: 'categoryid',
  877. key: 'categoryid',
  878. scopedSlots: { customRender: 'categoryid' },
  879. width: 150,
  880. },
  881. {
  882. title: '工种',
  883. dataIndex: 'engineerTypeTxt',
  884. key: 'engineerTypeTxt',
  885. scopedSlots: { customRender: 'engineerTypeTxt' },
  886. width: 100,
  887. },
  888. {
  889. title: '操作',
  890. dataIndex: 'action',
  891. key: 'action',
  892. scopedSlots: { customRender: 'action' },
  893. width: 150,
  894. },
  895. ];
  896. this.getBankQusetionsListFun(); // 查询:试题列表数据
  897. },
  898. // 查询:试题列表数据
  899. getBankQusetionsListFun() {
  900. this.loading = true;
  901. let params = {
  902. page: this.bank_pagination.current - 1,
  903. size: this.bank_pagination.pageSize,
  904. type: this.bank_checkedQuestionType,
  905. categoryid: this.bank_checkedQuestionTypeConditionChildren,
  906. engineertypeid: this.bank_engineeringWorkChooseValue,
  907. };
  908. this.$_http
  909. .get(this.$_API.INTERFACE_GET_EXAMS_QUESTION_LIST, { params })
  910. .then((res) => {
  911. let resData = res.data.content;
  912. resData.forEach((item) => {
  913. // 试题类别---注意之后从engineertypes中拿
  914. this.bank_questionType.forEach((it) => {
  915. if (item.type === it.code) {
  916. item.typeTxt = it.name;
  917. }
  918. });
  919. // 工种---注意之后从engineertypes中拿
  920. // this.bank_engineeringWorkList.forEach((it) => {
  921. // if (item.engineerTypes === it.id) {
  922. // item.engineerTypeTxt = it.name;
  923. // }
  924. // });
  925. if (
  926. item.engineerTypes &&
  927. item.engineerTypes[0] &&
  928. item.engineerTypes[0].id
  929. ) {
  930. item.engineerTypeTxt = item.engineerTypes[0].name;
  931. } else {
  932. item.engineerTypeTxt = '不限';
  933. }
  934. });
  935. this.bank_pagination.total = res.data.totalElements; // 总条数
  936. this.bank_tableData = [...resData];
  937. if (this.current_tableData.length > 0) {
  938. this.formateBankTableDisabledRowFun(); // 禁用
  939. }
  940. this.loading = false;
  941. })
  942. .catch(() => {
  943. this.loading = false;
  944. });
  945. },
  946. // 初始化分页参数
  947. initPagination() {
  948. this.bank_pagination.current = 1;
  949. this.bank_pagination.pageSize = 7;
  950. this.bank_pagination.total = 0;
  951. },
  952. // 操作:选择某个试题类型
  953. handleExamQuestionTypeFun(item) {
  954. if (this.bank_checkedQuestionType === item.code) {
  955. return;
  956. }
  957. this.bank_checkedQuestionType = item.code;
  958. this.initPagination(); // 初始化分页参数
  959. this.getBankQusetionsListFun(); // 查询:试题列表数据
  960. },
  961. // 操作:选择了某个工种
  962. handleChangeEngineeringWorkValue() {
  963. this.initPagination(); // 初始化分页参数
  964. this.getBankQusetionsListFun(); // 查询:试题列表数据
  965. },
  966. // 操作:选择了父类
  967. selectTypeConditionParent() {
  968. this.getTableChildrenListFun(); // 查询:试题类型列表-子类
  969. },
  970. // 操作:选择了子类
  971. selectTypeConditionChildren() {
  972. this.initPagination(); // 初始化分页参数
  973. this.getBankQusetionsListFun(); // 查询:试题列表数据
  974. },
  975. // 查询:试题类型列表-子类
  976. getTableChildrenListFun() {
  977. if (!this.bank_checkedQuestionTypeConditionParent) {
  978. this.bank_checkedQuestionTypeConditionChildren = '';
  979. this.bank_questionTypeConditionChildren = [];
  980. this.initPagination(); // 初始化分页参数
  981. this.getBankQusetionsListFun(); // 查询:试题列表数据
  982. return;
  983. }
  984. this.loading = true;
  985. let params = {
  986. categoryId: this.bank_checkedQuestionTypeConditionParent,
  987. };
  988. this.$_http
  989. .get(
  990. formatePathParams(
  991. this.$_API.INTERFACE_GET_EXAMS_QUESTION_TYPE_CONDITION_CHILDRENS,
  992. params
  993. )
  994. )
  995. .then((res) => {
  996. this.bank_questionTypeConditionChildren = res.data;
  997. this.bank_checkedQuestionTypeConditionChildren = this.bank_questionTypeConditionChildren[0].id;
  998. this.loading = false;
  999. this.initPagination(); // 初始化分页参数
  1000. this.getBankQusetionsListFun(); // 查询:试题列表数据
  1001. })
  1002. .catch(() => {
  1003. this.loading = false;
  1004. });
  1005. },
  1006. // 操作:添加
  1007. bankTableAddQuestion(record) {
  1008. // 加入当前试题列表
  1009. for (let i = 0; i < this.bank_tableData.length; i++) {
  1010. let bankItem = this.bank_tableData[i];
  1011. if (bankItem.id === record.id) {
  1012. this.current_tableData.push({ ...bankItem });
  1013. break;
  1014. }
  1015. }
  1016. this.current_pagination.total = this.current_tableData.length;
  1017. this.current_pagination.current = 1;
  1018. this.formateBankTableDisabledRowFun(); // 禁用
  1019. this.bank_selectedRowKeys = this.bank_selectedRowKeys.filter((id) => {
  1020. if (id !== record.id) {
  1021. return id;
  1022. }
  1023. });
  1024. },
  1025. // 操作:批量添加
  1026. bankTableAddSelectData() {
  1027. let that = this;
  1028. this.$confirm({
  1029. title: '批量添加',
  1030. content: `确认批量添加吗?`,
  1031. okText: '确认',
  1032. cancelText: '取消',
  1033. onOk() {
  1034. // 加入当前试题列表
  1035. let arr = [];
  1036. that.bank_tableData.forEach((bankItem) => {
  1037. that.bank_selectedRowKeys.forEach((id) => {
  1038. if (bankItem.id === id) {
  1039. arr.push({ ...bankItem });
  1040. }
  1041. });
  1042. });
  1043. that.current_tableData = [
  1044. ...new Set([...that.current_tableData, ...arr]),
  1045. ];
  1046. that.current_pagination.total = that.current_tableData.length;
  1047. that.current_pagination.current = 1;
  1048. that.formateBankTableDisabledRowFun(); // 禁用
  1049. // 清空选项
  1050. that.bank_selectedRowKeys = [];
  1051. },
  1052. onCancel() {},
  1053. });
  1054. },
  1055. // 操作:多选变化时
  1056. onBankTableSelectChange(selectedRowKeys) {
  1057. this.bank_selectedRowKeys = selectedRowKeys;
  1058. },
  1059. // 操作:清空选择
  1060. clearBankTableSelect() {
  1061. // 清空选项
  1062. this.bank_selectedRowKeys = [];
  1063. },
  1064. // 过滤:是否禁止选择
  1065. formateBankTableDisabledRowFun() {
  1066. this.disabledIdArr = this.current_tableData.map((currentItem) => {
  1067. return currentItem.id;
  1068. });
  1069. this.bank_tableData.forEach((bankItem) => {
  1070. if (this.disabledIdArr.includes(bankItem.id)) {
  1071. bankItem.disabled = true;
  1072. } else {
  1073. bankItem.disabled = false;
  1074. }
  1075. return bankItem;
  1076. });
  1077. this.bank_tableData = [...this.bank_tableData];
  1078. },
  1079. // #endregion
  1080. // 操作:详情
  1081. toQuestionDetailFun(record) {
  1082. if (!record || !record.id) {
  1083. this.$message.error('数据异常,请重新进入当前页面');
  1084. return;
  1085. }
  1086. switch (record.type) {
  1087. case EXAM_QUESTION_TYPE[0].code:
  1088. this.$router.push({
  1089. path: '/examQuestionManagement/create/singleChoice',
  1090. query: { id: record.id },
  1091. });
  1092. break;
  1093. case EXAM_QUESTION_TYPE[1].code:
  1094. this.$router.push({
  1095. path: '/examQuestionManagement/create/multipleChoice',
  1096. query: { id: record.id },
  1097. });
  1098. break;
  1099. case EXAM_QUESTION_TYPE[2].code:
  1100. this.$router.push({
  1101. path: '/examQuestionManagement/create/trueOrFalse',
  1102. query: { id: record.id },
  1103. });
  1104. break;
  1105. case EXAM_QUESTION_TYPE[3].code:
  1106. this.$router.push({
  1107. path: '/examQuestionManagement/create/gapFilling',
  1108. query: { id: record.id },
  1109. });
  1110. break;
  1111. default:
  1112. this.$message.error('试题类别异常,无法查看详情');
  1113. break;
  1114. }
  1115. },
  1116. // #region 基础信息变更
  1117. // 操作:选择日期、时间
  1118. onDateChange(date, dateString) {
  1119. if (date) {
  1120. this.examDateTime = dateString;
  1121. } else {
  1122. this.examDateTime = '';
  1123. }
  1124. },
  1125. // // 校验:考试时间
  1126. // checkExamDateTime(rule, value, callback) {
  1127. // if (value.dateTime) {
  1128. // callback();
  1129. // return;
  1130. // }
  1131. // callback('Please select datetime!');
  1132. // },
  1133. // 校验:考试时长
  1134. checkExamTimeLong(rule, value, callback) {
  1135. if (
  1136. value.hours !== '' &&
  1137. value.hours >= 0 &&
  1138. value.minutes !== '' &&
  1139. value.minutes >= 0
  1140. ) {
  1141. callback();
  1142. return;
  1143. }
  1144. callback('请输入时间,至少有一个大于0!');
  1145. },
  1146. // #endregion
  1147. // 操作:点击提交按钮
  1148. handleSubmitBtnFun() {
  1149. document.getElementById('examManualVolumeFormationSubmit').click();
  1150. },
  1151. // 操作:表单提交
  1152. handleSubmitFun(e) {
  1153. e.preventDefault();
  1154. this.loginForm.validateFields((err, values) => {
  1155. if (!err) {
  1156. let engineerTypeInfo = this.formatEngineeringWorkChooseValue(
  1157. values.engineeringWorkChooseValue
  1158. ); // 获取工种信息 typeConditionParentValue
  1159. let urlParams = {
  1160. engineertypeid: values.engineeringWorkChooseValue, // 工种
  1161. };
  1162. let params = {
  1163. name: values.name, // 考试名称
  1164. description: values.content, // 内容
  1165. duration: formateSeconds(
  1166. values.examTimeLong.hours,
  1167. values.examTimeLong.minutes
  1168. ), // 考试持续时间
  1169. startTime: this.examDateTime.replace(' ', 'T'), // 开始日期
  1170. deadline: formateDateTimeToAfter(
  1171. this.examDateTime,
  1172. values.examTimeLong.hours,
  1173. values.examTimeLong.minutes
  1174. ).replace(' ', 'T'), // 结束日期
  1175. tages: [],
  1176. engineerTypes: [engineerTypeInfo], // 信息集合:工种
  1177. examCategory: values.examTypeChooseValue, // 考试类别
  1178. totalPoints: this.current_tableGradesCount, // 总分
  1179. };
  1180. if (this.examDetailData.id) {
  1181. params.id = this.examDetailData.id;
  1182. }
  1183. this.httpQuestFun(urlParams, params);
  1184. }
  1185. });
  1186. },
  1187. // 获取工种信息
  1188. formatEngineeringWorkChooseValue(id) {
  1189. let seleteItem = {};
  1190. for (let i = 0; i < this.engineeringWorkList.length; i++) {
  1191. let item = this.engineeringWorkList[i];
  1192. if (item.id === id) {
  1193. seleteItem = item;
  1194. break;
  1195. }
  1196. }
  1197. return seleteItem;
  1198. },
  1199. // 表单提交请求:基础信息
  1200. httpQuestFun(urlParams, params) {
  1201. this.loading = true;
  1202. this.$_http
  1203. .post(
  1204. formateUrlParams(this.$_API.INTERFACE_POST_EXAM_ADD_INFO, urlParams),
  1205. params
  1206. )
  1207. .then((res) => {
  1208. this.loading = false;
  1209. if (res.data.id) {
  1210. this.httpQuestAddQuestionsFun(res.data.id); // 表单提交请求:题目
  1211. }
  1212. })
  1213. .catch(() => {
  1214. this.loading = false;
  1215. });
  1216. },
  1217. // 表单提交请求:题目
  1218. httpQuestAddQuestionsFun(examId) {
  1219. if (!examId) {
  1220. return;
  1221. }
  1222. this.loading = true;
  1223. let dataArr = [];
  1224. this.current_tableData.forEach((item) => {
  1225. let obj = {
  1226. examId: examId,
  1227. questionId: item.id,
  1228. grade: item.grade,
  1229. };
  1230. dataArr.push(obj);
  1231. });
  1232. this.$_http
  1233. .post(
  1234. formatePathParams(this.$_API.INTERFACE_POST_EXAM_ADD_QUESTIONS, {
  1235. examId,
  1236. }),
  1237. dataArr
  1238. )
  1239. .then(() => {
  1240. this.$message.success('添加考试成功');
  1241. this.loading = false;
  1242. })
  1243. .catch(() => {
  1244. this.loading = false;
  1245. });
  1246. },
  1247. },
  1248. };
  1249. </script>
  1250. <style lang="less"></style>
  1251. <style lang="less" scoped>
  1252. @import '~@/styles/common/variable.less';
  1253. .app-container {
  1254. overflow-y: auto;
  1255. .basic-information-box {
  1256. display: flex;
  1257. justify-content: space-between;
  1258. .basic-information-title {
  1259. font-size: 18px;
  1260. font-weight: bold;
  1261. color: @mainColorBlack65;
  1262. }
  1263. }
  1264. .current-table-title {
  1265. font-size: 18px;
  1266. color: @mainColorBlack65;
  1267. }
  1268. .disabledBtn {
  1269. color: #a6a6a6;
  1270. cursor: no-drop !important;
  1271. }
  1272. .submit-row {
  1273. width: 100%;
  1274. padding: @paddingMarginVal 0 @navTopHight;
  1275. display: flex;
  1276. justify-content: center;
  1277. }
  1278. }
  1279. </style>