SchoolSetStdno.vue 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. <template>
  2. <div class="school-set-stdno part-box part-box-pad">
  3. <el-form
  4. ref="modalFormComp"
  5. :model="modalForm"
  6. :rules="rules"
  7. label-width="180px"
  8. >
  9. <el-form-item prop="digit" label="学号位数:">
  10. <el-input-number
  11. v-model="modalForm.digit"
  12. :min="5"
  13. :max="15"
  14. :step="1"
  15. step-strictly
  16. :controls="false"
  17. style="width: 80px"
  18. ></el-input-number>
  19. <span class="tips-info">(如:10)</span>
  20. </el-form-item>
  21. <el-form-item label="学号是否包含字母:">
  22. <el-radio-group v-model="modalForm.containsLetter">
  23. <el-radio :label="true">是</el-radio>
  24. <el-radio :label="false">否</el-radio>
  25. </el-radio-group>
  26. </el-form-item>
  27. <template v-if="modalForm.containsLetter">
  28. <el-form-item prop="columns" label="字母所在列:">
  29. <el-select
  30. v-model="modalForm.columns"
  31. placeholder="请选择"
  32. multiple
  33. style="width: 200px"
  34. @change="columnChange"
  35. >
  36. <el-option
  37. v-for="n in modalForm.digit"
  38. :key="n"
  39. :value="n"
  40. :label="n"
  41. ></el-option>
  42. </el-select>
  43. <div v-if="modalForm.relationList.length" style="margin-top: 10px">
  44. <el-radio-group
  45. v-model="curSelectColumn"
  46. @change="selectColumnChange"
  47. >
  48. <el-radio-button
  49. v-for="(item, index) in modalForm.relationList"
  50. :key="index"
  51. :label="item.columnIndex"
  52. >第{{ item.columnIndex }}列</el-radio-button
  53. >
  54. </el-radio-group>
  55. </div>
  56. </el-form-item>
  57. <template v-if="modalForm.columns.length">
  58. <el-form-item prop="columnChar" label="使用字母:">
  59. <el-input
  60. v-model.trim="modalForm.columnChar"
  61. plachholder="请输入"
  62. style="width: 200px"
  63. @change="columnCharChange"
  64. ></el-input>
  65. <p class="tips-info">说明:请输入大写字母,最多输入10个字母</p>
  66. </el-form-item>
  67. <el-form-item label="字母映射关系:">
  68. <table
  69. v-if="curSelectColumnLetters.length"
  70. class="table table-tiny"
  71. style="width: 200px"
  72. >
  73. <tr>
  74. <th>使用字母</th>
  75. <th>映射数字</th>
  76. </tr>
  77. <tr v-for="(item, index) in curSelectColumnLetters" :key="index">
  78. <td>{{ item }}</td>
  79. <td>{{ index }}</td>
  80. </tr>
  81. </table>
  82. </el-form-item>
  83. </template>
  84. </template>
  85. </el-form>
  86. <!-- stdno view -->
  87. <div class="card-head-body">
  88. <h3 class="mb-1">答题卡学号区域预览:</h3>
  89. <head-stdno :data="headStdnoData"></head-stdno>
  90. </div>
  91. </div>
  92. </template>
  93. <script>
  94. import { deepCopy } from "@/plugins/utils";
  95. import { schoolSetStdnoInfo, schoolSetStdnoUpdate } from "../../api";
  96. import HeadStdno from "../../../../../card/elements/card-head/cardHeadSpin/HeadStdno.vue";
  97. export default {
  98. name: "school-set-stdno",
  99. components: { HeadStdno },
  100. props: {
  101. school: {
  102. type: Object,
  103. default() {
  104. return {};
  105. },
  106. },
  107. },
  108. data() {
  109. return {
  110. loading: false,
  111. stdnoInfo: [],
  112. modalForm: {
  113. digit: 10,
  114. containsLetter: false,
  115. columns: [],
  116. relationList: [],
  117. columnChar: "",
  118. },
  119. cachedModalForm: null,
  120. curSelectColumn: -1,
  121. curSelectColumnLetters: [],
  122. rules: {
  123. digit: [
  124. {
  125. required: true,
  126. message: "请输入学号位数",
  127. trigger: "change",
  128. },
  129. ],
  130. columns: [
  131. {
  132. required: true,
  133. validator: (rule, value, callback) => {
  134. if (!value || !value.length) {
  135. return callback(new Error(`请选择字母所在列`));
  136. }
  137. callback();
  138. },
  139. trigger: "change",
  140. },
  141. ],
  142. columnChar: [
  143. {
  144. required: true,
  145. validator: (rule, value, callback) => {
  146. if (!/^[A-Z]{1,10}$/.test(value)) {
  147. return callback(new Error(`只能输入大写字母,长度不超过10`));
  148. }
  149. const chars = Array.from(new Set((value || "").split(""))).join(
  150. ""
  151. );
  152. if (chars !== value) {
  153. return callback(new Error(`大写字母不可重复`));
  154. }
  155. callback();
  156. },
  157. trigger: "change",
  158. },
  159. ],
  160. },
  161. };
  162. },
  163. computed: {
  164. headStdnoData() {
  165. return {
  166. examNumberStyle: "FILL",
  167. fillNumber: this.modalForm.digit,
  168. containsLetter: this.modalForm.containsLetter,
  169. relationList: this.modalForm.relationList,
  170. };
  171. },
  172. },
  173. watch: {
  174. modalForm: {
  175. deep: true,
  176. handler() {
  177. const isChanged = this.checkConfigChanged();
  178. this.$emit("config-changed", isChanged);
  179. },
  180. },
  181. },
  182. mounted() {
  183. this.initData();
  184. },
  185. methods: {
  186. async initData() {
  187. const data = await schoolSetStdnoInfo(this.school.id);
  188. this.stdnoInfo = data.result;
  189. const config = data.result[0].value;
  190. if (!config) {
  191. this.modalForm = {
  192. digit: 10,
  193. containsLetter: false,
  194. columns: [],
  195. relationList: [],
  196. columnChar: "",
  197. };
  198. this.updateCachedModalForm();
  199. return;
  200. }
  201. this.modalForm = {
  202. digit: config.digit || 10,
  203. containsLetter: config.containsLetter,
  204. columns: [],
  205. relationList: config.relationList || [],
  206. columnChar: "",
  207. };
  208. this.modalForm.columns = this.modalForm.relationList.map(
  209. (item) => item.columnIndex
  210. );
  211. if (this.modalForm.columns.length) {
  212. this.curSelectColumn = this.modalForm.columns[0];
  213. this.selectColumnChange();
  214. }
  215. this.updateCachedModalForm();
  216. },
  217. updateCachedModalForm() {
  218. this.cachedModalForm = JSON.parse(JSON.stringify(this.modalForm));
  219. },
  220. checkConfigChanged() {
  221. if (!this.cachedModalForm) return false;
  222. return (
  223. JSON.stringify(this.modalForm) !== JSON.stringify(this.cachedModalForm)
  224. );
  225. },
  226. columnChange() {
  227. const relationList = this.modalForm.relationList || [];
  228. const relationMap = {};
  229. relationList.forEach((item) => {
  230. relationMap[item.columnIndex] = item.letters;
  231. });
  232. this.modalForm.columns.sort((a, b) => a - b);
  233. this.modalForm.relationList = this.modalForm.columns.map(
  234. (columnIndex) => {
  235. const letters = relationMap[columnIndex] || [];
  236. return {
  237. columnIndex,
  238. letters,
  239. };
  240. }
  241. );
  242. if (
  243. this.modalForm.columns.length &&
  244. !this.modalForm.columns.includes(this.curSelectColumn)
  245. ) {
  246. this.curSelectColumn = this.modalForm.columns[0];
  247. this.selectColumnChange();
  248. }
  249. },
  250. selectColumnChange() {
  251. const curRelation = this.modalForm.relationList.find(
  252. (item) => item.columnIndex === this.curSelectColumn
  253. );
  254. this.modalForm.columnChar = curRelation
  255. ? curRelation.letters.join("")
  256. : "";
  257. this.curSelectColumnLetters = curRelation ? curRelation.letters : [];
  258. },
  259. validateField(field) {
  260. return new Promise((resolve, reject) => {
  261. this.$refs.modalFormComp.validateField(field, (unvalid) => {
  262. if (unvalid) {
  263. reject(false);
  264. } else {
  265. resolve(true);
  266. }
  267. });
  268. });
  269. },
  270. async columnCharChange() {
  271. const res = await this.validateField("columnChar").catch(() => {});
  272. if (!res) {
  273. this.curSelectColumnLetters = [];
  274. return;
  275. }
  276. const curRelation = this.modalForm.relationList.find(
  277. (item) => item.columnIndex === this.curSelectColumn
  278. );
  279. if (!curRelation) return;
  280. curRelation.letters = this.modalForm.columnChar.split("");
  281. this.curSelectColumnLetters = curRelation.letters;
  282. },
  283. async confirm() {
  284. const valid = await this.$refs.modalFormComp.validate().catch(() => {});
  285. if (!valid) return;
  286. if (this.loading) return;
  287. this.loading = true;
  288. const val = {
  289. digit: this.modalForm.digit,
  290. containsLetter: this.modalForm.containsLetter,
  291. relationList: this.modalForm.containsLetter
  292. ? this.modalForm.relationList
  293. : [],
  294. };
  295. const datas = deepCopy(this.stdnoInfo);
  296. datas[0].value = val;
  297. const res = await schoolSetStdnoUpdate({
  298. param: datas,
  299. schoolId: this.school.id,
  300. }).catch(() => {});
  301. this.loading = false;
  302. if (!res) return;
  303. this.updateCachedModalForm();
  304. this.$emit("config-changed", false);
  305. this.initData();
  306. },
  307. },
  308. };
  309. </script>
  310. <style lang="scss" scoped>
  311. .school-set-stdno {
  312. width: 1000px;
  313. display: flex;
  314. justify-content: space-between;
  315. .el-form {
  316. flex-grow: 2;
  317. }
  318. .card-head-body {
  319. width: 340px;
  320. flex-grow: 0;
  321. flex-shrink: 0;
  322. }
  323. .head-stdno {
  324. border: 1px solid #000;
  325. height: 240px;
  326. }
  327. }
  328. </style>