ModifyPrintPlan.vue 19 KB

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