authenticate.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773
  1. <template>
  2. <view class="container">
  3. <wd-form ref="form" :model="formValue">
  4. <wd-cell-group border>
  5. <wd-input
  6. v-model="formValue.username"
  7. label="姓名"
  8. label-width="100px"
  9. prop="username"
  10. clearable
  11. placeholder="请输入姓名"
  12. :rules="[{ required: false, validator: validatorName, message: '请输入姓名' }]"
  13. />
  14. <wd-input
  15. v-if="cardType == '教师认证'"
  16. v-model="formValue.cardNumber"
  17. label="工号"
  18. label-width="100px"
  19. prop="cardNumber"
  20. clearable
  21. placeholder="请输入工号"
  22. :rules="[
  23. {
  24. required: false,
  25. message: '请输入工号'
  26. }
  27. ]"
  28. />
  29. <wd-input
  30. v-if="cardType == '暖心认证'"
  31. v-model="formValue.cardNumber"
  32. label="学号"
  33. label-width="100px"
  34. prop="cardNumber"
  35. clearable
  36. placeholder="请输入学号"
  37. :rules="[
  38. {
  39. required: false,
  40. message: '请输入学号'
  41. }
  42. ]"
  43. />
  44. <wd-input
  45. v-if="cardType == '教师认证'"
  46. v-model="formValue.college"
  47. label="所在院系"
  48. label-width="100px"
  49. prop="college"
  50. clearable
  51. placeholder="请输入所在院系"
  52. :rules="[
  53. {
  54. required: false,
  55. message: '请输入所在院系'
  56. }
  57. ]"
  58. />
  59. <wd-input
  60. v-if="cardType == '教师认证'"
  61. v-model="formValue.professor"
  62. label="职称"
  63. label-width="100px"
  64. prop="professor"
  65. clearable
  66. placeholder="请输入职称"
  67. :rules="[
  68. {
  69. required: false,
  70. message: '请输入职称'
  71. }
  72. ]"
  73. />
  74. <!-- <wd-input
  75. v-if="cardType == '暖心认证'"
  76. v-model="formValue.instructor"
  77. label="辅导员姓名"
  78. label-width="100px"
  79. prop="instructor"
  80. clearable
  81. placeholder="请输入辅导员姓名"
  82. :rules="[
  83. {
  84. required: false,
  85. message: '请输入辅导员姓名'
  86. }
  87. ]"
  88. /> -->
  89. <wd-input
  90. v-model="formValue.mobile"
  91. v-if="cardType == '教师认证'"
  92. label="手机号"
  93. label-width="100px"
  94. prop="mobile"
  95. clearable
  96. placeholder="请输入手机号码"
  97. :rules="[
  98. {
  99. required: false,
  100. validator: validatorPhone,
  101. message: '请输入手机号码'
  102. }
  103. ]"
  104. />
  105. <wd-cell prop="imgurl" v-if="cardType == '教师认证'">
  106. <view class="form_title">上传证件:</view>
  107. <wd-upload :file-list="frontFileList" :custom-upload="customUpload1"
  108. :limit="1"
  109. :build-form-data="beforeChoose1"
  110. :formData="formData2"
  111. @change="handleFrontChange">
  112. <view class="upload">
  113. <wd-icon color="#ABA6A6" name="photo" size="27"></wd-icon>
  114. 身份证正面
  115. </view>
  116. </wd-upload>
  117. </wd-cell>
  118. <wd-cell prop="imgurlBack" v-if="cardType == '教师认证'">
  119. <wd-upload :file-list="backFileList"
  120. :custom-upload="customUpload"
  121. :limit="1"
  122. :build-form-data="beforeChoose"
  123. :formData="formData2"
  124. @change="handleFileChange"
  125. >
  126. <view class="upload">
  127. <wd-icon color="#ABA6A6" name="photo" size="27"></wd-icon>
  128. 身份证反面
  129. </view>
  130. </wd-upload>
  131. </wd-cell>
  132. </wd-cell-group>
  133. <view class="footer">
  134. <wd-button type="primary" size="large" block @click="handleSubmit">点击提交</wd-button>
  135. </view>
  136. </wd-form>
  137. </view>
  138. </template>
  139. <script setup>
  140. import { ref,computed,watch } from 'vue'
  141. import { onLoad } from '@dcloudio/uni-app'
  142. import { myRequest,myUploadFile } from '@/utils/api.ts'
  143. import getLessLimitSizeImage from '@/utils/imageCompress.js'
  144. const BASE_URL = 'https://car.meiyishuoo.com/ride-sharing/carBuy'; //
  145. const cardType = ref('')
  146. // 表格绑定数据
  147. const formValue = ref({
  148. id: uni.getStorageSync('carUserInfo').id ,
  149. username: '',
  150. cardNumber: '',
  151. college: '',
  152. professor: '',
  153. // instructor: '',
  154. mobile: '',
  155. file1: '',
  156. file2: '',
  157. })
  158. const info = ref({})
  159. // 存储两处上传的文件列表
  160. const frontFileList = ref([]); // 身份证正面
  161. const backFileList = ref([]); // 身份证反面
  162. // 上传额外参数(响应式)
  163. const formData2 = computed(() => ({
  164. type: 'idCardBack' // 身份证反面标识,固定参数
  165. }));
  166. // 表格DOM
  167. const form = ref(null)
  168. // 是否修改
  169. const ifXiu = ref(false)
  170. // 监听backFileList变化,同步到formValue.file1
  171. // watch(
  172. // backFileList,
  173. // (newList) => {
  174. // // 取最新上传的第一张图片的url(若存在)
  175. // if (newList.length > 0) {
  176. // formValue.value.file2 = newList[0] || '';
  177. // } else {
  178. // // 若列表为空,清空file2(可选)
  179. // formValue.value.file2 = '';
  180. // }
  181. // console.log('formValue.file2已同步:', formValue.value.file2,formValue.value);
  182. // },
  183. // { deep: true }, // 深度监听,确保数组内对象变化也能触发
  184. // frontFileList,
  185. // (newList) => {
  186. // // 取最新上传的第一张图片的url(若存在)
  187. // if (newList.length > 0) {
  188. // formValue.value.file1 = newList[0] || '';
  189. // } else {
  190. // // 若列表为空,清空file1(可选)
  191. // formValue.value.file1 = '';
  192. // }
  193. // console.log('formValue.file1已同步:', formValue.value.file1);
  194. // },
  195. // { deep: true }, // 深度监听,确保数组内对象变化也能触发
  196. // );
  197. onLoad((options) => {
  198. console.log(options)
  199. if (options.cardType) {
  200. cardType.value = options.cardType
  201. if (options.info) {
  202. ifXiu.value=true
  203. uni.setNavigationBarTitle({
  204. title: '修改认证'
  205. })
  206. formValue.value = JSON.parse(decodeURIComponent(options.info))
  207. console.log(formValue.value)
  208. // 同步已上传的图片到上传组件的文件列表
  209. if (formValue.value.file1) {
  210. frontFileList.value.push(formValue.value.file1)
  211. }
  212. if (formValue.value.file2) {
  213. backFileList.value.push(formValue.value.file2)
  214. }
  215. } else {
  216. ifXiu.value=false
  217. uni.setNavigationBarTitle({
  218. title: cardType.value
  219. })
  220. }
  221. }
  222. })
  223. // 处理身份证正面上传变化
  224. // 文件选择前的校验与参数处理
  225. const beforeChoose1 = async ({ file, formData, resolve }) => {
  226. // 1. 提取文件后缀(修复原代码中file.url的错误,小程序中临时路径用path)
  227. const tempPath = file.path || file.url; // 兼容H5和小程序
  228. const lastDotIndex = tempPath.lastIndexOf('.');
  229. const fileExt = lastDotIndex > -1 ? tempPath.slice(lastDotIndex + 1).toLowerCase() : '';
  230. console.log('文件信息:', file, '路径:', tempPath, '后缀:', fileExt);
  231. // 2. 校验文件是否已上传(通过文件名去重)
  232. if (frontFileList.value.some(item => item.name === file.name)) {
  233. uni.showToast({ title: '当前图片已上传,请选择其他照片', icon: 'none' });
  234. resolve(false); // 阻止上传
  235. return;
  236. }
  237. // 3. 校验文件大小(5M以内)
  238. if (file.size >= 5 * 1024 * 1024) {
  239. uni.showToast({ title: '请上传小于5M的图片', icon: 'none' });
  240. resolve(false); // 阻止上传
  241. return;
  242. }
  243. // 4. 校验文件类型
  244. if (!['png', 'jpg', 'jpeg'].includes(fileExt)) {
  245. uni.showToast({ title: '请上传png/jpg/jpeg格式的图片', icon: 'none' });
  246. resolve(false); // 阻止上传
  247. return;
  248. }
  249. // 校验通过:返回包含允许上传的标识(兼容组件要求)
  250. resolve({
  251. ...formData,
  252. allowUpload: true // 显式允许上传
  253. });
  254. try {
  255. // 调用封装的上传方法
  256. const res = await myUploadFile({
  257. url: '/filesload.action',
  258. filePath: file.path || file.url, // 临时文件路径
  259. name: 'myFile', // 后端接收文件的字段名
  260. formData: formData2.value // 额外参数
  261. });
  262. if (res.code === 200) {
  263. frontFileList.value.push(res.data.url);
  264. uni.showToast({ title: '上传成功', icon: 'none' });
  265. console.log('上传成功,图片链接:', res.data.url,frontFileList);
  266. } else {
  267. // 接口返回错误
  268. // onError(res.message || '上传失败1');
  269. uni.showToast({ title: res.message || '上传失败2', icon: 'none' });
  270. }
  271. } catch (err) {
  272. console.error('上传失败:', err);
  273. uni.showToast({ title: '网络异常,请重试', icon: 'none' });
  274. }
  275. };
  276. const handleFrontChange = async ({ fileList }) => {
  277. frontFileList.value = fileList; // 自动同步删除后的列表
  278. };
  279. // 处理身份证反面上传
  280. // 文件选择前的校验与参数处理
  281. const beforeChoose = async ({ file, formData, resolve }) => {
  282. // 1. 提取文件后缀(修复原代码中file.url的错误,小程序中临时路径用path)
  283. const tempPath = file.path || file.url; // 兼容H5和小程序
  284. const lastDotIndex = tempPath.lastIndexOf('.');
  285. const fileExt = lastDotIndex > -1 ? tempPath.slice(lastDotIndex + 1).toLowerCase() : '';
  286. console.log('文件信息:', file, '路径:', tempPath, '后缀:', fileExt);
  287. // 2. 校验文件是否已上传(通过文件名去重)
  288. if (backFileList.value.some(item => item.name === file.name)) {
  289. uni.showToast({ title: '当前图片已上传,请选择其他照片', icon: 'none' });
  290. resolve(false); // 阻止上传
  291. return;
  292. }
  293. // 3. 校验文件大小(5M以内)
  294. if (file.size >= 5 * 1024 * 1024) {
  295. uni.showToast({ title: '请上传小于5M的图片', icon: 'none' });
  296. resolve(false); // 阻止上传
  297. return;
  298. }
  299. // 4. 校验文件类型
  300. if (!['png', 'jpg', 'jpeg'].includes(fileExt)) {
  301. uni.showToast({ title: '请上传png/jpg/jpeg格式的图片', icon: 'none' });
  302. resolve(false); // 阻止上传
  303. return;
  304. }
  305. // 校验通过:返回包含允许上传的标识(兼容组件要求)
  306. resolve({
  307. ...formData,
  308. allowUpload: true // 显式允许上传
  309. });
  310. console.log('beforeChoose校验通过,允许上传');
  311. try {
  312. // 调用封装的上传方法
  313. const res = await myUploadFile({
  314. url: '/filesload.action',
  315. filePath: file.path || file.url, // 临时文件路径
  316. name: 'myFile', // 后端接收文件的字段名
  317. formData: formData2.value // 额外参数
  318. });
  319. if (res.code === 200) {
  320. console.log(122)
  321. // 上传成功:调用组件的onSuccess更新文件列表
  322. // onSuccess({
  323. // ...file,
  324. // url: res.data.url, // 后端返回的在线图片地址
  325. // status: 'success' // 标记为成功状态
  326. // });
  327. backFileList.value.push(res.data.url);
  328. uni.showToast({ title: '上传成功', icon: 'none' });
  329. console.log('上传成功,图片链接:', res.data.url,backFileList);
  330. } else {
  331. // 接口返回错误
  332. // onError(res.message || '上传失败1');
  333. uni.showToast({ title: res.message || '上传失败2', icon: 'none' });
  334. }
  335. } catch (err) {
  336. // 网络错误或其他异常
  337. // onError('网络异常,请重试');
  338. console.error('上传失败:', err);
  339. uni.showToast({ title: '网络异常,请重试', icon: 'none' });
  340. }
  341. };
  342. // 监听文件列表变化(删除后会触发)
  343. const handleFileChange = ({ fileList }) => {
  344. backFileList.value = fileList; // 自动同步删除后的列表
  345. // console.log('当前文件列表:', backFileList);
  346. };
  347. // // 自定义上传逻辑(覆盖默认action上传,更灵活控制)
  348. // const customUpload = async (options) => {
  349. // // 打印日志确认是否被调用
  350. // console.log('customUpload被触发,文件信息:', options.file);
  351. // console.log('kljlllll')
  352. // const { file, onSuccess, onError } = options;
  353. // try {
  354. // // 调用封装的上传方法
  355. // const res = await myUploadFile({
  356. // url: '/filesload.action',
  357. // filePath: file.path || file.url, // 临时文件路径
  358. // name: 'myFile', // 后端接收文件的字段名
  359. // formData: formData2.value // 额外参数
  360. // });
  361. // if (res.code === 200) {
  362. // // 上传成功:调用组件的onSuccess更新文件列表
  363. // onSuccess({
  364. // ...file,
  365. // url: res.data.url, // 后端返回的在线图片地址
  366. // status: 'success' // 标记为成功状态
  367. // });
  368. // console.log('上传成功,图片链接:', res.data.url);
  369. // } else {
  370. // // 接口返回错误
  371. // onError(res.message || '上传失败1');
  372. // uni.showToast({ title: res.message || '上传失败2', icon: 'none' });
  373. // }
  374. // } catch (err) {
  375. // // 网络错误或其他异常
  376. // onError('网络异常,请重试');
  377. // console.error('上传失败:', err);
  378. // uni.showToast({ title: '网络异常,请重试', icon: 'none' });
  379. // }
  380. // };
  381. // 保存按钮回调
  382. const handleSubmit = () => {
  383. console.log(cardType.value,'k')
  384. if(cardType.value == '教师认证'){
  385. form.value
  386. .validate()
  387. .then(({ valid, errors }) => {
  388. if (valid) {
  389. if (ifXiu.value) {
  390. // 修改请求
  391. submitEditReq()
  392. } else {
  393. // 新增请求
  394. submitAddReq()
  395. }
  396. }
  397. })
  398. .catch((error) => {
  399. console.log(error, 'error')
  400. })
  401. }else if(cardType.value == '暖心认证'){
  402. form.value
  403. .validate()
  404. .then(({ valid, errors }) => {
  405. if (valid) {
  406. if (ifXiu.value) {
  407. // 修改请求
  408. submitEditReqStu()
  409. } else {
  410. console.log(cardType.value,'k xxx')
  411. // 新增请求
  412. submitAddReqStu()
  413. }
  414. }
  415. })
  416. .catch((error) => {
  417. console.log(error, 'error')
  418. })
  419. }
  420. }
  421. //教师认证
  422. // 新增请求
  423. const submitAddReq = async () => {
  424. const leng=frontFileList.value.length-1
  425. const leng2=frontFileList.value.length-1
  426. if (frontFileList.value.length > 0) {
  427. formValue.value.file1 = frontFileList.value[leng];
  428. } else {
  429. // 若列表为空,清空file2(可选)
  430. formValue.value.file1 = '';
  431. uni.showToast({ title: '请上传身份证正面照片', icon: 'none' });
  432. }
  433. if (backFileList.value.length > 0) {
  434. formValue.value.file2 = backFileList.value[leng2];
  435. } else {
  436. // 若列表为空,清空file2(可选)
  437. formValue.value.file2 = '';
  438. uni.showToast({ title: '请上传身份证反面照片', icon: 'none' });
  439. }
  440. // 基础数据(必传字段)
  441. const requestData = {
  442. username: formValue.value.username,
  443. cardNumber: formValue.value.cardNumber,
  444. college: formValue.value.college,
  445. professor: formValue.value.professor,
  446. mobile: formValue.value.mobile,
  447. file1: formValue.value.file1,
  448. file2: formValue.value.file2
  449. // 先不包含 professor
  450. };
  451. console.log(formValue.value,'aaammmmm')
  452. const res = await myRequest({
  453. url: '/vertifyinsertTea.action',
  454. method: 'post',
  455. data: requestData
  456. })
  457. // console.log(res)
  458. if (res.code == 200) {
  459. uni.showToast({
  460. title: res.message,
  461. icon: 'success'
  462. })
  463. setTimeout(() => {
  464. uni.reLaunch({
  465. url: '/pages/transportation/transportation'
  466. })
  467. }, 1500)
  468. }
  469. }
  470. // 修改请求
  471. const submitEditReq = async () => {
  472. const leng=frontFileList.value.length-1
  473. const leng2=frontFileList.value.length-1
  474. if (frontFileList.value.length > 0) {
  475. formValue.value.file1 = frontFileList.value[leng];
  476. } else {
  477. // 若列表为空,清空file2(可选)
  478. formValue.value.file1 = '';
  479. uni.showToast({ title: '请上传身份证正面照片', icon: 'none' });
  480. }
  481. if (backFileList.value.length > 0) {
  482. formValue.value.file2 = backFileList.value[leng2];
  483. } else {
  484. // 若列表为空,清空file2(可选)
  485. formValue.value.file2 = '';
  486. uni.showToast({ title: '请上传身份证反面照片', icon: 'none' });
  487. }
  488. // 基础数据(必传字段)
  489. const requestData = {
  490. id: formValue.value.id,
  491. username: formValue.value.username,
  492. cardNumber: formValue.value.cardNumber,
  493. college: formValue.value.college,
  494. professor: formValue.value.professor,
  495. mobile: formValue.value.mobile,
  496. file1: formValue.value.file1,
  497. file2: formValue.value.file2
  498. // 先不包含 professor
  499. };
  500. console.log(formValue.value,'aaammmmmxiu')
  501. const res = await myRequest({
  502. url: '/vertifyupdateTea.action',
  503. method: 'post',
  504. data: requestData
  505. })
  506. // console.log(res)
  507. if (res.code == 200) {
  508. uni.showToast({
  509. title: res.message,
  510. icon: 'success'
  511. })
  512. setTimeout(() => {
  513. uni.reLaunch({
  514. url: '/pages/transportation/transportation'
  515. })
  516. }, 1500)
  517. }
  518. }
  519. //暖心认证
  520. // 新增请求
  521. const submitAddReqStu = async () => {
  522. const leng=frontFileList.value.length-1
  523. const leng2=frontFileList.value.length-1
  524. if (frontFileList.value.length > 0) {
  525. formValue.value.file1 = frontFileList.value[leng];
  526. } else {
  527. // 若列表为空,清空file2(可选)
  528. formValue.value.file1 = '';
  529. uni.showToast({ title: '请上传身份证正面照片', icon: 'none' });
  530. }
  531. if (backFileList.value.length > 0) {
  532. formValue.value.file2 = backFileList.value[leng2];
  533. } else {
  534. // 若列表为空,清空file2(可选)
  535. formValue.value.file2 = '';
  536. uni.showToast({ title: '请上传身份证反面照片', icon: 'none' });
  537. }
  538. // 基础数据(必传字段)
  539. const requestData = {
  540. username: formValue.value.username,
  541. cardNumber: formValue.value.cardNumber,
  542. // college: formValue.value.college,
  543. // instructor: formValue.value.instructor,
  544. // mobile: formValue.value.mobile,
  545. // file1: formValue.value.file1,
  546. // file2: formValue.value.file2
  547. // 先不包含 professor
  548. };
  549. console.log(formValue.value,'aaammmmm')
  550. const res = await myRequest({
  551. url: '/vertifyinsertPtu.action',
  552. method: 'post',
  553. data: formValue.value
  554. })
  555. // console.log(res)
  556. if (res.code == 200) {
  557. uni.showToast({
  558. title: res.message,
  559. icon: 'success'
  560. })
  561. setTimeout(() => {
  562. uni.reLaunch({
  563. url: '/pages/transportation/transportation'
  564. })
  565. }, 1500)
  566. }
  567. }
  568. // 修改请求
  569. const submitEditReqStu = async () => {
  570. const leng=frontFileList.value.length-1
  571. const leng2=frontFileList.value.length-1
  572. if (frontFileList.value.length > 0) {
  573. formValue.value.file1 = frontFileList.value[leng];
  574. } else {
  575. // 若列表为空,清空file2(可选)
  576. formValue.value.file1 = '';
  577. uni.showToast({ title: '请上传身份证正面照片', icon: 'none' });
  578. }
  579. if (backFileList.value.length > 0) {
  580. formValue.value.file2 = backFileList.value[leng2];
  581. } else {
  582. // 若列表为空,清空file2(可选)
  583. formValue.value.file2 = '';
  584. uni.showToast({ title: '请上传身份证反面照片', icon: 'none' });
  585. }
  586. // 基础数据(必传字段)
  587. const requestData = {
  588. id: formValue.value.id,
  589. username: formValue.value.username,
  590. cardNumber: formValue.value.cardNumber,
  591. // college: formValue.value.college,
  592. // instructor: formValue.value.instructor,
  593. // mobile: formValue.value.mobile,
  594. // file1: formValue.value.file1,
  595. // file2: formValue.value.file2
  596. // 先不包含 professor
  597. };
  598. console.log(formValue.value,'aaammmmm')
  599. const res = await myRequest({
  600. url: '/vertifyupdatePtu.action',
  601. method: 'post',
  602. data: formValue.value
  603. })
  604. // console.log(res)
  605. if (res.code == 200) {
  606. uni.showToast({
  607. title: res.message,
  608. icon: 'success'
  609. })
  610. setTimeout(() => {
  611. uni.reLaunch({
  612. url: '/pages/transportation/transportation'
  613. })
  614. }, 1500)
  615. }
  616. }
  617. // 姓名验证规则
  618. const validatorName = (val) => {
  619. const result = val.replace(/\s+/g, '')
  620. if (result) {
  621. if (result.length > 1 && result.length < 5) {
  622. return Promise.resolve()
  623. } else {
  624. return Promise.reject('姓名为2-4个字符')
  625. }
  626. }
  627. }
  628. // 身份证号码验证规则
  629. const validatorNum = (val) => {
  630. if (val) {
  631. // 去除空格
  632. const cleanedId = val.replace(/\s+/g, '')
  633. // 基本格式校验:18位,前17位数字,最后一位可以是数字或X
  634. const idReg = /(^\d{18}$)|(^\d{17}(\d|X|x)$)/
  635. if (!idReg.test(cleanedId)) {
  636. return Promise.reject('请输入有效的18位身份证号码')
  637. }
  638. // 校验码验证
  639. // 加权因子
  640. const factors = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
  641. // 校验码对应值
  642. const parityBits = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']
  643. let sum = 0
  644. const code = cleanedId.toUpperCase() // 转为大写
  645. // 计算前17位与对应因子乘积的和
  646. for (let i = 0; i < 17; i++) {
  647. sum += parseInt(code.charAt(i)) * factors[i]
  648. }
  649. // 计算校验码
  650. const checkCode = parityBits[sum % 11]
  651. // 验证校验码
  652. if (code.charAt(17) !== checkCode) {
  653. return Promise.reject('身份证号码校验无效')
  654. }
  655. // 验证出生日期
  656. const year = parseInt(code.substr(6, 4))
  657. const month = parseInt(code.substr(10, 2))
  658. const day = parseInt(code.substr(12, 2))
  659. const birthDate = new Date(year, month - 1, day)
  660. if (birthDate.getFullYear() !== year || birthDate.getMonth() + 1 !== month || birthDate.getDate() !== day) {
  661. return Promise.reject('身份证号码中的出生日期无效')
  662. }
  663. return Promise.resolve()
  664. }
  665. }
  666. // 时间号码验证规则
  667. const validatorPhone = (val) => {
  668. const phoneReg = /^1[3-9]\d{9}$/
  669. if (val) {
  670. if (phoneReg.test(val)) {
  671. return Promise.resolve()
  672. } else {
  673. return Promise.reject('手机号码格式错误')
  674. }
  675. }
  676. }
  677. </script>
  678. <style lang="scss" scoped>
  679. .container {
  680. box-sizing: border-box;
  681. padding: 20rpx 0;
  682. height: 100vh;
  683. background-color: #fff;
  684. overflow-y: auto;
  685. .form_title {
  686. margin-bottom: 30rpx;
  687. font-size: 28rpx;
  688. text-align: left;
  689. }
  690. .upload {
  691. display: flex;
  692. flex-direction: column;
  693. align-items: center;
  694. justify-content: center;
  695. width: 690rpx;
  696. height: 316rpx;
  697. font-size: 28rpx;
  698. color: #bfbfbf;
  699. border-radius: 16rpx;
  700. border: 2rpx solid #707070;
  701. background-color: #fff;
  702. }
  703. .footer {
  704. margin: 50rpx auto 30rpx;
  705. width: 700rpx;
  706. :deep(.wd-button) {
  707. background-color: #ff8205;
  708. }
  709. }
  710. }
  711. </style>