ModifyExamConfigDetail.vue 20 KB

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