ModifyExamConfigDetail.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605
  1. <template>
  2. <el-dialog
  3. class="modify-exam-config-detail"
  4. :visible.sync="modalIsShow"
  5. :title="title"
  6. top="0"
  7. width="800px"
  8. :close-on-click-modal="false"
  9. :close-on-press-escape="false"
  10. append-to-body
  11. @open="visibleChange"
  12. >
  13. <el-form
  14. ref="modalFormComp"
  15. label-width="130px"
  16. :rules="rules"
  17. :model="modalForm"
  18. >
  19. <el-form-item prop="cardRuleId" label="题卡规则:">
  20. <card-rule-select
  21. ref="CardRuleSelect"
  22. v-model.trim="modalForm.cardRuleId"
  23. placeholder="请选择"
  24. clearable
  25. ></card-rule-select>
  26. <div class="tips-info">
  27. <p>说明:</p>
  28. <p>
  29. 1、若选择全部通卡,则命题老师只能选择通卡,若选择题卡规则,则专卡和通卡均可选择
  30. </p>
  31. <p>
  32. 2、若选择题卡规则,命题老师在该考试下自主创建题卡时,版头样式及版头内容为该规则对应样式及版头。
  33. </p>
  34. </div>
  35. </el-form-item>
  36. <div class="part-box">
  37. <h4 class="part-box-tips">
  38. 试卷&题卡印品:
  39. <el-checkbox
  40. v-show="infoShow"
  41. v-model="allSelected"
  42. label="全选"
  43. @change="selectAll"
  44. ></el-checkbox>
  45. </h4>
  46. <el-form-item prop="printContent" label="试卷、题卡:">
  47. <el-checkbox-group
  48. v-model="modalForm.printContent"
  49. @change="() => checkSelectAll()"
  50. >
  51. <el-checkbox
  52. v-for="(val, key) in PRINT_CONTENT_TYPE"
  53. :key="key"
  54. :label="key"
  55. >{{ val }}</el-checkbox
  56. >
  57. </el-checkbox-group>
  58. </el-form-item>
  59. <el-form-item
  60. v-if="modalForm.printContent.length"
  61. prop="backupMethod"
  62. label="备用数量:"
  63. >
  64. <el-select
  65. v-model="modalForm.backupMethod"
  66. class="mr-2"
  67. size="small"
  68. placeholder="请选择"
  69. >
  70. <el-option
  71. v-for="(val, key) in PAPER_BACKUP_TYPE"
  72. :key="key"
  73. :value="key"
  74. :label="val"
  75. ></el-option>
  76. </el-select>
  77. <el-input-number
  78. class="mr-1"
  79. v-model="modalForm.backupCount"
  80. size="small"
  81. :min="0"
  82. :max="200"
  83. :step="1"
  84. step-strictly
  85. :controls="false"
  86. style="width: 60px"
  87. ></el-input-number>
  88. <span>份</span>
  89. </el-form-item>
  90. <el-form-item
  91. v-show="infoShow"
  92. v-if="contentIncludesPaper"
  93. prop="drawRule"
  94. label="抽卷规则:"
  95. >
  96. <el-radio-group v-model="modalForm.drawRule">
  97. <el-radio
  98. v-for="(val, key) in DRAW_RULE_TYPE"
  99. :label="key"
  100. :key="key"
  101. >{{ val }}</el-radio
  102. >
  103. </el-radio-group>
  104. <div class="tips-info">
  105. <p>说明:</p>
  106. <p>
  107. 1.只抽取一次:不同印刷计划下,同一试卷编号下的卷型只能被抽取一次;
  108. </p>
  109. <p>
  110. 2.可反复抽取:不同印刷计划下,同一试卷编号下的卷型可重复抽取,系统默认优先抽取未曝光卷型。
  111. </p>
  112. </div>
  113. </el-form-item>
  114. </div>
  115. <div class="part-box" v-show="infoShow">
  116. <h4 class="part-box-tips">变量印品:</h4>
  117. <el-form-item
  118. v-for="(item, index) in modalForm.variableContent"
  119. :key="item.type"
  120. :label="`${TEMPLATE_CLASSIFY[item.type]}:`"
  121. :prop="`variableContent.${index}.templateId`"
  122. :rules="{
  123. required: false,
  124. validator: templateValidator,
  125. trigger: 'change'
  126. }"
  127. :required="!!item.templateId.length"
  128. >
  129. <el-checkbox-group
  130. v-model="item.templateId"
  131. @change="vals => tempChange(vals, `variableContent.${index}`)"
  132. >
  133. <el-checkbox
  134. v-for="temp in templateSources[item.type]"
  135. :label="temp.id"
  136. :key="temp.id"
  137. >{{ temp.name }}</el-checkbox
  138. >
  139. </el-checkbox-group>
  140. <div v-if="item.templateId.length">
  141. <el-select
  142. v-model="item.backupMethod"
  143. class="mr-2"
  144. size="small"
  145. placeholder="请选择"
  146. >
  147. <el-option
  148. v-for="(val, key) in PRINT_BACKUP_TYPE"
  149. :key="key"
  150. :value="key"
  151. :label="val"
  152. ></el-option>
  153. </el-select>
  154. <el-input-number
  155. v-model="item.backupCount"
  156. class="mr-1"
  157. size="small"
  158. :min="1"
  159. :max="200"
  160. :step="1"
  161. step-strictly
  162. :controls="false"
  163. style="width: 60px"
  164. ></el-input-number>
  165. <span>份</span>
  166. </div>
  167. </el-form-item>
  168. </div>
  169. <div class="part-box" v-show="infoShow">
  170. <h4 class="part-box-tips">普通印品:</h4>
  171. <el-form-item
  172. v-for="(item, index) in modalForm.ordinaryContent"
  173. :key="item.type"
  174. :label="`${TEMPLATE_CLASSIFY[item.type]}:`"
  175. :prop="`ordinaryContent.${index}.templateId`"
  176. :rules="{
  177. required: false,
  178. validator: templateValidator,
  179. trigger: 'change'
  180. }"
  181. :required="!!item.templateId.length"
  182. >
  183. <el-checkbox-group
  184. v-model="item.templateId"
  185. @change="vals => tempChange(vals, `ordinaryContent.${index}`)"
  186. >
  187. <el-checkbox
  188. v-for="temp in templateSources[item.type]"
  189. :label="temp.id"
  190. :key="temp.id"
  191. >{{ temp.name }}</el-checkbox
  192. >
  193. </el-checkbox-group>
  194. <div v-if="item.templateId.length">
  195. <el-select
  196. v-model="item.backupMethod"
  197. class="mr-2"
  198. size="small"
  199. placeholder="请选择"
  200. >
  201. <el-option
  202. v-for="(val, key) in PRINT_BACKUP_TYPE"
  203. :key="key"
  204. :value="key"
  205. :label="val"
  206. ></el-option>
  207. </el-select>
  208. <el-input-number
  209. v-model="item.backupCount"
  210. class="mr-1"
  211. size="small"
  212. :min="1"
  213. :max="200"
  214. :step="1"
  215. step-strictly
  216. :controls="false"
  217. style="width: 60px"
  218. ></el-input-number>
  219. <span>份</span>
  220. </div>
  221. </el-form-item>
  222. </div>
  223. <el-form-item prop="selectedPrint"></el-form-item>
  224. <el-form-item prop="orgIds" label="适用范围:">
  225. <select-orgs v-model="modalForm.orgIds" ref="SelectOrgs"></select-orgs>
  226. </el-form-item>
  227. </el-form>
  228. <div slot="footer">
  229. <el-button type="primary" :disabled="isSubmit" @click="submit"
  230. >确认</el-button
  231. >
  232. <el-button @click="cancel">取消</el-button>
  233. </div>
  234. </el-dialog>
  235. </template>
  236. <script>
  237. import {
  238. PRINT_CONTENT_TYPE,
  239. DRAW_RULE_TYPE,
  240. PRINT_BACKUP_TYPE,
  241. PAPER_BACKUP_TYPE,
  242. TEMPLATE_CLASSIFY
  243. } from "@/constants/enumerate";
  244. import { deepCopy } from "@/plugins/utils";
  245. import { updateExamConfig } from "../api";
  246. import { printPlanTemplateList } from "../../print/api";
  247. import SelectOrgs from "./SelectOrgs";
  248. const initModalForm = {
  249. id: null,
  250. examId: null,
  251. cardRuleId: "",
  252. orgIds: [],
  253. printContent: [],
  254. backupMethod: "ROOM",
  255. backupCount: 1,
  256. drawRule: "ONE",
  257. variableContent: [
  258. {
  259. type: "SIGN",
  260. templateId: [],
  261. oldTemplateId: [],
  262. backupMethod: "ROOM",
  263. backupCount: 1
  264. },
  265. {
  266. type: "PACKAGE",
  267. templateId: [],
  268. oldTemplateId: [],
  269. backupMethod: "ROOM",
  270. backupCount: 1
  271. }
  272. ],
  273. ordinaryContent: [
  274. {
  275. type: "CHECK_IN",
  276. templateId: [],
  277. oldTemplateId: [],
  278. backupMethod: "ROOM",
  279. backupCount: 1
  280. }
  281. ]
  282. };
  283. export default {
  284. name: "modify-exam-config-detail",
  285. components: { SelectOrgs },
  286. props: {
  287. instance: {
  288. type: Object,
  289. default() {
  290. return {};
  291. }
  292. }
  293. },
  294. computed: {
  295. isEdit() {
  296. return !!this.instance.id;
  297. },
  298. title() {
  299. return (this.isEdit ? "编辑" : "新增") + "考试配置";
  300. },
  301. contentIncludesPaper() {
  302. return this.modalForm.printContent.includes("PAPER");
  303. }
  304. },
  305. data() {
  306. const printContentValidator = (rule, value, callback) => {
  307. if (!this.modalForm.printContent.length) {
  308. return callback(new Error("请选择试卷"));
  309. }
  310. callback();
  311. };
  312. const backupMethodValidator = (rule, value, callback) => {
  313. if (!this.modalForm.printContent.length) {
  314. return callback();
  315. }
  316. if (!value) {
  317. return callback(new Error("请选择备份方式"));
  318. }
  319. if (!this.modalForm.backupCount && this.modalForm.backupCount !== 0) {
  320. return callback(new Error("请输入备份数量"));
  321. }
  322. callback();
  323. };
  324. const selectedPrintValidator = (rule, value, callback) => {
  325. const printInfo = [
  326. ...this.modalForm.variableContent,
  327. ...this.modalForm.ordinaryContent
  328. ];
  329. const hasPrintInfo = printInfo.some(item => item.templateId.length);
  330. if (hasPrintInfo || this.modalForm.printContent.length) {
  331. callback();
  332. } else {
  333. callback(new Error("必须选择一项印品"));
  334. }
  335. };
  336. return {
  337. modalIsShow: false,
  338. isSubmit: false,
  339. modalForm: deepCopy(initModalForm),
  340. PRINT_CONTENT_TYPE,
  341. DRAW_RULE_TYPE,
  342. PRINT_BACKUP_TYPE,
  343. PAPER_BACKUP_TYPE,
  344. TEMPLATE_CLASSIFY,
  345. variableContent: [],
  346. ordinaryContent: [],
  347. templateSources: {},
  348. oldPrintContent: [],
  349. allSelected: false,
  350. infoShow: true,
  351. rules: {
  352. cardRuleId: [
  353. {
  354. required: true,
  355. message: "请选择题卡规则",
  356. trigger: "change"
  357. }
  358. ],
  359. printContent: [
  360. {
  361. required: true,
  362. validator: printContentValidator,
  363. trigger: "change"
  364. }
  365. ],
  366. backupMethod: [
  367. {
  368. required: true,
  369. validator: backupMethodValidator,
  370. trigger: "change"
  371. }
  372. ],
  373. drawRule: [
  374. {
  375. required: true,
  376. message: "请选择抽卷规则",
  377. trigger: "change"
  378. }
  379. ],
  380. selectedPrint: [
  381. {
  382. required: false,
  383. validator: selectedPrintValidator,
  384. trigger: "change"
  385. }
  386. ],
  387. orgIds: [
  388. {
  389. required: true,
  390. validator: (rule, value, callback) => {
  391. if (value.length) {
  392. callback();
  393. } else {
  394. callback(new Error("请选择适用范围"));
  395. }
  396. },
  397. trigger: "change"
  398. }
  399. ]
  400. }
  401. };
  402. },
  403. mounted() {
  404. this.getTemplates();
  405. },
  406. methods: {
  407. visibleChange() {
  408. this.initData(this.instance);
  409. },
  410. cancel() {
  411. this.modalIsShow = false;
  412. },
  413. open() {
  414. this.modalIsShow = true;
  415. },
  416. async getTemplates() {
  417. const data = await printPlanTemplateList();
  418. const templateSources = {};
  419. const templates = [...data.variable, ...data.ordinary];
  420. templates.forEach(item => {
  421. templateSources[item.type] = item.template;
  422. });
  423. this.templateSources = templateSources;
  424. },
  425. async initData(val) {
  426. if (val.id) {
  427. this.modalForm = this.$objAssign(deepCopy(initModalForm), val);
  428. const transformInfo = item => {
  429. const templateIds = item.templateId ? [item.templateId] : [];
  430. return {
  431. type: item.type,
  432. templateId: templateIds,
  433. oldTemplateId: templateIds,
  434. backupMethod: item.backupMethod,
  435. backupCount: item.backupCount
  436. };
  437. };
  438. this.modalForm.variableContent = JSON.parse(val.variableContent).map(
  439. transformInfo
  440. );
  441. this.modalForm.ordinaryContent = JSON.parse(val.ordinaryContent).map(
  442. transformInfo
  443. );
  444. this.modalForm.printContent = JSON.parse(val.printContent);
  445. this.modalForm.orgIds = val.orgs.map(item => item.id);
  446. } else {
  447. let modalForm = this.$objAssign(deepCopy(initModalForm), val);
  448. modalForm.variableContent = modalForm.variableContent.filter(
  449. item => this.templateSources[item.type]
  450. );
  451. modalForm.ordinaryContent = modalForm.ordinaryContent.filter(
  452. item => this.templateSources[item.type]
  453. );
  454. this.modalForm = modalForm;
  455. }
  456. if (!this.checkHasSelect()) {
  457. this.allSelected = true;
  458. this.selectAll(this.allSelected);
  459. } else {
  460. this.checkSelectAll();
  461. }
  462. },
  463. getData() {
  464. let data = deepCopy(this.modalForm);
  465. const transformInfo = item => {
  466. const templateId = item.templateId.join();
  467. const template = this.templateSources[item.type].find(
  468. temp => temp.id === templateId
  469. );
  470. return {
  471. type: item.type,
  472. templateId,
  473. attachmentId: template && template.attachmentId,
  474. backupMethod: item.backupMethod,
  475. backupCount: item.backupCount
  476. };
  477. };
  478. data.printContent = JSON.stringify(this.modalForm.printContent);
  479. data.variableContent = JSON.stringify(
  480. this.modalForm.variableContent.map(transformInfo)
  481. );
  482. data.ordinaryContent = JSON.stringify(
  483. this.modalForm.ordinaryContent.map(transformInfo)
  484. );
  485. data.orgIds = this.$refs.SelectOrgs.getCheckedNode();
  486. return data;
  487. },
  488. selectAll(selected) {
  489. if (selected) {
  490. this.modalForm.printContent = Object.keys(this.PRINT_CONTENT_TYPE);
  491. this.modalForm.variableContent.forEach(item => {
  492. if (item.templateId && item.templateId.length) return;
  493. const source = this.templateSources[item.type][0];
  494. item.templateId = source && [source.id];
  495. item.oldTemplateId = source && [source.id];
  496. });
  497. this.modalForm.ordinaryContent.forEach(item => {
  498. if (item.templateId && item.templateId.length) return;
  499. const source = this.templateSources[item.type][0];
  500. item.templateId = source && [source.id];
  501. item.oldTemplateId = source && [source.id];
  502. });
  503. } else {
  504. this.modalForm.printContent = [];
  505. this.modalForm.variableContent.forEach(item => {
  506. item.templateId = [];
  507. item.oldTemplateId = [];
  508. });
  509. this.modalForm.ordinaryContent.forEach(item => {
  510. item.templateId = [];
  511. item.oldTemplateId = [];
  512. });
  513. }
  514. },
  515. checkSelectAll() {
  516. const vNotSelected = this.modalForm.variableContent.some(
  517. item => !item.templateId.length
  518. );
  519. const oNotSelected = this.modalForm.ordinaryContent.some(
  520. item => !item.templateId.length
  521. );
  522. const pNotSelected =
  523. this.modalForm.printContent.length <
  524. Object.keys(this.PRINT_CONTENT_TYPE).length;
  525. const selecteds = [vNotSelected, oNotSelected, pNotSelected];
  526. this.allSelected = !selecteds.some(item => item);
  527. },
  528. checkHasSelect() {
  529. const vSelected = this.modalForm.variableContent.some(
  530. item => item.templateId.length
  531. );
  532. const oSelected = this.modalForm.ordinaryContent.some(
  533. item => item.templateId.length
  534. );
  535. const pSelected = !!this.modalForm.printContent.length;
  536. const selecteds = [vSelected, oSelected, pSelected];
  537. return selecteds.some(item => item);
  538. },
  539. templateValidator(rule, value, callback) {
  540. const [field, index] = rule.field.split(".");
  541. const val = this.modalForm[field][index];
  542. if (val.templateId.length) {
  543. if (!val.backupMethod) {
  544. return callback(new Error("请选择备份方式"));
  545. }
  546. if (!val.backupCount) {
  547. return callback(new Error("请输入备份数量"));
  548. }
  549. callback();
  550. } else {
  551. callback();
  552. }
  553. },
  554. tempChange(vals, name) {
  555. const [field, index] = name.split(".");
  556. const info = this.modalForm[field][index];
  557. const newVals = vals.filter(item => !info.oldTemplateId.includes(item));
  558. info.templateId = newVals;
  559. info.oldTemplateId = newVals;
  560. this.checkSelectAll();
  561. this.$refs.modalFormComp.validateField("selectedPrint");
  562. },
  563. async submit() {
  564. const valid = await this.$refs.modalFormComp.validate().catch(() => {});
  565. if (!valid) return;
  566. if (this.isSubmit) return;
  567. this.isSubmit = true;
  568. let datas = this.getData();
  569. const data = await updateExamConfig(datas).catch(() => {
  570. this.isSubmit = false;
  571. });
  572. if (!data) return;
  573. this.isSubmit = false;
  574. this.$message.success(this.title + "成功!");
  575. this.$emit("modified");
  576. this.cancel();
  577. }
  578. }
  579. };
  580. </script>