newRegister.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615
  1. <template>
  2. <div id="newRegister">
  3. <div style="margin-bottom: 12px">
  4. <span style="font-size: 14px">第一步:</span>
  5. <el-select
  6. :style="marSty"
  7. :size="size"
  8. filterable
  9. v-model="formData.applyId"
  10. placeholder="请选择考试计划(必填)"
  11. @change="getSXAddress"
  12. >
  13. <el-option
  14. v-for="item in examLists"
  15. :key="item.applyId"
  16. :label="item.applyName"
  17. :value="item.applyId"
  18. >
  19. </el-option>
  20. </el-select>
  21. <el-select
  22. v-if="formData.applyId"
  23. :style="marSty"
  24. :size="size"
  25. filterable
  26. v-model="formData.applySiteAddress"
  27. placeholder="请选择考试地点(必填)"
  28. >
  29. <el-option
  30. v-for="item in applySiteAddress"
  31. :key="item.siteId"
  32. :label="item.siteAddress"
  33. :value="item.siteAddress"
  34. >
  35. </el-option>
  36. </el-select>
  37. <el-button :size="size" type="info" @click="advanced">选择学员</el-button>
  38. <el-input
  39. v-if="formData.idCards"
  40. type="textarea"
  41. :size="size"
  42. readonly
  43. :rows="1"
  44. style="width: 180px; vertical-align: top; margin: 0px 10px"
  45. placeholder="请点击选择学员按钮上传学员名单"
  46. v-model="formData.idCards"
  47. >
  48. </el-input>
  49. <el-button :size="size" type="warning" @click="downModel"
  50. >下载模板</el-button
  51. >
  52. </div>
  53. <div style="margin-bottom: 12px">
  54. <span style="font-size: 14px">第二步:</span>
  55. <label
  56. for="mobles4"
  57. class="el-button el-button--success el-button--mini"
  58. style="margin-right: 10px"
  59. >批量导入</label
  60. ><input
  61. style="display: none"
  62. type="file"
  63. id="mobles4"
  64. ref="input4"
  65. @change="importMobleadd"
  66. />
  67. </div>
  68. <div>
  69. <el-badge
  70. :hidden="!tableDataSuccess.length"
  71. :value="tableDataSuccess.length"
  72. class="item"
  73. >
  74. <el-button
  75. :size="size"
  76. :type="active === 1 ? 'primary' : ''"
  77. @click="active = 1"
  78. >成功导入</el-button
  79. >
  80. </el-badge>
  81. <el-badge
  82. :hidden="!tableDataError.length"
  83. :value="tableDataError.length"
  84. class="item"
  85. >
  86. <el-button
  87. :size="size"
  88. :type="active === 2 ? 'primary' : ''"
  89. @click="active = 2"
  90. >失败导入</el-button
  91. >
  92. </el-badge>
  93. </div>
  94. <div v-show="active === 1" class="exportBox" v-loading="loading">
  95. <h4 class="h4Sty">
  96. 成功导入<strong style="color: red">{{ tableDataSuccess.length }}</strong
  97. >人
  98. </h4>
  99. <el-table
  100. max-height="600"
  101. :data="tableDataSuccess"
  102. style="width: 100%"
  103. border
  104. :header-cell-style="{
  105. 'background-color': '#eee',
  106. color: '#333',
  107. fontSize: '14px',
  108. }"
  109. >
  110. <af-table-column
  111. v-for="(item, index) in computedForm(tableSet, 1)"
  112. :key="index"
  113. :prop="item.prop"
  114. :label="item.label"
  115. :width="item.width"
  116. align="center"
  117. >
  118. <template slot-scope="scope">
  119. <div v-if="item.scope === 'time'">
  120. <div>{{ scope.row[item.prop1] }}</div>
  121. <div>{{ scope.row[item.prop2] }} {{ scope.row[item.prop3] }}</div>
  122. </div>
  123. <span v-else>{{ scope.row[item.prop] }}</span>
  124. </template>
  125. </af-table-column>
  126. </el-table>
  127. </div>
  128. <div v-show="active === 2" class="exportBox" v-loading="loading">
  129. <h4 class="h4Sty">
  130. 失败导入<strong style="color: red">{{ tableDataError.length }}</strong
  131. >人
  132. <el-button
  133. v-if="tableDataError.length"
  134. style="margin-left: 10px"
  135. :size="size"
  136. type="success"
  137. @click="dowmErrorData"
  138. >下载失败数据</el-button
  139. >
  140. </h4>
  141. <el-table
  142. max-height="600"
  143. :data="tableDataError"
  144. style="width: 100%"
  145. border
  146. :header-cell-style="{
  147. 'background-color': '#eee',
  148. color: '#333',
  149. fontSize: '14px',
  150. }"
  151. >
  152. <af-table-column
  153. v-for="(item, index) in computedForm(tableSet, 2)"
  154. :key="index"
  155. :prop="item.prop"
  156. :label="item.label"
  157. :width="item.width"
  158. align="center"
  159. >
  160. <template slot-scope="scope">
  161. <span v-if="item.scope === 'time'">
  162. {{ changeDatas(scope.row[item.prop]) }}
  163. </span>
  164. <span v-else>{{ scope.row[item.prop] }}</span>
  165. </template>
  166. </af-table-column>
  167. </el-table>
  168. </div>
  169. <el-dialog
  170. :visible.sync="dialogPLS"
  171. width="660px"
  172. :show-close="false"
  173. :close-on-click-modal="false"
  174. >
  175. <div slot="title" class="hearders">
  176. <div class="leftTitle">高级输入</div>
  177. <div class="rightBoxs">
  178. <img
  179. src="@/assets/images/Close@2x.png"
  180. alt=""
  181. @click="dialogPLS = false"
  182. />
  183. </div>
  184. </div>
  185. <el-row :gutter="20">
  186. <el-col :span="12"
  187. ><h4>请输入学员的身份证号码,换行隔开,每行一个</h4>
  188. <el-input
  189. type="textarea"
  190. :rows="10"
  191. placeholder="请输入身份证"
  192. v-model="idcordList"
  193. >
  194. </el-input>
  195. </el-col>
  196. <el-col :span="12">
  197. <h4>快捷导入</h4>
  198. <el-link type="primary" @click="getDowm">下载模板</el-link>
  199. <label
  200. for="mobles3"
  201. class="el-button el-button--primary"
  202. style="margin-left: 14px; padding: 10px 20px"
  203. >上传学员名单</label
  204. ><input
  205. style="display: none"
  206. type="file"
  207. id="mobles3"
  208. ref="input1"
  209. @change="importMobleadds"
  210. />
  211. </el-col>
  212. </el-row>
  213. <span slot="footer" class="dialog-footer">
  214. <el-button @click="dialogPLS = false">取消</el-button>
  215. <el-button type="primary" @click="submitChecksPals">确定</el-button>
  216. </span>
  217. </el-dialog>
  218. </div>
  219. </template>
  220. <script>
  221. import * as baseUrls from "@/utils/request.js";
  222. import { mapGetters } from "vuex";
  223. export default {
  224. data() {
  225. return {
  226. loading: false, // 加载效果
  227. dialogPLS: false,
  228. active: 1,
  229. marSty: { marginRight: "10px" },
  230. size: "mini",
  231. formData: {
  232. applyId: "",
  233. applySiteAddress: "",
  234. idCards: "",
  235. },
  236. applySiteAddress: [],
  237. idcordList: "",
  238. tableDataSuccess: [],
  239. tableDataError: [],
  240. tableSet: [
  241. {
  242. label: "学员姓名",
  243. prop: "userName",
  244. },
  245. {
  246. label: "学员身份证",
  247. prop: "idCard",
  248. },
  249. {
  250. label: "学员报名类型",
  251. prop: "studentTypeName",
  252. },
  253. {
  254. label: "考试标题",
  255. prop: "applyName",
  256. },
  257. {
  258. label: "考试地点",
  259. prop: "applySiteAddress",
  260. },
  261. {
  262. label: "考试日期",
  263. prop: "applySiteExamTime",
  264. // scope: "time",
  265. },
  266. {
  267. label: "考试时间段",
  268. prop: "applySiteTime",
  269. },
  270. {
  271. label: "商品编码",
  272. prop: "code",
  273. },
  274. {
  275. label: "商品标题",
  276. prop: "goodsName",
  277. },
  278. {
  279. label: "预约登记",
  280. prop: "subscribeStatus",
  281. },
  282. {
  283. label: "考试登记",
  284. prop: "examStatus",
  285. },
  286. {
  287. label: "考试成绩",
  288. prop: "performance",
  289. },
  290. {
  291. label: "考试结果",
  292. prop: "result",
  293. },
  294. {
  295. label: "证书编号",
  296. prop: "certificateCode",
  297. },
  298. {
  299. label: "出错原因",
  300. prop: "cause",
  301. hidden: true,
  302. width: "260px",
  303. },
  304. ],
  305. };
  306. },
  307. computed: {
  308. ...mapGetters(["examLists"]),
  309. computedForm: function () {
  310. return function (tabs, int) {
  311. if (int === 1) {
  312. const ayst = tabs.filter((item) => {
  313. return !item.hidden;
  314. });
  315. return ayst;
  316. } else {
  317. return tabs;
  318. }
  319. };
  320. },
  321. },
  322. methods: {
  323. getSXAddress(int) {
  324. this.formData.applySiteAddress = "";
  325. this.$api
  326. .inquirepayservesiteInfo({ applyId: int, addressStatus: 1 })
  327. .then((res) => {
  328. this.applySiteAddress = res.rows;
  329. });
  330. },
  331. /**
  332. * 转换时间格式
  333. */
  334. changeDatas(time) {
  335. if (time) {
  336. var datas = this.$methodsTools.onlyForma(
  337. new Date(time).getTime() / 1000,
  338. false
  339. );
  340. return datas;
  341. } else {
  342. return "";
  343. }
  344. },
  345. importMobleadd(e) {
  346. this.loading = true
  347. var file = e.target.files[0];
  348. let formData = new FormData();
  349. formData.append("file", file);
  350. this.$api
  351. .editsystemimportUpdateData(formData)
  352. .then((res) => {
  353. this.tableDataSuccess = res.data.successList;
  354. this.tableDataError = res.data.errorList;
  355. this.$message.info("导入操作执行成功");
  356. })
  357. .finally(() => {
  358. e.target.value = "";
  359. this.loading = false
  360. });
  361. },
  362. advanced() {
  363. if (!this.formData.applyId || !this.formData.applySiteAddress) {
  364. this.$message.warning("请先选择考试计划和考试地点");
  365. return;
  366. }
  367. this.dialogPLS = true;
  368. this.idcordList = this.formData.idCards;
  369. },
  370. submitChecksPals() {
  371. if (this.idcordList) {
  372. let as = this.idcordList.split("\n") || [];
  373. let newArr = [];
  374. var reg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/;
  375. for (let i = 0; i < as.length; i++) {
  376. if (newArr.indexOf(as[i]) === -1 && reg.test(as[i])) {
  377. newArr.push(as[i]);
  378. }
  379. }
  380. if (newArr.length) {
  381. let idCardObj = newArr.map((item) => {
  382. return { idCard: item };
  383. });
  384. let data = {
  385. applyId: this.formData.applyId,
  386. applySiteAddress: this.formData.applySiteAddress,
  387. list: idCardObj,
  388. };
  389. this.$api.inquiresystemsubscribecheckIdCardData(data).then((res) => {
  390. this.formData.idCards = newArr.join("\n");
  391. this.dialogPLS = false;
  392. });
  393. } else {
  394. this.idcordList = "";
  395. this.$message.warning(
  396. "已删除重复身份证号码和无效身份证号码,请重新输入有效身份证号码"
  397. );
  398. return;
  399. }
  400. } else {
  401. this.formData.idCards = this.idcordList;
  402. this.dialogPLS = false;
  403. }
  404. },
  405. /**
  406. * 窗口下载模板
  407. */
  408. getDowm() {
  409. let url = baseUrls.BASE_IMG_URL + "/oss/images/file/20220214.xls" +
  410. `?time=${this.$methodsTools.getNewTime()}`;;
  411. let link = document.createElement("a");
  412. let fileName = "导入模板" + ".xlsx";
  413. document.body.appendChild(link);
  414. link.href = url;
  415. link.dowmload = fileName;
  416. link.click();
  417. link.remove();
  418. },
  419. /**
  420. * 导入
  421. */
  422. importMobleadds(e) {
  423. var self = this;
  424. var file = e.target.files[0];
  425. let formData = new FormData();
  426. formData.append("file", file);
  427. this.$api
  428. .editsystemimportIdsData(formData)
  429. .then((res) => {
  430. if (!res.data.length) {
  431. this.$message.warning("未检测到上传学员数据,请检查上传文件");
  432. return;
  433. }
  434. let idList = res.data.map((item) => {
  435. return item.idCard.toString();
  436. });
  437. if (this.idcordList) {
  438. var arr = this.idcordList.split("\n");
  439. var arrs = arr.concat(idList);
  440. var newArr = arrs.filter(function (value, index, self) {
  441. return self.indexOf(value) === index;
  442. });
  443. this.idcordList = newArr.join("\n");
  444. } else {
  445. var newArr = idList.filter(function (value, index, self) {
  446. return self.indexOf(value) === index;
  447. });
  448. this.idcordList = newArr.join("\n");
  449. }
  450. this.$message.success("上传成功");
  451. })
  452. .finally(() => {
  453. e.target.value = "";
  454. });
  455. },
  456. /**下载模板 */
  457. downModel() {
  458. if (!this.formData.applyId) {
  459. this.$message.warning("请选择考试计划");
  460. return;
  461. }
  462. if (!this.formData.applySiteAddress) {
  463. this.$message.warning("请选择考试地点");
  464. return;
  465. }
  466. var data = JSON.parse(JSON.stringify(this.formData));
  467. if (this.formData.idCards) {
  468. data.idCards = this.formData.idCards.split("\n");
  469. }
  470. // else {
  471. // this.$message.warning("请选择学员");
  472. // return;
  473. // }
  474. const indexs = this.examLists.findIndex((item) => {
  475. return item.applyId == data.applyId;
  476. });
  477. data.applyName = this.examLists[indexs].applyName;
  478. this.$api.inquiresystemsubscribeexportRegister(data).then((res) => {
  479. let url = baseUrls.baseURL + "common/download?fileName=" + res.msg;
  480. let link = document.createElement("a");
  481. let fileName = "导入模板" + ".xlsx";
  482. document.body.appendChild(link);
  483. link.href = url;
  484. link.dowmload = fileName;
  485. link.click();
  486. link.remove();
  487. });
  488. },
  489. /**
  490. * 下载错误数据
  491. */
  492. dowmErrorData() {
  493. this.$api
  494. .inquiresystemsubscribeexportexportErrorUpdate(this.tableDataError)
  495. .then((res) => {
  496. let url = baseUrls.baseURL + "common/download?fileName=" + res.msg;
  497. let link = document.createElement("a");
  498. let fileName = "导入模板" + ".xlsx";
  499. document.body.appendChild(link);
  500. link.href = url;
  501. link.dowmload = fileName;
  502. link.click();
  503. link.remove();
  504. });
  505. },
  506. },
  507. };
  508. </script>
  509. <style lang="less" scoped>
  510. .h4Sty {
  511. margin: 6px;
  512. font-size: 14px;
  513. }
  514. .exportBox {
  515. border: 1px solid #999;
  516. padding: 10px;
  517. margin-top: 10px;
  518. border-radius: 4px;
  519. }
  520. /deep/.el-button {
  521. border-radius: 8px;
  522. }
  523. /deep/.el-dialog {
  524. border-radius: 8px;
  525. .el-dialog__header {
  526. padding: 0;
  527. .hearders {
  528. height: 40px;
  529. display: flex;
  530. align-items: center;
  531. justify-content: space-between;
  532. padding: 0px 18px 0px 20px;
  533. border-bottom: 1px solid #e2e2e2;
  534. .leftTitle {
  535. font-size: 14px;
  536. font-weight: bold;
  537. color: #2f4378;
  538. }
  539. .rightBoxs {
  540. display: flex;
  541. align-items: center;
  542. img {
  543. width: 14px;
  544. height: 14px;
  545. margin-left: 13px;
  546. cursor: pointer;
  547. }
  548. }
  549. }
  550. }
  551. .el-dialog__footer {
  552. padding: 0;
  553. .dialog-footer {
  554. padding: 0px 40px;
  555. height: 70px;
  556. border-top: 1px solid #e2e2e2;
  557. display: flex;
  558. align-items: center;
  559. justify-content: flex-end;
  560. }
  561. }
  562. }
  563. .imgBox {
  564. width: 100%;
  565. // height: 210px;
  566. border: 1px solid #e2e2e2;
  567. border-radius: 8px;
  568. padding: 8px 8px 3px;
  569. display: flex;
  570. flex-direction: column;
  571. align-items: center;
  572. .imgLabel {
  573. flex: 1;
  574. width: 100%;
  575. border: 1px dotted #e2e2e2;
  576. color: #999;
  577. font-size: 14px;
  578. cursor: pointer;
  579. border-radius: 8px;
  580. .msPhoto {
  581. display: flex;
  582. justify-content: center;
  583. align-items: center;
  584. max-width: 100%;
  585. max-height: 270px;
  586. img {
  587. max-width: 100%;
  588. max-height: 270px;
  589. }
  590. }
  591. .imgbbx {
  592. display: flex;
  593. flex-direction: column;
  594. align-items: center;
  595. justify-content: center;
  596. width: 100%;
  597. height: 100%;
  598. i {
  599. font-weight: bold;
  600. margin: 14px 0;
  601. font-size: 24px;
  602. }
  603. }
  604. }
  605. p {
  606. margin: 5px 0px;
  607. }
  608. }
  609. .item {
  610. margin-top: 10px;
  611. margin-right: 20px;
  612. }
  613. </style>