index.vue 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984
  1. <template>
  2. <div>
  3. <el-dialog
  4. title="资料填写"
  5. :visible.sync="isShow"
  6. width="1000px"
  7. :close-on-click-modal="false"
  8. :close-on-press-escape="false"
  9. :show-close="false"
  10. >
  11. <div class="info__content">
  12. <el-row :gutter="20">
  13. <el-form
  14. :model="infoForm"
  15. ref="infoForm"
  16. :rules="rules"
  17. :disabled="STATUS"
  18. >
  19. <el-col
  20. v-for="(item, index) in listData"
  21. :span="item.fieldKey == 'commitment_electr_signature' ? 24 : 12"
  22. :key="index"
  23. >
  24. <el-form-item
  25. v-if="item.inputType == 1"
  26. :label="item.fieldName"
  27. label-width="120px"
  28. :prop="item.fieldKey"
  29. >
  30. <el-input
  31. :disabled="
  32. (item.fieldKey == 'name' && nameDisabledStatus) ||
  33. (item.fieldKey == 'idcard' && idcardDisabledStatus) ||
  34. (item.fieldKey == 'telphone' && telphoneDisabledStatus)
  35. ? true
  36. : false
  37. "
  38. clearable
  39. v-model.trim="infoForm[item.fieldKey]"
  40. :placeholder="`请输入${item.fieldName}`"
  41. />
  42. </el-form-item>
  43. <el-form-item
  44. v-else-if="item.inputType == 2"
  45. :label="item.fieldName"
  46. label-width="120px"
  47. :prop="item.fieldKey"
  48. >
  49. <el-select
  50. v-model="infoForm[item.fieldKey]"
  51. :placeholder="`请选择${item.fieldName}`"
  52. clearable
  53. >
  54. <el-option
  55. v-for="(items, indexs) in options[item.fieldKey]"
  56. :key="indexs"
  57. :label="items"
  58. :value="items"
  59. :disabled="
  60. item.fieldKey == 'education'
  61. ? eduDisAbledStatus(items)
  62. : false
  63. "
  64. >
  65. </el-option>
  66. </el-select>
  67. </el-form-item>
  68. <template v-else-if="item.inputType == 3 || item.inputType == 4">
  69. <div
  70. class="cns_sq"
  71. v-if="item.fieldKey == 'commitment_electr_signature'"
  72. >
  73. <div class="left">
  74. <h3>承诺书</h3>
  75. <p>
  76. 本人自愿做出如下承诺:本人己仔细阅读《广东省住房和城乡建设厅关于推进住房和城乡建设领域施工现场专业人员职业培训工作的通知》
  77. 全部内容并知晓和理解,本人的学历证书、身份证、工作年限、相片等所有资料完全真实、符合报名条件、资格审查要求和相关规定,本人在报名、审查、培训、测试等有关的事项中会严格道守相关规定和要求,如有虛假或与实际规定不符等情况造成的一切后果由本人承担。
  78. </p>
  79. <p style="text-align: end;">特此承诺!</p>
  80. </div>
  81. <div class="right">
  82. <h3>
  83. <span>
  84. 签名板:<span class="texts"
  85. >(请在下方签名区进行签名)</span
  86. >
  87. </span>
  88. <span class="btn_text" @click="retDraw" v-if="!STATUS"
  89. >清空</span
  90. >
  91. </h3>
  92. <el-form-item
  93. label=""
  94. label-width="0px"
  95. :prop="item.fieldKey"
  96. >
  97. <vue-esign
  98. v-if="!infoForm[item.fieldKey]"
  99. ref="esign"
  100. :isCrop="false"
  101. :lineWidth="5"
  102. :lineColor="'#333'"
  103. :bgColor="'#fff'"
  104. :height="480"
  105. :isClearBgColor="false"
  106. />
  107. <img
  108. v-else
  109. style="width: 100%; height: 100%"
  110. :src="$tools.splitImgHost(infoForm[item.fieldKey])"
  111. />
  112. </el-form-item>
  113. </div>
  114. </div>
  115. <el-form-item
  116. v-else
  117. :label="item.fieldName"
  118. label-width="120px"
  119. :prop="item.fieldKey"
  120. >
  121. <div
  122. v-if="infoForm[item.fieldKey]"
  123. style="display: inline-block;"
  124. >
  125. <el-image
  126. fit="contain"
  127. style="width: 80px; height: 80px;border-radius: 8px;border: 2px dotted #eee;"
  128. :src="$tools.splitImgHost(infoForm[item.fieldKey])"
  129. :preview-src-list="[
  130. $tools.splitImgHost(infoForm[item.fieldKey])
  131. ]"
  132. >
  133. </el-image
  134. ><span
  135. v-if="item.fieldKey == 'commitment_seal' || !STATUS"
  136. class="btn_text"
  137. @click="infoForm[item.fieldKey] = ''"
  138. >删除</span
  139. >
  140. </div>
  141. <label v-else style="display: inline-block;">
  142. <div class="uploadBox">
  143. <i class="el-icon-plus"></i>
  144. </div>
  145. <input
  146. style="display: none;"
  147. type="file"
  148. @change="uploadImg($event, item.fieldKey)"
  149. />
  150. </label>
  151. <span
  152. v-if="item.fieldKey == 'commitment_seal'"
  153. class="btn_text"
  154. @click="downloadStamp"
  155. >下载模板</span
  156. >
  157. <span style="vertical-align: bottom;color: #a4a4a4;" v-else>{{
  158. item.fieldKey == "recent_photos"
  159. ? "竖向白底证件照 文件大小<2M"
  160. : "文件大小<2M"
  161. }}</span>
  162. </el-form-item>
  163. </template>
  164. <el-form-item
  165. v-else-if="item.inputType == 5"
  166. :label="item.fieldName"
  167. label-width="120px"
  168. :prop="item.fieldKey"
  169. ><el-date-picker
  170. type="date"
  171. v-model="infoForm[item.fieldKey]"
  172. :placeholder="`请选择${item.fieldName}`"
  173. value-format="yyyy-MM-dd"
  174. >
  175. </el-date-picker>
  176. </el-form-item>
  177. </el-col>
  178. </el-form>
  179. </el-row>
  180. <div
  181. style="color:red;display: flex;"
  182. v-if="historyData.text && historyData.text.length > 0"
  183. >
  184. <div style="width:110px;">审核结果反馈:</div>
  185. <div>{{ historyData.text }}</div>
  186. </div>
  187. </div>
  188. <span slot="footer" class="dialog-footer">
  189. <el-button @click="close">取 消</el-button>
  190. <el-button type="primary" @click="submitForm" :loading="uploading"
  191. >确 定</el-button
  192. >
  193. </span>
  194. </el-dialog>
  195. </div>
  196. </template>
  197. <script>
  198. import * as imageConversion from "image-conversion";
  199. export default {
  200. name: "",
  201. props: {},
  202. data() {
  203. return {
  204. listData: [],
  205. options: {},
  206. infoForm: {},
  207. rules: {},
  208. historyData: {}, //历史数据
  209. cacheIdCardData: {}, //身份证数据
  210. nameDisabledStatus: false,
  211. idcardDisabledStatus: false,
  212. telphoneDisabledStatus: false,
  213. uploading: false,
  214. isShow: false,
  215. activeData: {},
  216. idcard_face_photo_old: "",
  217. recent_photos_old: "",
  218. checkStatus: 0, //是否审核通过才允许学习 1是0否
  219. STATUS: false //区分个人中心入口操作
  220. };
  221. },
  222. computed: {
  223. eduDisAbledStatus: function() {
  224. return function(item) {
  225. if (
  226. this.activeData.educationName == "继续教育" &&
  227. this.activeData.projectName == "施工现场专业人员" &&
  228. this.activeData.businessName == "七大员"
  229. ) {
  230. if (
  231. this.activeData.categoryName == "材料员" ||
  232. this.activeData.categoryName == "资料员" ||
  233. this.activeData.categoryName == "劳务员"
  234. ) {
  235. let list = [
  236. "职高",
  237. "高中",
  238. "专科",
  239. "本科",
  240. "硕士研究生",
  241. "博士研究生"
  242. ];
  243. return !list.includes(item);
  244. } else {
  245. let list = ["专科", "本科", "硕士研究生", "博士研究生"];
  246. return !list.includes(item);
  247. }
  248. } else {
  249. return false;
  250. }
  251. };
  252. }
  253. },
  254. methods: {
  255. async init(item, status = false) {
  256. this.STATUS = status;
  257. console.log(item, "item");
  258. this.activeData = item;
  259. //获取初始数据
  260. try {
  261. await this.getInitData();
  262. console.log("1");
  263. //获取历史数据
  264. await this.getHistoricalRecord();
  265. console.log("2");
  266. this.isShow = true;
  267. //回填数据
  268. this.backFillData();
  269. console.log("3");
  270. } catch (error) {
  271. console.log("4");
  272. console.log("抛出:", error);
  273. }
  274. },
  275. getInitData() {
  276. return new Promise((resolve, reject) => {
  277. let commitDictAry = {
  278. sex: "sys_user_sex",
  279. education: "edu_level",
  280. working_years: "working_years",
  281. apply_post: "apply_post"
  282. };
  283. this.$request.getbaseprofiletpId(this.activeData.goodsId).then(res => {
  284. if (!res.data) {
  285. //不需要填写
  286. this.isShow = false;
  287. this.$emit("callbackDataReview");
  288. return reject("不需要填写");
  289. }
  290. let Ary = [
  291. ...JSON.parse(res.data.keyValue),
  292. ...JSON.parse(res.data.keyValue2)
  293. ];
  294. let Obj = {};
  295. this.checkStatus = res.data.checkStatus || 0;
  296. Ary.forEach(i => {
  297. Obj[i.fieldKey] = [
  298. {
  299. required: i.required,
  300. message: `请${
  301. i.inputType == 1
  302. ? "输入"
  303. : i.inputType == 2 || i.inputType == 5
  304. ? "选择"
  305. : "上传"
  306. }${i.fieldName}`,
  307. trigger: i.inputType == 1 ? "blur" : "change"
  308. }
  309. ];
  310. if (i.fieldKey == "unit_tel" && i.required) {
  311. Obj[i.fieldKey].push({
  312. validator: (rule, value, callback) => {
  313. var reg_tel = /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/;
  314. var vartest = /^([0-9]{3,4}-)?[0-9]{7,8}$/;
  315. var vartest1 = /^([0-9]{3,4})?[0-9]{7,8}$/;
  316. if (
  317. reg_tel.test(value) ||
  318. vartest.test(value) ||
  319. vartest1.test(value)
  320. ) {
  321. return callback();
  322. } else {
  323. return callback(new Error("单位联系电话不正确"));
  324. }
  325. },
  326. trigger: ["change", "blur"]
  327. });
  328. }
  329. if (i.inputType == 2) {
  330. this.options[i.fieldKey] = this.$store.state.dictList[
  331. commitDictAry[i.fieldKey]
  332. ];
  333. }
  334. });
  335. this.rules = Obj;
  336. this.listData = Ary;
  337. resolve();
  338. });
  339. });
  340. },
  341. //获取历史记录
  342. getHistoricalRecord() {
  343. return new Promise((resolve, reject) => {
  344. this.$request
  345. .getbaseprofiletpgetInfo({
  346. goodsId: this.activeData.goodsId,
  347. orderGoodsId: this.activeData.orderGoodsId
  348. })
  349. .then(res => {
  350. if (!res.data) {
  351. //提示填写规则
  352. this.$confirm(`请填写资料`, "温馨提示", {
  353. confirmButtonText: "确定",
  354. cancelButtonText: "取消",
  355. closeOnClickModal: false,
  356. closeOnPressEscape: false,
  357. distinguishCancelAndClose: false,
  358. showClose: false
  359. })
  360. .then(_ => {
  361. let str = this.listData.map(i => i.fieldName).join("、");
  362. this.$confirm(
  363. `
  364. 本产品(或服务)提供【${this.activeData.goodsName}】课程的在线学习功能,为使用这些功能,我们需要使用您设备上的摄像头,并收集以下个人信息:
  365. ${str}
  366. ,学习详细记录。
  367. 我们会将上述信息提供至广东省建设执业注册管理中心等第三方组织使用,用于继续教育备案等。如果您拒绝,将导致这些功能无法实现,但不影响您使用本产品(或服务)的其他业务功能。
  368. `,
  369. "提示",
  370. {
  371. confirmButtonText: "确定",
  372. cancelButtonText: "返回",
  373. closeOnClickModal: false,
  374. closeOnPressEscape: false,
  375. distinguishCancelAndClose: false,
  376. showClose: false
  377. }
  378. )
  379. .then(_ => {
  380. resolve();
  381. })
  382. .catch(_ => {
  383. //停止执行-退出页面
  384. this.$router.back(-1);
  385. });
  386. })
  387. .catch(_ => {
  388. //停止执行-退出页面
  389. this.$router.back(-1);
  390. });
  391. } else if (res.data.status === 3 && res.data.changeStatus === 1) {
  392. //资料审核不通过,请前往重新填写
  393. this.$confirm(`资料审核不通过,请前往重新填写`, "提示", {
  394. confirmButtonText: "确定",
  395. cancelButtonText: "返回",
  396. closeOnClickModal: false,
  397. closeOnPressEscape: false,
  398. distinguishCancelAndClose: false,
  399. showClose: false
  400. })
  401. .then(_ => {
  402. this.historyData = Object.assign(
  403. { id: res.data.id, text: res.data.text },
  404. JSON.parse(res.data.keyValue)
  405. ); //历史数据
  406. resolve();
  407. })
  408. .catch(_ => {
  409. //停止执行-退出页面
  410. this.$router.back(-1);
  411. });
  412. } else if (this.STATUS) {
  413. this.historyData = Object.assign(
  414. { id: res.data.id },
  415. JSON.parse(res.data.keyValue)
  416. ); //历史数据
  417. resolve();
  418. } else if (this.checkStatus == 1 && res.data.status !== 1) {
  419. //后台设置需要审核通过才允许学习
  420. this.checkFunc();
  421. } else {
  422. this.isShow = false;
  423. //不需要填写
  424. this.$emit("callbackDataReview");
  425. return reject("不需要填写");
  426. }
  427. });
  428. });
  429. },
  430. //回填数据
  431. backFillData() {
  432. if (Object.keys(this.historyData).length > 0 || this.historyData.id) {
  433. for (let i in this.historyData) {
  434. this.$set(
  435. this.infoForm,
  436. i,
  437. this.historyData[i] ? this.historyData[i].value : null
  438. );
  439. if (i == "recent_photos") {
  440. this.recent_photos_old = this.historyData[i].value;
  441. }
  442. if (i == "idcard_face_photo") {
  443. this.idcard_face_photo_old = this.historyData[i].value;
  444. }
  445. }
  446. this.$nextTick(() => {
  447. this.$refs["infoForm"].clearValidate();
  448. });
  449. } else {
  450. if (!this.infoForm["name"]) {
  451. if (this.$store.state.userInfo.realname) {
  452. this.$set(
  453. this.infoForm,
  454. "name",
  455. this.$store.state.userInfo.realname
  456. );
  457. this.nameDisabledStatus = true;
  458. }
  459. } else {
  460. this.nameDisabledStatus = true;
  461. }
  462. if (!this.infoForm["idcard"]) {
  463. if (this.$store.state.userInfo.idCard) {
  464. this.$set(
  465. this.infoForm,
  466. "idcard",
  467. this.$store.state.userInfo.idCard
  468. );
  469. this.idcardDisabledStatus = true;
  470. }
  471. } else {
  472. this.idcardDisabledStatus = true;
  473. }
  474. if (!this.infoForm["telphone"]) {
  475. if (this.$store.state.userInfo.telphone) {
  476. this.$set(
  477. this.infoForm,
  478. "telphone",
  479. this.$store.state.userInfo.telphone
  480. );
  481. this.telphoneDisabledStatus = true;
  482. }
  483. } else {
  484. this.telphoneDisabledStatus = true;
  485. }
  486. if (
  487. !this.infoForm["work_unit"] &&
  488. this.$store.state.userInfo.companyName
  489. ) {
  490. this.$set(
  491. this.infoForm,
  492. "work_unit",
  493. this.$store.state.userInfo.companyName
  494. );
  495. }
  496. if (!this.infoForm["sex"] && this.$store.state.userInfo.sex) {
  497. this.$set(
  498. this.infoForm,
  499. "sex",
  500. this.$store.state.userInfo.sex == 1
  501. ? "男"
  502. : this.$store.state.userInfo.sex == 2
  503. ? "女"
  504. : null
  505. );
  506. }
  507. if (
  508. !this.infoForm["education"] &&
  509. this.$store.state.userInfo.eduLevel &&
  510. !(
  511. this.activeData.educationName == "继续教育" &&
  512. this.activeData.projectName == "施工现场专业人员" &&
  513. this.activeData.businessName == "七大员"
  514. )
  515. ) {
  516. this.$set(
  517. this.infoForm,
  518. "education",
  519. this.$store.state.userInfo.eduLevel
  520. );
  521. }
  522. if (
  523. !this.infoForm["recent_photos"] &&
  524. this.$store.state.userInfo.oneInchPhotos
  525. ) {
  526. this.$set(
  527. this.infoForm,
  528. "recent_photos",
  529. this.$store.state.userInfo.oneInchPhotos
  530. );
  531. this.recent_photos_old = this.$store.state.userInfo.oneInchPhotos;
  532. }
  533. if (
  534. !this.infoForm["idcard_face_photo"] &&
  535. this.$store.state.userInfo.idCardImg1
  536. ) {
  537. this.$set(
  538. this.infoForm,
  539. "idcard_face_photo",
  540. this.$store.state.userInfo.idCardImg1
  541. );
  542. this.idcard_face_photo_old = this.$store.state.userInfo.idCardImg1;
  543. }
  544. if (
  545. !this.infoForm["idcard_national_photo"] &&
  546. this.$store.state.userInfo.idCardImg2
  547. ) {
  548. this.$set(
  549. this.infoForm,
  550. "idcard_national_photo",
  551. this.$store.state.userInfo.idCardImg2
  552. );
  553. }
  554. }
  555. },
  556. //审核通过才允许学习
  557. checkFunc() {
  558. //后台设置需要审核通过才允许学习
  559. this.$confirm(
  560. `资料正在审核中,暂无法学习,请耐心等待!如需加急审核,请联系客服人员`,
  561. "提示",
  562. {
  563. confirmButtonText: "确定",
  564. cancelButtonText: "返回",
  565. closeOnClickModal: false,
  566. closeOnPressEscape: false,
  567. distinguishCancelAndClose: false,
  568. showClose: false
  569. }
  570. )
  571. .then(_ => {
  572. //停止执行-退出页面
  573. this.$router.back(-1);
  574. })
  575. .catch(_ => {
  576. //停止执行-退出页面
  577. this.$router.back(-1);
  578. });
  579. },
  580. //照片处理逻辑
  581. async uploadImg(e, item) {
  582. try {
  583. let A = ["idcard_face_photo"].indexOf(item); //["idcard_face_photo","idcard_national_photo"]
  584. let file = await this.uploadRules(e.target.files[0]);
  585. if (A !== -1) {
  586. const res = await this.faceCertificationIDCardOCR(A + 1, file);
  587. if (res.code == 500) {
  588. this.$message.error(res.msg);
  589. } else {
  590. this.cacheIdCardData = res.data;
  591. //身份证姓名身份证比对
  592. await this.idCardDataComparison();
  593. this.$set(this.infoForm, item, res.data.IdImgPath);
  594. }
  595. } else {
  596. this.$set(
  597. this.infoForm,
  598. item,
  599. await this.$upload.upload(file, 0, {}, false)
  600. );
  601. }
  602. this.$refs["infoForm"].validateField(item);
  603. e.target.value = "";
  604. } catch (error) {
  605. e.target.value = "";
  606. }
  607. },
  608. //清空签名板
  609. retDraw() {
  610. this.$set(this.infoForm, "commitment_electr_signature", "");
  611. this.$nextTick(() => {
  612. this.$refs.esign[0].reset();
  613. });
  614. },
  615. //校验及压缩
  616. uploadRules(file) {
  617. return new Promise((resolve, reject) => {
  618. const fileType = file.type;
  619. const isImage = fileType.indexOf("image") != -1;
  620. const sizeToM = file.size / 1024 / 1024;
  621. if (!isImage) {
  622. this.$message.error("只能上传图片格式png、jpg、gif!");
  623. reject(false);
  624. }
  625. if (sizeToM > 2) {
  626. imageConversion
  627. .compressAccurately(file, {
  628. size: 1024 * 2,
  629. width: 1000,
  630. height: 1000
  631. })
  632. .then(res => {
  633. res = new File([res], file.name, { type: res.type });
  634. resolve(res);
  635. });
  636. } else {
  637. resolve(file);
  638. }
  639. });
  640. },
  641. //身份证校验
  642. faceCertificationIDCardOCR(cardSide, file) {
  643. return new Promise(resolve => {
  644. var reader = new FileReader();
  645. // 将文件加载进入
  646. reader.readAsDataURL(file);
  647. reader.onload = e => {
  648. // 转换完成输出该文件base64编码
  649. let base64 = e.target.result;
  650. this.$request
  651. .faceCertificationIDCardOCR({
  652. cardSide: cardSide, //1人像 2 国徽
  653. cardImageBase64: base64,
  654. gradeId: this.activeData.gradeId
  655. })
  656. .then(res => {
  657. resolve(res);
  658. })
  659. .catch(err => {
  660. resolve(err);
  661. });
  662. };
  663. });
  664. },
  665. //身份证姓名身份证比对
  666. idCardDataComparison() {
  667. return new Promise((resolve, reject) => {
  668. if (
  669. this.infoForm["name"] &&
  670. this.cacheIdCardData["IdName"] &&
  671. this.infoForm["name"].trim() !== this.cacheIdCardData["IdName"]
  672. ) {
  673. var str = "输入的姓名和身份证人像面照片姓名不匹配,请联系客服";
  674. this.$message.warning(str);
  675. reject(str);
  676. } else if (
  677. this.infoForm["idcard"] &&
  678. this.cacheIdCardData["IdNum"] &&
  679. this.infoForm["idcard"] !== this.cacheIdCardData["IdNum"]
  680. ) {
  681. var str = "输入的身份证号和身份证人像面照片身份证号不匹配,请联系客服";
  682. this.$message.warning(str);
  683. reject(str);
  684. } else {
  685. resolve();
  686. }
  687. });
  688. },
  689. async downloadStamp() {
  690. await this.subCanvas();
  691. this.$request
  692. .baseProfileStampV2AddWord({
  693. goodsId: this.activeData.goodsId,
  694. keyValue: this.returnData()
  695. })
  696. .then(res => {
  697. let url = this.$tools.splitImgHost(res.msg);
  698. let name = res.msg.substring(res.msg.lastIndexOf("/") + 1);
  699. let image = new Image();
  700. // 解决跨域 Canvas 污染问题,
  701. image.setAttribute("crossorigin", "anonymous");
  702. image.onload = function() {
  703. var canvas = document.createElement("canvas");
  704. canvas.width = image.width;
  705. canvas.height = image.height;
  706. var context = canvas.getContext("2d");
  707. context.drawImage(image, 0, 0, image.width, image.height);
  708. var base64 = canvas.toDataURL("image/jpg"); //将图片格式转为base64
  709. var a = document.createElement("a"); // 生成一个a元素
  710. var event = new MouseEvent("click"); // 创建一个单击事件
  711. a.download = name; // 设置图片名称
  712. console.log(base64);
  713. a.href = base64; // 将生成的URL设置为a.href属性
  714. a.dispatchEvent(event); // 触发a的单击事件
  715. };
  716. image.src = url + "?time=" + Date.now(); //注意,这里是灵魂,否则依旧会产生跨域问题
  717. });
  718. },
  719. //将canvas签名生产oss地址
  720. subCanvas() {
  721. return new Promise((resolve, reject) => {
  722. const STATUS = this.listData.findIndex(
  723. i => i.fieldKey == "commitment_electr_signature"
  724. );
  725. if (!this.infoForm["commitment_electr_signature"] && STATUS !== -1) {
  726. this.$refs.esign[0]
  727. .generate() // 使用生成器调用把签字的图片转换成为base64图片格式
  728. .then(async res => {
  729. let url = await this.$upload.upload(
  730. this.convertBase64UrlToBlob(res),
  731. 0
  732. );
  733. this.$set(this.infoForm, "commitment_electr_signature", url);
  734. this.$refs["infoForm"].validateField(
  735. "commitment_electr_signature"
  736. );
  737. resolve();
  738. })
  739. .catch(err => {
  740. console.log(err, "err");
  741. resolve();
  742. });
  743. } else {
  744. resolve();
  745. }
  746. });
  747. },
  748. //canvas转file
  749. convertBase64UrlToBlob(urlData) {
  750. var localData = urlData; //dataUrl为base64位
  751. let base = atob(localData.substring(localData.indexOf(",") + 1)); // base是将base64编码解码,去掉data:image/png;base64部分
  752. let length = base.length;
  753. let url = new Uint8Array(length);
  754. while (length--) {
  755. url[length] = base.charCodeAt(length);
  756. }
  757. let file = new File([url], "a.jpg", {
  758. type: "image/jpg"
  759. });
  760. //最后将file,通过ajax请求做为参数传给服务器就可以了
  761. return file;
  762. },
  763. //证件照与身份证匹配
  764. IdCardCompareFace() {
  765. return new Promise(async (resolve, reject) => {
  766. if (
  767. !(
  768. this.infoForm["idcard_face_photo"] &&
  769. this.infoForm["recent_photos"] &&
  770. (this.infoForm["idcard_face_photo"] !==
  771. this.idcard_face_photo_old ||
  772. this.infoForm["recent_photos"] !== this.recent_photos_old)
  773. )
  774. ) {
  775. resolve();
  776. return;
  777. }
  778. this.$request
  779. .faceCertificationIdCardCompareFace({
  780. urlA: this.infoForm["idcard_face_photo"],
  781. oneInchPhotos: await this.$tools.imageToBase64(
  782. this.$tools.splitImgHost(this.infoForm["recent_photos"])
  783. )
  784. })
  785. .then(res => {
  786. if (res.data >= 70) {
  787. resolve();
  788. } else {
  789. var str = "证件照和身份证人像面照片不匹配";
  790. this.$message.warning(str);
  791. reject(str);
  792. }
  793. })
  794. .catch(err => {
  795. reject(err);
  796. });
  797. });
  798. },
  799. close() {
  800. if (this.STATUS) {
  801. this.isShow = false;
  802. } else {
  803. this.$router.back(-1);
  804. }
  805. },
  806. returnData() {
  807. let map = new Map();
  808. this.listData.forEach(i => {
  809. map.set(i.fieldKey, {
  810. fieldKey: i.fieldKey,
  811. value: this.infoForm[i.fieldKey],
  812. fieldName: i.fieldName,
  813. status: this.historyData[i.fieldKey]
  814. ? this.infoForm[i.fieldKey] == this.historyData[i.fieldKey].value
  815. ? 0
  816. : 1
  817. : 0
  818. });
  819. });
  820. return JSON.stringify(Object.fromEntries(map));
  821. },
  822. async submitForm() {
  823. //签名需在表单验证前执行完毕 否则会导致表单验证不通过
  824. await this.subCanvas();
  825. this.$refs["infoForm"].validate(async valid => {
  826. if (valid) {
  827. //独立操作上传承诺书
  828. if (this.STATUS) {
  829. this.uploading = true;
  830. if (this.infoForm["commitment_seal"]) {
  831. this.$request
  832. .baseprofiletpcommitmentupload({
  833. id: this.historyData.id,
  834. imageUrl: this.infoForm["commitment_seal"]
  835. })
  836. .then(res => {
  837. this.$message.success("提交成功");
  838. this.isShow = false;
  839. this.$emit("callbackDataReview");
  840. })
  841. .catch(err => {
  842. this.$message.error(err.msg);
  843. })
  844. .finally(() => {
  845. this.uploading = false;
  846. });
  847. } else {
  848. this.$message.error("请上传承诺书盖章");
  849. this.uploading = false;
  850. }
  851. return;
  852. }
  853. //end
  854. try {
  855. this.uploading = true;
  856. await this.idCardDataComparison();
  857. await this.IdCardCompareFace();
  858. let obj = this.returnData();
  859. if (this.historyData.id) {
  860. let data = {
  861. id: this.historyData.id,
  862. goodsId: this.activeData.goodsId,
  863. orderGoodsId: this.activeData.orderGoodsId,
  864. keyValue: obj
  865. };
  866. this.$request
  867. .editbaseprofiletp(data)
  868. .then(res => {
  869. this.$message.success("提交成功");
  870. this.isShow = false;
  871. if (this.checkStatus == 1) {
  872. //后台设置需要审核通过才允许学习
  873. this.checkFunc();
  874. return;
  875. }
  876. this.$emit("callbackDataReview");
  877. })
  878. .catch(err => {
  879. this.$message.warning(err.msg);
  880. })
  881. .finally(() => {
  882. this.uploading = false;
  883. });
  884. } else {
  885. let data = {
  886. profileTpId: this.activeData.goodsId,
  887. goodsId: this.activeData.goodsId,
  888. orderGoodsId: this.activeData.orderGoodsId,
  889. keyValue: obj
  890. };
  891. this.$request
  892. .addbaseprofiletp(data)
  893. .then(res => {
  894. this.$message.success("提交成功");
  895. this.isShow = false;
  896. if (this.checkStatus == 1) {
  897. //后台设置需要审核通过才允许学习
  898. this.checkFunc();
  899. return;
  900. }
  901. this.$emit("callbackDataReview");
  902. })
  903. .catch(err => {
  904. this.$message.warning(err.msg);
  905. })
  906. .finally(() => {
  907. this.uploading = false;
  908. });
  909. }
  910. } catch (error) {
  911. this.uploading = false;
  912. }
  913. } else {
  914. console.log("error submit!!");
  915. return false;
  916. }
  917. });
  918. }
  919. }
  920. };
  921. </script>
  922. <style lang="scss" scoped>
  923. /deep/ .el-dialog {
  924. margin-top: 2vh !important;
  925. border-radius: 18px;
  926. & > .el-dialog__header {
  927. border-bottom: 2px solid #eee;
  928. & > .el-dialog__title {
  929. font-size: 16px;
  930. }
  931. }
  932. }
  933. .uploadBox {
  934. border: 2px dotted rgb(190, 190, 190);
  935. display: flex;
  936. align-items: center;
  937. justify-content: center;
  938. width: 80px;
  939. height: 80px;
  940. border-radius: 8px;
  941. & > i {
  942. font-size: 30px;
  943. font-weight: bold;
  944. color: rgb(190, 190, 190);
  945. }
  946. }
  947. .cns_sq {
  948. display: flex;
  949. background-color: rgb(247, 248, 250);
  950. border-radius: 8px;
  951. height: 330px;
  952. margin-bottom: 22px;
  953. .left {
  954. flex: 1;
  955. padding: 10px 20px;
  956. p {
  957. line-height: 30px;
  958. }
  959. }
  960. .right {
  961. flex: 1;
  962. padding: 10px 20px;
  963. h3 {
  964. display: flex;
  965. align-items: center;
  966. justify-content: space-between;
  967. margin-bottom: 16px;
  968. .texts {
  969. color: #a4a4a4;
  970. }
  971. }
  972. }
  973. }
  974. .btn_text {
  975. color: #409eff;
  976. cursor: pointer;
  977. user-select: none;
  978. font-weight: 400;
  979. margin-left: 8px;
  980. }
  981. </style>