story#7189,回程车小程序司机端-迁移认证页面

This commit is contained in:
2025-09-09 11:00:58 +08:00
parent cebb173ec4
commit 990db65d25
45 changed files with 2377 additions and 2 deletions

72
src/api/authentication.js Normal file
View File

@ -0,0 +1,72 @@
import request from '@/utils/http'
// 根据订单 获取报备类型
/*export function getReportListByOrder(key){
return request({
url: '/order/baseDriverReportConfigs/getByOrderId',
method:'GET',
params: key
})
}*/
// 弹框
export function successPopup( data) {
return request({
url: '/returnOrder/wechatDriver/user/successPopup',
method:'POST',
contentType: 'application/x-www-form-urlencoded',
data
})
}
// 认证进度
export function infoVerifyProgress(data){
return request({
url: '/returnOrder/wechatDriver/user/infoVerifyProgress',
method:'POST',
contentType: 'application/json',
data
})
}
// 认证详情
export function driverInfoVerifyDetail(data) {
return request({
url:'/returnOrder/wechatDriver/user/driverInfoVerifyDetail',
method:'POST',
data: data,
contentType: 'application/json',
})
}
// 我的信息
export function getMyInfo(data) {
return request({
url:'/returnOrder/wechatDriver/user/driverDetail',
method:'POST',
data: data,
})
}
// ocr识别
export function ocrRecognize( data) {
return request( {
url:'/returnOrder/wechatDriver/user/ocrRecognize',
data: data,
method:'POST',
contentType: 'application/json'
})
}
// 认证
export function driverInfoVerify( data) {
return request({
url:'/returnOrder/wechatDriver/user/driverInfoVerify',
data: data,
method:'POST',
contentType: 'application/json'
})
}
// 实名认证
export function driverRealName( data) {
return request('/returnOrder/wechatDriver/user/driverRealNameAuth', {
data: data,
method:'POST',
contentType: 'application/json'
})
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 790 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 441 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 277 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 727 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 901 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 803 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 470 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 795 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 725 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 721 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 727 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

View File

@ -0,0 +1,43 @@
const authenticationRouter = [
{
path: '/auditList',
name: 'auditList',
component: () => import('@/views/rvDriverAuthentication/auditList.vue'),
meta:{
title: '小板运输司机认证',
}
},
{
path: '/personAudit',
name: 'personAudit',
component: () => import('@/views/rvDriverAuthentication/personAudit.vue'),
meta:{
title: '实名认证',
}
},
{
path: '/carAudit',
name: 'carAudit',
component: () => import('@/views/rvDriverAuthentication/carAudit.vue'),
meta:{
title: '驾驶证认证',
}
},
{
path: '/carInfoAudit',
name: 'carInfoAudit',
component: () => import('@/views/rvDriverAuthentication/carInfoAudit.vue'),
meta:{
title: '车辆信息认证',
}
},
{
path: '/bankInfo',
name: 'bankInfo',
component: () => import('@/views/rvDriverAuthentication/bankInfo.vue'),
meta:{
title: '银行卡信息认证',
}
},
]
export default authenticationRouter

View File

@ -5,6 +5,7 @@ import kpiRouter from './kpi-router'
import invoiceRouter from "@/router/invoice-router";
import secondHandRouter from "@/router/second-hand-router";
import reportRouter from "@/router/report-router"
import authenticationRouter from "@/router/authentication-router"
const routes = [
{
path: '/',
@ -294,7 +295,8 @@ const routes = [
...kpiRouter,
...invoiceRouter,
...secondHandRouter,
...reportRouter
...reportRouter,
...authenticationRouter
]
const router = new VueRouter({

View File

@ -47,4 +47,84 @@ select{
font-size: 14px;
color: #000000;
}
.text_center {
text-align: center;
}
//同意协议勾选
.protocol-list {
display: flex;
//align-items: top;
margin-top: 5px;
justify-content: center;
position: fixed;
bottom: 20px;
text-align: center;
width: 100%;
padding: 20px;
box-sizing: border-box;
.protocol-text {
font-size: 12px;
color: #203152;
line-height: 18px;
//text-align: left;
.linkColor {
color: #3364B7;
word-break: keep-all;
}
}
}
.icon_register {
width: 100%;
height: auto;
}
.mr15 {
margin-right: 15px;
}
.mt20 {
margin-top: 20px;
}
.flex_vertical_center {
display: flex;
align-items: center;
}
.flex {
display: flex;
}
.flex_between {
justify-content: space-between;
}
/*@mixin wh($w,$h) {
width: $w;
height: $h;
}
@mixin flex(){
display: flex;
}
@mixin alignCenter(){
@include flex();
align-items: center;
}
@mixin col(){
@include flex();
flex-direction: column;
}
@mixin colBothCenter(){
@include col();
justify-content: center;
align-items: center;
}
@mixin sizingPadding($t,$r,$b,$l) {
box-sizing: border-box;
padding: $t $r $b $l;
}*/
/*@mixin weigthSize($wei,$size){
font-weight:$wei ;
font-size: $size;
}
@mixin weigthSizeColor($wei,$size,$col){
@include weigthSize($wei,$size);
color: $col;
}*/

43
src/styles/infoShow.scss Normal file
View File

@ -0,0 +1,43 @@
.carInfo{
margin-top: 10px;
box-sizing: border-box;
width: 100%;
min-height: 151px;
background: #FFFFFF;
padding:8px 23px 17px 30px ;
display: flex;
justify-content: space-between;
.left_wrap,.right_wrap{
display: flex;
flex-direction: column;
justify-content: space-around;
}
.title {
font-size: 14px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #323643;
.mar_left{
margin-left: 8px;
}
.star {
color: red;
margin-right: 3px;
}
}
.right_wrap{
align-items: flex-end;
.phone{
font-size: 13px;
font-weight: 500;
color: #323643;
}
input{
font-size: 12px;
text-align: right;
&::-webkit-input-placeholder { /* WebKit browserswebkit内核浏览器 */
color: #A1A1A1;
}
}
}
}

View File

@ -105,3 +105,32 @@
color: $col;
line-height: $hei;
}
@mixin width_height($width,$height){
width: $width;
height: $height;
}
@mixin flex($row,$colum){
display: flex;
justify-content: $row;
align-items: $colum;
}
@mixin center(){
display: flex;
align-items: center;
}
@mixin direction($justify-content){
display: flex;
flex-direction: column;
justify-content: $justify-content;
}
@mixin iconImg($width,$height,$marginRight){
width: $width;
height: $height;
margin-right: $marginRight;
}
@mixin iconImgLeft($width,$height,$marginRight){
width: $width;
height: $height;
margin-left: $marginRight;
}

View File

@ -42,11 +42,89 @@ const timeFormat=(data) =>{
return formattedDate;
}
// 认证状态
const verifyStatus=(id)=> {
const ids = String(id)
const status = {
'0': 1, // 个人信息认证
'-1': 1, // 已注册
'7': 1, // 已发送待认证
'1': 2, // 驾照信息认证
'2': 3, // 车辆信息审核
'3': 4, // 银行卡信息审核
'4': 5, // 认证中
'8': 6, // 审核中
'11': 6, // 审核失败
'12': 6 // 审核成功
}
return status[ids]
}
// 认证状态 简易版
const verifyStatusSimple=(id)=> {
const ids = String(id)
const status = {
'0': 1, // 个人信息认证
'-1': 1, // 已注册
'7': 1, // 已发送待认证
'1': 3, // 驾照信息认证
'2': 3, // 车辆信息审核
'3': 4, // 银行卡信息审核
'4': 5, // 认证中
'8': 6, // 审核中
'11': 6, // 审核失败
'12': 6 // 审核成功
}
return status[ids]
}
// 认证状态
const tipString=(id)=> {
const ids = String(id)
const status = {
'0': { // 个人信息认证
tip: '认证待提交',
button: '待认证'
},
'1': { // 驾照信息认证
tip: '认证待提交',
button: '待认证'
},
'2': { // 车辆信息审核
tip: '认证待提交',
button: '待认证'
},
'3': { // 银行卡信息审核
tip: '认证待提交',
button: '待认证'
},
'4': { // 认证中
tip: '认证待提交',
button: '待认证'
},
'8': { // 审核中
tip: '认证审核中',
button: '审核中'
},
'11': { // 审核失败
tip: '认证审核失败',
button: '审核失败'
},
'12': { // 审核成功
tip: '认证审核成功',
button: '审核成功'
},
}
return status[ids]
}
module.exports = {
formatNumber,
formatDate,
leftCopy,
timeFormat,
formatDate1
formatDate1,
verifyStatus,
verifyStatusSimple,
tipString
}

View File

@ -5,6 +5,12 @@ export const myMixins = {
}
},
methods: {
showFun() {
if( localStorage.getItem('infoVerify') == 8 || localStorage.getItem('infoVerify') == 12 ) {
return false
}
return true
},
goPage(page, query) {
this.$router.push({
name: page,

View File

@ -0,0 +1,148 @@
<template>
<div class="content">
<div class="navBar">
<van-nav-bar
title="小板运输司机认证"
left-arrow
left-arrow-color="#FFFFFF"
:border="false"
:fixed="true"
:safe-area-inset-top="true"
@click-left="h5GoBack"
/>
</div>
<img class="icon_register" mode="widthFix" src="@/assets/authentication/icon_register.png" />
<tip-bar :title="'应国家政策要求:从事货运行业的司机用户,身份证照片、驾驶证信息、行驶证信息、人车合影及承运资质信息必须进行实名认证。'"></tip-bar>
<div class="audit_list">
<audit-item title="个人信息" tip="上传本人头像和身份证"
:url="currentFlag(1) ? personActiveUrl : personUrl"
:pass="currentFlag(1)" :current-class="currentStep == 1"
@detail="showDetail('personAudit')" @upload="showDetail('personAudit')"></audit-item>
<audit-item title="驾照信息" tip="上传驾驶证" :url="currentFlag(2) ? driverActiveUrl : driverUrl" v-if="type != 'simple'" :pass="currentFlag(2)" :current-class="currentStep == 2"
@detail="showDetail('carAudit')" @upload="showDetail('carAudit')"></audit-item>
<audit-item title="车辆信息" tip="上传行驶证与车辆照片" :url="currentFlag(3) ? carActiveUrl : carUrl" :pass="currentFlag(3)" :current-class="currentStep == 3"
@detail="showDetail('carInfoAudit')" @upload="showDetail('carInfoAudit')"></audit-item>
<audit-item title="银行卡信息" tip="上传本人银行卡信息" :url="currentFlag(4) ? bankActiveUrl :bankUrl" :pass="currentFlag(4)" :current-class="currentStep == 4"
@detail="showDetail('bankInfo')" @upload="showDetail('bankInfo')"></audit-item>
<audit-item title="审核信息" :tip="auditTip" :status="statusStr" :url="currentFlag(5) ? bankActiveUrl :bankUrl" :pass="currentFlag(5)" :current-class="currentStep == 5" :button-hide="false"
></audit-item>
</div>
<fixed-button v-if="verifyStatus == 11" @myClick="showDetail('personAudit')" title="重新认证"></fixed-button>
<success-dialog ref="successDialog"></success-dialog>s
</div>
</template>
<script>
import successDialog from "./component/successDialog.vue";
import auditItem from "./component/auditItem";
import tipBar from "./component/tipBar";
import { verifyStatus, verifyStatusSimple ,tipString} from '@/utils/common';
import { myMixins } from '@/utils/myMixins.js';
import fixedButton from "./component/fixedButton";
import {infoVerifyProgress} from "@/api/authentication"
export default {
name:"auditList",
data() {
return {
personUrl: require('@/assets/authentication/audit_icon4_gray.png'),
personActiveUrl: require('@/assets/authentication/audit_icon4.png'),
driverUrl: require('@/assets/authentication/audit_icon1_gray.png'),
driverActiveUrl: require('@/assets/authentication/aduit_icon1.png'),
carUrl: require('@/assets/authentication/audit_icon2_gray.png'),
carActiveUrl: require('@/assets/authentication/audit_icon2.png'),
bankUrl: require('@/assets/authentication/audit_icon3_gray.png'),
bankActiveUrl: require('@/assets/authentication/audit_icon3.png'),
currentStep: undefined,
auditTip: '',
statusStr: '',
verifyStatus: '',
type: localStorage.getItem('type')
}
},
mixins: [ myMixins ],
components: {
tipBar,
auditItem,
fixedButton,
successDialog
},
// onLoad() {
// },
// async onPullDownRefresh() {
// await this.refresh()
// uni.stopPullDownRefresh()
// },
async mounted() {
// await this.$onLaunched;
await this.refresh()
},
methods: {
async getRegisterInfo(data) {
let res = await infoVerifyProgress( data)
// console.log("res",res)
localStorage.setItem('infoVerify', res?.data?.infoVerify?.code)
localStorage.setItem('failReason', res?.data?.verifyRemark)
localStorage.setItem('authIsSuccess', res?.data?.authIsSuccess)
localStorage.setItem('name', res?.data?.name)
},
async refresh() {
await this.getRegisterInfo()
await this.getVerifyStatus()
let obj = await tipString(localStorage.getItem('infoVerify'))
this.verifyStatus = localStorage.getItem('infoVerify')
if( this.verifyStatus == 11 ) {
this.auditTip = localStorage.getItem('failReason')
localStorage.setItem('authIsSuccess', 0)
} else {
this.auditTip = obj.tip
}
if( this.verifyStatus == 12 && parseInt(localStorage.getItem('authIsSuccess')) != 1) { // 审核通过
this.$refs.successDialog.openHandler()
}
this.statusStr = obj.button
},
currentFlag(status) {
return this.currentStep > status
},
showDetail(path) {
this.goPage(path)
},
getVerifyStatus() {
if( this.type == 'simple' ) {
this.currentStep = verifyStatusSimple(localStorage.getItem('infoVerify'))
} else {
this.currentStep = verifyStatus(localStorage.getItem('infoVerify'))
}
},
}
}
</script>
<style lang="scss">
@import "@/styles/common.scss";
.navBar{
margin-bottom: 46px;
}
.content {
font-size: 0;
padding-bottom: 80px;
}
.audit_list {
padding: 20px 30px;
.audit_item:after{
left: 18px;
position: absolute;
content: '';
display: block;
width: 2px;
top: 56px;
height: 48px;
background: rgba($color: #B2C2E4, $alpha: 0.59);
}
.audit_item:last-child {
&::after{
display: none !important;
}
}
}
</style>

View File

@ -0,0 +1,139 @@
<template>
<div class="content">
<div class="navBar">
<van-nav-bar
title="银行卡信息认证"
left-arrow
left-arrow-color="#FFFFFF"
:border="false"
:fixed="true"
:safe-area-inset-top="true"
@click-left="h5GoBack"
/>
</div>
<tip-bar :title="'温馨提示:服务完成后,平台代收的运费需要提现到您的银行卡账户中,请确保您上传的银行卡信息真实可用。'"></tip-bar>
<photo-item title="银行卡正面照片" :left-url="form.bankCardFront || bank" :show="show" @leftImg="bankHandler"></photo-item>
<div class="carInfo">
<div class="left_wrap title">
<span class="mar_left">姓名</span>
<div>
<span class="star">*</span>
<span>账户号</span>
</div>
<div>
<span class="star">*</span>
<span>开户行</span>
</div>
</div>
<div class="right_wrap">
<input type="text" disabled placeholder="请输入持卡人姓名" v-model="form.name">
<input type="text" placeholder="请输入银行卡号" v-model="form.cardNumber">
<input type="text" placeholder="请输入开户行" v-model="form.bankName">
</div>
</div>
<fixed-button @myClick="clickHandler" v-if="showFun()"></fixed-button>
<!-- <protocol-dialog></protocol-dialog>-->
</div>
</template>
<script>
// import protocolDialog from "./component/protocolDialog";
import fixedButton from "./component/fixedButton";
import photoItem from "./component/photoItem";
import tipBar from "./component/tipBar";
import { ocrRecognize, driverInfoVerify, driverInfoVerifyDetail } from '@/api/authentication.js'
import { leftCopy } from '@/utils/common.js'
import { myMixins } from '@/utils/myMixins.js'
export default {
name: "bankInfo",
components: {
tipBar,
photoItem,
fixedButton,
// protocolDialog
},
mixins: [myMixins],
data() {
return {
bank: require('@/assets/authentication/bank_icon1.png'),
show: undefined,
form: {
bankCardFront: '',
bankName: '',
cardNumber: '',
name: '',
},
type:localStorage.getItem('type')
}
},
async onLoad(options) {
if(options?.show) {
this.show = options.show
}
if( this.show ) {
await this.getDetail()
}
},
async onShow() {
},
methods: {
async clickHandler() {
if(!this.form.bankCardFront) {
this.$toast('银行卡照片未上传');
return
}
if( this.form.name && this.form.cardNumber && this.form.bankName ) {
let res = await driverInfoVerify( {
verifyType: 4,
...this.form,
type: this.type || 'full',
})
this.$toast('操作成功')
await this.getRegisterInfo({
verifyType: 4
})
setTimeout(() => {
this.h5GoBack()
}, 100)
console.log('注册', res)
} else {
this.$toast('银行卡信息识别错误')
}
},
async bankHandler(data) {
this.form.bankName = ''
this.form.cardNumber = ''
this.form.name = ''
this.form.bankCardFront = data
let res = await this.orcHandler(this.form.bankCardFront, 5)
leftCopy(this.form, {...res?.data?.data})
},
async getDetail() { // 认证详情
let res = await driverInfoVerifyDetail( {
verifyType: 4
})
leftCopy(this.form, {...res?.data?.bankCardInfoData})
console.log('bank', res)
},
async orcHandler(url, type) { // ocr 识别
let res = await ocrRecognize( {
ocrType: type,
imageUrl: url
});
return res;
},
}
}
</script>
<style lang="scss">
@import "@/styles/common.scss";
@import "@/styles/infoShow.scss";
page {
background: #F4F5F7;
}
.navBar{
margin-bottom: 46px;
}
</style>

View File

@ -0,0 +1,211 @@
<template>
<div class="content">
<div class="navBar">
<van-nav-bar
title="驾驶证认证"
left-arrow
left-arrow-color="#FFFFFF"
:border="false"
:fixed="true"
:safe-area-inset-top="true"
@click-left="h5GoBack"
/>
</div>
<tip-bar :title="'应国家政策要求:从事货运行业的司机用户,身份证照片、驾驶证信息、行驶证信息、人车合影及承运资质信息必须进行实名认证。'"></tip-bar>
<photo-item title="上传驾驶证" :left-url="form.drivingLicenceFront || carFront" :right-url="form.drivingLicenceContrary || carBack"
:show="show" @leftImg="carFrontHandler" @rightImg="carBackHandler"></photo-item>
<div class="carInfo">
<div class="left_wrap title">
<div class="form_item">
<div>
<span class="star">*</span>
<span>姓名</span>
</div>
<span class="phone">{{form.name}}</span>
</div>
<div class="form_item">
<div>
<span class="star">*</span>
<span>身份证号</span>
</div>
<input class="phone" type="text" placeholder="请输入持卡人身份证号" v-model="form.licenseNumber">
</div>
<div class="form_item">
<div>
<span class="star">*</span>
<span>准驾类型</span>
</div>
<span class="phone">{{form.approvedType}}</span>
</div>
<div class="form_item">
<div>
<span class="star">*</span>
<span>初次领证日期</span>
</div>
<span class="phone">{{form.initialIssueDate}}</span>
</div>
<div class="form_item">
<div>
<span class="star">*</span>
<span>有效期限</span>
</div>
<span class="phone">{{form.validPeriod}}</span>
</div>
<div class="form_item">
<div>
<span class="star">*</span>
<span>档案编号</span>
</div>
<span class="phone">{{form.recordNumber}}</span>
</div>
</div>
</div>
<fixed-button @myClick="clickHandler" v-if="showFun()"></fixed-button>
<!-- <protocol-dialog></protocol-dialog>-->
</div>
</template>
<script>
// import protocolDialog from "./component/protocolDialog";
import fixedButton from "./component/fixedButton";
import photoItem from "./component/photoItem";
import tipBar from "./component/tipBar";
import { ocrRecognize, driverInfoVerify, driverInfoVerifyDetail } from '@/api/authentication.js'
import { leftCopy } from '@/utils/common.js'
import { myMixins } from '@/utils/myMixins.js'
export default {
name: "carAudit",
components: {
tipBar,
photoItem,
fixedButton,
// protocolDialog
},
mixins: [ myMixins ],
data() {
return {
carFront: require('@/assets/authentication/car_icon1.png'),
carBack: require('@/assets/authentication/car_icon2.png'),
form: {
name: '',
drivingLicenceFront: '',
drivingLicenceContrary: '',
licenseNumber: '',
approvedType: '', // 准驾车型
initialIssueDate: '', // 初次领证日期
validPeriod: '', // 有效期
recordNumber: '', // 档案编号
},
show: undefined,
type: localStorage.getItem('type'),
}
},
async onLoad(options) {
if(options?.show) {
this.show = options.show
}
if( this.show ) {
await this.getDetail()
}
},
async onShow() {
},
methods: {
backInit() {
this.form.recordNumber = ''
},
frontInit() {
this.form.licenseNumber = ''
this.form.approvedType = ''
this.form.initialIssueDate = ''
this.form.validPeriod = ''
},
async carFrontHandler(data) {
await this.frontInit();
this.form.drivingLicenceFront = data
await this.idOrcHandler(this.form.drivingLicenceFront)
},
async carBackHandler(data) {
await this.backInit();
this.form.drivingLicenceContrary = data
await this.idOrcHandler(this.form.drivingLicenceContrary, 'back')
},
async idOrcHandler(url, type = 'front') { // ocr 识别
let res = await ocrRecognize({
ocrType: 2,
imageUrl: url
});
let carInfo
if(type == 'back') {
carInfo = res?.data?.data?.back?.data
this.form.recordNumber = carInfo?.recordNumber || ''
} else {
carInfo = res?.data?.data?.face?.data
leftCopy(this.form, {...carInfo})
}
},
async getDetail() { // 认证详情
let res = await driverInfoVerifyDetail( {
verifyType: 2
})
leftCopy(this.form, {...res?.data?.drivingLicenseInfoData})
console.log('carAudit', res)
},
async clickHandler() { // 点击去认证
if( !this.form.drivingLicenceFront ) {
this.$toast('驾驶证正面照片未上传')
return
}
if( !this.form.drivingLicenceContrary ) {
this.$toast('驾驶证反面照片未上传')
return
}
if(!this.form.licenseNumber || !this.form.initialIssueDate || !this.form.validPeriod) {
this.$toast('驾驶证正面识别错误,请重新上传')
return
}
if(!this.form.recordNumber) {
this.$toast('驾驶证反面识别错误,请重新上传')
return
}
await driverInfoVerify({
verifyType: 2,
type: this.type || 'full',
...this.form,
})
this.$toast('操作成功')
await this.getRegisterInfo({
verifyType: 2
})
setTimeout(() => {
this.h5GoBack()
}, 100)
}
}
}
</script>
<style lang="scss">
@import "@/styles/common.scss";
@import "@/styles/infoShow.scss";
page {
background: #F4F5F7;
}
.navBar{
margin-bottom: 46px;
}
.carInfo .title {
width: 100% !important;
}
.form_item {
line-height: 30px;
display: flex;
align-items: center;
justify-content: space-between;
}
.phone {
flex: 1;
text-align: right;
}
</style>

View File

@ -0,0 +1,433 @@
<template>
<div class="content">
<div class="navBar">
<van-nav-bar
title="车辆信息认证"
left-arrow
left-arrow-color="#FFFFFF"
:border="false"
:fixed="true"
:safe-area-inset-top="true"
@click-left="h5GoBack"
/>
</div>
<tip-bar :title="'应国家政策要求:从事货运行业的司机用户,身份证照片、驾驶证信息、行驶证信息、人车合影及承运资质信息必须进行实名认证。'"></tip-bar>
<div class="titleWrap">
<div class="natureWrap">
<span class="title"><span class="star">*</span>业务性质</span>
<radio-group @change="radioChange" class="flexWrap">
<label class="flexWrap labelWrap1" v-for="(item, index) in options" :key="item.value">
<div class="flexWrap center"><radio :value="item.value" :checked="(index+1) === Number(form.businessNature)" />{{item.name}}</div>
</label>
</radio-group>
</div>
<div class="natureWrap regionWrap" v-if="form.businessNature == 2">
<span class="title"><span class="star">*</span>所在地区</span>
<picker class="pickerWrap" mode="region" @change="bindRegionChange" :value="region">
<div class="picker">{{regionspan}}</div>
</picker>
</div>
</div>
<photo-item title="上传行驶证" :left-url="form.vehicleLicenseFront || driveFront" :right-url="form.vehicleLicenseBack || driveBack" v-if="type != 'simple'"
:show="show" @leftImg="vehicleFrontHandler" @rightImg="vehicleBackHandler"></photo-item>
<photo-item title="上传车辆照片" :left-url="form.vehicleFrontPhoto || carHead" :right-url="form.peopleVehiclePhoto || personCar" v-if="type != 'simple'"
:show="show" @leftImg="carPhotoHandler" @rightImg="personPhotoHandler"></photo-item>
<photo-item title="是否有救援责任险/货物运输险" :url-list="form.carrierLiabilityInsurancePhoto" :in-sure="form.hasInsurancePhoto"
:show="show" @urlList="carrierHandler" @insureHandle="insureHandle"></photo-item>
<div class="titleWrap">
<div class="natureWrap">
<span class="title"><span class="star">*</span>随车小轮个数</span>
<radio-group @change="wheelChange" class="flexWrap">
<label class="flexWrap labelWrap2" v-for="(item, index) in tyreOptions" :key="item.value">
<div class="flexWrap center"><radio :value="item.value" :checked="(index*2) === Number(form.wheelNum)" />{{item.name}}</div>
</label>
</radio-group>
</div>
</div>
<div class="carInfo" v-if="type != 'simple'">
<div class="left_wrap title">
<div class="form_item">
<div>
<span class="star">*</span>
<span>车牌号</span>
</div>
<span class="phone">{{form.licensePlateNumber}}</span>
</div>
<div class="form_item">
<div>
<span class="star">*</span>
<span>车架号</span>
</div>
<span class="phone">{{form.vinCode}}</span>
</div>
<div class="form_item">
<div>
<span class="star">*</span>
<span>车型</span>
</div>
<span class="phone">{{form.vehicleType}}</span>
</div>
<div class="form_item">
<div>
<span class="star">*</span>
<span>品牌车型</span>
</div>
<span class="phone">{{form.vehicleLicenseModel}}</span>
</div>
<div class="form_item">
<div>
<span class="star">*</span>
<span>行驶证人</span>
</div>
<span class="phone">{{form.vehicleLicenseOwner}}</span>
</div>
<div class="form_item">
<div>
<span>检验记录</span>
</div>
<span class="phone">{{form.inspectionRecord}}</span>
</div>
<div class="form_item">
<div>
<span class="star">*</span>
<span>总质量</span>
</div>
<span class="phone">{{form.totalWeight}}</span>
</div>
<div class="form_item">
<div>
<span class="star">*</span>
<span>整备质量</span>
</div>
<span class="phone">{{form.curbWeight}}</span>
</div>
<div class="form_item">
<div>
<span class="star">*</span>
<span>外廓尺寸</span>
</div>
<span class="phone">{{form.overallDimension}}</span>
</div>
<div class="form_item">
<div>
<span class="star"></span>
<span>档案编号</span>
</div>
<span class="phone">{{form.vehicleLicenseRecordNumber}}</span>
</div>
<div class="form_item">
<div>
<span class="star"></span>
<span>行驶证备注</span>
</div>
<span class="phone">{{form.vehicleLicenseRemarks}}</span>
</div>
<div class="form_item">
<div>
<span class="star">*</span>
<span>车头照片中的车牌号码</span>
</div>
<span class="phone">{{form.carNumber}}</span>
</div>
</div>
</div>
<fixed-button @myClick="clickHandler" v-if="showFun()" :noBg="true"></fixed-button>
<!-- <protocol-dialog></protocol-dialog>-->
</div>
</template>
<script>
// import protocolDialog from "./component/protocolDialog";
import fixedButton from "./component/fixedButton";
import photoItem from "./component/photoItem";
import tipBar from "./component/tipBar";
import { ocrRecognize, driverInfoVerify, driverInfoVerifyDetail } from '@/api/authentication.js'
import { leftCopy } from '@/utils/common.js'
import { myMixins } from '@/utils/myMixins.js'
export default {
name: "carInfoAudit",
components: {
tipBar,
photoItem,
fixedButton,
// protocolDialog
},
mixins: [myMixins],
data() {
return {
region: [],
driveFront: require('@/assets/authentication/carInfo_icon1.png'),
driveBack: require('@/assets/authentication/carInfo_icon2.png'),
carHead:require('@/assets/authentication/carInfo_icon3.png'),
personCar:require('@/assets/authentication/carInfo_icon4.png'),
liabilityInsurance:require('@/assets/authentication/carInfo_icon5.png'),
form: {
vehicleLicenseFront: '', // 行驶证主页照片
vehicleLicenseBack: '', // 行驶证副页照片
vehicleLicenseAddress: '', // 行驶证地址
engineNumber: '', // 行驶证发动机号
licensePlateNumber: '', // 车牌号
vinCode: '', // 车架号
vehicleType: '', // 车型
vehicleLicenseModel: '', // 行驶证车辆品牌车型
vehicleLicenseOwner: '', // 行驶证所有人
inspectionRecord: '', // 检验记录
totalWeight: '', // 总质量
curbWeight: '', // 整备质量
overallDimension: '', // 外廓尺寸
vehicleLicenseRecordNumber: '', // 行驶证档案编号
vehicleLicenseRemarks: '', // 行驶证备注
vehicleFrontPhoto: '', // 车头照片
carNumber: '', // 车头照片中的车牌号码
peopleVehiclePhoto: '', // 人车合影照片
carrierLiabilityInsurancePhoto: [], // 承运人责任险照片,如多张用英文逗号分开
businessNature:'',
areaCode:'',
hasInsurancePhoto:'',
wheelNum:-1,
region:[],
},
show: undefined,
type: localStorage.getItem('type'),
options:[{value:1,name:'全国跑圈业务'},{value:2,name:'固定区域救援业务'}],
tyreOptions:[{value:0,name:'0'},{value:2,name:'2'},{value:4,name:'4'}]
}
},
async onLoad(options) {
if(options?.show) {
this.show = options.show
}
if( this.show ) {
await this.getDetail()
}
},
async onShow() {
},
methods: {
bindRegionChange(e){
this.region=e?.detail?.value
let code=e?.detail?.code
this.form.areaCode=code[code.length - 1]
},
radioChange(val){
this.form.businessNature=val?.detail?.value
if(this.form.businessNature==1){
this.region=[]
this.form.areaCode=''
}
},
wheelChange(val){
this.form.wheelNum=val?.detail?.value
},
async getDetail() { // 认证详情
let res = await driverInfoVerifyDetail( {
verifyType: 3
})
leftCopy(this.form, {...res?.data?.vehicleInfoData})
this.form.carrierLiabilityInsurancePhoto=this.form.carrierLiabilityInsurancePhoto ? res?.data?.vehicleInfoData?.carrierLiabilityInsurancePhoto?.split(',') : []
if(this.form.businessNature==2){
this.region=res?.data?.vehicleInfoData?.region
if(this.region[0].includes('市')){
this.region?.unshift(this.region[0])
// console.log('第一个包含市')
}
}else {
this.region=[]
}
// this.form.hasInsurancePhoto=1
// this.form.carrierLiabilityInsurancePhoto=['http://file.sino-assist.com/group1/M00/07/78/wKgBzGij5QSAFO1hAAEBNU8G9Ww026.jpg?date=2025-08-19','http://file.sino-assist.com/group1/M00/07/78/wKgBzGij5QqADCNWAAZMtM4Se54125.png?date=2025-08-19']
},
async clickHandler() {
if( this.type != 'simple' ) {
if(!this.form.businessNature){
this.$toast('请选择业务性质')
return
}
if(this.form.businessNature==2 && !this.form.areaCode){
this.$toast('请选择所在地区')
return
}
if(!this.form.vehicleLicenseFront) {
this.$toast('行驶证主页未上传')
return
}
if(!this.form.licensePlateNumber || !this.form.vehicleType ) {
this.$toast('行驶证主页信息识别错误')
return
}
if(!this.form.vehicleLicenseBack) {
this.$toast('行驶证副页未上传')
return
}
if(!this.form.totalWeight) {
this.$toast('行驶证副页信息识别错误')
return
}
if(!this.form.carNumber) {
this.$toast('车辆信息识别错误')
return
}
if( !this.form.peopleVehiclePhoto ) {
this.$toast('人车合影未上传')
return
}
if(this.form.hasInsurancePhoto == -1){
this.$toast('请选择是否有救援责任险')
return
}
if(this.form.hasInsurancePhoto==1 && this.form.carrierLiabilityInsurancePhoto?.length<=0){
this.$toast('救援责任险/货物运输险未上传')
return
}
if(this.form.wheelNum==-1){
this.$toast('请选择随车小轮个数')
return
}
}
await driverInfoVerify( {
verifyType: 3,
type: this.type || 'full',
...this.form,
carrierLiabilityInsurancePhoto:this.form.carrierLiabilityInsurancePhoto?.length>0 ? this.form.carrierLiabilityInsurancePhoto?.join(',') : ''
})
this.$toast('操作成功')
await this.getRegisterInfo({
verifyType: 3
})
setTimeout(() => {
this.h5GoBack()
}, 100)
},
carrierHandler(data) { // 承运人责任险照片
this.form.carrierLiabilityInsurancePhoto = data
},
insureHandle(val){
this.form.hasInsurancePhoto=val
},
vehicleFrontInit() {
this.form.licensePlateNumber = ''
this.form.vinCode = ''
this.form.vehicleType = ''
this.form.vehicleLicenseModel = ''
this.form.vehicleLicenseOwner = ''
},
async vehicleFrontHandler(data) { // 行驶证正面照及ocr识别
await this.vehicleFrontInit()
this.form.vehicleLicenseFront = data
let vehicleInfo = await this.orcHandler(this.form.vehicleLicenseFront, 3)
let tempInfo = vehicleInfo?.data?.data?.face?.data
this.form.licensePlateNumber = tempInfo.licensePlateNumber
this.form.vinCode = tempInfo.vinCode
this.form.vehicleType = tempInfo.vehicleType
this.form.vehicleLicenseModel = tempInfo.model
this.form.vehicleLicenseOwner = tempInfo.owner
this.form.vehicleLicenseAddress = tempInfo.address
this.form.engineNumber = tempInfo.engineNumber
},
vehicleBackInit() {
this.form.inspectionRecord = ''
this.form.totalWeight = ''
this.form.curbWeight = ''
this.form.overallDimension = ''
this.form.vehicleLicenseRecordNumber = ''
this.form.vehicleLicenseRemarks = ''
},
async vehicleBackHandler(data) {
await this.vehicleBackInit()
this.form.vehicleLicenseBack = data
let vehicleInfo = await this.orcHandler(this.form.vehicleLicenseBack, 3)
let tempInfo = vehicleInfo?.data?.data?.back?.data
this.form.inspectionRecord = tempInfo.inspectionRecord
this.form.totalWeight = tempInfo.totalWeight
this.form.curbWeight = tempInfo.curbWeight
this.form.overallDimension = tempInfo.overallDimension
this.form.vehicleLicenseRecordNumber = tempInfo.recordNumber
this.form.vehicleLicenseRemarks = tempInfo.remarks
},
async carPhotoHandler(data) { // 车头照
this.form.carNumber = ''
this.form.vehicleFrontPhoto = data
let carInfo = await this.orcHandler(this.form.vehicleFrontPhoto, 6)
this.form.carNumber = carInfo?.data
},
personPhotoHandler(data){ // 人车合影
this.form.peopleVehiclePhoto = data
},
async orcHandler(url, type) { // ocr 识别
let res = await ocrRecognize( {
ocrType: type,
imageUrl: url
});
return res;
},
},
computed: {
regionText() {
return this.region.length ? `${this.region[0]}/${this.region[1]}/${this.region[2]}` : '请选择所在地区';
}
},
}
</script>
<style lang="scss">
@import "@/styles/common.scss";
@import "@/styles/infoShow.scss";
page {
background: #F4F5F7;
}
.navBar{
margin-bottom: 46px;
}
.content {
/*padding-bottom: 86px;*/
}
.carInfo .title {
width: 100% !important;
}
.form_item {
line-height: 30px;
display: flex;
align-items: center;
justify-content: space-between;
}
.carInfo {
padding-bottom: 86px;
}
.star{
color: red;
margin-right: 3px;
}
.titleWrap{
margin-bottom: 10px;
background-color: #FFFFFF;
padding: 15px 12px 15px 17px;
.natureWrap{
display: flex;
align-items: center;
justify-content: space-between;
font-size: 13px !important;
}
.regionWrap{
margin-top: 8px;
}
.flexWrap{
display:flex;
}
.labelWrap1{
margin-left: 10px;
}
.labelWrap2{
margin-left: 15px;
}
radio{
width: 24px;
transform: scale(0.7);
transform-origin: center; /* 保持中心点不变 */
}
.center{
align-items: center;
justify-content: center;
}
}
</style>

View File

@ -0,0 +1,131 @@
<template>
<div class="audit_item flex flex_between">
<div class="item_left flex">
<img class="main_img mr15" :src="url" />
<div class="flex_fit">
<div class="main_title active">{{title}}</div>
<div class="main_tip">{{tip}}</div>
</div>
</div>
<div class="pass_item" v-if="pass" @click="showDetail">
<span>{{status}}</span>
<img v-if="title != '审核信息'" class="arrow_icon" src="@/assets/authentication/arrow_right.png" />
</div>
<div class="uploadBtn" :class="{'activeBtn': currentClass }"
v-else-if="!pass && buttonHide" @click="uploadHandler">{{buttonTitle}}</div>
</div>
</template>
<script>
export default {
name: "auditItem",
data() {
return {
}
},
methods: {
uploadHandler(){
if( !this.pass && this.currentClass ) {
this.$emit('upload')
}
},
showDetail() {
this.$emit('detail')
}
},
props: {
buttonHide: {
type: Boolean,
default: true
},
status: {
type: String,
default: '查看'
},
title: {
type: String,
default: ''
},
tip: {
type: String,
default: ''
},
url: {
type: String,
default: require('@/assets/authentication/aduit_icon1.png')
},
pass: {
type: Boolean,
default: false
},
currentClass: {
type: Boolean,
default: false
},
buttonTitle: {
type: String,
default: '上传'
}
}
}
</script>
<style lang="scss" scoped>
.audit_item {
width: 100%;
padding: 20px 0;
box-sizing: border-box;
position: relative;
.item_left {
flex: 1;
.main_img {
width: 36px;
height: 36px;
}
.flex_fit {
flex: 1;
}
.main_title {
font-size: 17px;
font-weight: bold;
line-height: 24px;
color: #33495E;
}
.active {
color: #33495E;
}
.main_tip {
font-size: 14px;
font-weight: 500;
color: #33495E;
line-height: 20px;
margin-right: 5px;
}
}
.uploadBtn {
width: 68px;
height: 31px;
background: rgba($color: #5B739D, $alpha: 0.24);
color: #fff;
font-size: 13px;
border-radius: 4px;
line-height: 31px;
text-align: center;
}
.activeBtn {
background: #3364B7;
}
.pass_item {
font-size: 13px;
color: rgba($color: #000, $alpha: 0.59);
.arrow_icon {
width: 8px;
height: 12px;
vertical-align: sub;
margin-left: 5px;
}
}
}
</style>

View File

@ -0,0 +1,56 @@
<template>
<div class="button_fixed" :class="{ 'noBg': noBg }">
<div class="button_wrap" @click="clickHandler">
{{title}}
</div>
</div>
</template>
<script>
export default {
name: "fixedButton",
props: {
title: {
type: String,
default: '下一步'
},
noBg: {
type: Boolean,
default: false
}
},
methods: {
clickHandler() {
this.$emit('myClick')
}
}
}
</script>
<style lang="scss" scoped>
.button_fixed {
width: 100%;
background: #F4F5F7;
padding: 20px 0;
box-sizing: border-box;
position: fixed;
bottom: 0;
left: 0;
z-index: 1111;
.button_wrap {
width: calc(100% - 80px);
height: 46px;
background: #354D93;
border-radius: 23px;
margin: 0 auto;
line-height: 46px;
color: #fff;
font-size: 15px;
text-align: center;
}
}
.noBg {
background: none
}
</style>

View File

@ -0,0 +1,282 @@
<template>
<div class="photo_wrap">
<template v-if="title.indexOf('责任险/货物') !== -1">
<div class="photo_title custom-title">
<span><span class="star">*</span>{{title}}</span>
<radio-group @change="radioChange" class="flexWrap">
<label class="flexWrap labelWrap" v-for="(item, index) in options" :key="item.value">
<div class="flexWrap center"><radio :value="item.value" :checked="index == inSure" />{{item.name}}</div>
</label>
</radio-group>
</div>
<div class="photoWrap" v-if="inSure == 1">
<template v-if="urlList.length>0">
<div v-for="(item,index) in urlList" :key="index" @click="chooseHandler('urlList',index)">
<img class="photo_item" mode="widthFix" :src="item.replace(/http:\/\//g, 'https://')" />
</div>
</template>
<div v-if="urlList.length < 3" @click="chooseHandler('urlList')" class="tipWrap">
<img class="photo_item" mode="widthFix" src="@/assets/authentication/carInfo_icon5.png" />
<img class="camera" v-if="showFun()" src="@/assets/authentication/camera.png" />
<span class="picNum">({{urlList.length}}/3)</span>
</div>
</div>
</template>
<template v-else>
<div class="photo_title">
<span class="star">*</span>
<span>{{title}}</span>
</div>
<div class="photo_img flex flex_between">
<div @click="chooseHandler('leftImg')">
<template v-if="form.leftImg">
<img class="photo_item" mode="widthFix" :src="form.leftImg.replace(/http:\/\//g, 'https://')" />
</template>
<template v-else>
<img class="photo_item" mode="widthFix" :src="leftUrl.replace(/http:\/\//g, 'https://')" />
<img class="camera" v-if="showFun()" src="@/assets/authentication/camera.png" />
</template>
<div></div>
</div>
<div v-if="rightUrl" @click="chooseHandler('rightImg')">
<template v-if="form.rightImg">
<img class="photo_item" mode="widthFix" :src="form.rightImg.replace(/http:\/\//g, 'https://')" />
</template>
<template v-else>
<img class="photo_item" mode="widthFix" :src="rightUrl.replace(/http:\/\//g, 'https://')" />
<img class="camera" v-if="showFun()" src="@/assets/authentication/camera.png" />
</template>
</div>
</div>
</template>
</div>
</template>
<script>
let baseUrl=''
if (window.location.href.includes('www.sinoassist.com')) {
baseUrl = 'https://www.sinoassist.com'
} else {
baseUrl = 'https://crm1.sino-assist.com'
}
export default {
name: "photoItem",
props: {
title: {
type: String,
},
leftUrl: {
type: String,
default: require('@/assets/authentication/person_header.png')
},
rightUrl: {
type: String,
},
show: {
},
urlList: {
type: Array,
},
inSure:{
type:Number,
}
},
data() {
return {
form: {
leftImg: '',
rightImg: '',
urlList:[],
isInsure:-1,
},
options:[{value:0,name:'否'},{value:1,name:'是'}],
}
},
mounted() {
console.log("inSure",this.inSure)
},
methods: {
radioChange(e){
this.form.isInsure=e?.detail?.value
if(this.form.isInsure==0){
this.form.urlList=[]
this.$emit('urlList', this.form.urlList)
}
this.$emit('insureHandle',e?.detail?.value)
},
showFun() {
if( localStorage.getItem('infoVerify') == 8 || localStorage.getItem('infoVerify') == 12 ) {
return false
}
return true
},
async chooseHandler(type,i) {
console.log("type,i",type,i,baseUrl)
return
// #ifdef MP-WEIXIN
// await this.weChatImage(type,i)
// #endif
// #ifndef MP-WEIXIN
// await this.commonImage(type,i)
// #endif
},
/* commonImage(type,index) {
uni.chooseImage({
success: (chooseImageRes) => {
const tempFilePaths = chooseImageRes.tempFilePaths;
uni.uploadFile({
url: baseUrl + '/order/uploadImage', //仅为示例,非真实的接口地址
filePath: tempFilePaths[0],
name: 'file',
success: async (uploadFileRes) => {
if (type=='urlList' && (index==0 || index)){
this.$set( this.form.urlList,index,JSON.parse(uploadFileRes.data).data)
} else if(type=='urlList'){
this.form[type].push(JSON.parse(uploadFileRes.data).data)
}else {
this.form[type] = JSON.parse(uploadFileRes.data).data
}
this.$emit(type, this.form[type])
},
fail: () => {
this.$toast('上传失败')
}
});
},
fail: (res) => {
console.log('选择照片出错', res)
// this.$toast('选择照片出错,请重试')
}
})
},
weChatImage(type,index) {
uni.chooseMedia({
sourceType: ['album', 'camera'],
mediaType: ['image'],
count: 1,
success: (chooseImageRes) => {
const tempFilePaths = chooseImageRes.tempFiles[0].tempFilePath;
uni.uploadFile({
url: baseUrl + '/order/uploadImage', //仅为示例,非真实的接口地址
filePath: tempFilePaths,
name: 'file',
success: async (uploadFileRes) => {
if (type=='urlList' && (index==0 || index)){
this.$set( this.form.urlList,index,JSON.parse(uploadFileRes.data).data)
}else if(type=='urlList'){
this.form[type].push(JSON.parse(uploadFileRes.data).data)
}else{
this.form[type] = JSON.parse(uploadFileRes.data).data
}
this.$emit(type, this.form[type])
},
fail: () => {
this.$toast('上传失败')
}
});
},
fail: (res) => {
console.log('选择照片出错', res)
// this.$toast('选择照片出错,请重试')
}
})
}
*/
}
}
</script>
<style lang="scss" scoped>
@import "@/styles/common.scss";
.photo_wrap {
padding: 20px 12px 22px 17px;
background: #FFFFFF;
margin-bottom: 10px;
.photo_title {
font-size: 14px;
padding-left: 10px;
margin-bottom: 5px;
.star {
color: red;
margin-right: 3px;
}
}
.custom-title{
display: flex;
justify-content: space-between;
.flexWrap{
display:flex;
}
.labelWrap{
margin-left: 10px;
}
radio{
width: 24px;
transform: scale(0.7);
transform-origin: center; /* 保持中心点不变 */
}
.center{
align-items: center;
justify-content: center;
}
}
.photoWrap{
width: 100%;
display: flex;
flex-wrap: wrap;
.tipWrap{
position: relative;
display: flex;
flex-wrap: wrap;
}
.picNum{
position: absolute;
z-index: 111;
color: #206FFF ;
top: 3px;
right: 3px;
font-size: 11px;
}
div:nth-child(2n+1) {
margin-right: 4px;
}
div {
width: calc(50% - 3px);
position: relative;
.photo_item {
width: 100%;
height: 95px !important;
}
.camera {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 35px;
height: 34px;
}
}
}
.photo_img {
width: 100%;
div {
width: calc(50% - 3px);
position: relative;
.photo_item {
width: 100%;
height: 95px !important;
}
.camera {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 35px;
height: 34px;
}
}
}
}
</style>

View File

@ -0,0 +1,195 @@
<template>
<div class="privacy" v-if="showPrivacy">
<div class="content">
<div class="title">隐私保护指引</div>
<div class="pop_con">
在使用当前小程序服务之前请仔细阅读<text class="pop_protocol" @click="openPrivacyContract">{{privacyContractName}}</text>如你同意{{privacyContractName}}请点击同意开始使用
</div>
<div class="pop_button_wrap" :style="{'height': 50 + 'px', 'lineHeight': 50 + 'px'}">
<div class="border_right" @click="exitMiniProgram">
拒绝
</div>
<button id="agree-btn" plain="true" class="pop_confirm" open-type="agreePrivacyAuthorization" @agreeprivacyauthorization="handleAgreePrivacyAuthorization">同意</button>
</div>
</div>
</div>
</template>
<script>
import { myMixins } from '@/utils/myMixins.js';
import twoBtn from "@/components/twoBtn";
export default {
name: "protocolDialog",
data() {
return {
privacyContractName: '',
showPrivacy: false
}
},
components: {
twoBtn
},
mixins: [myMixins],
created() {
if (wx.getPrivacySetting) {
const version = wx.getAppBaseInfo().SDKVersion
if (this.compareVersion(version, '2.32.3') >= 0) {
wx.getPrivacySetting({
success: (res) => {
if (res.needAuthorization) {
this.showPrivacy = true;
this.privacyContractName = res.privacyContractName
} else{
this.$emit("agree")
this.showPrivacy = false;
}
}
})
}
} else {
// 低版本基础库不支持 wx.getPrivacySetting 接口,隐私接口可以直接调用
this.$emit("agree")
this.showPrivacy = false;
}
},
/**
* 组件的生命周期
*/
pageLifetimes: {
show() {
const _ = this
const version = wx.getAppBaseInfo().SDKVersion
if (_.compareVersion(version, '2.32.3') >= 0) {
wx.getPrivacySetting({
success(res) {
console.log('隐私设置:', res)
if (res.errMsg == "getPrivacySetting:ok") {
this.privacyContractName = res.privacyContractName;
this.showPrivacy = res.needAuthorization;
}
}
})
}
}
},
/**
* 组件的方法列表
*/
methods: {
// 打开隐私协议页面
openPrivacyContract() {
wx.openPrivacyContract({
fail: () => {
wx.showToast({
title: '遇到错误',
icon: 'error'
})
}
})
},
// 拒绝隐私协议
exitMiniProgram() {
// 直接退出小程序
wx.exitMiniProgram()
this.showPrivacy = false
},
// 同意隐私协议
handleAgreePrivacyAuthorization() {
console.log('我点击同意了')
this.showPrivacy = false
this.$emit('agree')
},
// 比较版本号
compareVersion(v1, v2) {
v1 = v1.split('.')
v2 = v2.split('.')
const len = Math.max(v1.length, v2.length)
while (v1.length < len) {
v1.push('0')
}
while (v2.length < len) {
v2.push('0')
}
for (let i = 0; i < len; i++) {
const num1 = parseInt(v1[i])
const num2 = parseInt(v2[i])
if (num1 > num2) {
return 1
} else if (num1 < num2) {
return -1
}
}
return 0
}
},
}
</script>
<style scoped lang="scss">
.privacy {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: rgba(0, 0, 0, .5);
z-index: 9999999;
display: flex;
align-items: center;
justify-content: center;
.content {
width: 632rpx;
padding-top: 48rpx !important;
box-sizing: border-box;
background: #fff;
border-radius: 16rpx;
}
}
.content .title {
font-size: 16px;
color: #000;
margin-bottom: 10px;
text-align: center;
}
/*登录弹框样式*/
.pop_con {
color: #203152;
font-size: 14px;
margin-bottom: 30px;
/*text-align: left;*/
padding: 0 20px;
line-height: 26px;
text-align: center;
}
.pop_protocol {
color: #1D64D2;
word-break: keep-all;
}
.pop_button_wrap {
display: flex;
border-top: 1rpx solid rgba($color: #979797, $alpha: 0.34);
div {
width: calc(50% - 1rpx);
text-align: center;
font-size: 14px;
color: rgba(0,0,0,0.73);
}
.border_right {
border-right: 1rpx solid rgba($color: #979797, $alpha: 0.34);
}
.pop_confirm {
color: #1D64D2;
border: none;
background-color: transparent;
}
}
</style>

View File

@ -0,0 +1,135 @@
<template>
<div class="dialog_wrap">
<van-popup ref="success" v-model="poupShow">
<div class="pop_wrap">
<img class="tip_bg" src="@/assets/authentication/tipBg.png" />
<div class="pop_title">
恭喜您
</div>
<div class="pop_content">
<div>
您的信息已经认证完成
</div>
<div>
请开启您的接单赚钱之旅
</div>
<div>
关注服务号新订单及时提醒接单更快
</div>
</div>
<div class="tip_button_wrap">
<div class="continue" @click="focusHandler">
关注
</div>
</div>
</div>
</van-popup>
</div>
</template>
<script>
import { successPopup,getMyInfo } from '@/api/authentication'
import { myMixins } from '@/utils/myMixins.js'
export default {
name: "successDialog",
data() {
return {
poupShow:false,
}
},
mixins: [ myMixins ],
components: {},
methods: {
async getMineInfo() { // 获取用户信息
let myInfo = await getMyInfo()
if(!( myInfo.code != 200 || !myInfo.data.phone)) {
localStorage.setItem('phone', myInfo?.data?.phone)
localStorage.setItem('infoVerify', myInfo?.data?.infoVerify?.code || 0) // 认证进度
localStorage.setItem('authIsSuccess', myInfo?.data?.authIsSuccess)
localStorage.setItem('name', myInfo?.data?.name)
localStorage.setItem('attentionState', myInfo?.data?.attentionState)
}
},
openHandler() {
this.poupShow=true
},
async focusHandler() {
let focusFlag = localStorage.getItem('attentionState'); // 是否关注过公众号的标志
if( focusFlag ) {
await this.continueHandler()
} else {//去关注公众号页面
this.goPage('https://mp.weixin.qq.com/s/VNy_ppgDTLtwTtdRV_vPgA')
}
},
async continueHandler() {
await successPopup();
this.poupShow=false
await this.getMineInfo()
}
}
}
</script>
<style lang="scss" scoped>
@import "@/styles/common.scss";
// 弹框样式
.pop_wrap {
width: 304px;
height: 267px;
position: relative;
.tip_bg {
position: absolute;
width: 304px;
height: 267px;
top: 0;
left: 0;
z-index: 100;
}
.pop_title {
font-size: 19px;
font-weight: bold;
color: #3364B7;
position: absolute;
width: 304px;
text-align: center;
top: 100px;
z-index: 101;
}
.pop_content {
width: 304px;
position: absolute;
top: 130px;
z-index: 101;
font-size: 14px;
color: #4C5361;
div {
width: 100%;
text-align: center;
line-height: 20px;
}
}
.tip_button_wrap {
position: absolute;
z-index: 101;
width: 275px;
margin: 0 auto;
bottom: 14px;
display: flex;
border-top: 1px solid #F1F2F5;
left: 15px;
height: 45px;
div {
font-size: 13px;
width: 100%;
text-align: center;
line-height: 45px;
}
.close {
color: #999B9F;
border-right: 1px solid #F1F2F5;
}
.continue {
color: #3364B7;
}
}
}
</style>

View File

@ -0,0 +1,44 @@
<template>
<div class="tip_content" :style="styleCls">
<img class="icon_tip" mode="widthFix" src="@/assets/authentication/icon_tip.png" />
<span>{{title}}</span>
</div>
</template>
<script>
export default {
name: "tipBar",
props: {
title: {
type: String,
default: ''
},
styleCls: {
type: String,
default: ''
}
}
}
</script>
<style lang="scss" scoped>
.tip_content{
width: 100%;
box-sizing: border-box;
padding: 10px 22px;
line-height: 15px;
background: #FFF0EE;
.icon_tip{
width: 13px;
height: 13px;
margin-right: 6px;
position: relative;
margin-bottom: -3px;
}
span{
font-size: 11px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #FF6337;
}
}
</style>

View File

@ -0,0 +1,248 @@
<template>
<div class="content">
<div class="navBar">
<van-nav-bar
title="实名认证"
left-arrow
left-arrow-color="#FFFFFF"
:border="false"
:fixed="true"
:safe-area-inset-top="true"
@click-left="h5GoBack"
/>
</div>
<tip-bar :title="'应国家政策要求:从事货运行业的司机用户,身份证照片、驾驶证信息、行驶证信息、人车合影及承运资质信息必须进行实名认证。'"></tip-bar>
<photo-item title="个人头像" v-if="type != 'simple'" :show="show" :left-url="form.icon ||headerUrl" @leftImg="headerHandler"></photo-item>
<photo-item title="身份证正反面" :show="show" :left-url="form.identityCardFront || idFront" :right-url="form.identityCardContrary || idBack"
@leftImg="idFrontHandler" @rightImg="idBackHandler" ></photo-item>
<div class="carInfo">
<div class="left_wrap title">
<span class="mar_left">注册手机号</span>
<div>
<span class="star">*</span>
<span>本人姓名</span>
</div>
<div>
<span class="star">*</span>
<span>本人性别</span>
</div>
<div>
<span class="star">*</span>
<span>本人身份证号</span>
</div>
</div>
<div class="right_wrap">
<span class="phone">{{form.phone}}</span>
<input type="text" disabled placeholder="请输入持卡人姓名" v-model="form.name">
<input type="text" disabled placeholder="请输入持卡人性别" v-model="form.sex">
<input type="text" placeholder="请输入持卡人身份证号" v-model="form.identityCardNumber">
</div>
</div>=
<fixed-button title="实名认证" @myClick="goRealName" v-if="showFun() && !esignFlag"></fixed-button>
<fixed-button @myClick="clickHandler" v-if="showFun() && esignFlag"></fixed-button>
<!-- <protocol-dialog></protocol-dialog>-->
</div>
</template>
<script>
// import protocolDialog from "./component/protocolDialog";
import fixedButton from "./component/fixedButton";
import photoItem from "./component/photoItem";
import tipBar from "./component/tipBar";
import { ocrRecognize, driverInfoVerify, driverInfoVerifyDetail, driverRealName } from '@/api/authentication'
import { leftCopy } from '@/utils/common.js'
import { myMixins } from '@/utils/myMixins.js'
// import {version} from "@/utils/baseUrl"
export default {
name: "personAudit",
components: {
tipBar,
photoItem,
fixedButton,
// protocolDialog
},
mixins: [myMixins],
data() {
return {
form: {
phone: localStorage.getItem('phone'),
name: '',
sex: '',
identityCardNumber: '',
icon: '',
identityCardFront: '',
identityCardContrary: '',
idCardAuthority: '', // 发证机关
idCardValidStartTime: '', // 有效期开始
idCardValidEndTime: '', // 有效期结束
},
validPeriod: '', // 有效期
headerUrl: require('@/assets/authentication/person_header.png'),
idFront: require('@/assets/authentication/person_idcard1.png'),
idBack: require('@/assets/authentication/person_idcard2.png'),
user:'',
cardId:'',
show: undefined,
type: localStorage.getItem('type'),
esignFlag: false,
}
},
async onLoad(options) {
if(options?.show) {
this.show = options.show
if( this.show ) {
await this.getDetail()
}
}
},
async onShow() {
this.esignFlag = localStorage.getItem('esignFlag');
},
methods: {
async getDetail() {
let res = await driverInfoVerifyDetail( {
verifyType: 1
})
leftCopy(this.form, {...res?.data?.personalInfoData})
},
async headerHandler(data) {
this.form.icon = data
},
async idFrontHandler(data) { // 身份证正面
this.form.identityCardFront = data
await this.idOrcHandler(this.form.identityCardFront)
},
async idBackHandler(data) {
this.form.identityCardContrary = data
await this.idBackOrcHandler(this.form.identityCardContrary)
},
initForm() {
this.form.name = ''
this.form.sex = ''
this.form.identityCardNumber = ''
},
backInit() {
this.validPeriod = ''
},
async idBackOrcHandler(url) {
let res = await ocrRecognize( {
ocrType: 1,
imageUrl: url
});
let idInfo = res?.data?.data?.back?.data
// let validPeriod = '2014.07.09-长期'
let validPeriod = idInfo?.validPeriod; // 有效期
this.form.idCardAuthority = idInfo?.issueAuthority
let dateArr = validPeriod.split('-');
let startDate = dateArr[0];
let endDate = dateArr[1];
this.form.idCardValidStartTime = startDate.replace(/\./g, '/') + ' 00:00:00';
if( endDate.indexOf('长期') != -1 ) {
this.form.idCardValidEndTime = '2099/01/01 00:00:00'
} else {
this.form.idCardValidEndTime = endDate.replace(/\./g, '/') + ' 00:00:00';
}
// console.log('this.form.idCardValidStartTime', this.form.idCardValidStartTime);
// console.log('this.form.idCardValidEndTime', this.form.idCardValidEndTime);
},
async idOrcHandler(url) {
await this.initForm()
let res = await ocrRecognize({
ocrType: 1,
imageUrl: url
});
let idInfo = res?.data?.data?.face?.data
this.form.name = idInfo?.name
this.form.sex = idInfo?.sex
this.form.identityCardNumber = idInfo?.idNumber
},
async goRealName() {
if (!this.form.identityCardContrary) {
this.$toast('身份证反面照片未上传')
return
}
if( !this.form.idCardValidStartTime ) {
this.$toast('身份证反面识别错误')
return
}
if (!this.form.identityCardFront) {
this.$toast('身份证正面照片未上传')
return
}
if(this.form.name && this.form.identityCardNumber) {
let res = await driverRealName( {
phone: this.form.phone,
name: this.form.name,
idNo: this.form.identityCardNumber,
})
let info = res?.data
console.log('info', info)
/* let env = version=='release' ? 'prod' : 'sml'
uni.navigateToMiniProgram({
appId: 'wx1cf2708c2de46337', // 上链公证签小程序APPID
path: '/pages/index/index', // 上链公证签页面地址
extraData: {
requestObj: { // 必填,入参
flowId: info?.flowId, // 必填认证流程Id
type: 'REALNAME',// 必填,业务类型:实名 REALNAME
env: env // 非必填,对接环境:线上 prod(默认), 模拟 sml(用于对接调试阶段)
},
callbackObj: { // 非必填,回传数据:签署完成后会将此数据完整回传
}
},
})*/
} else {
this.$toast('身份证信息识别错误')
}
},
async clickHandler() {
if (!this.form.identityCardContrary) {
this.$toast('身份证反面照片未上传')
return
}
if( !this.form.idCardValidStartTime ) {
this.$toast('身份证反面识别错误')
return
}
if (!this.form.identityCardFront) {
this.$toast('身份证正面照片未上传')
return
}
if(this.form.name && this.form.identityCardNumber) {
await driverInfoVerify( {
verifyType: 1,
type: this.type || 'full',
...this.form,
})
this.$toast('操作成功')
await this.getRegisterInfo({
verifyType: 1
})
setTimeout(() => {
}, 100)
} else {
this.$toast('身份证信息识别错误')
}
},
}
}
</script>
<style lang="scss">
@import "@/styles/common.scss";
@import "@/styles/infoShow.scss";
page {
background: #F4F5F7;
}
.navBar{
margin-bottom: 46px;
}
.empty{
width: 100%;
height:151px;
}
.content {
padding-bottom: 86px;
}
</style>