ModifyPrintTemplate.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. <template>
  2. <el-dialog
  3. class="modify-template"
  4. :visible.sync="modalIsShow"
  5. :title="title"
  6. width="700px"
  7. top="10px"
  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="140px"
  16. :rules="rules"
  17. :model="modalForm"
  18. >
  19. <el-form-item prop="name" label="模板名称:">
  20. <el-input
  21. v-model.trim="modalForm.name"
  22. placeholder="建议不超过30个字,规则名称不允许重复"
  23. style="width: 100%"
  24. clearable
  25. ></el-input>
  26. </el-form-item>
  27. <el-form-item prop="remark" label="备注:">
  28. <el-input
  29. v-model="modalForm.remark"
  30. type="textarea"
  31. resize="none"
  32. :rows="2"
  33. :maxlength="50"
  34. clearable
  35. show-word-limit
  36. placeholder="建议不超过50个字"
  37. ></el-input>
  38. </el-form-item>
  39. <el-form-item prop="classify" label="分类:">
  40. <el-select v-model="modalForm.classify" placeholder="请选择" clearable>
  41. <el-option
  42. v-for="(val, key) in categories"
  43. :key="key"
  44. :value="key"
  45. :label="val"
  46. ></el-option>
  47. </el-select>
  48. </el-form-item>
  49. <template v-if="modalForm.classify === 'SIGN'">
  50. <el-form-item prop="testDesc" label="文字说明:">
  51. <el-input
  52. v-model="modalForm.textDesc"
  53. type="textarea"
  54. resize="none"
  55. :rows="2"
  56. :maxlength="500"
  57. clearable
  58. show-word-limit
  59. placeholder="建议不超过500个字"
  60. ></el-input>
  61. </el-form-item>
  62. <el-form-item label="显示字段:" prop="fields">
  63. <el-checkbox
  64. v-for="field in signDatas.basic"
  65. :key="field.code"
  66. v-model="field.enable"
  67. >{{ field.name }}</el-checkbox
  68. >
  69. <el-divider></el-divider>
  70. <el-checkbox
  71. v-for="field in signDatas.table"
  72. :key="field.code"
  73. v-model="field.enable"
  74. :disabled="field.code === 'studentSign'"
  75. @change="signFieldChange"
  76. >{{ field.name }}</el-checkbox
  77. >
  78. </el-form-item>
  79. <el-divider content-position="left">签到表页面设置</el-divider>
  80. <el-form-item
  81. label="考生数据显示方式:"
  82. prop="diallel"
  83. style="margin-bottom: 0"
  84. >
  85. <el-radio-group v-model="modalForm.diallel">
  86. <el-radio :label="false">单列</el-radio>
  87. <el-radio :label="true">双列</el-radio>
  88. </el-radio-group>
  89. </el-form-item>
  90. <el-form-item
  91. label="是否增加空白页:"
  92. prop="addBlankPage"
  93. style="margin-bottom: 0"
  94. >
  95. <el-radio-group v-model="modalForm.addBlankPage">
  96. <el-radio :label="false">否</el-radio>
  97. <el-radio :label="true">是</el-radio>
  98. </el-radio-group>
  99. </el-form-item>
  100. <el-form-item
  101. label="考生信息行间距:"
  102. prop="lineHeightTimes"
  103. style="margin-bottom: 0"
  104. >
  105. <el-radio-group v-model="modalForm.lineHeightTimes">
  106. <el-radio :label="1">1倍</el-radio>
  107. <el-radio :label="1.5">1.5倍</el-radio>
  108. <el-radio :label="2">2倍</el-radio>
  109. </el-radio-group>
  110. </el-form-item>
  111. <el-form-item
  112. label="考生信息字号:"
  113. prop="fontSize"
  114. style="margin-bottom: 0"
  115. >
  116. <el-radio-group v-model="modalForm.fontSize">
  117. <el-radio label="SMALL">小</el-radio>
  118. <el-radio label="MEDIUM">中</el-radio>
  119. <el-radio label="LARGE">大</el-radio>
  120. </el-radio-group>
  121. </el-form-item>
  122. <el-form-item label="信息宽度设置:" prop="fieldWidth">
  123. <el-table :data="signTableDatas" border>
  124. <el-table-column prop="name" label="列名"></el-table-column>
  125. <el-table-column label="宽度" width="200px">
  126. <template slot-scope="scope">
  127. <el-input-number
  128. v-model="scope.row.rate"
  129. :min="1"
  130. :max="100"
  131. :step="1"
  132. step-strictly
  133. :controls="false"
  134. ></el-input-number>
  135. <span class="ml-1">%</span>
  136. </template>
  137. </el-table-column>
  138. </el-table>
  139. </el-form-item>
  140. </template>
  141. <el-form-item
  142. v-else-if="modalForm.classify === 'PACKAGE'"
  143. label="显示字段:"
  144. prop="fields"
  145. >
  146. <el-checkbox
  147. v-for="field in packageDatas.title"
  148. :key="field.code"
  149. v-model="field.enable"
  150. >{{ field.name }}</el-checkbox
  151. >
  152. <el-divider></el-divider>
  153. <el-checkbox
  154. v-for="field in packageDatas.basic"
  155. :key="field.code"
  156. v-model="field.enable"
  157. >{{ field.name }}</el-checkbox
  158. >
  159. </el-form-item>
  160. <el-form-item
  161. v-else-if="modalForm.classify === 'CHECK_IN'"
  162. prop="attachmentId"
  163. label="上传模板文件:"
  164. >
  165. <upload-file-view
  166. :upload-data="uploadData"
  167. :upload-url="uploadUrl"
  168. :format="format"
  169. @valid-error="validError"
  170. @upload-success="uploadSuccess"
  171. ref="UploadFileView"
  172. ></upload-file-view>
  173. </el-form-item>
  174. </el-form>
  175. <div slot="footer">
  176. <el-button type="primary" :disabled="isSubmit" @click="submit"
  177. >确认</el-button
  178. >
  179. <el-button @click="cancel">取消</el-button>
  180. </div>
  181. </el-dialog>
  182. </template>
  183. <script>
  184. import { templateDetail, updateTemplate, examRuleDetail } from "../api";
  185. import { attachmentDetail } from "../../login/api";
  186. import UploadFileView from "@/components/UploadFileView";
  187. import { calcSum } from "@/plugins/utils";
  188. const initModalForm = {
  189. id: null,
  190. name: "",
  191. type: "",
  192. remark: "",
  193. classify: "",
  194. diallel: true,
  195. addBlankPage: false,
  196. lineHeightTimes: 1,
  197. textDesc: "",
  198. attachmentId: "",
  199. fontSize: "SMALL",
  200. };
  201. export default {
  202. name: "modify-print-template",
  203. components: { UploadFileView },
  204. props: {
  205. instance: {
  206. type: Object,
  207. default() {
  208. return {};
  209. },
  210. },
  211. },
  212. computed: {
  213. isEdit() {
  214. return !!this.instance.id;
  215. },
  216. title() {
  217. return (this.isEdit ? "编辑" : "新增") + "模板";
  218. },
  219. signTableDatas() {
  220. return this.signDatas.table.filter((item) => item.enable);
  221. },
  222. },
  223. data() {
  224. const fieldsValidator = (rule, value, callback) => {
  225. if (this.modalForm.classify === "PACKAGE") {
  226. if (!this.packageDatas.basic.some((item) => item.enable)) {
  227. return callback(new Error("请选择显示字段"));
  228. }
  229. return callback();
  230. } else {
  231. if (
  232. !this.signDatas.basic.some((item) => item.enable) ||
  233. !this.signDatas.table.some((item) => item.enable)
  234. ) {
  235. return callback(new Error("请选择显示字段"));
  236. }
  237. return callback();
  238. }
  239. };
  240. const fieldsWidthValidator = (rule, value, callback) => {
  241. if (this.signTableDatas.some((item) => !item.rate)) {
  242. return callback(new Error("请完成设置"));
  243. }
  244. const rateSum = calcSum(this.signTableDatas.map((item) => item.rate));
  245. if (rateSum !== 100) {
  246. return callback(
  247. new Error(`宽度总和需要等于100,当前总和为 ${rateSum}`)
  248. );
  249. }
  250. return callback();
  251. };
  252. return {
  253. modalIsShow: false,
  254. isSubmit: false,
  255. PACKAGE_DATA: [],
  256. SIGN_DATA: {},
  257. modalForm: {},
  258. attachment: {},
  259. format: ["ftl", "html", "pdf"],
  260. categories: {
  261. SIGN: "签到表",
  262. PACKAGE: "卷袋贴",
  263. CHECK_IN: "考试情况登记表",
  264. },
  265. rules: {
  266. name: [
  267. {
  268. required: true,
  269. message: "题卡规则名称不能超过30个字",
  270. max: 30,
  271. trigger: "change",
  272. },
  273. ],
  274. classify: [
  275. {
  276. required: true,
  277. message: "请选择分类",
  278. trigger: "change",
  279. },
  280. ],
  281. attachmentId: [
  282. {
  283. required: true,
  284. message: "请上传模板文件",
  285. trigger: "change",
  286. },
  287. ],
  288. fields: [
  289. {
  290. required: true,
  291. validator: fieldsValidator,
  292. trigger: "change",
  293. },
  294. ],
  295. fieldWidth: [
  296. {
  297. required: true,
  298. validator: fieldsWidthValidator,
  299. trigger: "change",
  300. },
  301. ],
  302. },
  303. packageDatas: { title: [], basic: [] },
  304. signDatas: { basic: [], table: [] },
  305. // upload
  306. uploadUrl: "/api/admin/common/file/upload",
  307. uploadData: {
  308. type: "UPLOAD",
  309. },
  310. };
  311. },
  312. created() {
  313. this.getScopeField();
  314. },
  315. methods: {
  316. async getScopeField() {
  317. const examRule = await examRuleDetail();
  318. this.PACKAGE_DATA = examRule.packageScope
  319. ? JSON.parse(examRule.packageScope)
  320. : { title: [], basic: [] };
  321. this.SIGN_DATA = examRule.signScope
  322. ? JSON.parse(examRule.signScope)
  323. : { basic: [], table: [] };
  324. },
  325. async initData(val) {
  326. if (val.id) {
  327. const data = await templateDetail(val.id);
  328. this.modalForm = this.$objAssign(initModalForm, data);
  329. const unAttachmentTemps = ["SIGN", "PACKAGE"];
  330. if (unAttachmentTemps.includes(this.modalForm.classify)) {
  331. this.initEditFieldData(data);
  332. } else {
  333. this.getAttachment();
  334. }
  335. } else {
  336. this.modalForm = this.$objAssign(initModalForm, val);
  337. this.getDefaultFieldData();
  338. }
  339. },
  340. getDefaultFieldData() {
  341. this.packageDatas.title = this.PACKAGE_DATA.title.map((item) => {
  342. return { ...item, enable: false };
  343. });
  344. this.packageDatas.basic = this.PACKAGE_DATA.basic.map((item) => {
  345. return { ...item, enable: false };
  346. });
  347. this.signDatas.basic = this.SIGN_DATA.basic.map((item) => {
  348. return { ...item, enable: false };
  349. });
  350. this.signDatas.table = this.SIGN_DATA.table.map((item) => {
  351. return { ...item, rate: undefined, enable: false };
  352. });
  353. this.signDatas.table.push({
  354. code: "studentSign",
  355. name: "签名",
  356. rate: undefined,
  357. enable: true,
  358. });
  359. },
  360. initEditFieldData(data) {
  361. const displayRange = data.displayRange
  362. ? JSON.parse(data.displayRange)
  363. : null;
  364. if (!displayRange) {
  365. this.getDefaultFieldData();
  366. return;
  367. }
  368. if (data.classify === "PACKAGE") {
  369. this.packageDatas = displayRange;
  370. } else {
  371. this.signDatas = displayRange;
  372. }
  373. },
  374. async getAttachment() {
  375. if (!this.instance.attachmentId) return;
  376. const data = await attachmentDetail(this.instance.attachmentId);
  377. this.attachment = data;
  378. this.$nextTick(() => {
  379. this.$refs.UploadFileView.setAttachmentName(`${data.name}${data.type}`);
  380. });
  381. },
  382. signFieldChange() {
  383. this.$refs.modalFormComp.validateField("fieldWidth", () => {});
  384. },
  385. visibleChange() {
  386. this.initData(this.instance);
  387. this.$nextTick(() => {
  388. this.$refs.modalFormComp.clearValidate();
  389. });
  390. },
  391. cancel() {
  392. this.modalIsShow = false;
  393. },
  394. open() {
  395. this.modalIsShow = true;
  396. },
  397. async submit() {
  398. const valid = await this.$refs.modalFormComp.validate().catch(() => {});
  399. if (!valid) return;
  400. if (this.isSubmit) return;
  401. this.isSubmit = true;
  402. let datas = {
  403. ...this.modalForm,
  404. };
  405. if (this.modalForm.classify === "PACKAGE") {
  406. datas.displayRange = this.packageDatas;
  407. } else if (this.modalForm.classify === "SIGN") {
  408. let signTableRates = {};
  409. this.signTableDatas.forEach((item) => {
  410. signTableRates[item.code] = item.rate;
  411. });
  412. this.signDatas.table.forEach((item) => {
  413. item.rate = signTableRates[item.code] || 0;
  414. });
  415. datas.displayRange = this.signDatas;
  416. }
  417. const data = await updateTemplate(datas).catch(() => {});
  418. this.isSubmit = false;
  419. if (!data) return;
  420. this.$message.success("保存成功!");
  421. this.$emit("modified");
  422. this.cancel();
  423. },
  424. validError(errorData) {
  425. this.$message.error(errorData.message);
  426. },
  427. uploadSuccess(data) {
  428. this.$message.success("上传成功!");
  429. this.modalForm.attachmentId = data.id;
  430. this.$refs.modalFormComp.validateField("attachmentId");
  431. },
  432. },
  433. };
  434. </script>