Commit d2c4018b authored by kang.nie@inzymeits.com's avatar kang.nie@inzymeits.com
Browse files

初始化代码

parent de8a8ae5
Pipeline #3105 failed with stages
in 0 seconds
<template>
<div class="page">
<pageTitle title="企业实名认证" />
<steps :data="dict.enterpriseRealnameSteps" :index="2" />
<page-module name="责任人基本信息" icon="info">
<CompBasicInfo ref="baseInfo" :data="baseData" type="enterprise" />
</page-module>
<page-module name="证件信息" icon="idcard">
<CompCertificateInfo ref="certInfo" :data="certData" @read-cert="onReadCert" />
</page-module>
<page-module name="文件信息" icon="folder">
<el-row>
<el-col :span="12">
<FileInfo ref="contractInfo" :sign="true" :data="contractData" :upload-type="['camera', 'sign']" :attachment-url="attachmentUrl" sign-key="companyAgreement" label="入网协议"/>
</el-col>
<el-col :span="12">
<FileInfo ref="fileInfo" :data="fileData" label="企业实名认证授权书"/>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<FileInfo ref="dutyInfo" :sign="true" :data="dutyData" :upload-type="['camera', 'sign']" sign-key="realnameNotice" label="责任告知书"/>
</el-col>
</el-row>
</page-module>
<page-module name="联系信息" icon="tel">
<CompConcatInfo ref="concatInfo" :data="concatData" />
</page-module>
<div class="next-step">
<el-button size="small" plain @click="onPrevStep">上一步</el-button>
<el-button size="small" type="primary" @click="onNextStep">下一步</el-button>
</div>
<CompAttachment :vin="attachment.vin" :file-id="attachment.fileId" @change="handleAttachmentChange" />
</div>
</template>
<script>
import { checkSmsCaptcha } from '@/api/realname-person'
import { submitEnterpriseRnrWithFile, submitEnterpriseRnr } from '@/api/realname-enterprise'
import { mapGetters } from 'vuex'
import CompAttachment from '@/components/CompAttachment'
import CompBasicInfo from '@/components/CompBasicInfo'
import CompCertificateInfo from '@/components/CompCertificateInfo'
import CompConcatInfo from '@/components/CompConcatInfo'
import FileInfo from '@/components/FileInfo'
import Common from '@/components/Common'
export default {
name: 'EnterpriseRealnameStep3',
components: {
CompAttachment,
CompBasicInfo,
CompCertificateInfo,
FileInfo,
CompConcatInfo
},
mixins: [Common],
data() {
return {
pageData: {
baseData: {},
certData: {},
fileData: {},
contractData: {},
dutyData: {},
concatData: {}
},
attachment: {
vin: [],
fileId: ''
},
attachmentUrl: ''
}
},
computed: {
...mapGetters(['dict', 'deviceType']),
baseData() {
return this.pageData.baseData || {}
},
certData() {
return this.pageData.certData || {}
},
fileData() {
return this.pageData.fileData || {}
},
dutyData() {
return this.pageData.dutyData || {}
},
concatData() {
return this.pageData.concatData || {}
},
contractData() {
return this.pageData.contractData || {}
}
},
created() {
this.init()
},
activated() {
this.$refs.baseInfo.clearValidate()
this.$refs.certInfo.clearValidate()
this.$refs.contractInfo.clearValidate()
this.$refs.fileInfo.clearValidate()
this.$refs.dutyInfo.clearValidate()
this.$refs.concatInfo.clearValidate()
},
methods: {
/**
* 附件改变方法
*/
handleAttachmentChange(val) {
this.attachmentUrl = val
},
init() {
this.getCacheData()
if (this.$route.params.from === 'prev') {
this.restoreCacheData()
} else {
this.resetStepData()
}
// 从缓存中取出数据
const stepPad = this.cacheGetStepData('EnterpriseRealnameStepPad1') || {}
const stepPc = this.cacheGetStepData('EnterpriseRealnameStep1') || {}
this.attachment = {
vin: stepPad.iccidList || [],
fileId: stepPc.checkData ? stepPc.checkData.fileId : ''
}
},
getCacheData() {
this.cacheData = this.cacheGetStepData(this.cacheKey)
},
restoreCacheData() {
if (this.isValidObject(this.cacheData)) {
this.pageData = this.cloneObject(this.cacheData)
} else {
this.resetStepData()
}
},
resetStepData() {
this.pageData = {
baseData: {},
certData: {},
fileData: {},
dutyData: {},
concatData: {},
contractData: {}
}
},
onReadCert(data) {
this.$set(this.pageData.baseData, 'name', data.name)
this.$set(this.pageData.baseData, 'sex', data.gender)
this.$refs.baseInfo.validate()
},
/**
* 上一步
* @time 2022-04-23 16:33:24
*/
onPrevStep() {
this.$router.push({ name: 'EnterpriseRealnameStep2', params: { from: 'prev' }})
},
getSubmitData() {
const stepPad1Data = this.cacheGetStepData('EnterpriseRealnameStepPad1') || {}
const step1Data = this.cacheGetStepData('EnterpriseRealnameStep1') || {}
const step2Data = this.cacheGetStepData('EnterpriseRealnameStep2') || {}
const step3Data = this.cacheGetStepData('EnterpriseRealnameStep3') || {}
const ret = {
companyName: step2Data.baseData.companyName,
companyType: step2Data.baseData.companyType,
industryType: step2Data.baseData.industryType,
companyCertType: step2Data.certData.companyCertType,
licenseImages: step2Data.certData.licenseImages.map(item => item.uuid),
companyCertNumber: step2Data.certData.companyCertNumber,
companyCertAddress: step2Data.certData.companyCertAddress,
companyContactAddress: step2Data.certData.companyContactAddress,
corporationName: step3Data.baseData.name,
corporationGender: step3Data.baseData.sex,
corporationCertType: step3Data.certData.type,
corporationPhotoPic: step3Data.certData.photoUrls.filter(item => item.url.id !== null).map(item => item.url.id),
corporationCertNumber: step3Data.certData.no,
corporationCertAddress: step3Data.certData.address,
corporationCertExpirationDate: step3Data.certData.validDate,
corporationCertEffectiveDate: step3Data.certData.certEffectiveDate,
corporationContactAddress: step3Data.certData.connectAddress,
corporationPhone: step3Data.concatData.phone,
verificationCode: step3Data.concatData.veCode,
authorizationLetterPic: step3Data.fileData.fileList.map(item => item.uuid),
dutyPic: step3Data.dutyData.fileList.map(item => item.uuid),
contractPic: step3Data.contractData.fileList.map(item => item.uuid),
vinList: stepPad1Data.vinList ? stepPad1Data.vinList.map(vin => vin.vin) : '',
fileId: step1Data.checkData ? step1Data.checkData.fileId : '',
isVehicleCompany: 0
}
return ret
},
/**
* 下一步
* @time 2022-04-23 15:50:05
*/
async onNextStep() {
try {
const valid = [
this.$refs.baseInfo.validate(),
this.$refs.certInfo.validate(),
this.$refs.contractInfo.validate(),
this.$refs.fileInfo.validate(),
this.$refs.dutyInfo.validate(),
this.$refs.concatInfo.validate()
]
await Promise.all(valid)
const baseData = this.$refs.baseInfo.getPendingCacheData()
const certData = this.$refs.certInfo.getPendingCacheData()
const contractData = this.$refs.contractInfo.getPendingCacheData()
const fileData = this.$refs.fileInfo.getPendingCacheData()
const dutyData = this.$refs.dutyInfo.getPendingCacheData()
const concatData = this.$refs.concatInfo.getPendingCacheData()
this.cacheSetStepData(this.cacheKey, { baseData, certData, fileData, contractData, dutyData, concatData })
// 如果当前是平板
if (window.OS.isTablet) {
// 当前提交的数据
const reqData = this.getSubmitData()
// 提交接口
const { h5LivenessUrl } = await (this.$store.getters.deviceType === 'aio' ? submitEnterpriseRnrWithFile : submitEnterpriseRnr)({
...(reqData || {}),
source: 'PAD'
})
// 跳转到活体认证页面
window.location.href = h5LivenessUrl
return
}
// 校验手机号输入是否正确
await checkSmsCaptcha({
phone: concatData.phone,
captcha: concatData.veCode
})
this.$router.push({ name: 'EnterpriseRealnameStep4' })
} catch (e) {
console.log(e)
e.anchor()
}
}
}
}
</script>
<template>
<div v-loading.fullscreen.lock="fullscreenLoading" class="page">
<pageTitle v-loading.fullscreen.lock="fullscreenLoading" title="企业实名认证" />
<steps :data="dict.enterpriseRealnameSteps" :index="3" />
<PageModuleTabs
:tabs="TABS"
v-if="device.showTakePhoto"
v-model="tabName"
>
<CompFaceRecognition ref="faceInfo" :type="livenessType" :take="tabName == 'carmer'" :data="faceData"/>
</PageModuleTabs>
<page-module v-else name="活体视频上传" icon="video">
<CompFaceRecognition ref="faceInfo" :type="livenessType" :data="faceData"/>
</page-module>
<div class="next-step">
<el-button size="small" plain @click="onPrevStep">上一步</el-button>
<el-button size="small" type="primary" @click="onSubmit">提交</el-button>
</div>
<comp-confirm
:show.sync="showSuccessConfirm"
:desc="successConfirmDesc"
:show-cancel-btn="false"
type="success"
@on-sure="onSure"
/>
<comp-confirm
:show.sync="showErrorConfirm"
:desc="errorConfirmDesc"
/>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
import { getLivenessCode, enterpriseSubmitRnr } from '@/api/realname-enterprise'
import CompFaceRecognition from '@/components/CompFaceRecognition'
import CompConfirm from '@/components/CompConfirm'
import PageModuleTabs from '@/components/PageModule/tabs'
import Common from '@/components/Common'
const TABS = [
{
label: '活体视频上传',
value: 'video',
icon: require('@/assets/image/video@2x.png')
},
{
label: '在线拍摄视频',
value: 'carmer',
icon: require('@/assets/image/icon_user@2x.png')
}
]
export default {
name: 'EnterpriseRealnameStep4',
components: {
CompFaceRecognition,
CompConfirm,
PageModuleTabs
},
mixins: [Common],
data() {
return {
TABS,
showSuccessConfirm: false,
successConfirmDesc: '',
pageData: {},
showErrorConfirm: false,
errorConfirmDesc: '',
livenessType: '',
fullscreenLoading: false,
tabName: 'video'
}
},
computed: {
...mapGetters(['dict', 'device']),
faceData() {
return this.pageData.faceData || {}
}
},
created() {
this._initMount = true
this.init()
},
methods: {
errorTips(errMsg) {
this.showErrorConfirm = true
this.errorConfirmDesc = errMsg
},
successTips(msg) {
this.showSuccessConfirm = true
this.successConfirmDesc = msg
},
/**
* 上一步
* @time 2022-04-23 16:33:24
*/
onPrevStep() {
this.$router.push({ name: 'EnterpriseRealnameStep3', params: { from: 'prev' }})
},
getSubmitData() {
const step1Data = this.cacheGetStepData('EnterpriseRealnameStep1')
const step2Data = this.cacheGetStepData('EnterpriseRealnameStep2')
const step3Data = this.cacheGetStepData('EnterpriseRealnameStep3')
const ret = {
companyName: step2Data.baseData.companyName,
companyType: step2Data.baseData.companyType,
industryType: step2Data.baseData.industryType,
companyCertType: step2Data.certData.companyCertType,
licenseImages: step2Data.certData.licenseImages.map(item => item.uuid),
companyCertNumber: step2Data.certData.companyCertNumber,
companyCertAddress: step2Data.certData.companyCertAddress,
companyContactAddress: step2Data.certData.companyContactAddress,
corporationName: step3Data.baseData.name,
corporationGender: step3Data.baseData.sex,
corporationCertType: step3Data.certData.type,
corporationPhotoPic: step3Data.certData.photoUrls.filter(item => item.url.id !== null).map(item => item.url.id),
corporationCertNumber: step3Data.certData.no,
corporationCertAddress: step3Data.certData.address,
corporationCertExpirationDate: step3Data.certData.validDate,
corporationCertEffectiveDate: step3Data.certData.certEffectiveDate,
corporationContactAddress: step3Data.certData.connectAddress,
corporationPhone: step3Data.concatData.phone,
verificationCode: step3Data.concatData.veCode,
authorizationLetterPic: step3Data.fileData.fileList.map(item => item.uuid),
dutyPic: step3Data.dutyData.fileList.map(item => item.uuid),
contractPic: step3Data.contractData.fileList.map(item => item.uuid),
liveVerificationVideo: this.$refs.faceInfo.getFormData().fileList[0].uuid,
fileId: step1Data.checkData.fileId,
requestId: this._remoteLiveData.requestId,
isVehicleCompany: 0
}
return ret
},
async init() {
this.fullscreenLoading = true
this._remoteLiveData = await this.getLivenessCode()
this.fullscreenLoading = false
this.livenessType = this._remoteLiveData ? this._remoteLiveData.livenessType : ''
this.pageData = {
faceData: {
number: this._remoteLiveData ? this._remoteLiveData.livenessCode : ''
}
}
},
async onSubmit() {
if (this.faceData.number === '') {
this.errorTips('获取活体数字验证码失败,请刷新页面重试')
return
}
try {
await this.$refs.faceInfo.validate()
this.fullscreenLoading = true
const respData = await this.enterpriseSubmitRnr(this.getSubmitData())
this.fullscreenLoading = false
if (!respData.isOk) {
this.errorTips(respData.data.message || '实名认证失败')
return
}
if (respData.data.verifyStatus === 0) {
this.successTips('实名认证成功')
} else if (respData.data.verifyStatus === 1) {
this.successTips('已转入人工审核,请注意查询认证进度')
} else {
this.errorTips('实名认证失败')
}
} catch (e) {
console.log(e)
e.anchor()
}
},
async getLivenessCode() {
try {
const ret = await getLivenessCode()
return ret
} catch (e) {
return null
}
},
async enterpriseSubmitRnr(params) {
try {
const respData = await enterpriseSubmitRnr({
data: {
...params
},
hideToast: true
})
return {
isOk: true,
data: respData
}
} catch (e) {
return {
isOk: false,
data: e
}
}
},
onSure() {
sessionStorage.clear()
this.$router.push({ name: 'HomePage' })
}
}
}
</script>
const range = [
'PersonRealnameStep1',
'PersonRealnameStep2',
'PersonRealnameStep3'
]
export default {
beforeRouteLeave(to, from, next) {
if (range.indexOf(to.name) === -1) {
range.forEach(name => {
this.cacheDelStepData(name)
})
}
next()
},
created() {
this._isInitMount = true
this.init()
},
activated() {
if (this._isInitMount) {
this._isInitMount = false
return
}
this.show()
},
methods: {
// 从前一个页面进入当前页时,先从缓存恢复数据,否则重建
// 其他情况进入当前页,重建
initRenderPage() {
if (this.$route.params.from === 'prev') {
this.restorePageDataFromCache()
} else {
this.initEmptyPageData()
}
},
// 获取车卡关系验证请求参数
getVerifyVinCardsInfoParams(data, addition) {
const iccidList = data.iccidList.filter(item => item.iccid !== '').map(item => item.iccid)
const vin = data.vin
const rnrId = data.rnrId
return {
iccidList,
vin,
rnrId,
...addition
}
},
// 获取提交自然人实名认证请求参数
getSubmitPersonRealNameAuthParams(data) {
const {
step1Data,
step2Data,
step3Data
} = data
const busTypeData = step1Data.busTypeData
const carCardData = step1Data.carCardData
const masterData = step2Data.masterData
const delegateData = step2Data.delegateData
const ret = {
// 业务类型
customerType: busTypeData.userType === 'new' ? 0 : 1,
isConsigner: busTypeData.isDelegate,
// 车卡信息
vin: carCardData.vin,
iccidList: carCardData.iccidList.filter(item => item.iccid !== '').map(item => item.iccid),
// 基本信息
fullName: masterData.basicInfoData.name,
gender: masterData.basicInfoData.sex,
// 证件信息
certAddress: masterData.certInfoData.address,
certExpirationDate: masterData.certInfoData.validDate,
certEffectiveDate: masterData.certInfoData.certEffectiveDate,
certPic: masterData.certInfoData.photoUrls.filter(item => item.url.id !== null).map(item => item.url.id),
certNumber: masterData.certInfoData.no,
certType: masterData.certInfoData.type,
contactAddress: masterData.certInfoData.connectAddress,
// 文件信息
contractPic: masterData.fileInfoData.protocolUrl.map(item => item.uuid),
purchaseContractPic: busTypeData.userType === 'new' ? [] : masterData.fileInfoData.contractUrl.map(item => item.uuid),
purchaseInvoicePic: busTypeData.userType === 'new' ? [] : masterData.fileInfoData.billUrl.map(item => item.uuid),
transferCertificatePic: busTypeData.userType === 'new' ? [] : masterData.fileInfoData.transferUrl.map(item => item.uuid),
dutyPic: masterData.fileInfoData.notifyUrl.map(item => item.uuid),
// 联系信息
phone: masterData.concatInfoData.phone,
verificationCode: masterData.concatInfoData.veCode,
// 委托人
consignerInfo: {
// 基本信息
fullName: '',
gender: '',
// 证件信息
certType: '',
certPic: [],
certNumber: '',
certAddress: '',
certExpirationDate: '',
contactAddress: '',
// 委托书
attorneyLetterPic: '',
// 联系信息
phone: '',
verificationCode: ''
},
liveVerificationVideo: step3Data ? step3Data.fileData.fileList[0].uuid : '',
requestId: step3Data ? step3Data.requestId : ''
}
if (busTypeData.isDelegate) {
ret.consignerInfo.fullName = delegateData.basicInfoData.name
ret.consignerInfo.gender = delegateData.basicInfoData.sex
ret.consignerInfo.certType = delegateData.certInfoData.type
ret.consignerInfo.certPic = delegateData.certInfoData.photoUrls.filter(item => item.url.id !== null).map(item => item.url.id)
ret.consignerInfo.certNumber = delegateData.certInfoData.no
ret.consignerInfo.certAddress = delegateData.certInfoData.address
ret.consignerInfo.certExpirationDate = delegateData.certInfoData.validDate
ret.consignerInfo.certEffectiveDate = delegateData.certInfoData.certEffectiveDate
ret.consignerInfo.contactAddress = delegateData.certInfoData.connectAddress
ret.consignerInfo.attorneyLetterPic = delegateData.fileInfoData.fileList.map(item => item.uuid)
ret.consignerInfo.phone = delegateData.concatInfoData.phone
ret.consignerInfo.verificationCode = delegateData.concatInfoData.veCode
}
return ret
}
}
}
import Schema from 'async-validator'
const step1Descriptor = {
busTypeData: {
type: 'object',
required: true,
fields: {
userType: { type: 'string', required: true },
isDelegate: { type: 'boolean', required: true }
}
},
carCardData: {
type: 'object',
required: true,
fields: {
vin: { type: 'string', required: true },
iccidList: {
type: 'array',
required: true,
defaultField: {
type: 'object',
required: true,
fields: {
iccid: { type: 'string' },
state: { type: 'string', required: true },
_formId: { type: 'number', required: true },
_inputId: { type: 'number', required: true }
}
}
}
}
}
}
const step1Validator = new Schema(step1Descriptor)
// 第2步车主数据校验
const step2MasterDataDescriptor = {
isDelegate: {
type: 'boolean',
required: true
},
vin: {
type: 'string',
required: true
},
userType: {
type: 'string',
required: true
},
masterData: {
type: 'object',
required: true,
fields: {
basicInfoData: {
type: 'object',
required: true,
fields: {
name: { type: 'string', required: true },
sex: { type: 'string', required: true },
vin: { type: 'string', required: true }
}
},
certInfoData: {
type: 'object',
required: true,
fields: {
address: { type: 'string', required: true },
connectAddress: { type: 'string', required: false },
no: { type: 'string', required: true },
type: { type: 'string', required: true },
validDate: { type: 'string', required: true },
photoUrls: {
type: 'array',
required: true,
defaultField: {
type: 'object',
required: true,
fields: {
id: { type: 'number', required: true },
url: { type: 'object' }
}
}
}
}
},
fileInfoData: {
type: 'object',
required: true,
fields: {
protocolUrl: {
type: 'array',
required: true,
defaultField: {
type: 'object',
required: true,
fields: {
accessUrl: { type: 'string' }
}
}
},
contractUrl: {
type: 'array',
defaultField: {
type: 'object',
required: true,
fields: {
accessUrl: { type: 'string' }
}
}
},
billUrl: {
type: 'array',
defaultField: {
type: 'object',
required: true,
fields: {
accessUrl: { type: 'string' }
}
}
},
transferUrl: {
type: 'array',
defaultField: {
type: 'object',
required: true,
fields: {
accessUrl: { type: 'string' }
}
}
}
}
},
concatInfoData: {
type: 'object',
required: true,
fields: {
phone: { type: 'string', required: true },
veCode: { type: 'string' }
}
}
}
}
}
const step2MasterDataValidator = new Schema(step2MasterDataDescriptor)
// 第2步代办人数据校验
const step2DelegateDataDescriptor = {
delegateData: {
type: 'object',
required: true,
fields: {
basicInfoData: {
type: 'object',
required: true,
fields: {
name: { type: 'string', required: true },
sex: { type: 'string', required: true }
}
},
certInfoData: {
type: 'object',
required: true,
fields: {
address: { type: 'string', required: true },
connectAddress: { type: 'string', required: false },
no: { type: 'string', required: true },
type: { type: 'string', required: true },
validDate: { type: 'string', required: true },
photoUrls: {
type: 'array',
required: true,
defaultField: {
type: 'object',
required: true,
fields: {
id: { type: 'number', required: true },
url: { type: 'object' }
}
}
}
}
},
fileInfoData: {
type: 'object',
required: true,
fields: {
fileList: {
type: 'array',
required: true,
defaultField: {
type: 'object',
required: true,
fields: {
accessUrl: { type: 'string', required: true }
}
}
}
}
},
concatInfoData: {
type: 'object',
required: true,
fields: {
phone: { type: 'string', required: true },
veCode: { type: 'string' }
}
}
}
}
}
const step2DelegateDataValidator = new Schema(step2DelegateDataDescriptor)
export default {
methods: {
step1Validate(data = {}) {
return new Promise((resolve, reject) => {
step1Validator.validate(data || {}, (errors, fields) => {
if (errors) {
resolve(false)
return
}
resolve(true)
})
})
},
step2Validate(data = {}) {
data = data || {}
const masterData = {
isDelegate: data.isDelegate,
vin: data.vin,
userType: data.userType,
masterData: data.masterData
}
return new Promise((resolve, reject) => {
if (data.isDelegate) {
step2MasterDataValidator.validate(masterData, (errors, fields) => {
if (errors) {
resolve(false)
return
}
step2DelegateDataValidator.validate({
delegateData: data.delegateData
}, (errors, fields) => {
if (errors) {
resolve(false)
return
}
resolve(true)
})
})
return
}
step2MasterDataValidator.validate(masterData, (errors, fields) => {
if (errors) {
resolve(false)
return
}
resolve(true)
})
})
}
}
}
<template>
<div v-loading.fullscreen.lock="loading" class="page-person-real-result">
<page-title title="完成人脸识别"/>
<section class="page-rnr-result">
<main class="page-rnr-result-content">
<div :class="[STATUS.FAIL, STATUS.TX_VALID_FAIL].includes(status) ? 'icon-result-fail' : 'icon-result-success'" class="page-rnr-result-icon" />
<div v-if="status === STATUS.FAIL" class="page-rnr-result-title">认证失败</div>
<div v-else-if="status === STATUS.MAN_WORK" class="page-rnr-result-title">已转入人工审核,请注意查询认证进度</div>
<div v-else-if="status === STATUS.TX_VALID_FAIL" class="page-rnr-result-title">腾讯活体认证失败</div>
<div v-else class="page-rnr-result-title">恭喜您认证成功</div>
</main>
<div class="next-step">
<el-button v-if="status === STATUS.TX_VALID_FAIL" size="small" plain @click.stop="handleToTxVerify">重新认证</el-button>
<el-button v-else size="small" type="primary" @click.stop="handleToNextPage(status === STATUS.FAIL ? 'PersonRealnameStep1' : 'HomePage')">{{ status === STATUS.FAIL ? '重新认证' : '返回首页' }}</el-button>
</div>
</section>
</div>
</template>
<script>
import { livenessCallback } from '@/api/realname-person'
// 状态
const STATUS = {
// 加载中
PENDING: -1,
// 腾讯活体认证失败
TX_VALID_FAIL: 2,
// 成功
SUCCESS: 0,
// 人工审核中
MAN_WORK: 1,
// 失败
FAIL: 3
}
export default {
name: 'MarkupPersonResult',
data() {
return {
STATUS,
status: STATUS.PENDING,
h5LivenessUrl: '',
loading: true
}
},
mounted() {
// 开始提交实名信息
this.fetchRnrCallback(this.$route.query)
},
methods: {
/**
* 提交实名认证的接口
*/
async fetchRnrCallback(query) {
// 标记当前在loading中
this.loading = true
try {
// 开始提交数据
const { status, h5LivenessUrl } = await livenessCallback({
...(query || {}),
source: 'PAD'
})
// 标记当前提交成功
this.status = status
// h5活体验证的链接
this.h5LivenessUrl = h5LivenessUrl
// 标记当前loading结束
this.loading = false
return
} catch (error) {
console.error(error)
}
// 标记当前loading结束
this.loading = false
// 标记当前提交失败
this.status = STATUS.FAIL
},
/**
* 跳转到活体认证
*/
handleToTxVerify() {
// 跳转到活体认证页面
window.location.href = this.h5LivenessUrl
},
/**
* 跳转到下一个页面
* @param pageName 页面名称
*/
handleToNextPage(pageName) {
this.$router.push({ name: pageName })
}
}
}
</script>
<style lang="scss">
.page-person-real-result {
padding-bottom: 64px;
.next-step {
z-index: 5;
}
.page-rnr-result {
.page-rnr-result-content {
padding-top: 72px;
.page-rnr-result-icon {
background-size: 100% 100%;
background-repeat: no-repeat;
width: 324px;
height: 245px;
margin: 0 auto;
&.icon-result-success {
background-image: url(../../assets/rnr/ico_success.png);
}
&.icon-result-fail {
background-image: url(../../assets/rnr/ico_fail.png);
}
}
.page-rnr-result-title {
color: #212026;
font-size: 36px;
font-weight: 500;
text-align: center;
margin-top: 24px;
}
}
.page-rnr-main-fixed-btn-group {
background-color: #ffffff;
bottom: 0px;
height: 148px;
padding: 20px 32px;
position: fixed;
left: 0px;
right: 0px;
.page-rnr-main-btn-next {
font-size: 30px;
height: 96px;
}
}
}
}
</style>
<template>
<div v-loading.fullscreen.lock="fullscreenLoading" class="page-person-real-step1">
<page-title title="自然人实名认证"/>
<steps :data="stepData"/>
<page-module name="业务类型" icon="star">
<CompBusType ref="busType" :data="busTypeData" @change="userType => (isBind = userType === 'old')" />
</page-module>
<page-module name="车卡信息" icon="car">
<CompCarCard ref="carCard" :data="carCardData" @on-canenable="carCardLoading = !$event" :is-bind="isBind" />
</page-module>
<div class="next-step">
<el-button :disabled="carCardLoading" size="small" type="primary" @click.stop="clickNextStep">下一步</el-button>
</div>
</div>
</template>
<script>
import { checkVinCard } from '@/api/iccid'
import PageTitle from '@/components/PageTitle'
import Steps from '@/components/Steps'
import CompBusType from '@/components/CompBusType'
import CompCarCard from '@/components/CompCarCard'
import Common from '@/components/Common'
import SelfCommon from './components/common'
export default {
name: 'PersonRealnameStep1',
components: {
PageTitle,
Steps,
CompBusType,
CompCarCard
},
mixins: [Common, SelfCommon],
data() {
return {
stepData: ['车卡信息录入', '填写客户信息', '完成人脸识别'],
pageData: {},
isBind: false,
carCardLoading: false,
fullscreenLoading: false
}
},
computed: {
busTypeData() {
return this.pageData.busTypeData || {}
},
carCardData() {
return this.pageData.carCardData || {}
}
},
methods: {
init() {
this.initStepCachePageData()
this.initRenderPage()
},
show() {
// todo
},
// 初始化空页面数据
initEmptyPageData() {
this.pageData = this.makeEmptyPageDataTemplate()
},
// 从缓存恢复数据
restorePageDataFromCache() {
const _step1CachePageData = this._step1CachePageData
if (this.isValidObject(_step1CachePageData)) {
this.pageData = this.cloneObject(_step1CachePageData)
} else {
this.initEmptyPageData()
}
},
// 获取缓存的 step page data
initStepCachePageData() {
this._step1CachePageData = this.cacheGetStepData(this.cacheKey)
},
// 下一步
async clickNextStep() {
try {
await Promise.all([
this.$refs.busType.validate(),
this.$refs.carCard.validate()
])
this.nextStepHandler()
} catch (e) {
e.anchor()
}
},
async nextStepHandler() {
// 校验车卡关系
this.fullscreenLoading = true
const retData = await this.verifyVinCardsInfo()
this.fullscreenLoading = false
if (retData === null) {
return
}
const step1CachePageData = this.makeEmptyPageDataTemplate()
step1CachePageData.busTypeData = this.$refs.busType.getPendingCacheData()
step1CachePageData.carCardData = this.$refs.carCard.getPendingCacheData()
this.cacheSetStepData(this.cacheKey, step1CachePageData)
this.$router.push({
name: 'PersonRealnameStep2'
})
},
async verifyVinCardsInfo() {
try {
return await checkVinCard(this.getVerifyVinCardsInfoParams(this.$refs.carCard.getPendingCacheData(), { businessType: this.isBind ? 2 : 1 }))
} catch (e) {
return null
}
},
makeEmptyPageDataTemplate() {
return {
busTypeData: null,
carCardData: null
}
}
}
}
</script>
<style lang="scss">
.page-person-real-step1 {
padding-bottom: 64px;
.next-step {
z-index: 5;
}
}
</style>
<template>
<div class="page-person-real-step2">
<page-title title="填写客户信息"/>
<steps :data="stepData" :index="1"/>
<div v-if="pageData.userType === 'new'" key="newUser">
<div v-if="!pageData.isDelegate" key="self">
<page-module name="基本信息" icon="info">
<comp-basic-info ref="masterBasicInfo" :data="masterBasicInfoData"/>
</page-module>
<page-module name="证件信息" icon="idcard">
<comp-certificate-info ref="masterCertInfo" :data="masterCertInfoData" @read-cert="(data)=> onReadCert(data, 'master')"/>
</page-module>
<page-module name="文件信息" icon="folder">
<CompMasterFileInfo ref="masterFileInfo" :data="masterFileInfoData" :type="pageData.userType" :attachment-url="attachmentUrl" />
</page-module>
<page-module name="联系信息" icon="tel">
<comp-concat-info ref="masterConcatInfo" :data="masterConcatInfoData"/>
</page-module>
</div>
<div v-else key="delegate">
<page-module name="车主基本信息" icon="info">
<comp-basic-info ref="masterBasicInfo" :data="masterBasicInfoData"/>
</page-module>
<page-module name="车主证件信息" icon="idcard">
<comp-certificate-info ref="masterCertInfo" :data="masterCertInfoData" @read-cert="(data)=> onReadCert(data, 'master')"/>
</page-module>
<page-module name="车主文件信息" icon="folder">
<CompMasterFileInfo ref="masterFileInfo" :data="masterFileInfoData" :type="pageData.userType" :attachment-url="attachmentUrl" />
</page-module>
<page-module name="车主联系信息" icon="tel">
<comp-concat-info ref="masterConcatInfo" :data="masterConcatInfoData" :need-vcode="false"/>
</page-module>
<page-module name="代办人基本信息" icon="info">
<comp-basic-info ref="delegateBasicInfo" :data="delegateBasicInfoData" :show-vin="false"/>
</page-module>
<page-module name="代办人证件信息" icon="idcard">
<comp-certificate-info ref="delegateCertInfo" :data="delegateCertInfoData" @read-cert="(data)=> onReadCert(data, 'delegate')"/>
</page-module>
<page-module name="代办人文件信息" icon="folder">
<file-info
ref="delegateFileInfo"
:limit="1"
:file-size="10"
:data="delegateFileInfoData"
label="委托书"
placeholder="上传文件"
/>
</page-module>
<page-module name="代办人联系信息" icon="tel">
<comp-concat-info ref="delegateConcatInfo" :data="delegateConcatInfoData" />
</page-module>
</div>
</div>
<div v-else key="oldUser">
<div v-if="!pageData.isDelegate" key="self">
<page-module name="基本信息" icon="info">
<comp-basic-info ref="masterBasicInfo" :data="masterBasicInfoData"/>
</page-module>
<page-module name="证件信息" icon="idcard">
<comp-certificate-info ref="masterCertInfo" :data="masterCertInfoData" @read-cert="(data)=> onReadCert(data, 'master')"/>
</page-module>
<page-module name="文件信息" icon="folder">
<CompMasterFileInfo ref="masterFileInfo" :data="masterFileInfoData" :type="pageData.userType" :attachment-url="attachmentUrl" />
</page-module>
<page-module name="联系信息" icon="tel">
<comp-concat-info ref="masterConcatInfo" :data="masterConcatInfoData"/>
</page-module>
</div>
<div v-else key="delegate">
<page-module name="车主基本信息" icon="info">
<comp-basic-info ref="masterBasicInfo" :data="masterBasicInfoData"/>
</page-module>
<page-module name="车主证件信息" icon="idcard">
<comp-certificate-info ref="masterCertInfo" :data="masterCertInfoData" @read-cert="(data)=> onReadCert(data, 'master')"/>
</page-module>
<page-module name="车主文件信息" icon="folder">
<CompMasterFileInfo ref="masterFileInfo" :data="masterFileInfoData" :type="pageData.userType" :attachment-url="attachmentUrl" />
</page-module>
<page-module name="车主联系信息" icon="tel">
<comp-concat-info ref="masterConcatInfo" :data="masterConcatInfoData" :need-vcode="false"/>
</page-module>
<page-module name="代办人基本信息" icon="info">
<comp-basic-info ref="delegateBasicInfo" :data="delegateBasicInfoData" :show-vin="false"/>
</page-module>
<page-module name="代办人证件信息" icon="idcard">
<comp-certificate-info ref="delegateCertInfo" :data="delegateCertInfoData" @read-cert="(data)=> onReadCert(data, 'delegate')"/>
</page-module>
<page-module name="代办人文件信息" icon="folder">
<file-info
ref="delegateFileInfo"
:limit="1"
:file-size="10"
:data="delegateFileInfoData"
label="委托书"
placeholder="上传文件"
/>
</page-module>
<page-module name="代办人联系信息" icon="tel">
<comp-concat-info ref="delegateConcatInfo" :data="delegateConcatInfoData" />
</page-module>
</div>
</div>
<div class="next-step">
<el-button size="small" plain @click.stop="clickPrevStep">上一步</el-button>
<el-button size="small" type="primary" @click.stop="clickNextStep">下一步</el-button>
</div>
<comp-confirm
:show.sync="showErrorConfirm"
:desc="errorConfirmDesc"
/>
<CompAttachment :vin="attachment.vin" :iccid="attachment.iccid" @change="handleAttachmentChange" />
</div>
</template>
<script>
import { submitPersonRealNameAuthH5, checkSmsCaptcha } from '@/api/realname-person'
import CompAttachment from '@/components/CompAttachment'
import PageTitle from '@/components/PageTitle'
import Steps from '@/components/Steps'
import Common from '@/components/Common'
import CompBasicInfo from '@/components/CompBasicInfo'
import CompCertificateInfo from '@/components/CompCertificateInfo'
import CompConcatInfo from '@/components/CompConcatInfo'
import CompMasterFileInfo from '@/components/CompMasterFileInfo'
import FileInfo from '@/components/FileInfo'
import ValidateStep from './components/validate-step'
import SelfCommon from './components/common'
import CompConfirm from '@/components/CompConfirm'
export default {
name: 'PersonRealnameStep2',
components: {
PageTitle,
Steps,
CompBasicInfo,
CompCertificateInfo,
CompMasterFileInfo,
FileInfo,
CompConcatInfo,
CompConfirm,
CompAttachment
},
mixins: [Common, SelfCommon, ValidateStep],
data() {
return {
stepData: ['车卡信息录入', '填写客户信息', '完成人脸识别'],
pageData: {
userType: '',
isDelegate: false,
vin: '',
masterData: {
basicInfoData: {
vin: ''
}
},
delegateData: {
basicInfoData: {}
}
},
attachment: {
vin: '',
iccid: []
},
attachmentUrl: '',
showErrorConfirm: false,
errorConfirmDesc: ''
}
},
computed: {
masterData() {
return this.pageData.masterData || {}
},
masterBasicInfoData() {
return this.masterData.basicInfoData || {}
},
masterCertInfoData() {
return this.masterData.certInfoData || {}
},
masterFileInfoData() {
return this.masterData.fileInfoData || {}
},
masterConcatInfoData() {
return this.masterData.concatInfoData || {}
},
delegateData() {
return this.pageData.delegateData || {}
},
delegateBasicInfoData() {
return this.delegateData.basicInfoData || {}
},
delegateCertInfoData() {
return this.delegateData.certInfoData || {}
},
delegateFileInfoData() {
return this.delegateData.fileInfoData || {}
},
delegateConcatInfoData() {
return this.delegateData.concatInfoData || {}
}
},
methods: {
/**
* 附件变化方法
*/
handleAttachmentChange(val) {
this.attachmentUrl = val
},
errorTips(errMsg) {
this.showErrorConfirm = true
this.errorConfirmDesc = errMsg
},
async init() {
this.initStepCachePageData()
const canEnter = await this.canEnter()
if (!canEnter) {
this.$router.replace({
name: 'PersonRealnameStep1'
})
} else {
this.initRenderPage()
}
},
async show() {
this.initStepCachePageData()
const canEnter = await this.canEnter()
if (!canEnter) {
this.$router.replace({
name: 'PersonRealnameStep1'
})
} else {
// 更新依赖数据
this.updateDepData()
}
},
// 初始化空页面数据
initEmptyPageData() {
const step1CachePageData = this._step1CachePageData
this.pageData = this.makeEmptyPageDataTemplate()
this.pageData.userType = (step1CachePageData.busTypeData || {}).userType
this.pageData.isDelegate = !!((step1CachePageData.busTypeData || {}).isDelegate)
this.pageData.vin = (step1CachePageData.carCardData || {}).vin || ''
this.pageData.masterData.basicInfoData.vin = this.pageData.vin
},
// 从缓存恢复数据
restorePageDataFromCache() {
const step2CachePageData = this._step2CachePageData
if (this.isValidObject(step2CachePageData)) {
this.pageData = this.cloneObject(step2CachePageData)
} else {
this.initEmptyPageData()
}
},
// 更新依赖前一步的数据
updateDepData() {
const step1CachePageData = this._step1CachePageData
this.pageData.userType = (step1CachePageData.busTypeData || {}).userType
this.pageData.isDelegate = !!((step1CachePageData.busTypeData || {}).isDelegate)
this.pageData.vin = (step1CachePageData.carCardData || {}).vin || ''
if (this.isValidObject(this.pageData.masterData) && this.isValidObject(this.pageData.masterData.basicInfoData)) {
this.pageData.masterData.basicInfoData.vin = this.pageData.vin
}
},
// 获取缓存的 step page data
initStepCachePageData() {
this._step1CachePageData = this.cacheGetStepData('PersonRealnameStep1')
this._step2CachePageData = this.cacheGetStepData(this.cacheKey)
if (this._step1CachePageData) {
const carCardData = this._step1CachePageData.carCardData || {}
this.attachment = {
vin: carCardData.vin,
iccid: carCardData.iccidList.filter(item => item.iccid !== '').map(item => item.iccid)
}
}
},
// 是否可以进入当前页检查
async canEnter() {
const step1CachePageData = this._step1CachePageData
const result = await this.step1Validate(step1CachePageData)
return result
},
// 上一步
clickPrevStep() {
this.$router.push({
name: 'PersonRealnameStep1',
params: {
from: 'prev'
}
})
},
// 下一步
async clickNextStep() {
try {
const validateList = [
this.$refs.masterBasicInfo.validate(),
this.$refs.masterCertInfo.validate(),
this.$refs.masterFileInfo.validate(),
this.$refs.masterConcatInfo.validate()
]
if (this.pageData.isDelegate) {
validateList.push(...[
this.$refs.delegateBasicInfo.validate(),
this.$refs.delegateCertInfo.validate(),
this.$refs.delegateFileInfo.validate(),
this.$refs.delegateConcatInfo.validate()
])
}
await Promise.all(validateList)
// 校验车主和委托人证件信息
if (this.pageData.isDelegate) {
const masterCertInfo = this.$refs.masterCertInfo.getPendingCacheData()
const delegateCertInfo = this.$refs.delegateCertInfo.getPendingCacheData()
if (masterCertInfo.type === delegateCertInfo.type && masterCertInfo.no === delegateCertInfo.no) {
this.errorTips('车主证件信息与委托代办人证件信息一致,请更换')
return
}
}
// 手机号校验成功,则跳转下一步
this.clickNextStepHandler()
} catch (e) {
console.error('校验错误:', e)
e.anchor()
}
},
async clickNextStepHandler() {
const step2CachePageData = this.makeEmptyPageDataTemplate()
step2CachePageData.userType = this.pageData.userType
step2CachePageData.isDelegate = this.pageData.isDelegate
step2CachePageData.vin = this.pageData.vin
const masterBasicInfoData = this.$refs.masterBasicInfo.getPendingCacheData()
const masterCertInfoData = this.$refs.masterCertInfo.getPendingCacheData()
const masterFileInfoData = this.$refs.masterFileInfo.getPendingCacheData()
const masterConcatInfoData = this.$refs.masterConcatInfo.getPendingCacheData()
step2CachePageData.masterData = {
basicInfoData: masterBasicInfoData,
certInfoData: masterCertInfoData,
fileInfoData: masterFileInfoData,
concatInfoData: masterConcatInfoData
}
// 校验参数
let phoneValidParams = {
phone: masterConcatInfoData.phone,
captcha: masterConcatInfoData.veCode
}
if (this.pageData.isDelegate) {
const delegateBasicInfoData = this.$refs.delegateBasicInfo.getPendingCacheData()
const delegateCertInfoData = this.$refs.delegateCertInfo.getPendingCacheData()
const delegateFileInfoData = this.$refs.delegateFileInfo.getPendingCacheData()
const delegateConcatInfoData = this.$refs.delegateConcatInfo.getPendingCacheData()
step2CachePageData.delegateData = {
basicInfoData: delegateBasicInfoData,
certInfoData: delegateCertInfoData,
fileInfoData: delegateFileInfoData,
concatInfoData: delegateConcatInfoData
}
phoneValidParams = {
phone: delegateConcatInfoData.phone,
captcha: delegateConcatInfoData.veCode
}
}
this.cacheSetStepData(this.cacheKey, step2CachePageData)
// 如果当前是平板下,调用h5的接口,跳转腾讯活体
if (window.OS.isTablet) {
// 请求入参
const reqData = this.getSubmitPersonRealNameAuthParams({
step1Data: this.cacheGetStepData('PersonRealnameStep1'),
step2Data: this.cacheGetStepData('PersonRealnameStep2')
})
// 开始提交接口
const { h5LivenessUrl } = await submitPersonRealNameAuthH5({
...(reqData || {}),
source: 'PAD'
})
// 跳转去活体
window.location.href = h5LivenessUrl
return
}
// 校验手机号输入是否正确
await checkSmsCaptcha(phoneValidParams)
this.$router.push({
name: 'PersonRealnameStep3'
})
},
makeEmptyPageDataTemplate() {
return {
userType: '',
isDelegate: false,
vin: '',
masterData: {
basicInfoData: {
vin: ''
}
},
delegateData: {
basicInfoData: {}
}
}
},
onReadCert(data, type) {
if (type === 'master') {
this.$set(this.pageData.masterData.basicInfoData, 'name', data.name)
this.$set(this.pageData.masterData.basicInfoData, 'sex', data.gender)
this.$refs.masterCertInfo.validate()
} else {
this.$set(this.pageData.delegateData.basicInfoData, 'name', data.name)
this.$set(this.pageData.delegateData.basicInfoData, 'sex', data.gender)
this.$refs.delegateCertInfo.validate()
}
this.$refs.masterBasicInfo.validate()
}
}
}
</script>
<style lang="scss">
.page-person-real-step2 {
padding-bottom: 64px;
.next-step {
z-index: 5;
}
}
</style>
<template>
<div v-loading.fullscreen.lock="fullscreenLoading" class="page-person-real-step3">
<page-title title="完成人脸识别"/>
<steps :data="stepData" :index="2"/>
<PageModuleTabs
:tabs="TABS"
v-if="device.showTakePhoto"
v-model="tabName"
>
<CompFaceRecognition ref="face" :type="livenessType" :take="tabName == 'carmer'" :data="faceData"/>
</PageModuleTabs>
<page-module v-else name="活体视频上传" icon="video">
<CompFaceRecognition ref="face" :type="livenessType" :data="faceData"/>
</page-module>
<div class="next-step">
<el-button size="small" plain @click.stop="clickPrevStep">上一步</el-button>
<el-button size="small" type="primary" @click.stop="clickNextStep">提交</el-button>
</div>
<comp-confirm
:show.sync="showErrorConfirm"
:desc="errorConfirmDesc"
/>
<comp-confirm
:show.sync="showSuccessConfirm"
:desc="successConfirmDesc"
type="success"
@on-sure="successSureHandler"
/>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
import PageModuleTabs from '@/components/PageModule/tabs'
import { submitPersonRealNameAuth, getLivenessCode } from '@/api/realname-person'
import PageTitle from '@/components/PageTitle'
import Steps from '@/components/Steps'
import Common from '@/components/Common'
import CompConfirm from '@/components/CompConfirm'
import CompFaceRecognition from '@/components/CompFaceRecognition'
import ValidateStep from './components/validate-step'
import SelfCommon from './components/common'
const TABS = [
{
label: '活体视频上传',
value: 'video',
icon: require('@/assets/image/video@2x.png')
},
{
label: '在线拍摄视频',
value: 'carmer',
icon: require('@/assets/image/icon_user@2x.png')
}
]
export default {
name: 'PersonRealnameStep3',
components: {
PageTitle,
Steps,
CompConfirm,
CompFaceRecognition,
PageModuleTabs
},
mixins: [Common, SelfCommon, ValidateStep],
data() {
return {
fullscreenLoading: false,
showErrorConfirm: false,
errorConfirmDesc: '',
showSuccessConfirm: false,
successConfirmDesc: '',
stepData: ['车卡信息录入', '填写客户信息', '完成人脸识别'],
livenessType: '',
pageData: {},
tabName: 'video',
TABS
}
},
computed: {
...mapGetters(['device']),
faceData() {
return this.pageData.faceData || {}
}
},
methods: {
errorTips(errMsg) {
this.showErrorConfirm = true
this.errorConfirmDesc = errMsg
},
successTips(msg) {
this.showSuccessConfirm = true
this.successConfirmDesc = msg
},
async init() {
this.fullscreenLoading = true
this._remoteLiveData = await this.getLivenessCode()
this.fullscreenLoading = false
this.initStepCachePageData()
const canEnter = await this.canEnter()
if (!canEnter) {
this.$router.replace({
name: 'PersonRealnameStep1'
})
} else {
this.initRenderPage()
}
},
async show() {
this.initStepCachePageData()
const canEnter = await this.canEnter()
if (!canEnter) {
this.$router.replace({
name: 'PersonRealnameStep1'
})
} else {
this.updateDepData()
}
},
// 初始化空页面数据
initEmptyPageData() {
this.pageData = this.makeEmptyPageDataTemplate()
this.livenessType = this._remoteLiveData ? this._remoteLiveData.livenessType : ''
this.pageData.faceData = {
number: this._remoteLiveData ? this._remoteLiveData.livenessCode : ''
}
},
// 从缓存恢复数据
restorePageDataFromCache() {
const step3CachePageData = this._step3CachePageData
if (this.isValidObject(step3CachePageData)) {
this.pageData = this.cloneObject(step3CachePageData)
} else {
this.initEmptyPageData()
}
},
updateDepData() {
// todo
},
// 获取缓存的 step page data
initStepCachePageData() {
this._step1CachePageData = this.cacheGetStepData('PersonRealnameStep1')
this._step2CachePageData = this.cacheGetStepData('PersonRealnameStep2')
this._step3CachePageData = this.cacheGetStepData(this.cacheKey)
},
// 是否可以进入当前页检查
async canEnter() {
const step1IsOk = await this.step1Validate(this._step1CachePageData)
const step2IsOk = await this.step2Validate(this._step2CachePageData)
return step1IsOk && step2IsOk
},
// 上一步
clickPrevStep() {
this.$router.push({
name: 'PersonRealnameStep2',
params: {
from: 'prev'
}
})
},
// 下一步
async clickNextStep() {
if (this.faceData.number === '') {
this.errorTips('获取活体数字验证码失败,请刷新页面重试')
return
}
try {
await this.$refs.face.validate()
this.clickNextStepHandler()
} catch (e) {
e.anchor()
}
},
async clickNextStepHandler() {
const submitData = {
step1Data: this._step1CachePageData,
step2Data: this._step2CachePageData,
step3Data: {
fileData: this.$refs.face.getFormData(),
number: this.faceData.number,
requestId: this._remoteLiveData.requestId
}
}
this.fullscreenLoading = true
const respData = await this.submitPersonRealNameAuth(this.getSubmitPersonRealNameAuthParams(submitData))
this.fullscreenLoading = false
if (!respData.isOk) {
this.errorTips(respData.data.message || '实名认证失败')
return
}
if (respData.data.verifyStatus === 0) {
this.successTips('实名认证成功')
} else if (respData.data.verifyStatus === 1) {
this.successTips('已转入人工审核,请注意查询认证进度')
} else {
this.errorTips('实名认证失败')
}
},
successSureHandler() {
this.$router.push({
name: 'Home'
})
},
makeEmptyPageDataTemplate() {
return {
faceData: null
}
},
async submitPersonRealNameAuth(params) {
try {
const respData = await submitPersonRealNameAuth({
data: {
...params
},
hideToast: true
})
return {
isOk: true,
data: respData
}
} catch (e) {
return {
isOk: false,
data: e
}
}
},
async getLivenessCode() {
try {
const ret = await getLivenessCode()
return ret
} catch (e) {
return null
}
}
}
}
</script>
<style lang="scss">
.page-person-real-step3 {
padding-bottom: 64px;
.next-step {
z-index: 5;
}
}
</style>
<template>
<div v-loading.fullscreen.lock="fullscreenLoading" class="page page-search page-car-auth">
<div class="manage-title">单车认证查询</div>
<div class="search-form">
<el-form ref="searchForm" :rules="rules" :model="searchForm" label-width="90px" size="small" @submit.native.prevent>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="车辆VIN码" prop="vin">
<el-input v-model="searchForm.vin" maxlength="17" placeholder="请输入车辆VIN码" clearable />
</el-form-item>
</el-col>
<el-col :span="12">
<el-button size="small" type="primary" icon="iconfont icon-search" @click="onSearch">搜索</el-button>
<el-button size="small" type="gray" icon="iconfont icon-clear" @click="onClear">清除</el-button>
</el-col>
</el-row>
</el-form>
</div>
<div class="search-body">
<div class="search-title">认证进度查询结果</div>
<div v-if="list.length > 0">
<div v-for="(item, index) in list" :key="index" class="auth-content" >
<div class="auth-date">
<div v-if="item.year">{{ item.year }}</div>
</div>
<div class="auth-step">
<div class="step-item">
<div class="step-time">申请时间:{{ item.startCheckDate }} </div>
<div class="step-cont">
<div class="step-head">
<div class="step-name">{{ item.title }}</div>
<el-tag v-if="[0, 1, 2].includes(+item.orderStatus)" size="mini" type="warning">{{ AUDIT_STATUS[item.orderStatus] }}</el-tag>
<el-tag v-else-if="+item.orderStatus === 3" size="mini" type="success">{{ AUDIT_STATUS[item.orderStatus] }}</el-tag>
<el-tag v-else-if="[4, 9].includes(+item.orderStatus)" size="mini" type="danger">{{ AUDIT_STATUS[item.orderStatus] }}</el-tag>
</div>
<ul class="step-body">
<li>ICCID:{{ item.iccid }}</li>
<li>组织名称:{{ item.orgName || '-' }}</li>
<li>车主/责任人:{{ item.fullName }}</li>
<li>手机号:{{ item.phone }}</li>
<li>所属企业:{{ item.companyName || '-' }}</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<div v-else class="empty-data">暂无数据</div>
</div>
</div>
</template>
<script>
import { carAuthList1 } from '@/api/search'
const AUDIT_STATUS = ['已提交', '待分派/认领', '待审核', '审核通过', '未通过', '', '', '', '', '作废']
export default {
name: 'CarAuth1',
data() {
const checkVin = (rule, value, callback) => {
if (!value) {
callback(new Error('车辆VIN码不能为空'))
} else if (value.length !== 17) {
callback(new Error('车辆VIN码格式不正确'))
} else {
callback()
}
}
return {
fullscreenLoading: false,
searchForm: {
vin: ''
},
AUDIT_STATUS,
searchData: {},
list: [],
rules: {
vin: [
{ required: true, trigger: 'blur', message: '车辆VIN码不能为空' },
{ validator: checkVin, trigger: 'blur' }
]
}
}
},
methods: {
/**
* 获取数据
* @time 2021-11-06 13:23:29
*/
async getData() {
const param = {
...this.searchData
}
this.fullscreenLoading = true
try {
const data = await carAuthList1(param)
this.list = data || []
const dataInfo = {}
const { businessType } = this.$store.getters.dict
this.list.forEach(item => {
const time = item.startCheckDate.substring(0, 4)
if (!dataInfo[time]) {
dataInfo[time] = []
item.year = time
}
dataInfo[time].push(item)
item.title = businessType.find(type => +type.value === +item.orderType).label
})
} catch (error) {
console.error(error)
}
this.fullscreenLoading = false
},
/**
* 搜索事件
* @time 2021-11-06 14:45:23
*/
onSearch() {
this.$refs.searchForm.validate(valid => {
if (valid) {
this.searchData = { ...this.searchForm }
this.getData()
}
})
},
/**
* 清除事件
* @time 2021-11-06 14:45:23
*/
onClear() {
this.$refs.searchForm.resetFields()
this.searchData = { ...this.searchForm }
this.list = []
// this.getData()
}
}
}
</script>
<style lang="scss">
.page-car-auth {
padding: 24px;
.search-body {
.auth-date {
margin-top: -6px;
}
}
}
</style>
<template>
<div class="page-search page-auth-search">
<div class="page-car-auth">
<div class="manage-title">态势感知看板(截止昨日)</div>
<div class="search-count">
<dl class="count-item count1">
<dt>自然人实名数</dt>
<dd>{{ statistics.peopleRnrNum || 0 }}</dd>
</dl>
<dl class="count-item count2">
<dt>企业实名数</dt>
<dd>{{ statistics.companyRnrNum || 0 }}</dd>
</dl>
<dl class="count-item count3">
<dt>车企实名成功率</dt>
<dd>{{ statistics.vehicleCompanyRnrSuccessRate }}</dd>
</dl>
<dl class="count-item count4">
<dt>车企人工审核平均时长</dt>
<dd>{{ statistics.vehicleHandleTimeAvg }}</dd>
</dl>
</div>
</div>
<SearchTable
title="认证进度查询"
ref="searchTableRef"
v-model="searchForm"
@reset="handleReset"
@submit="handleSubmit"
>
<template #slot-form>
<el-col :span="isTablet ? 12 : 6">
<el-form-item label="车辆VIN码" prop="vin" label-width="120px">
<el-input v-model="searchForm.vin" placeholder="请输入车辆VIN码" clearable />
</el-form-item>
</el-col>
<el-col :span="isTablet ? 12 : 6">
<el-form-item label="关联ICCID" prop="iccid" label-width="120px">
<el-input v-model="searchForm.iccid" placeholder="请输入关联ICCID" clearable />
</el-form-item>
</el-col>
<el-col :span="isTablet ? 12 : 6" :class="isTablet ? 'mt-16' : ''">
<el-form-item label="车主/企业责任人" prop="user" label-width="120px">
<el-input v-model="searchForm.user" placeholder="请输入车主/企业责任人" clearable />
</el-form-item>
</el-col>
<el-col :span="isTablet ? 12 : 6" :class="isTablet ? 'mt-16' : ''">
<el-form-item label="车主/责任人手机" prop="userPhone" label-width="120px">
<el-input v-model="searchForm.userPhone" placeholder="请输入车主/责任人手机号码" clearable />
</el-form-item>
</el-col>
<el-col :span="isTablet ? 24 : 12" class="mt-16">
<el-form-item label="提审日期" prop="sendCheck" label-width="120px">
<el-date-picker v-model="searchForm.sendCheck" :editable="false" type="datetimerange" start-placeholder="请选择开始时间" end-placeholder="请选择结束时间" align="right" />
</el-form-item>
</el-col>
<el-col :span="isTablet ? 12 : 6" class="mt-16">
<el-form-item label="业务类型" prop="orderType" label-width="120px">
<el-select v-model="searchForm.orderType" placeholder="请选择业务类型" clearable>
<el-option v-for="item in dict.businessType" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="isTablet ? 12 : 6" class="mt-16">
<el-form-item label="审核进度" prop="status" label-width="120px">
<el-select v-model="searchForm.checkStatus" placeholder="请选择审核进度" clearable>
<el-option v-for="status in auditStatus" v-bind="status" :key="status.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="isTablet ? 12 : 6" class="mt-16">
<el-form-item label="企业名称" prop="companyName" label-width="120px">
<el-input v-model="searchForm.companyName" placeholder="请输入企业名称" clearable />
</el-form-item>
</el-col>
<!-- <el-col :span="isTablet ? 12 : 6" class="mt-16">
<el-form-item label="组织名称" prop="carCompanyName" label-width="120px">
<el-input v-model="searchForm.carCompanyName" placeholder="请输入车企名称" clearable />
</el-form-item>
</el-col> -->
<!-- <el-col :span="6" class="mt-16" >
<el-form-item label="经销商名称" prop="dealer" label-width="120px">
<el-input v-model="searchForm.dealer" placeholder="请输入经销商名称" clearable />
</el-form-item>
</el-col> -->
<!-- <el-col :span="8">
<el-form-item label="审核人" prop="operator">
<el-input v-model="searchForm.operator" placeholder="请输入审核人" clearable />
</el-form-item>
</el-col> -->
<!-- <el-col :span="12" class="mt-16">
<el-form-item label="审核日期" prop="auditTime" label-width="120px">
<el-date-picker v-model="searchForm.auditTime" :editable="false" type="datetimerange" start-placeholder="提交开始时间" end-placeholder="提交结束时间" align="right" />
</el-form-item>
</el-col> -->
</template>
<template #slot-table>
<el-table-column label="认证进度" fixed="left" prop="orderStatus" min-width="150" >
<template slot-scope="scope">
<span v-if="[0, 1, 2].includes(+scope.row.orderStatus)" class="status warning">{{ AUDIT_STATUS[scope.row.orderStatus] }}</span>
<span v-else-if="+scope.row.orderStatus === 3" class="status success">{{ AUDIT_STATUS[scope.row.orderStatus] }}</span>
<span v-else-if="[4, 9].includes(+scope.row.orderStatus)" class="status fail">{{ AUDIT_STATUS[scope.row.orderStatus] }}</span>
</template>
</el-table-column>
<el-table-column label="车辆VIN码" prop="iotId" min-width="200" />
<el-table-column label="关联ICCID" prop="iccid" min-width="200" />
<el-table-column label="企业名称" prop="companyName" min-width="230" show-overflow-tooltip />
<el-table-column label="车主/责任人" prop="fullName" min-width="150" />
<el-table-column label="车主/责任人手机" prop="phone" min-width="200" />
<el-table-column label="认证日期" prop="startCheckDate" min-width="200" />
<el-table-column label="组织名称" prop="orgName" min-width="230" show-overflow-tooltip />
<el-table-column label="业务类型" min-width="180">
<template slot-scope="scope">
<span>{{ getOrderType(scope.row) }}</span>
</template>
</el-table-column>
<el-table-column label="审核人" prop="checkUser" min-width="140" />
<el-table-column label="审核日期" prop="endCheckDate" min-width="180" />
</template>
</SearchTable>
</div>
</template>
<script>
import SearchTable from '@/components/SearchTable'
import { mapGetters } from 'vuex'
import { carAuthList2, queryCheckStatistics } from '@/api/search'
const AUDIT_STATUS = ['已提交', '待分派/认领', '待审核', '审核通过', '未通过', '', '', '', '', '作废']
const ORDER_TYPE = ['', '自然人实名认证', '自然人代办人实名认证', '自然人二手车实名认证', '自然人二手车代办人实名认证', '自然人二手车解绑', '企业实名认证', '企业责任人变更']
export default {
name: 'CarAuth2',
components: {
SearchTable
},
data() {
return {
totalCount: 0,
searchForm: {
vin: '',
iccid: '',
user: '',
sendCheck: [],
userPhone: '',
orderType: '',
checkStatus: '',
companyName: '',
carCompanyName: '',
dealer: '',
operator: '',
auditTime: []
},
// 统计看板数据
statistics: {},
AUDIT_STATUS,
ORDER_TYPE,
list: [],
isTablet: window.OS.isTablet
}
},
computed: {
...mapGetters(['dict']),
// 审核状态
auditStatus() {
return AUDIT_STATUS.map((item, index) => {
return {
label: item,
value: index
}
}).filter(item => !!item.label)
}
},
async mounted() {
this.statistics = await queryCheckStatistics() || {}
},
methods: {
/**
* 获取订单类型
*/
getOrderType(row) {
try {
return this.dict.businessType.find(type => +type.value === +row.orderType).label
} catch (error) {
return ''
}
},
/**
* 获取数据
* @param formData 表格数据
* @param callback 回调函数
*/
async handleSubmit(formData, callback) {
try {
const formDataCopy = { ...formData }
// 如果当前选择了提审时间
if (formDataCopy.sendCheck && formDataCopy.sendCheck.length > 0) {
formDataCopy.startSendCheck = formDataCopy.sendCheck[0]
formDataCopy.endSendCheck = formDataCopy.sendCheck[1]
}
// 如果当前选择了审核时间
if (formDataCopy.auditTime && formDataCopy.auditTime.length > 0) {
formDataCopy.startCheck = formDataCopy.auditTime[0]
formDataCopy.endCheck = formDataCopy.auditTime[1]
}
// 是否车企实名
formDataCopy.isVehicleCompany = !formDataCopy.carCompanyName ? 0 : 1
// 删除原来的数据
delete formDataCopy.sendCheck
delete formDataCopy.auditTime
// 列表数据
const respData = await carAuthList2(formDataCopy)
// 开始渲染页面
callback(respData)
} catch (error) {
console.error(error)
}
},
/**
* 重置方法
*/
handleReset() {
Object.keys(this.searchForm).forEach(key => {
this.searchForm[key] = ['string', 'number'].includes(typeof key) ? '' : []
})
},
/**
* 清除事件
* @time 2021-11-06 14:45:23
*/
onClear() {
this.searchForm.currPage = 1
this.$refs.searchForm.resetFields()
this.searchData = { ...this.searchForm }
this.list = []
// this.getData()
}
}
}
</script>
<style lang="scss">
.page-auth-search {
.page-car-auth {
padding: 24px 24px 0;
}
.search-count {
margin: 0 auto;
background: #fff;
box-sizing: border-box;
display: flex;
justify-content: space-between;
align-items: center;
.count-item {
margin-right: 24px;
padding: 24px;
box-sizing: border-box;
width: 25%;
height: 112px;
color: #fff;
border-radius: 4px;
background-size: 100% 112px;
background-position: 0 0;
background-repeat: no-repeat;
display: flex;
align-items: flex-start;
flex-direction: column;
justify-content: center;
position: relative;
overflow: hidden;
&:before {
content: '';
width: 118px;
height: 112px;
background: url(../../assets/image/count_light.png) no-repeat 0 0 / 118px 112px;
position: absolute;
left: 0;
top: 0;
}
&:after {
content: '';
width: 100px;
height: 100px;
position: absolute;
right: 0;
bottom: 0;
}
&:last-child {
margin-right: 0;
}
&.count1 {
background: linear-gradient(90deg, #77B4FF 0%, #2A68FF 100%);
&:after {
background: url(../../assets/image/count1.png) no-repeat 0 0 / 100px 100px;
}
}
&.count2 {
background: linear-gradient(90deg, #6A8EFF 0%, #2A4EFF 100%);
&:after {
background: url(../../assets/image/count2.png) no-repeat 0 0 / 100px 100px;
}
}
&.count3 {
background: linear-gradient(90deg, #70E592 0%, #1EB980 100%);
&:after {
background: url(../../assets/image/count3.png) no-repeat 0 0 / 100px 100px;
}
}
&.count4 {
background: linear-gradient(90deg, #59BEF8 0%, #0D7FE1 100%);
&:after {
background: url(../../assets/image/count4.png) no-repeat 0 0 / 100px 100px;
}
}
dt {
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
}
dd {
margin-top: 5px;
font-size: 28px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
position: relative;
white-space: nowrap;
z-index: 1;
i {
font-size: 18px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
font-style: normal;
}
}
}
}
.status {
position: relative;
padding-left: 10px;
&.success:before {
background: #25C343;
}
&.warning:before {
background: #FF9C00;
}
&.fail:before {
background: #FF4D4F;
}
&:before {
content: '';
width: 6px;
height: 6px;
border-radius: 3px;
left: -5px;
top: 50%;
margin-top: -3px;
position: absolute;
}
}
.mt-16 {
margin-top: 16px;
}
.el-col {
&:last-child {
margin-top: 16px;
}
}
}
</style>
<template>
<SearchTable
title="服务对账"
ref="searchTableRef"
v-model="formData"
@submit="handleSubmit"
>
<template #slot-form>
<el-col :span="isTablet ? 12 : 6">
<el-form-item label="月份" prop="vin" label-width="120px">
<el-date-picker
v-model="formData.month"
type="monthrange"
range-separator="至"
start-placeholder="开始月份"
end-placeholder="结束月份"
/>
</el-form-item>
</el-col>
</template>
<template #slot-table>
<el-table-column label="月份" prop="month" min-width="200" />
<el-table-column label="服务类型" prop="serviceType" min-width="200" />
<el-table-column label="调用次数" prop="time" min-width="200" />
</template>
</SearchTable>
</template>
<script>
import SearchTable from '@/components/SearchTable'
export default {
name: 'CheckAccount',
components: { SearchTable },
data() {
return {
isTablet: window.OS.isTablet,
formData: {}
}
},
methods: {
/**
* 触发提交方法
* @param formData 当前表单填写的内容
* @param callback 回调函数
*/
handleSubmit(formData, callback) {
console.log('formData: ', formData)
callback({ list: [], total: 0 })
}
}
}
</script>
<style lang="scss">
</style>
<template>
<SearchTable
class="page-search-system-log"
title="日志查询"
ref="searchTableRef"
v-model="formData"
@submit="handleSubmit"
@reset="handleReset"
>
<template #slot-form>
<el-col :span="isTablet ? 12 : 6">
<el-form-item label="组织" label-width="80px" prop="orgId">
<Organ v-model="formData.orgId" :type="0" />
</el-form-item>
</el-col>
<el-col :span="isTablet ? 12 : 6">
<el-form-item label="用户名" prop="account" label-width="80px">
<el-input v-model="formData.account" placeholder="请输入用户名" clearable />
</el-form-item>
</el-col>
<el-col :span="isTablet ? 12 : 6" :style="{ marginTop: isTablet ? '16px' : '0px' }">
<el-form-item label="手机号" prop="phone" label-width="80px">
<el-input v-model="formData.phone" maxlength="11" placeholder="请输入手机号" clearable />
</el-form-item>
</el-col>
<el-col :span="isTablet ? 12 : 6" :style="{ marginTop: isTablet ? '16px' : '0px' }">
<el-form-item label="日志类型" prop="logCategory" label-width="80px">
<el-select v-model="formData.logCategory" placeholder="请选择日志类型" clearable @change="formData.logOpt = ''">
<el-option v-for="(logType, index) in logCategorys" :label="logType.logCategory" :value="logType.logCategory" :key="index" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="isTablet ? 12 : 6" style="margin-top: 16px;">
<el-form-item label="操作类型" prop="vin" label-width="80px">
<el-select v-model="formData.logOpt" placeholder="请选择操作类型" clearable>
<el-option v-for="(type, index) in logOpts" :label="type" :value="type" :key="index" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="isTablet ? 24 : 6" style="margin-top: 16px;">
<el-form-item label="时间" prop="createTime" label-width="80px">
<el-date-picker
v-model="formData.createTime"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
clearable
/>
</el-form-item>
</el-col>
</template>
<template #slot-table>
<el-table-column label="用户名" prop="account" min-width="200" />
<el-table-column label="手机号码" prop="phone" min-width="200" />
<el-table-column label="日志类型" prop="logCategory" min-width="200" />
<el-table-column label="操作类型" prop="logOpt" min-width="200" />
<el-table-column label="操作内容" prop="logContent" min-width="200" />
<el-table-column label="IP地址" prop="ip" min-width="200" />
<el-table-column label="操作时间" prop="createTime" min-width="200" />
</template>
</SearchTable>
</template>
<script>
import dayjs from 'dayjs'
import Organ from '@/components/Organ'
import SearchTable from '@/components/SearchTable'
import { mapGetters } from 'vuex'
import { fetchLogCategory, fetchLogList } from '@/api/search'
export default {
name: 'SystemLog',
components: { Organ, SearchTable },
data() {
// 组织id
const { organId } = this.$store.getters
return {
isTablet: window.OS.isTablet,
formData: {
orgId: organId,
account: '',
phone: '',
logCategory: '',
logOpt: '',
createTime: []
},
logCategorys: [],
dict: {}
}
},
computed: {
...mapGetters(['dict']),
/**
* 操作类型
*/
logOpts() {
// 日志类型
const { logCategory } = this.formData
// 如果选择了日志类型
if (logCategory) {
return this.logCategorys.find(category => category.logCategory === logCategory).logOptList
}
return []
}
},
async mounted() {
// 查询日志类型
const { logDetailList } = await fetchLogCategory() || {}
// 记录当前日志类型
this.logCategorys = logDetailList
},
methods: {
/**
* 点击重置方法
*/
handleReset() {
// 组织id
const { organId } = this.$store.getters
// 设置组织id
this.formData.orgId = organId
// 开始触发提交方法
this.$refs.searchTableRef.handleSubmit()
},
/**
* 触发提交方法
* @param formData 当前表单填写的内容
* @param callback 回调函数
*/
async handleSubmit(formData, callback) {
// 如果当前选择了时间
if (formData.createTime && formData.createTime.length === 2) {
formData.createTimeStart = dayjs(formData.createTime[0]).startOf('day').valueOf()
formData.createTimeEnd = dayjs(formData.createTime[1]).endOf('day').valueOf()
delete formData.createTime
}
// 开始请求接口
const { list, totalCount } = await fetchLogList(formData)
// 开始渲染页面
callback({ list, totalCount })
}
}
}
</script>
<style lang="scss">
.page-search-system-log {
.component-search-table-btn-wrap {
margin-top: 16px;
}
}
</style>
<template>
<div v-loading.fullscreen.lock="fullscreenLoading" class="page">
<el-form ref="form" :model="form" label-width="80px" label-position="top" size="small">
<page-module name="车卡文件上传" icon="folder">
<div class="download-template-file">
<span class="name">文件上传</span>
<el-link type="primary" icon="el-icon-download" @click="downloadTemplateFile">下载模板</el-link>
</div>
<div class="file-upload-wrap">
<div class="file-upload-l">
<el-upload
ref="upload"
:limit="1"
:data="upload.data"
:headers="upload.headers"
:file-list="form.fileList"
:action="upload.action"
:before-upload="onBefore"
:on-remove="onRemove"
:on-success ="onSuccess"
:on-error ="onError"
:on-exceed="onExceed"
class="file-uploader"
accept=".xls,.xlsx"
name="file"
multiple>
<el-button slot="trigger" size="small" type="primary">选择文件</el-button>
<el-button :disabled="checkBtnStatus" style="margin-left: 8px;" size="small" type="primary" @click="checkVinData">校验数据</el-button>
<div slot="tip" class="el-upload__tip">只能上传excel文件,文件大小不超过10MB,记录数不超过5000条</div>
</el-upload>
</div>
<div class="file-upload-r"/>
</div>
</page-module>
<page-module v-if="showCheckData" name="校验结果" icon="check">
<div class="file-upload-check">
<div v-if="form.checkData.failCount > 0" class="check-l fail"/>
<div v-else class="check-l success"/>
<div class="check-r">
<div v-if="form.checkData.totalCount === form.checkData.failCount" class="info">全部数据验证失败,请更新后重试</div>
<template v-else-if="form.checkData.failCount > 0">
<div class="info">{{ form.checkData.failCount }}条车卡数据验证失败</div>
<div class="tips">异常数据不进入后续的实名认证环节</div>
<div class="btns">
<el-button type="primary" plain size="small" icon="el-icon-download" @click="downloadCheckFailFile">下载文件</el-button>
</div>
</template>
<div v-else class="info">全部数据验证成功</div>
</div>
</div>
</page-module>
</el-form>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
import { getToken } from '@/utils/auth'
import { postUploadFile, vehicleUnboundVerifyVinCards } from '@/api/special-business'
import { downloadFailFile } from '@/api/realname-car-enterprise'
export default {
name: 'CarUnbindFile',
components: {},
props: {
data: {
type: Object,
default() {
return {}
}
}
},
data() {
return {
fullscreenLoading: false,
upload: {
data: {
rootPath: '',
path: ''
},
headers: {
'Authorization': `bearer ${getToken()}`
},
action: postUploadFile
},
form: {
fileId: '',
checkData: {},
fileList: []
}
}
},
computed: {
...mapGetters(['dict']),
checkBtnStatus() {
return !this.form.fileId
},
showCheckData() {
const keys = Object.keys(this.form.checkData)
return keys.length > 0
}
},
watch: {
data() {
this.updateInternalData()
}
},
created() {
this.init()
},
methods: {
init() {
this.updateInternalData()
},
updateInternalData() {
if (typeof this.data === 'object' && this.data !== null) {
this.form = {
fileId: this.data.fileId || '',
checkData: this.data.checkData || {},
fileList: this.data.fileList || []
}
} else {
this.form = {
fileId: '',
checkData: {},
fileList: []
}
}
},
/**
* 上传前校验
* @time 2021-12-06 10:02:49
*/
onBefore(file) {
const type1 = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
const type2 = 'application/vnd.ms-excel'
let isExcel = false
if (file.type === type1 || file.type === type2) {
isExcel = true
}
const isLt10M = file.size / 1024 / 1024 <= 10
if (!isExcel) {
this.$message.error('车卡信息文件只支持excel文件')
return false
}
if (!isLt10M) {
this.$message.error('车卡信息文件大小不能超过10MB')
return false
}
},
/**
* 文件上传
* @time 2021-12-06 10:02:33
*/
onSuccess(json) {
if (json.success) {
this.$message.success('文件上传成功')
const data = json.data || {}
this.form.fileList = [{
name: data.fileName,
url: data.accessUrl,
uuid: data.uuid
}]
this.form.fileId = data.uuid
}
},
/**
* 上传错误
* @param {Object} err 错误对象
* @time 2021-12-15 14:14:49
*/
onError() {
this.$message.error('文件上传失败')
this.$refs.upload.clearFiles()
this.onRemove()
},
/**
* 响应删除文件操作
* @time 2021-12-09 09:52:56
*/
onRemove(file, fileList) {
this.form = {
fileId: '',
checkData: {},
fileList: []
}
this.$emit('check', this.form)
},
/**
* 上传数量限制
* @time 2021-12-06 10:03:10
*/
onExceed() {
this.$message.error('最多上传1个excel文件')
},
/**
* 校验车卡信息
* @time 2022-04-23 14:27:21
*/
checkVinData() {
this.fullscreenLoading = true
return vehicleUnboundVerifyVinCards({ fileId: this.form.fileId }).then(data => {
this.fullscreenLoading = false
this.form.checkData = data
this.$emit('check', this.form)
}).catch(() => {
this.fullscreenLoading = false
this.$emit('check', {})
})
},
getFormData() {
return this.form
},
// 获取待缓存数据
getPendingCacheData() {
return this.getFormData()
},
/**
* 下载校验失败的文件
* @time 2022-04-23 15:02:50
*/
downloadCheckFailFile() {
// location.href = `${process.env.VUE_APP_ROUTER}static/template.xlsx`
this.fullscreenLoading = true
return downloadFailFile({
uuid: this.form.checkData.fileId,
fileName: this.form.checkData.fileName || this.form.fileList[0].name
}).then(() => {
this.fullscreenLoading = false
}).catch(() => {
this.fullscreenLoading = false
})
},
/**
* 下载车卡模板文件
* @time 2022-04-23 15:02:50
*/
downloadTemplateFile() {
location.href = `${process.env.VUE_APP_ROUTER}static/template.xlsx`
}
}
}
</script>
<style scoped lang="scss">
.download-template-file {
margin: 20px 0 0 0;
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #71747B;
.name {
margin-right: 16px;
}
}
.file-upload-wrap {
margin: 10px auto 0;
display: flex;
justify-content: space-between;
.file-upload-l {
flex: 1;
}
.file-upload-r {
width: 238px;
height: 144px;
background: url(~@/assets/image/file_upload.png) no-repeat 0 0 / 238px 144px;
}
}
.file-upload-check {
margin: 20px auto 0;
display: flex;
.check-l {
width: 483px;
height: 200px;
flex: none;
&.success {
background: url(~@/assets/image/result_img_success.png) no-repeat 0 0;
}
&.fail {
background: url(~@/assets/image/result_img_fail.png) no-repeat 0 0;
}
}
.check-r {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
flex: 1;
.info {
font-size: 16px;
font-family: PingFangSC-Semibold, PingFang SC;
font-weight: 600;
color: #111;
}
.tips {
margin: 8px auto 16px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: rgba(132, 133, 138, 0.7);
}
}
}
</style>
<template>
<div class="page">
<pageTitle title="车企实名解绑" />
<steps :data="stepsData" :index="stepIndex" :margin="margin" />
<car-unbind-file ref="carSimFile" :data="pageData" @check="onCheck" />
<div class="next-step">
<el-button :disabled="nextBtnStatus" size="small" type="primary" @click="onNextStep">下一步</el-button>
</div>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
import CarUnbindFile from './components/car-unbind-file'
import Common from '@/components/Common'
import { checkVinCard } from '@/api/iccid'
export default {
name: 'CarUnbindingStepOne',
components: {
CarUnbindFile
},
mixins: [Common],
data() {
return {
stepsData: ['车卡信息', '车企信息'],
stepIndex: 0,
margin: '0 200px 0 200px',
pageData: {}
}
},
computed: {
...mapGetters(['dict']),
nextBtnStatus() {
const { failCount, totalCount } = this.pageData.checkData
if (failCount > 0 && failCount === totalCount || !totalCount) {
return true
}
return false
}
},
created() {
this.init()
},
methods: {
init() {
this.getCacheData()
if (this.$route.params.from === 'prev') {
this.restoreCacheData()
} else {
this.resetStepData()
}
},
getCacheData() {
this.cacheData = this.cacheGetStepData(this.cacheKey)
},
restoreCacheData() {
if (this.isValidObject(this.cacheData)) {
this.pageData = this.cloneObject(this.cacheData)
} else {
this.resetStepData()
}
},
resetStepData() {
this.pageData = {
fileId: '',
checkData: {},
fileList: []
}
},
async onNextStep() {
// 写入缓存
const data = this.$refs.carSimFile.getPendingCacheData()
const { fileId } = this.pageData
await checkVinCard({ fileId, businessType: 9 })
this.cacheSetStepData(this.cacheKey, data)
// 前往下一步
this.$router.push({
name: 'CarUnbindingStepTwo'
})
},
onCheck(data) {
this.pageData = data
}
}
}
</script>
<template>
<div v-loading.fullscreen.lock="fullscreenLoading" element-loading-spinner="page-loading" class="page car-unbinding-page">
<pageTitle title="车企实名解绑" />
<steps :data="stepsData" :index="stepIndex" :margin="margin" />
<el-form ref="form" :model="form" label-width="80px" label-position="top" size="small">
<page-module name="车企信息" icon="car">
<el-row :gutter="40">
<el-col :span="12">
<el-form-item label="企业名称" prop="companyName">
<el-input v-model="form.companyName" placeholder="请输入企业名称" clearable disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="40">
<el-col :span="12">
<el-form-item label="企业证件类型" prop="companyCertType">
<el-select v-model="form.companyCertType" placeholder="请选择企业证件类型" disabled>
<el-option v-for="item of dict.companyCertType" :key="item.key" v-bind="item" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="40">
<el-col :span="12">
<el-form-item label="企业证件号码" prop="companyCertNumber">
<el-input v-model="form.companyCertNumber" placeholder="请输入企业证件号码" clearable disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="40">
<el-col :span="12">
<el-form-item label="责任人姓名" prop="corporationName">
<el-input v-model="form.corporationName" placeholder="请输入责任人姓名" clearable disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="40">
<el-col :span="12">
<el-form-item label="责任人手机号" prop="corporationPhone">
<el-input v-model="form.corporationPhone" placeholder="请输入责任人手机号" clearable disabled />
</el-form-item>
</el-col>
</el-row>
</page-module>
<div class="next-step">
<el-button size="small" plain @click="handlePrev">上一步</el-button>
<el-button size="small" type="primary" @click="handleSendMsg">提交</el-button>
</div>
</el-form>
<comp-confirm
:show.sync="tipVisible"
:show-cancel-btn="false"
:desc="unbindData.msg"
:type="unbindData.type"
@on-sure="closeVisible"
/>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
import CompConfirm from '@/components/CompConfirm'
import { manufacturerRnrGetDetail, vehicleUnbound } from '@/api/special-business'
import Common from '@/components/Common'
export default {
name: 'CarUnbindingStepTwo',
components: {
CompConfirm
},
mixins: [Common],
data() {
return {
fullscreenLoading: false,
stepsData: ['车卡信息', '车企信息'],
stepIndex: 1,
margin: '0 230px 0 230px',
form: {
companyName: '',
companyCertType: '',
companyCertNumber: '',
corporationName: '',
corporationPhone: ''
},
unbindStatus: false, // 解绑状态, 默认失败
unbindData: {
msg: '',
type: ''
},
tipVisible: false,
cacheData: null,
fileId: ''
}
},
computed: {
...mapGetters(['dict'])
},
mounted() {
this.initFuc()
},
methods: {
/**
* 获取车企详情
* @time 2022-04-24 12:16:26
*/
initFuc() {
// 获取车企详情
this.fullscreenLoading = true
manufacturerRnrGetDetail({})
.then(res => {
this.fullscreenLoading = false
this.form = res
})
.catch(() => {
this.fullscreenLoading = false
})
// 获取上一步的缓存, 没有将无法提交
this.cacheData = this.cacheGetStepData('CarUnbindingStepOne')
if (this.cacheData) {
this.fileId = this.cacheData.fileId
} else {
// 不应该进入页面, 从头开始
this.$router.replace({
name: 'CarUnbindingStepOne'
})
}
},
/**
* 返回上一步
* @time 2022-04-23 15:59:56
*/
handlePrev() {
this.$router.push({
name: 'CarUnbindingStepOne',
params: {
from: 'prev'
}
})
},
/**
* 确认弹出
* @time 2022-04-23 14:20:57
*/
handleSendMsg() {
// 提交车企解绑信息
this.fullscreenLoading = true
vehicleUnbound({
// vehicleCompanyId: '', // 不需要
fileId: this.fileId
}).then(data => {
this.fullscreenLoading = false
this.unbindStatus = true
this.unbindData.msg = '卡解绑成功'
this.unbindData.type = 'success'
this.tipVisible = true
}).catch((err) => {
this.fullscreenLoading = false
this.unbindStatus = false
this.unbindData.msg = err.message || '卡解绑失败'
this.unbindData.type = 'info'
this.tipVisible = true
})
},
/**
* 关闭解绑成功弹出
* @time 2022-04-23 15:59:13
*/
closeVisible() {
if (this.unbindStatus) {
// 成功
this.$router.replace({
name: 'Home'
})
} else {
// 失败
this.tipVisible = false
}
}
}
}
</script>
<style lang="scss">
.car-unbinding-page{
.is-disabled{
.el-input__inner{
color: #333;
}
}
}
</style>
<template>
<div v-loading.fullscreen.lock="fullscreenLoading" element-loading-spinner="page-loading" class="page">
<pageTitle title="一车多卡绑定" />
<steps :data="stepsData" :index="stepIndex" :margin="margin" />
<page-module name="车卡信息" icon="car">
<comp-car-card ref="compCarCard" :data="cacheData" souce-page="BIND" />
</page-module>
<div class="next-step">
<el-button size="small" type="primary" @click="handleNext">下一步</el-button>
</div>
</div>
</template>
<script>
import Common from '@/components/Common'
import CompCarCard from '@/components/CompCarCard'
import { checkVinCard } from '@/api/iccid'
export default {
name: 'CardBindingStepOne',
components: {
CompCarCard
},
mixins: [Common],
data() {
return {
fullscreenLoading: false,
stepsData: ['车卡信息录入', '客户确认'],
stepIndex: 0,
margin: '0 200px 0 200px',
cacheData: null
}
},
created() {
this.init()
},
methods: {
/**
* 初始化
* @time 2022-04-24 16:50:27
*/
init() {
if (this.$route.params.from) {
// 表明是返回上一步 读缓存
this.cacheData = this.cacheGetStepData(this.cacheKey)
}
},
/**
* 下一步操作
* @time 2022-04-24 16:50:14
*/
async handleNext() {
try {
await this.$refs.compCarCard.validate()
const data = this.$refs.compCarCard.getPendingCacheData()
// 校验车卡关系
const verifyData = {
iccidList: [],
vin: data.vin,
rnrId: data.data,
businessType: 5
}
data.iccidList.forEach(item => {
if (item.iccid !== '') {
verifyData.iccidList.push(item.iccid)
}
})
this.fullscreenLoading = true
const retData = await checkVinCard(verifyData)
let isAlert = false
if (retData.iccidVerifyResults && retData.iccidVerifyResults.length > 0) {
const resList = retData.iccidVerifyResults
for (let i = 0; i < resList.length; i++) {
if (!resList[i].exist) {
// 车卡关系不正常
isAlert = true
break
}
}
}
this.fullscreenLoading = false
if (isAlert) {
this.$message.error('数据校验不通过')
return false
}
// 写入缓存
this.cacheSetStepData(this.cacheKey, {
vin: data.vin,
iccidList: data.iccidList
})
// 前往下一步
this.$router.push({
name: 'CardBindingStepTwo'
})
} catch (e) {
this.fullscreenLoading = false
if (e.anchor) {
e.anchor()
}
}
}
}
}
</script>
<template>
<div v-loading.fullscreen.lock="fullscreenLoading" element-loading-spinner="page-loading" class="page">
<pageTitle title="一车多卡绑定" />
<steps :data="stepsData" :index="stepIndex" :margin="margin" />
<comp-client-confirm
ref="compClientConfirm"
:form-data="formData"
:wait-visible.sync="waitVisible"
:opreator-uuid="opreatorUuid"
type="BIND"
prompt-info="操作等待中..."
/>
<div class="next-step">
<el-button size="small" plain @click="handlePrev">上一步</el-button>
<el-button size="small" type="primary" @click="handleSendMsg">发送确认短信</el-button>
</div>
<comp-confirm
:show.sync="tipVisible"
:desc="desc"
:show-cancel-btn="false"
@on-sure="closeVisible"
/>
</div>
</template>
<script>
import Common from '@/components/Common'
import CompClientConfirm from '@/components/CompClientConfirm'
import CompConfirm from '@/components/CompConfirm'
import { surplusCardBind } from '@/api/special-business'
export default {
name: 'CardBindingStepTwo',
components: {
CompClientConfirm,
CompConfirm
},
mixins: [Common],
data() {
return {
stepsData: ['车卡信息录入', '客户确认'],
stepIndex: 1,
margin: '0 230px 0 230px',
waitVisible: false,
formData: {}, // 上一步的数据, 需要读取缓存
fullscreenLoading: false,
unbindInfo: {},
opreatorUuid: '',
tipVisible: false,
desc: ''
}
},
created() {
this.formData = this.cacheGetStepData('CardBindingStepOne')
},
methods: {
/**
* 返回上一步
* @time 2022-04-23 15:59:56
*/
handlePrev() {
this.$router.push({
name: 'CardBindingStepOne',
params: {
from: 'prev'
}
})
},
/**
* 确认弹出
* @time 2022-04-23 14:20:57
*/
handleSendMsg() {
// bfd331a547764865b2a0b4309f8c95c3
const curRnrId = this.$refs.compClientConfirm.rnrId
if (!curRnrId) {
this.$message.error('获取当前车卡的实名信息失败')
return false
}
this.fullscreenLoading = true
// 提交绑定剩余卡
const arr = []
this.formData.iccidList.map(item => {
if (item.iccid !== '') {
arr.push(item.iccid)
}
})
surplusCardBind({
vin: this.formData.vin,
iccidList: arr,
rnrId: curRnrId
}).then(data => {
this.opreatorUuid = data.orderId
this.fullscreenLoading = false
this.waitVisible = true
}).catch((err) => {
this.fullscreenLoading = false
this.tipVisible = true
this.desc = err.message
})
},
/**
* 关闭警告
* @time 2022-04-23 15:59:13
*/
closeVisible() {
this.tipVisible = false
}
}
}
</script>
<template>
<div>
<page-module name="业务类型" icon="star">
<el-radio-group v-model="ownerType" @change="handleOwnerType">
<el-row :gutter="40" class="new-car-owner-box">
<el-col :span="12">
<el-radio :label="0" border class="new-car-owner">
<el-row>
<el-col class="owner-type-title">原车解绑</el-col>
<el-col class="owner-type-info">由原车主现场解绑</el-col>
</el-row>
</el-radio>
</el-col>
<el-col :span="12">
<el-radio :label="1" border class="used-car-new-owner">
<el-row>
<el-col class="owner-type-title">二手车解绑</el-col>
<el-col class="owner-type-info">由新车主代解绑</el-col>
</el-row>
</el-radio>
</el-col>
</el-row>
</el-radio-group>
</page-module>
<steps :data="stepsData" :index="stepIndex" :margin="margin" />
</div>
</template>
<script>
export default {
name: 'OwnerType',
props: {
curType: {
type: [Number, String],
default: () => 0
},
stepIndex: {
type: [Number, String],
default: () => 0
}
},
data() {
return {
ownerType: 0,
stepsData: ['车卡信息录入', '客户确认'],
margin: '0 200px 0 200px'
}
},
watch: {
curType: {
handler(val, oldVal) {
if (val !== oldVal) {
this.ownerType = val
if (val === 0) {
this.stepsData = ['车卡信息录入', '客户确认']
this.margin = '0 200px 0 200px'
} else {
this.stepsData = ['车卡信息录入', '客户信息录入', '人脸识别']
this.margin = '0 0 0 0'
}
}
},
immediate: true
}
},
methods: {
handleOwnerType(val) {
if (this.$route.name === 'CardUnbindingStepOne') {
this.$emit('change-type', val)
return false
}
const owner = val
this.$router.push({
name: 'CardUnbindingStepOne',
params: { owner }
})
}
}
}
</script>
<style scoped lang="scss">
.special-business-card-binding{
.new-car-owner-box .el-radio{
display: flex;
width: 346px;
height: 106px;
align-items: center;
padding-left: 24px;
}
.new-car-owner{
background: url('~@/assets/special-business/new_car_owner@2x.png') no-repeat;
background-size: 45%;
background-position: right
}
.used-car-new-owner{
background: url('~@/assets/special-business/used_car_new_owner@2x.png') no-repeat;
background-size: 45%;
background-position: right
}
.owner-type-title{
font-size: 16px;
color: #212026;
padding-bottom: 5px;
}
.owner-type-info{
font-size: 12px;
color: #84858a;
}
}
</style>
<template>
<div v-loading.fullscreen.lock="fullscreenLoading" element-loading-spinner="page-loading" class="page special-business-card-binding">
<pageTitle title="卡解绑" />
<owner-type ref="ownerTypeRef" :step-index="0" :cur-type="onwnerType" @change-type="handleOwnerType" />
<page-module name="车卡信息" icon="car">
<comp-car-card v-if="isExit" ref="compCarCard" :data="cacheData" :is-bind="true" :souce-page="soucePage" />
</page-module>
<div class="next-step">
<el-button size="small" type="primary" @click="handleNext">下一步</el-button>
</div>
</div>
</template>
<script>
import Common from '@/components/Common'
import OwnerType from './components/owner-type'
import CompCarCard from '@/components/CompCarCard'
import { checkVinCard } from '@/api/iccid'
export default {
name: 'CardUnbindingStepOne',
components: {
OwnerType,
CompCarCard
},
mixins: [Common],
data() {
return {
fullscreenLoading: false,
onwnerType: 0,
cacheData: null,
isExit: true,
soucePage: 'SPECIAL'
}
},
mounted() {
this.init()
},
methods: {
/**
* 初始化
* @time 2022-04-24 16:50:27
*/
init() {
if (this.$route.params.owner) {
this.onwnerType = this.$route.params.owner
this.soucePage = this.onwnerType !== 1 ? 'SPECIAL' : 'UNBIND'
}
if (this.$route.params.from) {
// 表明是返回上一步 读缓存
this.cacheData = this.cacheGetStepData(this.cacheKey)
if (this.cacheData) {
this.onwnerType = this.cacheData.onwnerType
this.soucePage = this.onwnerType !== 1 ? 'SPECIAL' : 'UNBIND'
}
}
},
/**
* 重置组件
* @time 2022-05-05 10:19:20
*/
handleOwnerType(val) {
this.onwnerType = val
this.soucePage = this.onwnerType !== 1 ? 'SPECIAL' : 'UNBIND'
this.cacheData = null
this.isExit = false
this.$nextTick(() => {
this.isExit = true
})
},
/**
* 前往下一步
* @time 2022-05-05 10:20:40
*/
async handleNext() {
try {
await this.$refs.compCarCard.validate()
const data = this.$refs.compCarCard.getPendingCacheData()
// 校验车卡关系
const verifyData = {
iccidList: [],
vin: data.vin,
rnrId: data.rnrId,
businessType: +this.$refs.ownerTypeRef.ownerType === 1 ? 7 : 6
}
data.iccidList.forEach(item => {
if (item.iccid !== '') {
verifyData.iccidList.push(item.iccid)
}
})
this.fullscreenLoading = true
await checkVinCard(verifyData)
this.fullscreenLoading = false
// 写入缓存
this.cacheSetStepData(this.cacheKey, {
onwnerType: this.$refs.ownerTypeRef.ownerType,
vin: data.vin,
iccidList: data.iccidList
})
// 前往下一步
const ownerType = this.$refs.ownerTypeRef.ownerType
if (ownerType === 0) {
this.$router.push({
name: 'CardUnbindingStepTwo'
})
} else {
this.$router.push({
name: 'CardUnbindingStepTwoSnd'
})
}
} catch (e) {
this.fullscreenLoading = false
if (e.anchor) {
e.anchor()
}
}
}
}
}
</script>
<template>
<div v-loading.fullscreen.lock="fullscreenLoading" element-loading-spinner="page-loading" class="page special-business-card-binding">
<pageTitle title="卡解绑" />
<owner-type ref="ownerTypeRef" :step-index="2" :cur-type="onwnerType" />
<PageModuleTabs
:tabs="TABS"
v-if="device.showTakePhoto"
v-model="tabName"
>
<CompFaceRecognition ref="faceRecognition" :type="livenessType" :take="tabName == 'carmer'" :data="faceData"/>
</PageModuleTabs>
<page-module v-else name="活体视频上传" icon="video">
<CompFaceRecognition ref="faceRecognition" :type="livenessType" :data="faceData"/>
</page-module>
<div class="next-step">
<el-button size="small" plain @click="handlePrev">上一步</el-button>
<el-button size="small" type="primary" @click="handleNext">提交</el-button>
</div>
<comp-confirm
:show.sync="tipVisible"
:show-cancel-btn="false"
:desc="unbindData.msg"
:type="unbindData.type"
@on-sure="closeVisible"
/>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
import PageModuleTabs from '@/components/PageModule/tabs'
import Common from '@/components/Common'
import CompConfirm from '@/components/CompConfirm'
import OwnerType from './components/owner-type'
import CompFaceRecognition from '@/components/CompFaceRecognition'
import { cardUnbindSecondHandPersonal, getLivenessCode } from '@/api/special-business'
const TABS = [
{
label: '活体视频上传',
value: 'video',
icon: require('@/assets/image/video@2x.png')
},
{
label: '在线拍摄视频',
value: 'carmer',
icon: require('@/assets/image/icon_user@2x.png')
}
]
export default {
name: 'CardUnbindingStepThree',
components: {
CompConfirm,
OwnerType,
CompFaceRecognition,
PageModuleTabs
},
mixins: [Common],
data() {
return {
TABS,
fullscreenLoading: false,
onwnerType: 1,
unbindStatus: false, // 解绑状态, 默认失败
livenessType: '',
unbindData: {
msg: '',
type: ''
},
tipVisible: false,
faceData: null,
tabName: 'video'
}
},
computed: {
...mapGetters(['device'])
},
mounted() {
this.initFuc()
},
methods: {
/**
* 初始化
* @time 2022-05-04 12:35:20
*/
initFuc() {
this.fullscreenLoading = true
getLivenessCode()
.then((res) => {
this.faceData = res
this.faceData.number = res.livenessCode
this.fullscreenLoading = false
this.livenessType = res.livenessType
})
.catch((err) => {
console.log(err)
this.$message.error('获取活体数字验证码失败,请刷新页面重试')
this.fullscreenLoading = false
})
},
/**
* 返回上一步
* @time 2022-04-23 15:59:56
*/
handlePrev() {
const ownerType = this.$refs.ownerTypeRef.ownerType
if (ownerType === 0) {
this.$router.push({
name: 'CardUnbindingStepTwo',
params: {
from: 'prev'
}
})
} else {
this.$router.push({
name: 'CardUnbindingStepTwoSnd',
params: {
from: 'prev'
}
})
}
},
/**
* 提交审核
* @time 2022-04-24 16:00:12
*/
handleNext() {
// 二手车解绑
const fileObj = this.$refs.faceRecognition.$refs.file.$refs.formRef
const cacheData1 = this.cacheGetStepData('CardUnbindingStepOne')
const cacheData2 = this.cacheGetStepData('CardUnbindingStepTwoSnd')
fileObj.validate((valid) => {
if (valid) {
const iccidArr = []
if (cacheData1 && cacheData1.iccidList) {
cacheData1.iccidList.forEach(ele => {
if (ele.iccid !== '') {
iccidArr.push(ele.iccid)
}
})
}
const { formData, concatData, fileList1, fileList2, certData } = cacheData2
const certPicArr = []
if (certData && certData.photoUrls) {
certData.photoUrls.forEach(ele => {
certPicArr.push(ele.url.id)
})
}
const contractPic = []
if (fileList1) {
fileList1.fileList.forEach(ele => {
contractPic.push(ele.uuid)
})
}
const certificatePic = []
if (fileList2) {
fileList2.fileList.forEach(ele => {
certificatePic.push(ele.uuid)
})
}
const videoList = this.$refs.faceRecognition.$refs.file.form.fileList
const videoArr = []
videoList.forEach(ele => {
videoArr.push(ele.uuid)
})
// 组装整体数据
const reqData = {
customerType: 1,
isConsigner: false,
vin: cacheData1.vin,
iccidList: iccidArr,
// 新车主基本
fullName: formData.fullName,
gender: formData.gender,
// 新车主证件
certType: certData.type,
certPic: certPicArr,
certNumber: certData.no,
certAddress: certData.address,
certExpirationDate: certData.validDate,
certEffectiveDate: certData.certEffectiveDate,
contactAddress: certData.connectAddress,
// 新车主文件
purchaseContractPic: contractPic,
transferCertificatePic: certificatePic,
// 新车主联系
phone: concatData.phone,
verificationCode: concatData.veCode,
// 人脸识别地址
requestId: this.faceData.requestId,
liveVerificationVideo: videoArr[0]
}
this.fullscreenLoading = true
cardUnbindSecondHandPersonal(reqData)
.then((res) => {
this.fullscreenLoading = false
this.unbindStatus = true
this.unbindData.msg = '已转入人工审核, 请注意查询认证进度'
this.unbindData.type = 'success'
this.tipVisible = true
})
.catch((err) => {
this.fullscreenLoading = false
this.unbindStatus = false
this.unbindData.msg = err.message || '校验失败, 请重试'
this.unbindData.type = 'info'
this.tipVisible = true
})
}
})
},
/**
* 关闭解绑成功弹出
* @time 2022-04-23 15:59:13
*/
closeVisible() {
if (this.unbindStatus) {
// 成功
this.$router.replace({
name: 'Home'
})
} else {
// 失败
this.tipVisible = false
}
}
}
}
</script>
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment