authenticate.vue 21 KB

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