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

初始化代码

parent 2d7d3f82
Pipeline #3104 failed with stages
in 0 seconds
<template>
<Page class="page-rnr-person-base">
<template #slot-title>
<span>{{ currentFlow }}/{{ totalFlow }}</span>
<span>身份信息</span>
</template>
<UserInfo :value="formData" :cert-type="personMarkup.certType" :customer="true" ref="userRef" />
<template slot="slot-operation">
<van-button type="primary" class="page-rnr-main-btn-before" round color="linear-gradient(120deg, #EDF3FF 0%, #E9F0FF 97%)" @click="handleToBefore">上一步</van-button>
<van-button type="primary" class="page-rnr-main-btn-next" round color="linear-gradient(120deg, #4F4CFB 0%, #376FF4 97%)" @click="handleToNext">下一步</van-button>
</template>
</Page>
</template>
<script>
import { mapGetters } from 'vuex'
import Page from '@/components/Page'
import UserInfo from '@/components/UserInfo'
import ErrorWrap from '@/components/ErrorWrap'
import flowMixin from '@/minxin/flow'
import { SET_PERSON_CARD, SET_OCR_PIC } from '@/store/modules/markup'
export default {
name: 'MarkupPersonBase',
components: { Page, ErrorWrap, UserInfo },
mixins: [flowMixin],
data() {
return {
ocrUploading: false,
fileList: [],
formData: {
certAddress: '',
certExpirationDate: '',
certNumber: '',
contactAddress: '',
fullName: '',
gender: ''
}
}
},
computed: {
...mapGetters(['personMarkup'])
},
methods: {
/**
* 调到到下一页:腾讯的实名认证平台
*/
handleToNext() {
// 校验不通过的字段
try {
const formData = this.$refs.userRef.validate()
// 将当前数据保存到store中
this.$store.commit(`markup/${SET_PERSON_CARD}`, formData)
this.$store.commit(`markup/${SET_OCR_PIC}`, formData.ocrPic)
// 跳转到支付结果页
this.routerToNextPage('MarkupPersonNotification')
} catch (error) {
console.error('校验失败:', error)
}
},
/**
* 跳转到上一页
*/
handleToBefore() {
// 回退到上个页面
this.$router.back()
}
}
}
</script>
<style lang="scss">
.page-rnr-person-base {
.page-rnr-main-fixed-btn-group {
display: flex;
justify-content: space-between;
.page-rnr-main-btn-before {
color: #242424 !important;
flex: 1;
height: 96px;
}
.page-rnr-main-btn-next {
flex: 2;
margin-left: 40px;
height: 96px;
}
}
.van-cell__label {
.page-rnr-flex {
display: flex;
justify-content: space-between;
}
}
}
</style>
<template>
<Page class="page-rnr-person-card">
<template #slot-title>
<span>1/{{ totalFlow }}</span>
<span>车卡信息</span>
</template>
<VinScan ref="vinScanRef" :hide-scan="true" @change="handleChangeVin" />
<div class="page-rnr-main-card page-rnr-main-card-iccid">
<div class="page-rnr-main-card-title">
<div class="page-rnr-main-card-title-tl">ICCID</div>
<div class="page-rnr-main-card-title-tr">{{ iccidList.length }}/5</div>
</div>
<List v-model="iccidList" @click="handleOpenEditIccid" />
<van-button class="rnr-main-card-add-btn" plain hairline round block color="#0761F3" @click="handleOpenAddIccid"><i class="imageicon imageicon-add" />添加</van-button>
</div>
<template #slot-operation>
<van-button :disabled="iccidList.length === 0" :loading="submitLoading" type="primary" class="page-rnr-main-btn-next" round color="linear-gradient(120deg, #4F4CFB 0%, #376FF4 97%)" block @click="handleToNext">下一步</van-button>
</template>
<InputActionSheet
:title="addType === 'add' ? '添加卡号' : '修改卡号'"
:rules="{ iccid: 'iccid' }"
:data="newIccid"
:visible.sync="showAddVin"
label="ICCID"
@submit="handleAddIccid"
/>
</Page>
</template>
<script>
import Page from '@/components/Page'
import List from '@/components/List'
import InputActionSheet from '@/components/InputActionSheet'
import VinScan from '@/components/VinScan'
import ErrorWrap from '@/components/ErrorWrap.vue'
import { getIccidListByVin, verifyVinCards } from '@/api/markup'
import { Toast } from 'vant'
import flowMixin from '@/minxin/flow'
import { SET_PERSON_CARD } from '@/store/modules/markup'
export default {
name: 'MarkupPersonCard',
components: { Page, ErrorWrap, VinScan, List, InputActionSheet },
mixins: [flowMixin],
data() {
const { customerType } = this.$route.query
return {
addType: 'add',
customerType: +customerType,
isConsigner: +this.$route.query.isConsigner === 1,
isLoading: false,
vin: '',
newIccid: '',
showSearchBtn: true,
showAddVin: false,
submitLoading: false,
iccidList: []
}
},
methods: {
/**
* 改变vin码
* @param vin 当前输入的vin码
*/
handleChangeVin(vin) {
// 如果当前输入的内容和之前输入的vin不一致,则需要展示搜索按钮
if (vin !== this.vin) {
this.showSearchBtn = true
}
// 记下当前输入的vin码
this.vin = vin
// 如果当前带入vin了,则手动查询一遍接口
this.handleFetchIccidByVin()
},
/**
* 通过vin号搜索iccid的集合
* @param value
*/
async handleFetchIccidByVin() {
// 获取输入的vin号
const vin = this.vin
// 展示loading
this.isLoading = true
try {
// 当前iccid的集合
const { iccidList } = await getIccidListByVin({ vin })
// 不展示搜索
this.showSearchBtn = false
// 页面开始渲染
this.iccidList = iccidList
} catch (error) {
console.error(error)
}
// 展示loading
this.isLoading = false
},
/**
* 编辑指定的iccid
* @param index 当前需要编辑的iccid
*/
handleOpenEditIccid(iccid, index) {
// 标记当前是编辑
this.addType = 'edit'
// 展示弹框
this.showAddVin = true
// 当前的iccid
this.newIccid = iccid
// 记住当前编辑的索引
this.editIndex = index
},
/**
* 新增一条iccid
*/
handleOpenAddIccid() {
// 标记当前是编辑
this.addType = 'add'
// 展示弹框
this.showAddVin = true
// 清空iccid
this.newIccid = ''
},
/**
* 新增一条iccid数据
*/
handleAddIccid(iccid) {
// 关闭弹框
this.showAddVin = false
// 如果当年是新增
if (this.addType === 'add') {
// 开始添加一条iccid
this.iccidList.push(iccid)
} else {
this.$set(this.iccidList, this.editIndex, iccid)
}
// 清空数据
this.newIccid = ''
},
/**
* 跳转到下一页
*/
async handleToNext() {
// 如果vin号输入不正确
if (!this.vin) {
return
}
// 如果vin码输入不合法
if (this.vin.length !== 17) {
return
}
// 如果vin-scan中输入的vin长度不等于17位
if (this.$refs.vinScanRef.vin.length !== 17) {
return
}
// 如果当前没有输入或选择iccid
if (this.iccidList.length === 0) {
Toast('请至少添加1个ICCID号')
return
}
// 如果当前iccid超过5个
if (this.iccidList.length > 5) {
Toast('ICCID号最多不能超过5个')
return
}
// 展示loading框
this.submitLoading = true
try {
// 校验vin号和iccid是否合法
await verifyVinCards({
businessType: 1,
vin: this.vin,
iccidList: this.iccidList
})
} catch (error) {
// 关闭loading框
this.submitLoading = false
return
}
// 关闭loading框
this.submitLoading = false
// 开始保存数据
this.$store.commit(`markup/${SET_PERSON_CARD}`, {
customerType: 0,
isConsigner: false,
vin: this.vin,
iccidList: this.iccidList
})
// 开始跳转页面
this.$router.push({ name: 'MarkupPersonIdcard', query: { step: 2 }})
}
}
}
</script>
<style lang="scss">
.page-rnr-person-card {
.van-field__button {
margin-left: 0px;
padding-left: 24px;
.page-rnr-icon-scan {
background-image: url(../../../assets/rnr/ico_scan.svg);
background-size: 100% 100%;
width: 30px;
height: 30px;
}
}
.page-rnr-main-fixed-btn-group {
.page-rnr-main-btn-next {
height: 96px;
}
}
.page-rnr-main-iccid-icon-del {
background-image: url(../../../assets/rnr/ico_del.png);
background-size: 100% 100%;
width: 30px;
height: 30px;
}
.page-rnr-main-iccid-icon-close {
background-image: url(../../../assets/rnr/ico_close.png);
background-size: 100% 100%;
width: 30px;
height: 30px;
}
.page-rnr-main-card-btn-iccid-add {
padding: 0 24px;
.page-rnr-main-card-btn-iccid {
margin-top: 24px;
.van-icon {
margin-right: 14px;
}
}
}
.page-rnr-main-iccid-container {
padding: 0px 24px;
.page-rnr-main-iccid-item {
background-image: linear-gradient(121deg, #617DFF 0%, #AEC6FF 98%);
border-radius: 16px;
display: flex;
height: 125px;
margin-top: 12px;
position: relative;
.page-rnr-main-iccid-item-icon {
background-image: url(../../../assets/rnr/ico_iccid.png);
background-size: 100% 100%;
width: 110px;
height: 101px;
margin: 24px 36px 0 42px;
}
.page-rnr-main-iccid-item-split {
background: #FFFFFF;
display: block;
width: 1px;
height: 80px;
opacity: 0.29;
margin-top: 20px;
}
.van-cell {
background-color: transparent;
padding: 0 16px 0 40px !important;
height: 45px;
margin-top: 40px;
.van-field__control {
color: #FFFFFF !important;
font-size: 32px !important;
font-weight: 400 !important;
}
.van-field__button {
padding-left: 60px;
}
}
&:first-child {
margin-top: 0;
}
&:before {
background-image: url(../../../assets/rnr/gradient.png);
background-size: 100% 100%;
content: "";
display: block;
position: absolute;
top: -12px;
left: 0px;
right: 0px;
height: 24px;
z-index: -1;
}
}
::-webkit-input-placeholder {
color: rgba(255, 255, 255, 0.4) !important;
font-weight: 400;
}
:-moz-placeholder {
color: rgba(255, 255, 255, 0.4) !important;
font-weight: 400;
}
::-moz-placeholder {
color: rgba(255, 255, 255, 0.4) !important;
font-weight: 400;
}
:-ms-input-placeholder {
color: rgba(255, 255, 255, 0.4) !important;
font-weight: 400;
}
}
.page-rnr-action-sheet {
padding: 30px;
.page-rnr-action-sheet-title {
color: #242424;
font-size: 32px;
font-weight: 500;
line-height: 45px;
padding: 0 0 0 24px;
}
.van-cell {
background-color: transparent;
padding: 0;
&.van-field {
background-color: transparent;
padding: 44px 26px;
position: relative;
.van-field__label {
color: #242424;
font-size: 32px;
font-weight: 400;
height: 45px;
}
.van-cell__value {
height: 45px;
.van-field__control {
color: #242424;
font-size: 32px;
}
&.van-field__value {
position: relative;
.van-field__error-message {
position: absolute;
left: -220px;
bottom: -90px;
}
}
}
}
&.van-cell--required {
.van-cell__title {
span {
padding-left: 20px;
}
}
&:before {
left: 0px;
font-size: 16px;
}
}
.van-cell__title {
span {
color: #242424;
font-size: 32px;
font-weight: 400;
}
}
.van-cell__label {
margin-top: 36px;
}
&:after {
position: absolute;
box-sizing: border-box;
content: ' ';
pointer-events: none;
right: 0px;
bottom: 0;
left: 0px;
border-bottom: 1PX solid #ebedf0 !important;
transform: scaleY(.5);
}
}
.page-rnr-action-sheet-btn {
margin: 112px 0px 88px;
}
}
.page-rnr-main-card-iccid {
padding-bottom: 36px !important;
.page-rnr-main-card-title {
align-items: center;
display: flex;
height: 46px;
padding: 30px 0 48px;
justify-content: space-between;
.page-rnr-main-card-title-tl {
color: #242424;
font-size: 32px;
font-weight: 500;
flex-shrink: 0;
}
.page-rnr-main-card-title-tr {
color: #CACACA;
font-size: 32px;
flex-shrink: 0;
}
}
.rnr-main-card-add-btn {
margin-top: 24px;
.imageicon {
margin-bottom: -4px;
margin-right: 12px;
}
}
}
}
</style>
<template>
<Page class="page-rnr-person-file" title="文件信息">
<template #slot-title>
<span>{{ currentFlow }}/{{ totalFlow }}</span>
<span>文件信息</span>
</template>
<template #slot-before-main>
<div class="page-rnr-person-file-tip">文件类型为图片文件,允许支持的照片格式包括bmp、jpg/jpeg、png,小于500K。</div>
</template>
<div class="page-rnr-main-card">
<ErrorWrap :error-message="inputError.purchaseContractPic" :error="!!inputError.purchaseContractPic">
<van-cell id="purchaseContractPic" :required="true" title="购车合同" class="van-field">
<template #label>
<BridgeUpload v-model="formData.purchaseContractPic" :customer="true">
<div class="page-rnr-main-card-upload-normal">
<div class="icon-upload-camera" />
</div>
</BridgeUpload>
</template>
</van-cell>
</ErrorWrap>
</div>
<div class="page-rnr-main-card">
<ErrorWrap>
<van-cell id="contractPic" title="购车发票或行驶本之一" class="van-field">
<template #label>
<BridgeUpload v-model="formData.purchaseInvoicePic" :customer="true">
<div class="page-rnr-main-card-upload-normal">
<div class="icon-upload-camera" />
</div>
</BridgeUpload>
</template>
</van-cell>
</ErrorWrap>
</div>
<div class="page-rnr-main-card">
<ErrorWrap :error-message="inputError.transferCertificatePic" :error="!!inputError.transferCertificatePic">
<van-cell id="contractPic" :required="true" title="过户证明" class="van-field">
<template #label>
<BridgeUpload v-model="formData.transferCertificatePic" :customer="true">
<div class="page-rnr-main-card-upload-normal">
<div class="icon-upload-camera" />
</div>
</BridgeUpload>
</template>
</van-cell>
</ErrorWrap>
</div>
<template #slot-operation>
<van-button type="primary" class="page-rnr-main-btn-before" round color="linear-gradient(120deg, #EDF3FF 0%, #E9F0FF 97%)" @click="handleToBefore">上一步</van-button>
<van-button :disabled="btnDisable" type="primary" class="page-rnr-main-btn-next" round color="linear-gradient(120deg, #4F4CFB 0%, #376FF4 97%)" @click="handleToNext">下一步</van-button>
</template>
</Page>
</template>
<script>
import Page from '@/components/Page'
import ErrorWrap from '@/components/ErrorWrap'
import BridgeUpload from '@/components/BridgeUpload'
import { fileUpload } from '@/api/markup'
import { Toast } from 'vant'
import { validate } from '@/utils/validate'
import { SET_PERSON_FILE } from '@/store/modules/markup'
import flowMixin from '@/minxin/flow'
export default {
name: 'MarkupPersonCard',
components: { Page, BridgeUpload, ErrorWrap },
mixins: [flowMixin],
data() {
return {
inputError: {},
countTime: 59,
isSend: false,
showSms: false,
formData: {
purchaseContractPic: [],
purchaseInvoicePic: [],
transferCertificatePic: []
}
}
},
computed: {
/**
* 按钮是否禁用
*/
btnDisable() {
const { transferCertificatePic, purchaseContractPic } = this.formData
return transferCertificatePic.length === 0 || purchaseContractPic.length === 0
}
},
methods: {
/**
* 删除文件
*/
handleDeleteFile(files, { index }, key) {
this.formData[key].splice(index, 1)
},
/**
* 上传文件
* @param origin 源文件
* @param key 字段key
*/
handleUploadFile(origin, key) {
// 获取当前文件
let files = origin
// 如果当前不是数组,则将其变成数组
if (!(files instanceof Array)) {
files = [files]
}
// 将文件的uuid都展示在界面上
files.forEach(async file => {
// 文件可访问路径和文件的uuid
const { uuid } = await fileUpload({ file: file.content })
// 将文件id保存在照片中
this.formData[key].push(uuid)
// 开始校验上传字段
this.validate([key])
})
},
/**
* 调到到下一页:签名页
*/
async handleToNext() {
// 校验不通过的字段
const failField = this.validate(['purchaseContractPic', 'purchaseInvoicePic', 'transferCertificatePic'])
// 如果当前校验失败
if (failField) {
return
}
// 将当前数据保存到store中
this.$store.commit(`markup/${SET_PERSON_FILE}`, this.formData)
// 跳转页面
this.routerToNextPage('MarkupPersonNotification')
},
/**
* 校验用户输入
*/
validate(ruleKeys) {
// 错误的字段,错误的信息
const [failField, failMessage] = validate(this.formData, ruleKeys)
// 如果当前有错误信息
ruleKeys.forEach(key => {
this.$set(this.inputError, key, failField === key ? failMessage : '')
})
return failField
},
/**
* 跳转到上一页
*/
handleToBefore() {
// 回退到上个页面
this.$router.back()
},
/**
* 图片超过最大限制
*/
handleOverSize() {
Toast('选择的图片超过最大限制,请重新选择')
}
}
}
</script>
<style lang="scss">
.page-rnr-person-file {
.page-rnr-main {
margin-top: 0px;
}
.page-rnr-main-fixed-btn-group {
display: flex;
justify-content: space-between;
.page-rnr-main-btn-before {
color: #242424 !important;
flex: 1;
height: 96px;
}
.page-rnr-main-btn-next {
flex: 2;
margin-left: 40px;
height: 96px;
}
}
.icon-upload-camera {
background-image: url(../../../assets/rnr/ico_camera.png);
background-size: 100% 100%;
position: absolute;
width: 80px;
height: 80px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.page-rnr-main-card-upload-normal {
background-image: url(../../../assets/rnr/ico_pic.png);
background-color: #F7F8FA;
background-size: 196px 196px;
background-repeat: no-repeat;
background-position: center;
border-radius: 8px;
width: 196px;
height: 196px;
}
.page-rnr-main-btn {
font-size: 32px !important;
&.disabled {
color: #CACACA !important;
}
}
.van-cell__label {
.page-rnr-flex {
display: flex;
justify-content: space-between;
}
}
.page-rnr-person-file-tip {
font-size: 24px;
color: rgba(255, 255, 255, 0.6);
font-weight: 400;
padding: 14px 48px 18px;
}
}
</style>
<template>
<Page
:next-disable="!formData.certPic[0] || !formData.certPic[1]"
class="page-rnr-person-idcard"
@next="handleToNext"
>
<template #slot-title>
<span>{{ currentFlow }}/{{ totalFlow }}</span>
<span>证件信息</span>
</template>
<template #slot-before-main>
<div class="page-rnr-person-idcard-tip">文件类型为图片文件,允许支持的照片格式包括bmp、jpg/jpeg、png,小于500K。</div>
</template>
<div class="page-rnr-main-card">
<!-- 身份证选择上传 -->
<FormRender
ref="formRenderRef"
v-if="formData.certType === 'IDCARD'"
v-model="formData"
:schema="SCHEMA1"
@change="handleFormDataChange"
/>
<!-- 其他证件照片的选择上传 -->
<FormRender
ref="formRenderRef"
v-else
v-model="formData"
:schema="SCHEMA2"
@change="handleFormDataChange"
/>
</div>
<MustKnow v-if="formData.certType === 'IDCARD'" />
<template #slot-operation>
<van-button type="primary" class="page-rnr-main-btn-before" round color="linear-gradient(120deg, #EDF3FF 0%, #E9F0FF 97%)" @click="handleToBefore">上一步</van-button>
<van-button :disabled="!formData.certPic[0] || !formData.certPic[1]" type="primary" class="page-rnr-main-btn-next" round color="linear-gradient(120deg, #4F4CFB 0%, #376FF4 97%)" @click="handleToNext">下一步</van-button>
</template>
</Page>
</template>
<script>
import cache from '@/utils/cache'
import { cuscImageUpload } from '@/api/markup'
import Page from '@/components/Page'
import MustKnow from '@/components/MustKnow'
import FormRender from '@/components/FormRender'
import { SET_PERSON_IDCARD } from '@/store/modules/markup'
import flowMixin from '@/minxin/flow'
export default {
name: 'MarkupPersonCard',
components: { Page, FormRender, MustKnow },
mixins: [flowMixin],
data() {
const { CARD_TYPE } = this.$store.getters.dict
return {
formData: {
certType: 'IDCARD',
certPic: []
},
SCHEMA1: {
certType: {
label: '证件类型',
type: 'rnr-select',
rules: [
{ required: true }
],
options: CARD_TYPE
},
certPic: {
type: 'rnr-idcard',
compress: {},
api: file => cuscImageUpload({ file }).then(resp => resp.uuid),
rules: [
{ required: true },
{
validator(value) {
// 如果人像面没有上传
if (!value[0] || value[0].length === 0) {
return { result: false, message: '请上传身份证人像面' }
}
if (!value[1] || value[1].length === 0) {
return { result: false, message: '请上传身份证国徽面' }
}
return true
}
}
]
}
},
SCHEMA2: {
certType: {
label: '证件类型',
type: 'rnr-select',
rules: [
{ required: true }
],
options: CARD_TYPE
},
certPic: {
type: 'rnr-file',
size: 'large',
compress: {},
maxCount: 2,
api: file => cuscImageUpload({ file }).then(resp => resp.uuid),
rules: [
{ required: true },
{
validator(value) {
// 如果人像面没有上传
if (!value[0] || value[0].length === 0) {
return { result: false, message: '请上传证件信息正面' }
}
if (!value[1] || value[1].length === 0) {
return { result: false, message: '请上传证件信息反面' }
}
return true
}
}
]
}
}
}
},
methods: {
/**
* 表单项改变方法
* @param value 当前双向绑定的值
* @param key 当前改变的字段key
*/
handleFormDataChange(value, key) {
if (key === 'certType') {
this.formData.certPic = []
}
},
/**
* 调到到下一页:腾讯的实名认证平台
*/
async handleToNext() {
// 开始校验数据
this.$refs.formRenderRef.validate()
// 取出双向绑定的身份证照片id
const { certType, certPic } = this.formData
// 将当前数据保存到store中
this.$store.commit(`markup/${SET_PERSON_IDCARD}`, { certType, certPic: certPic.map(pic => pic.uuid) })
// 当前证件照片的识别key
const CERT_PIC_STORAGE_KEY = `cert-pic-${Date.now()}`
// 将证件信息保存到缓存中
cache.set(CERT_PIC_STORAGE_KEY, certPic, { noStorage: true })
// 跳转到基本信息页
this.routerToNextPage('MarkupPersonBase', { certPicKey: CERT_PIC_STORAGE_KEY })
},
/**
* 跳转到上一页
*/
handleToBefore() {
// 回退到上个页面
this.$router.back()
}
}
}
</script>
<style lang="scss">
.page-rnr-person-idcard {
padding-bottom: 72px;
.page-rnr-main {
margin-top: 0px !important;
.rnr-idcard, .rnr-file {
padding: 48px 0;
}
}
.page-rnr-person-idcard-tip {
font-size: 24px;
color: rgba(255, 255, 255, 0.6);
font-weight: 400;
padding: 14px 48px 18px;
}
}
</style>
<template>
<Page class="page-rnr-person-agreement">
<template #slot-title>
<span>{{ currentFlow }}/{{ totalFlow }}</span>
<span>责任告知书</span>
</template>
<div class="page-rnr-main-card">
<van-loading v-if="!notificationUrl" class="global-loading" color="#0094ff" />
<Painter ref="painterRef" v-else>
<img crossOrigin :src="notificationUrl">
<img :src="signUrl" class="fixed-right">
</Painter>
</div>
<div class="page-rnr-sign-wrapper">
<div v-if="signUrl" class="page-rnr-sign-fill" @click="showSign = true">
<img :src="signUrl" class="page-rnr-sign-img">
<div class="page-rnr-sign-btn">重签</div>
</div>
<div v-else class="page-rnr-sign" @click="openSign">点击在此处签名</div>
</div>
<template #slot-operation>
<van-button type="primary" class="page-rnr-main-btn-before" round color="linear-gradient(120deg, #EDF3FF 0%, #E9F0FF 97%)" @click="handleToBefore">上一步</van-button>
<van-button :disabled="btnDisable" :loading="loading" type="primary" class="page-rnr-main-btn-next" round color="linear-gradient(120deg, #4F4CFB 0%, #376FF4 97%)" @click="handleToNext">下一步</van-button>
</template>
<Sign :visible.sync="showSign" @submit="handleSignChange" />
</Page>
</template>
<script>
import Painter from '@/components/Painter'
import { fileUpload } from '@/api/markup'
import { SET_PERSON_DUTY_PIC, DISPATCH_INIT_PROTOCAL } from '@/store/modules/markup'
import Page from '@/components/Page'
import signMixin from '@/minxin/sign'
import flowMixin from '@/minxin/flow'
export default {
name: 'MarkupPersonNotification',
components: { Page, Painter },
mixins: [flowMixin, signMixin],
data() {
return {
loading: false,
showSms: false,
notificationUrl: ''
}
},
async mounted() {
// 查询协议数据
await this.$store.dispatch(`markup/${DISPATCH_INIT_PROTOCAL}`)
// 当前请求到的协议数据
const { protocalMarkup } = this.$store.getters
// 协议链接
this.notificationUrl = protocalMarkup[window.os.isTablet ? 'realnameNoticeVertical' : 'realnameNoticeHorizontal'].fileUrl
},
methods: {
/**
* 调到到下一页:腾讯的实名认证平台
*/
async handleToNext(formData) {
// 展示按钮loading
this.loading = true
try {
// 开始绘制canvas
const file = await this.$refs.painterRef.draw()
// 开始导出图片
const { uuid } = await fileUpload({ file })
// 开始保存数据
this.$store.commit(`markup/${SET_PERSON_DUTY_PIC}`, {
dutyPic: [uuid]
})
// 跳转到
this.routerToNextPage('MarkupPersonAgreement')
} catch (error) {
console.error(error)
}
this.loading = false
},
/**
* 跳转到上一页
*/
handleToBefore() {
// 回退到上个页面
this.$router.back()
}
}
}
</script>
<style lang="scss">
.page-rnr-person-agreement {
.page-rnr-main {
margin-top: 30px;
.page-rnr-main-card {
padding: 24px 24px 168px;
height: calc(100vh - 450px);
overflow: auto;
.page-rnr-main-canvas {
width: 100%;
}
}
.page-rnr-sign-wrapper {
background: #ffffff;
bottom: 196px;
padding: 24px 32px;
position: fixed;
left: 24px;
right: 24px;
.page-rnr-sign {
align-items: center;
background: #F7F8FA;
border: 1px dashed rgba(7, 97, 243, 1);
border-radius: 12px;
color: #0761F3;
display: flex;
font-size: 24px;
font-weight: 400;
height: 120px;
justify-content: center;
}
.page-rnr-sign-fill {
align-items: center;
background: #F7F8FA;
border-radius: 12px;
bottom: 148px;
display: flex;
height: 120px;
justify-content: space-between;
padding: 0px 48px 0px 132px;
.page-rnr-sign-img {
width: auto;
height: 100px;
}
.page-rnr-sign-btn {
color: #0761F3;
font-size: 24px;
font-weight: 400;
}
}
}
.page-rnr-main-fixed-btn-group {
display: flex;
justify-content: space-between;
.page-rnr-main-btn-before {
color: #242424 !important;
flex: 1;
height: 96px;
}
.page-rnr-main-btn-next {
flex: 2;
margin-left: 40px;
height: 96px;
}
}
}
}
</style>
<template>
<Page class="page-rnr-person-file">
<template #slot-title>
<span>{{ currentFlow }}/{{ totalFlow }}</span>
<span>证件信息</span>
</template>
<template #slot-before-main>
<div class="page-rnr-person-file-tip">文件类型为图片文件,允许支持的照片格式包括bmp、jpg/jpeg、png,小于500K。</div>
</template>
<div class="page-rnr-main-card">
<ErrorWrap :error-message="inputError.certPic" :error="!!inputError.certPic">
<van-cell id="contractPic" :required="true" title="证件信息" class="van-field">
<template #label>
<BridgeUpload
:max-count="3"
:compress="{}"
:security="true"
:customer="true"
v-model="formData.certPic"
>
<div class="page-rnr-main-card-upload-normal">
<div class="icon-upload-camera" />
</div>
</BridgeUpload>
</template>
</van-cell>
</ErrorWrap>
</div>
<template #slot-operation>
<van-button type="primary" class="page-rnr-main-btn-before" round color="linear-gradient(120deg, #EDF3FF 0%, #E9F0FF 97%)" @click="handleToBefore">上一步</van-button>
<van-button type="primary" class="page-rnr-main-btn-next" round color="linear-gradient(120deg, #4F4CFB 0%, #376FF4 97%)" @click="handleToNext">下一步</van-button>
</template>
</Page>
</template>
<script>
import Page from '@/components/Page'
import ErrorWrap from '@/components/ErrorWrap'
import BridgeUpload from '@/components/BridgeUpload'
import { validate } from '@/utils/validate'
import flowMixin from '@/minxin/flow'
import { SET_PERSON_PAPER } from '@/store/modules/markup'
export default {
name: 'MarkupPersonCard',
components: { Page, BridgeUpload, ErrorWrap },
mixins: [flowMixin],
data() {
const { customerType } = this.$store.getters.personRnr
return {
inputError: {},
countTime: 59,
isSend: false,
showSms: false,
customerType,
formData: {
certPic: []
}
}
},
methods: {
/**
* 调到到下一页:腾讯的实名认证平台
*/
async handleToNext() {
// 校验不通过的字段
const failFiled = this.validate()
// 如果当前有字段没校验通过
if (failFiled) {
return
}
// 保存到store中
this.$store.commit(`markup/${SET_PERSON_PAPER}`, this.formData)
// 跳转到支付结果页
this.routerToNextPage('MarkupPersonNotification')
},
/**
* 校验用户输入
*/
validate(ruleKeys = ['certPic']) {
// 错误的字段,错误的信息
const [failField, failMessage] = validate(this.formData, ruleKeys)
// 如果当前有错误信息
ruleKeys.forEach(key => {
this.$set(this.inputError, key, failField === key ? failMessage : '')
})
return failField
},
/**
* 跳转到上一页
*/
handleToBefore() {
// 回退到上个页面
this.$router.back()
}
}
}
</script>
<style lang="scss">
.page-rnr-person-file {
.page-rnr-main {
margin-top: 0px;
}
.page-rnr-main-fixed-btn-group {
display: flex;
justify-content: space-between;
.page-rnr-main-btn-before {
color: #242424 !important;
flex: 1;
height: 96px;
}
.page-rnr-main-btn-next {
flex: 2;
margin-left: 40px;
height: 96px;
}
}
.icon-upload-camera {
background-image: url(../../../assets/rnr/ico_camera.png);
background-size: 100% 100%;
position: absolute;
width: 80px;
height: 80px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.page-rnr-main-card-upload-normal {
background-image: url(../../../assets/rnr/ico_pic.png);
background-color: #F7F8FA;
background-size: 196px 196px;
background-repeat: no-repeat;
background-position: center;
border-radius: 8px;
width: 196px;
height: 196px;
}
.page-rnr-main-btn {
font-size: 32px !important;
&.disabled {
color: #CACACA !important;
}
}
.van-cell__label {
.page-rnr-flex {
display: flex;
justify-content: space-between;
}
}
.page-rnr-person-file-tip {
font-size: 24px;
color: rgba(255, 255, 255, 0.6);
font-weight: 400;
padding: 14px 48px 18px;
}
.van-dialog {
box-sizing: border-box;
width: 685px;
padding: 0 40px 50px;
.van-dialog__header {
padding: 60px 0 12px;
}
.van-field__button {
padding-left: 30px;
.page-rnr-main-btn {
color: #0761F3;
font-size: 32px;
font-weight: 400;
}
}
.page-rnr-main-btn-confirm {
margin-top: 44px;
}
}
}
</style>
<template>
<van-loading v-if="status === STATUS.PENDING" vertical color="#0094ff" class="loading-container">加载中...</van-loading>
<section v-else 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="page-rnr-main-fixed-btn-group">
<van-button v-if="status === STATUS.TX_VALID_FAIL" type="primary" class="page-rnr-main-btn-next" round block color="linear-gradient(120deg, #4F4CFB 0%, #376FF4 97%)" @click="handleToTxVerify">重新认证</van-button>
<van-button v-else type="primary" class="page-rnr-main-btn-next" round block color="linear-gradient(120deg, #4F4CFB 0%, #376FF4 97%)" @click="handleToNextPage(status === STATUS.FAIL ? 'MarkupPersonCard' : 'UserHome')">{{ status === STATUS.FAIL ? '重新认证' : '返回首页' }}</van-button>
</div>
</section>
</template>
<script>
import { livenessCallback } from '@/api/markup'
// 状态
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: ''
}
},
activated() {
// 开始提交实名信息
this.fetchSubmitRnr(this.$route.query)
},
methods: {
/**
* 提交实名认证的接口
*/
async fetchSubmitRnr(query) {
try {
// 开始提交数据
const { status, h5LivenessUrl } = await livenessCallback(this.$route.query)
// 标记当前提交成功
this.status = status
// h5活体验证的链接
this.h5LivenessUrl = h5LivenessUrl
return
} catch (error) {
console.error(error)
}
// 标记当前提交失败
this.status = STATUS.FAIL
},
/**
* 跳转到活体认证
*/
handleToTxVerify() {
// 跳转到活体认证页面
window.location.href = this.h5LivenessUrl
},
/**
* 跳转到下一个页面
* @param pageName 页面名称
*/
handleToNextPage(pageName) {
this.$router.push({ name: pageName })
}
}
}
</script>
<style lang="scss">
.page-rnr-result {
.page-rnr-result-content {
padding-top: 72px;
.page-rnr-result-icon {
background-size: 100% 100%;
background-repeat: no-repeat;
width: 648px;
height: 490px;
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;
}
}
}
.loading-container {
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
position: fixed;
}
</style>
.page-rnr-main-fixed-btn-group {
display: flex;
justify-content: space-between;
.page-rnr-main-btn-before {
color: #242424 !important;
flex: 1;
height: 96px;
}
.page-rnr-main-btn-next {
flex: 2;
height: 96px;
}
}
\ No newline at end of file
<template>
<Page class="page-rnr-person-agreement" title="入网协议">
<div class="page-rnr-main-card">
<van-loading v-if="!notificationUrl" class="global-loading" color="#0094ff" />
<Painter ref="painterRef" v-else>
<img crossOrigin :src="notificationUrl">
<img :src="signUrl" class="fixed-right">
<h1>* 附件</h1>
<div v-for="vin in enterpriseRnr.iccidList" :key="vin.vin">
<p>VIN: {{ vin.vin }}</p>
<p>ICCID: {{ (vin.iccidList || []).join(', ') }}</p>
<p style="border-top: 1px solid #e7e9ed;" />
</div>
</Painter>
</div>
<div class="page-rnr-sign-wrapper">
<div v-if="signUrl" class="page-rnr-sign-fill" @click="showSign = true">
<img :src="signUrl" class="page-rnr-sign-img">
<div class="page-rnr-sign-btn">重签</div>
</div>
<div v-else class="page-rnr-sign" @click="showSign = true">点击在此处签名</div>
</div>
<template #slot-operation>
<van-button type="primary" class="page-rnr-main-btn-before" round color="linear-gradient(120deg, #EDF3FF 0%, #E9F0FF 97%)" @click="handleToBefore">上一步</van-button>
<van-button :disabled="btnDisable" :loading="loading" type="primary" class="page-rnr-main-btn-next" round color="linear-gradient(120deg, #4F4CFB 0%, #376FF4 97%)" @click="handleOpenSms">下一步</van-button>
</template>
<Sign :visible.sync="showSign" @submit="handleSignChange" />
<PhoneVerify :visible.sync="showSms" :loading="loading" @submit="handleToNext" />
</Page>
</template>
<script>
import Painter from '@/components/Painter'
import signMixin from '@/minxin/sign'
import { mapGetters } from 'vuex'
import Page from '@/components/Page'
import { DISPATCH_INIT_PROTOCAL } from '@/store/modules/rnr'
import PhoneVerify from '@/components/PhoneVerify'
import { fileUpload, submitEnterpriseRnr } from '@/api/rnr'
export default {
name: 'RnrEnterpriseAgreement',
components: { Page, PhoneVerify, Painter },
mixins: [signMixin],
data() {
return {
loading: false,
showSms: false,
contractPic: [],
notificationUrl: ''
}
},
computed: {
...mapGetters(['enterpriseRnr'])
},
async mounted() {
// 查询协议数据
await this.$store.dispatch(`rnr/${DISPATCH_INIT_PROTOCAL}`)
// 当前请求到的协议数据
const { protocal } = this.$store.getters
// 协议链接
this.notificationUrl = protocal[window.os.isTablet ? 'companyAgreementVertical' : 'companyAgreementHorizontal'].fileUrl
},
methods: {
/**
* 调到到下一页:腾讯的实名认证平台
*/
async handleToNext({ phone, verificationCode }) {
// 呈现loading状态
this.loading = true
try {
// 取出数据
let enterpriseRnr = this.$store.getters.enterpriseRnr || {}
// 如果当前是委托人
if (enterpriseRnr.isConsigner) {
enterpriseRnr.consignerInfo = {
...enterpriseRnr.consignerInfo,
corporationPhone: phone,
verificationCode
}
} else {
enterpriseRnr = {
...enterpriseRnr,
corporationPhone: phone,
verificationCode
}
}
// 开始提交数据
const { h5LivenessUrl } = await submitEnterpriseRnr({
...enterpriseRnr,
contractPic: this.contractPic
})
// 跳转到活体认证页面
window.location.href = h5LivenessUrl
} catch (error) {
console.error(error)
}
// 关闭loading状态
this.loading = false
},
/**
* 打开协议管理
*/
async handleOpenSms() {
// 展示loading框
this.loading = true
try {
// 开始绘制canvas
const file = await this.$refs.painterRef.draw()
// 开始导出图片
const { uuid } = await fileUpload({ file })
// 记录当前照片
this.contractPic = [uuid]
// 展示短信验证码
this.showSms = true
} catch (error) {
console.error(error)
}
this.loading = false
},
/**
* 跳转到上一页
*/
handleToBefore() {
// 回退到上个页面
this.$router.back()
}
}
}
</script>
<style lang="scss">
@import "../rnr.scss";
.page-rnr-person-agreement {
.page-rnr-main {
margin-top: 30px;
.page-rnr-main-card {
padding: 24px 24px 168px;
height: calc(100vh - 450px);
overflow: auto;
.page-rnr-main-canvas {
width: 100%;
}
}
.page-rnr-sign-wrapper {
background: #ffffff;
bottom: 196px;
padding: 24px 32px;
position: fixed;
left: 24px;
right: 24px;
.page-rnr-sign {
align-items: center;
background: #F7F8FA;
border: 1px dashed rgba(7, 97, 243, 1);
border-radius: 12px;
color: #0761F3;
display: flex;
font-size: 24px;
font-weight: 400;
height: 120px;
justify-content: center;
}
.page-rnr-sign-fill {
align-items: center;
background: #F7F8FA;
border-radius: 12px;
bottom: 148px;
display: flex;
height: 120px;
justify-content: space-between;
padding: 0px 48px 0px 132px;
.page-rnr-sign-img {
width: auto;
height: 100px;
}
.page-rnr-sign-btn {
color: #0761F3;
font-size: 24px;
font-weight: 400;
}
}
}
.page-rnr-main-fixed-btn-group {
display: flex;
justify-content: space-between;
.page-rnr-main-btn-before {
color: #242424 !important;
flex: 1;
height: 96px;
}
.page-rnr-main-btn-next {
flex: 2;
height: 96px;
}
}
}
}
</style>
<template>
<Page title="车卡信息" :show-operation="vinList.length > 0">
<div class="page-rnr-main-card">
<ScanCard :success-num="successNum" :fail-num="failNum" :total="vinList.length" @add="handleOpenVin" @scan="handleScanVin">
<div v-if="vinList.length > 0" class="page-rnr-main-vin-wrapper" slot="content">
<ErrorWrap v-for="(vin, index) in vinList" :key="vin.vin" :error="!vin.result" :error-message="vin.errorMsg">
<van-field
:value="vin.vin"
:label="index + 1"
readonly
input-align="right"
@click="handleEditVin(index)"
>
<template #button>
<i class="imageicon imageicon-del" @click.stop="handleDeleteVin(index)" />
</template>
</van-field>
</ErrorWrap>
</div>
</ScanCard>
</div>
<template #slot-operation>
<van-button :loading="loading" type="primary" class="page-rnr-main-btn-next" round color="linear-gradient(120deg, #4F4CFB 0%, #376FF4 97%)" block @click="handleToNext">下一步</van-button>
</template>
<InputActionSheet :visible.sync="sheet.show" :title="sheet.title" :data="sheet.data" :rules="{ vin: 'vin' }" @submit="handleConfirmVin" />
</Page>
</template>
<script>
import { SET_ENTERPRISE_CARD } from '@/store/modules/rnr'
import { checkVin } from '@/api/rnr'
import Page from '@/components/Page'
import ScanCard from '@/components/ScanCard'
import InputActionSheet from '@/components/InputActionSheet'
import { Toast } from 'vant'
import ErrorWrap from '@/components/ErrorWrap'
export default {
name: 'RnrEnterpriseCard',
components: { Page, ScanCard, InputActionSheet, ErrorWrap },
data() {
return {
sheet: {
show: false,
title: '',
data: ''
},
successNum: 0,
failNum: 0,
loading: false,
showOperation: false,
vinList: []
}
},
methods: {
/**
* 打开vin码输入的弹框
*/
handleOpenVin() {
// 弹出框
this.sheet.title = '添加VIN码'
this.sheet.show = true
this.sheet.data = ''
this.sheet.vinIndex = -1
},
/**
* 编辑当前vin码
* @param index 当前vin码所处的索引
*/
handleEditVin(index) {
// 弹出框
this.sheet.title = '修改VIN码'
this.sheet.show = true
this.sheet.vinIndex = index
this.sheet.data = this.vinList[index].vin
},
/**
* 删除指定所有的vin号
* @param index 删除行数据
*/
handleDeleteVin(index) {
this.vinList.splice(index, 1)
},
/**
* 跳转到下一页
*/
async handleToNext() {
// 展示loading框
this.loading = true
try {
// iccid的集合
const iccidList = []
// 当前输入的vin码
const vinList = this.vinList.map(vin => {
// 重置校验结果
vin.result = true
vin.errorMsg = ''
return vin.vin
})
// 开始校验数据
const { checkList } = await checkVin({ vinList })
// 校验失败的,将错误信息赋值给原来的组件
const failVinList = checkList.filter(vin => {
this.vinList.forEach(vinItem => {
if (vinItem.vin === vin.vin) {
vinItem.result = vin.checkResult
vinItem.errorMsg = vin.errorMsg
// 获取集合
iccidList.push({
vin: vin.vin,
iccidList: vin.iccidList
})
}
})
return !vin.checkResult
})
// 校验失败的vin数量
this.failNum = failVinList.length
// 成功的vin数量
this.successNum = vinList.length - this.failNum
// 如果车卡关系校验有失败的
if (failVinList.length > 0) {
Toast('车卡关系校验不成功,请重新输入')
this.loading = false
return
}
// 将值保存到store中
this.$store.commit(`rnr/${SET_ENTERPRISE_CARD}`, { vinList, iccidList })
// 开始跳转页面
this.$router.push({ name: 'RnrEnterpriseCert' })
} catch (error) {
console.error(error)
}
this.loading = false
},
/**
* 扫码添加的vin码
* @param vin 待添加的vin
*/
handleScanVin(vin) {
// 设置当前索引是-1
this.sheet.vinIndex = -1
// 添加一个vin
this.handleConfirmVin(vin)
},
/**
* 同步用户输入的vin码
* @param vin 当前输入的vin码
*/
handleConfirmVin(vin) {
// 当前vin码集合
const { vinIndex } = this.sheet
// 如果当前是编辑
if (vinIndex >= 0) {
// 重新赋值
this.vinList[vinIndex].vin = vin
// 清空之前的校验
this.vinList[vinIndex].result = true
this.vinList[vinIndex].errorMsg = ''
} else {
this.vinList.push({
result: true,
vin,
errorMsg: ''
})
}
}
}
}
</script>
<style lang="scss">
.page-rnr {
.component-scan-code {
.van-cell__title {
padding-left: 32px;
}
.imageicon-del {
margin-bottom: -6px;
margin-left: 64px;
}
}
.page-rnr-main-vin-wrapper {
max-height: calc(100vh - 720px);
overflow: auto;
}
.page-rnr-main-fixed-btn-group {
.page-rnr-main-btn-next {
height: 96px;
}
}
}
</style>
<template>
<Page class="page-rnr-enterprise-file" title="企业证件信息">
<template #slot-before-main>
<div class="page-rnr-person-file-tip">文件类型为图片文件,允许支持的照片格式包括bmp、jpg/jpeg、png,小于500K。</div>
</template>
<div class="page-rnr-main-card">
<ErrorWrap :error-message="errorMessage" :error="!!errorMessage">
<van-cell id="contractPic" :required="true" title="证件信息" class="van-field">
<template #label>
<BridgeUpload
:max-count="3"
:compress="{}"
:security="true"
v-model="licenseImages"
>
<div class="page-rnr-main-card-upload-normal">
<div class="icon-upload-camera" />
</div>
</BridgeUpload>
</template>
</van-cell>
</ErrorWrap>
</div>
<template #slot-operation>
<van-button type="primary" class="page-rnr-main-btn-before" round color="linear-gradient(120deg, #EDF3FF 0%, #E9F0FF 97%)" @click="handleToBefore">上一步</van-button>
<van-button type="primary" class="page-rnr-main-btn-next" round color="linear-gradient(120deg, #4F4CFB 0%, #376FF4 97%)" @click="handleToNext">下一步</van-button>
</template>
</Page>
</template>
<script>
import { SET_ENTERPRISE_CERT_IMAGE } from '@/store/modules/rnr'
import Page from '@/components/Page'
import ErrorWrap from '@/components/ErrorWrap'
import BridgeUpload from '@/components/BridgeUpload'
import { Toast } from 'vant'
import { validate } from '@/utils/validate'
export default {
name: 'RnrEnterpriseCertImage',
components: { Page, BridgeUpload, ErrorWrap },
data() {
return {
errorMessage: '',
licenseImages: []
}
},
methods: {
/**
* 调到到下一页:腾讯的实名认证平台
*/
handleToNext() {
// 取出企业证件照片
const licenseImages = this.licenseImages
// 如果当前有字段没校验通过
if (licenseImages.length === 0) {
this.errorMessage = '请上传照片'
return
}
// 清空错误信息
this.errorMessage = ''
// 将当前数据保存到缓存中
this.$store.commit(`rnr/${SET_ENTERPRISE_CERT_IMAGE}`, { licenseImages })
// 跳转到责任人页面
this.$router.push({ name: 'RnrEnterpriseIdcard' })
},
/**
* 校验用户输入
*/
validate(ruleKeys = ['certPic']) {
// 错误的字段,错误的信息
const [failField, failMessage] = validate(this.formData, ruleKeys)
// 如果当前有错误信息
ruleKeys.forEach(key => {
failField === key && Toast.fail(failMessage)
})
return failField
},
/**
* 跳转到上一页
*/
handleToBefore() {
// 回退到上个页面
this.$router.back()
},
/**
* 跳转到首页
*/
handleToHome() {
this.$router.push({ name: 'Home' })
}
}
}
</script>
<style lang="scss">
.page-rnr-enterprise-file {
.page-rnr-main {
margin-top: 0px;
}
.page-rnr-main-fixed-btn-group {
display: flex;
justify-content: space-between;
.page-rnr-main-btn-before {
color: #242424 !important;
flex: 1;
height: 96px;
}
.page-rnr-main-btn-next {
flex: 2;
margin-left: 40px;
height: 96px;
}
}
.icon-upload-camera {
background-image: url(../../../assets/rnr/ico_camera.png);
background-size: 100% 100%;
position: absolute;
width: 80px;
height: 80px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.page-rnr-main-card-upload-normal {
background-image: url(../../../assets/rnr/ico_pic.png);
background-color: #F7F8FA;
background-size: 196px 196px;
background-repeat: no-repeat;
background-position: center;
border-radius: 8px;
width: 196px;
height: 196px;
}
.page-rnr-main-btn {
font-size: 32px !important;
&.disabled {
color: #CACACA !important;
}
}
.van-cell__label {
.page-rnr-flex {
display: flex;
justify-content: space-between;
}
}
.page-rnr-person-file-tip {
font-size: 24px;
color: rgba(255, 255, 255, 0.6);
font-weight: 400;
padding: 14px 48px 18px;
}
.van-dialog {
box-sizing: border-box;
width: 685px;
padding: 0 40px 50px;
.van-dialog__header {
padding: 60px 0 12px;
}
.van-field__button {
padding-left: 30px;
.page-rnr-main-btn {
color: #0761F3;
font-size: 32px;
font-weight: 400;
}
}
.page-rnr-main-btn-confirm {
margin-top: 44px;
}
}
}
</style>
<template>
<Page title="企业信息">
<EnterpriseCert ref="certRef" />
<template #slot-operation>
<van-button type="primary" class="page-rnr-main-btn-before" round color="linear-gradient(120deg, #EDF3FF 0%, #E9F0FF 97%)" @click="handleToBefore">上一步</van-button>
<van-button type="primary" class="page-rnr-main-btn-next" round color="linear-gradient(120deg, #4F4CFB 0%, #376FF4 97%)" @click="handleToNext">下一步</van-button>
</template>
</Page>
</template>
<script>
import { SET_ENTERPRISE_CERT } from '@/store/modules/rnr'
import Page from '@/components/Page'
import EnterpriseCert from '@/components/EnterpriseCert'
export default {
name: 'EnterpriseCertInfo',
components: { Page, EnterpriseCert },
methods: {
/**
* 跳转到上一页
*/
handleToBefore() {
// 回退到上个页面
this.$router.back()
},
/**
* 跳转到首页
*/
handleToHome() {
this.$router.push({ name: 'Home' })
},
handleToNext() {
// 开始校验
try {
const formData = this.$refs.certRef.validate()
// 将值保存到缓存中
this.$store.commit(`rnr/${SET_ENTERPRISE_CERT}`, formData)
// 开始跳转页面
this.$router.push({ name: 'RnrEnterpriseCertImage' })
} catch (error) {
console.error(error)
}
}
}
}
</script>
<style lang="scss">
.page-rnr-main-fixed-btn-group {
display: flex;
justify-content: space-between;
.page-rnr-main-btn-before {
color: #242424 !important;
flex: 1;
height: 96px;
}
.page-rnr-main-btn-next {
flex: 2;
margin-left: 40px;
height: 96px;
}
}
</style>
<template>
<Page class="page-rnr-enterprise-file" title="文件信息">
<template #slot-before-main>
<div class="page-rnr-person-file-tip">文件类型为图片文件,允许支持的照片格式包括bmp、jpg/jpeg、png,小于500K。</div>
</template>
<div class="page-rnr-main-card">
<ErrorWrap :error-message="inputError.authorizationLetterPic" :error="!!inputError.authorizationLetterPic">
<van-cell id="authorizationLetterPic" :required="true" title="企业实名认证授权书" class="van-field">
<template #label>
<BridgeUpload v-model="formData.authorizationLetterPic">
<div class="page-rnr-main-card-upload-normal">
<div class="icon-upload-camera" />
</div>
</BridgeUpload>
</template>
</van-cell>
</ErrorWrap>
</div>
<template #slot-operation>
<van-button type="primary" class="page-rnr-main-btn-before" round color="linear-gradient(120deg, #EDF3FF 0%, #E9F0FF 97%)" @click="handleToBefore">上一步</van-button>
<van-button :loading="loading" :disabled="btnDisable" type="primary" class="page-rnr-main-btn-next" round color="linear-gradient(120deg, #4F4CFB 0%, #376FF4 97%)" @click="handleToNext">下一步</van-button>
</template>
</Page>
</template>
<script>
import { SET_ENTERPRISE_FILE } from '@/store/modules/rnr'
import PhoneVerify from '@/components/PhoneVerify'
import Page from '@/components/Page'
import ErrorWrap from '@/components/ErrorWrap'
import BridgeUpload from '@/components/BridgeUpload'
import { fileUpload } from '@/api/rnr'
import { Toast } from 'vant'
import { validate } from '@/utils/validate'
import flowMixin from '@/minxin/flow'
export default {
name: 'RnrEnterpriseFile',
components: { Page, BridgeUpload, PhoneVerify, ErrorWrap },
mixins: [flowMixin],
data() {
return {
inputError: {},
loading: false,
formData: {
authorizationLetterPic: []
}
}
},
computed: {
/**
* 按钮是否禁用
*/
btnDisable() {
const { authorizationLetterPic } = this.formData
return authorizationLetterPic.length === 0
}
},
methods: {
/**
* 删除文件
*/
handleDeleteFile(files, { index }, key) {
this.formData[key].splice(index, 1)
},
/**
* 上传文件
* @param origin 源文件
* @param key 字段key
*/
handleUploadFile(origin, key) {
// 获取当前文件
let files = origin
// 如果当前不是数组,则将其变成数组
if (!(files instanceof Array)) {
files = [files]
}
// 将文件的uuid都展示在界面上
files.forEach(async file => {
// 文件可访问路径和文件的uuid
const { uuid } = await fileUpload({ file: file.content })
// 将文件id保存在照片中
this.formData[key].push(uuid)
// 开始校验上传字段
this.validate([key])
})
},
/**
* 调到到下一页:签名页
*/
async handleToNext({ phone, verificationCode }) {
// 校验不通过的字段
const failField = this.validate(['authorizationLetterPic'])
// 如果当前校验失败
if (failField) {
return
}
// 将当前数据保存到store中
this.$store.commit(`rnr/${SET_ENTERPRISE_FILE}`, {
...this.formData,
corporationPhone: phone,
verificationCode
})
this.$router.push({ name: 'RnrEnterpriseNotification' })
},
/**
* 校验用户输入
*/
validate(ruleKeys) {
// 错误的字段,错误的信息
const [failField, failMessage] = validate(this.formData, ruleKeys)
// 如果当前有错误信息
ruleKeys.forEach(key => {
this.$set(this.inputError, key, failField === key ? failMessage : '')
})
return failField
},
/**
* 跳转到上一页
*/
handleToBefore() {
// 回退到上个页面
this.$router.back()
},
/**
* 图片超过最大限制
*/
handleOverSize() {
Toast('选择的图片超过最大限制,请重新选择')
}
}
}
</script>
<style lang="scss">
.page-rnr-enterprise-file {
.page-rnr-main {
margin-top: 0px;
}
.page-rnr-main-fixed-btn-group {
display: flex;
justify-content: space-between;
.page-rnr-main-btn-before {
color: #242424 !important;
flex: 1;
height: 96px;
}
.page-rnr-main-btn-next {
flex: 2;
height: 96px;
margin-left: 40px;
}
}
.icon-upload-camera {
background-image: url(../../../assets/rnr/ico_camera.png);
background-size: 100% 100%;
position: absolute;
width: 80px;
height: 80px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.page-rnr-main-card-upload-normal {
background-image: url(../../../assets/rnr/ico_pic.png);
background-color: #F7F8FA;
background-size: 196px 196px;
background-repeat: no-repeat;
background-position: center;
border-radius: 8px;
width: 196px;
height: 196px;
}
.page-rnr-main-btn {
font-size: 32px !important;
&.disabled {
color: #CACACA !important;
}
}
.van-cell__label {
.page-rnr-flex {
display: flex;
justify-content: space-between;
}
}
.page-rnr-person-file-tip {
font-size: 24px;
color: rgba(255, 255, 255, 0.6);
font-weight: 400;
padding: 14px 48px 18px;
}
}
</style>
<template>
<Page
title="责任人证件信息"
class="page-rnr-enterprise-idcard"
@next="handleToNext"
>
<template #slot-before-main>
<div class="page-rnr-enterprise-idcard-tip">文件类型为图片文件,允许支持的照片格式包括bmp、jpg/jpeg、png,小于500K。</div>
</template>
<Card>
<!-- 身份证选择上传 -->
<FormRender
ref="formRenderRef"
v-if="formData.certType === 'IDCARD'"
v-model="formData"
:schema="SCHEMA1"
@change="handleFormDataChange"
/>
<!-- 其他证件照片的选择上传 -->
<FormRender
ref="formRenderRef"
v-else
v-model="formData"
:schema="SCHEMA2"
@change="handleFormDataChange"
/>
</Card>
<MustKnow v-if="formData.certType === 'IDCARD'" />
<template slot="slot-operation">
<van-button type="primary" class="page-rnr-main-btn-before" round color="linear-gradient(120deg, #EDF3FF 0%, #E9F0FF 97%)" @click="handleToBefore">上一步</van-button>
<van-button :disabled="!formData.certPic[0] || !formData.certPic[1]" type="primary" class="page-rnr-main-btn-next" round color="linear-gradient(120deg, #4F4CFB 0%, #376FF4 97%)" @click="handleToNext">下一步</van-button>
</template>
</Page>
</template>
<script>
import Card from '@/components/Card'
import cache from '@/utils/cache'
import { cuscImageUpload } from '@/api/rnr'
import flowMixin from '@/minxin/flow'
import Page from '@/components/Page'
import MustKnow from '@/components/MustKnow'
import FormRender from '@/components/FormRender'
import { SET_ENTERPRISE_PAPER } from '@/store/modules/rnr'
export default {
name: 'RnrPersonCard',
components: { Page, FormRender, Card, MustKnow },
mixins: [flowMixin],
data() {
const { CARD_TYPE } = this.$store.getters.dict
return {
formData: {
certType: 'IDCARD',
certPic: []
},
SCHEMA1: {
certType: {
label: '证件类型',
type: 'rnr-select',
rules: [
{ required: true }
],
options: CARD_TYPE
},
certPic: {
type: 'rnr-idcard',
compress: {},
api: file => cuscImageUpload({ file }).then(resp => resp.uuid),
rules: [
{ required: true },
{
validator(value) {
// 如果人像面没有上传
if (!value[0] || value[0].length === 0) {
return { result: false, message: '请上传身份证人像面' }
}
if (!value[1] || value[1].length === 0) {
return { result: false, message: '请上传身份证国徽面' }
}
return true
}
}
]
}
},
SCHEMA2: {
certType: {
label: '证件类型',
type: 'rnr-select',
rules: [
{ required: true }
],
options: CARD_TYPE
},
certPic: {
type: 'rnr-file',
size: 'large',
compress: {},
maxCount: 2,
api: file => cuscImageUpload({ file }).then(resp => resp.uuid),
rules: [
{ required: true },
{
validator(value) {
// 如果人像面没有上传
if (!value[0] || value[0].length === 0) {
return { result: false, message: '请上传证件信息正面' }
}
if (!value[1] || value[1].length === 0) {
return { result: false, message: '请上传证件信息反面' }
}
return true
}
}
]
}
}
}
},
methods: {
/**
* 表单项改变方法
* @param value 当前双向绑定的值
* @param key 当前改变的字段key
*/
handleFormDataChange(value, key) {
if (key === 'certType') {
this.formData.certPic = []
}
},
/**
* 调到到下一页:腾讯的实名认证平台
*/
async handleToNext() {
// 开始校验数据
this.$refs.formRenderRef.validate()
// 取出双向绑定的身份证照片id
const { certType, certPic } = this.formData
// 将当前数据保存到store中
this.$store.commit(`rnr/${SET_ENTERPRISE_PAPER}`, { corporationCertType: certType, corporationPhotoPic: certPic.map(pic => pic.uuid) })
// 当前证件照片的识别key
const CERT_PIC_STORAGE_KEY = `cert-pic-${Date.now()}`
// 将证件信息保存到缓存中
cache.set(CERT_PIC_STORAGE_KEY, certPic, { noStorage: true })
// 跳转到基本信息页
this.$router.push({ name: 'RnrEnterpriseUser', query: { certPicKey: CERT_PIC_STORAGE_KEY }})
},
/**
* 跳转到上一页
*/
handleToBefore() {
// 回退到上个页面
this.$router.back()
}
}
}
</script>
<style lang="scss">
.page-rnr-enterprise-idcard {
padding-bottom: 72px;
.page-rnr-main {
margin-top: 0px !important;
.rnr-idcard, .rnr-file {
padding: 48px 0;
}
}
.page-rnr-enterprise-idcard-tip {
font-size: 24px;
color: rgba(255, 255, 255, 0.6);
font-weight: 400;
padding: 14px 48px 18px;
}
}
</style>
<template>
<Page class="page-rnr-person-agreement" title="责任告知书">
<div class="page-rnr-main-card">
<van-loading v-if="!notificationUrl" class="global-loading" color="#0094ff" />
<Painter ref="painterRef" v-else>
<img crossOrigin :src="notificationUrl">
<img :src="signUrl" class="fixed-right">
</Painter>
</div>
<div class="page-rnr-sign-wrapper">
<div v-if="signUrl" class="page-rnr-sign-fill" @click="showSign = true">
<img :src="signUrl" class="page-rnr-sign-img">
<div class="page-rnr-sign-btn">重签</div>
</div>
<div v-else class="page-rnr-sign" @click="openSign">点击在此处签名</div>
</div>
<template #slot-operation>
<van-button type="primary" class="page-rnr-main-btn-before" round color="linear-gradient(120deg, #EDF3FF 0%, #E9F0FF 97%)" @click="handleToBefore">上一步</van-button>
<van-button :disabled="btnDisable" :loading="loading" type="primary" class="page-rnr-main-btn-next" round color="linear-gradient(120deg, #4F4CFB 0%, #376FF4 97%)" @click="handleToNext">下一步</van-button>
</template>
<Sign :visible.sync="showSign" @submit="handleSignChange" />
</Page>
</template>
<script>
import Painter from '@/components/Painter'
import { fileUpload } from '@/api/rnr'
import { SET_ENTERPRISE_DUTY_PIC, DISPATCH_INIT_PROTOCAL } from '@/store/modules/rnr'
import Page from '@/components/Page'
import signMixin from '@/minxin/sign'
import flowMixin from '@/minxin/flow'
export default {
name: 'RnrEnterpriseNotification',
components: { Page, Painter },
mixins: [flowMixin, signMixin],
data() {
return {
loading: false,
showSms: false,
notificationUrl: ''
}
},
async mounted() {
// 查询协议数据
await this.$store.dispatch(`rnr/${DISPATCH_INIT_PROTOCAL}`)
// 当前请求到的协议数据
const { protocal } = this.$store.getters
// 协议链接
this.notificationUrl = protocal[window.os.isTablet ? 'realnameNoticeVertical' : 'realnameNoticeHorizontal'].fileUrl
},
methods: {
/**
* 调到到下一页:腾讯的实名认证平台
*/
async handleToNext(formData) {
this.loading = true
try {
// 开始绘制canvas
const file = await this.$refs.painterRef.draw()
// 开始导出图片
const { uuid } = await fileUpload({ file })
// 开始保存数据
this.$store.commit(`rnr/${SET_ENTERPRISE_DUTY_PIC}`, {
dutyPic: [uuid]
})
// 跳转到
this.$router.push({ name: 'RnrEnterpriseAgreement' })
} catch (error) {
console.error(error)
}
this.loading = false
},
/**
* 跳转到上一页
*/
handleToBefore() {
// 回退到上个页面
this.$router.back()
}
}
}
</script>
<style lang="scss">
@import "../rnr.scss";
.page-rnr-person-agreement {
.page-rnr-main {
margin-top: 30px;
.page-rnr-main-card {
padding: 24px 24px 168px;
height: calc(100vh - 450px);
overflow: auto;
.page-rnr-main-canvas {
width: 100%;
}
}
.page-rnr-sign-wrapper {
background: #ffffff;
bottom: 196px;
padding: 24px 32px;
position: fixed;
left: 24px;
right: 24px;
.page-rnr-sign {
align-items: center;
background: #F7F8FA;
border: 1px dashed rgba(7, 97, 243, 1);
border-radius: 12px;
color: #0761F3;
display: flex;
font-size: 24px;
font-weight: 400;
height: 120px;
justify-content: center;
}
.page-rnr-sign-fill {
align-items: center;
background: #F7F8FA;
border-radius: 12px;
bottom: 148px;
display: flex;
height: 120px;
justify-content: space-between;
padding: 0px 48px 0px 132px;
.page-rnr-sign-img {
width: auto;
height: 100px;
}
.page-rnr-sign-btn {
color: #0761F3;
font-size: 24px;
font-weight: 400;
}
}
}
.page-rnr-main-fixed-btn-group {
display: flex;
justify-content: space-between;
.page-rnr-main-btn-before {
color: #242424 !important;
flex: 1;
height: 96px;
}
.page-rnr-main-btn-next {
flex: 2;
margin-left: 40px;
height: 96px;
}
}
}
}
</style>
<template>
<Page class="page-rnr-enterprise-file" title="责任人证件信息">
<template #slot-before-main>
<div class="page-rnr-person-file-tip">文件类型为图片文件,允许支持的照片格式包括bmp、jpg/jpeg、png,小于500K。</div>
</template>
<div class="page-rnr-main-card">
<ErrorWrap :error-message="inputError.certPic" :error="!!inputError.certPic">
<van-cell id="contractPic" :required="true" title="证件信息" class="van-field">
<template #label>
<BridgeUpload
:max-count="3"
:compress="{}"
:security="true"
v-model="formData.certPic"
>
<div class="page-rnr-main-card-upload-normal">
<div class="icon-upload-camera" />
</div>
</BridgeUpload>
</template>
</van-cell>
</ErrorWrap>
</div>
<template #slot-operation>
<van-button type="primary" class="page-rnr-main-btn-before" round color="linear-gradient(120deg, #EDF3FF 0%, #E9F0FF 97%)" @click="handleToBefore">上一步</van-button>
<van-button type="primary" class="page-rnr-main-btn-next" round color="linear-gradient(120deg, #4F4CFB 0%, #376FF4 97%)" @click="handleToNext">下一步</van-button>
</template>
</Page>
</template>
<script>
import Page from '@/components/Page'
import ErrorWrap from '@/components/ErrorWrap'
import BridgeUpload from '@/components/BridgeUpload'
import { validate } from '@/utils/validate'
import { SET_ENTERPRISE_PAPER } from '@/store/modules/rnr'
export default {
name: 'RnrEnterprisePaper',
components: { Page, BridgeUpload, ErrorWrap },
data() {
const { customerType } = this.$store.getters.personRnr
return {
inputError: {},
countTime: 59,
isSend: false,
showSms: false,
customerType,
formData: {
certPic: []
}
}
},
methods: {
/**
* 调到到下一页:腾讯的实名认证平台
*/
handleToNext() {
// 校验不通过的字段
const failFiled = this.validate()
// 如果当前有字段没校验通过
if (failFiled) {
return
}
// 证件照片
const { certPic } = this.formData
// 保存到store中
this.$store.commit(`rnr/${SET_ENTERPRISE_PAPER}`, { corporationPhotoPic: certPic })
// 开始跳转页面
this.$router.push({ name: 'RnrEnterpriseFile' })
},
/**
* 校验用户输入
*/
validate(ruleKeys = ['certPic']) {
// 错误的字段,错误的信息
const [failField, failMessage] = validate(this.formData, ruleKeys)
// 如果当前有错误信息
ruleKeys.forEach(key => {
this.$set(this.inputError, key, failField === key ? failMessage : '')
})
return failField
},
/**
* 跳转到上一页
*/
handleToBefore() {
// 回退到上个页面
this.$router.back()
}
}
}
</script>
<style lang="scss">
.page-rnr-enterprise-file {
.page-rnr-main {
margin-top: 0px !important;
}
.page-rnr-main-fixed-btn-group {
display: flex;
justify-content: space-between;
.page-rnr-main-btn-before {
color: #242424 !important;
flex: 1;
height: 96px;
}
.page-rnr-main-btn-next {
flex: 2;
margin-left: 40px;
height: 96px;
}
}
.icon-upload-camera {
background-image: url(../../../assets/rnr/ico_camera.png);
background-size: 100% 100%;
position: absolute;
width: 80px;
height: 80px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.page-rnr-main-card-upload-normal {
background-image: url(../../../assets/rnr/ico_pic.png);
background-color: #F7F8FA;
background-size: 196px 196px;
background-repeat: no-repeat;
background-position: center;
border-radius: 8px;
width: 196px;
height: 196px;
}
.page-rnr-main-btn {
font-size: 32px !important;
&.disabled {
color: #CACACA !important;
}
}
.van-cell__label {
.page-rnr-flex {
display: flex;
justify-content: space-between;
}
}
.page-rnr-person-file-tip {
font-size: 24px;
color: rgba(255, 255, 255, 0.6);
font-weight: 400;
padding: 14px 48px 18px;
}
.van-dialog {
box-sizing: border-box;
width: 685px;
padding: 0 40px 50px;
.van-dialog__header {
padding: 60px 0 12px;
}
.van-field__button {
padding-left: 30px;
.page-rnr-main-btn {
color: #0761F3;
font-size: 32px;
font-weight: 400;
}
}
.page-rnr-main-btn-confirm {
margin-top: 44px;
}
}
}
</style>
<template>
<van-loading v-if="status === STATUS.PENDING" vertical color="#0094ff" class="loading-container">加载中...</van-loading>
<section v-else class="page-rnr-enterprise">
<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="page-rnr-main-fixed-btn-group">
<van-button v-if="status === STATUS.TX_VALID_FAIL" type="primary" class="page-rnr-main-btn-next" round block color="linear-gradient(120deg, #4F4CFB 0%, #376FF4 97%)" @click="handleToTxVerify">重新认证</van-button>
<van-button v-else type="primary" class="page-rnr-main-btn-next" round block color="linear-gradient(120deg, #4F4CFB 0%, #376FF4 97%)" @click="handleToNextPage(status === STATUS.FAIL ? 'RnrEnterpriseCard' : 'Home')">{{ status === STATUS.FAIL ? '重新认证' : '返回首页' }}</van-button>
</div>
</section>
</template>
<script>
import { enterpriseLivenessCallback } from '@/api/rnr'
// 状态
const STATUS = {
// 加载中
PENDING: -1,
// 腾讯活体认证失败
TX_VALID_FAIL: 2,
// 成功
SUCCESS: 0,
// 人工审核中
MAN_WORK: 1,
// 失败
FAIL: 3
}
export default {
name: 'RnrEnterpriseResult',
data() {
return {
STATUS,
status: STATUS.PENDING,
h5LivenessUrl: ''
}
},
activated() {
// 开始提交实名信息
this.fetchSubmitRnr(this.$route.query)
},
methods: {
/**
* 提交实名认证的接口
*/
async fetchSubmitRnr(query) {
try {
// 开始提交数据
const { status, h5LivenessUrl } = await enterpriseLivenessCallback(this.$route.query)
// 标记当前提交成功
this.status = status
// h5活体验证的链接
this.h5LivenessUrl = h5LivenessUrl
return
} catch (error) {
console.error(error)
}
// 标记当前提交失败
this.status = STATUS.FAIL
},
/**
* 跳转到活体认证
*/
handleToTxVerify() {
// 跳转到活体认证页面
window.location.href = this.h5LivenessUrl
},
/**
* 跳转到下一个页面
* @param pageName 页面名称
*/
handleToNextPage(pageName) {
this.$router.push({ name: pageName })
}
}
}
</script>
<style lang="scss">
.page-rnr-enterprise {
.page-rnr-result-content {
padding-top: 72px;
.page-rnr-result-icon {
background-size: 100% 100%;
background-repeat: no-repeat;
width: 648px;
height: 490px;
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;
}
}
}
.loading-container {
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
position: fixed;
}
</style>
<template>
<Page title="责任人身份信息">
<UserInfo ref="userRef" :cert-type="enterpriseRnr.corporationCertType" />
<template #slot-operation>
<van-button type="primary" class="page-rnr-main-btn-before" round color="linear-gradient(120deg, #EDF3FF 0%, #E9F0FF 97%)" @click="handleToBefore">上一步</van-button>
<van-button type="primary" class="page-rnr-main-btn-next" round color="linear-gradient(120deg, #4F4CFB 0%, #376FF4 97%)" @click="handleToNext">下一步</van-button>
</template>
</Page>
</template>
<script>
import { mapGetters } from 'vuex'
import { SET_ENTERPRISE_OWNER } from '@/store/modules/rnr'
import Page from '@/components/Page'
import UserInfo from '@/components/UserInfo'
export default {
name: 'RnrEnterpriseUser',
components: { Page, UserInfo },
computed: {
...mapGetters(['enterpriseRnr'])
},
methods: {
/**
* 跳转到上一页
*/
handleToBefore() {
// 回退到上个页面
this.$router.back()
},
/**
* 跳转到首页
*/
handleToHome() {
this.$router.push({ name: 'Home' })
},
handleToNext() {
// 开始校验
try {
const formData = this.$refs.userRef.validate()
// 将值塞到缓存中
this.$store.commit(
`rnr/${SET_ENTERPRISE_OWNER}`,
Object.keys(formData).reduce((memo, key) => {
if (key === 'fullName') {
memo['corporationName'] = formData[key]
} else {
const alias = `corporation${key.slice(0, 1).toUpperCase() + key.slice(1)}`
memo[alias] = formData[key]
}
return memo
}, {})
)
// 开始跳转页面
this.$router.push({ name: 'RnrEnterpriseFile' })
} catch (error) {
console.error(error)
}
}
}
}
</script>
<style lang="scss">
.page-rnr-main-fixed-btn-group {
display: flex;
justify-content: space-between;
.page-rnr-main-btn-before {
color: #242424 !important;
flex: 1;
height: 96px;
}
.page-rnr-main-btn-next {
flex: 2;
margin-left: 40px;
height: 96px;
}
}
</style>
<template>
<Page class="page-rnr-person-agreement">
<template #slot-title>
<span>{{ currentFlow }}/{{ totalFlow }}</span>
<span>入网协议</span>
</template>
<div class="page-rnr-main-card">
<van-loading v-if="!notificationUrl" class="global-loading" color="#0094ff" />
<Painter ref="painterRef" v-else>
<img crossOrigin :src="notificationUrl">
<img :src="signUrl" class="fixed-right">
<h1>* 附件</h1>
<p>VIN: {{ personRnr.vin }}</p>
<p>ICCID: {{ (personRnr.iccidList || []).join(', ') }}</p>
</Painter>
</div>
<div class="page-rnr-sign-wrapper">
<div v-if="signUrl" class="page-rnr-sign-fill" @click="showSign = true">
<img :src="signUrl" class="page-rnr-sign-img">
<div class="page-rnr-sign-btn">重签</div>
</div>
<div v-else class="page-rnr-sign" @click="showSign = true">点击在此处签名</div>
</div>
<template #slot-operation>
<van-button type="primary" class="page-rnr-main-btn-before" round color="linear-gradient(120deg, #EDF3FF 0%, #E9F0FF 97%)" @click="handleToBefore">上一步</van-button>
<van-button :disabled="btnDisable" :loading="loading" type="primary" class="page-rnr-main-btn-next" round color="linear-gradient(120deg, #4F4CFB 0%, #376FF4 97%)" @click="handleOpenSms">下一步</van-button>
</template>
<Sign :visible.sync="showSign" @submit="handleSignChange" />
<PhoneVerify :visible.sync="showSms" :loading="loading" @submit="handleToNext" />
</Page>
</template>
<script>
import Painter from '@/components/Painter'
import { mapGetters } from 'vuex'
import cache from '@/utils/cache'
import { DISPATCH_INIT_PROTOCAL } from '@/store/modules/rnr'
import signMixin from '@/minxin/sign'
import flowMixin from '@/minxin/flow'
import Page from '@/components/Page'
import PhoneVerify from '@/components/PhoneVerify'
import { fileUpload, submitRnr } from '@/api/rnr'
export default {
name: 'RnrPersonAgreement',
components: { Page, PhoneVerify, Painter },
mixins: [signMixin, flowMixin],
data() {
return {
loading: false,
showSms: false,
contractPic: [],
notificationUrl: ''
}
},
computed: {
...mapGetters(['personRnr'])
},
async mounted() {
// 查询协议数据
await this.$store.dispatch(`rnr/${DISPATCH_INIT_PROTOCAL}`)
// 当前请求到的协议数据
const { protocal } = this.$store.getters
// 协议链接
this.notificationUrl = protocal[window.os.isTablet ? 'peopleAgreementVertical' : 'peopleAgreementHorizontal'].fileUrl
},
methods: {
/**
* 调到到下一页:腾讯的实名认证平台
*/
async handleToNext(formData) {
// 呈现loading状态
this.loading = true
try {
// 取出数据
let personRnr = this.$store.getters.personRnr || {}
// 如果当前是委托人
if (personRnr.isConsigner) {
personRnr.consignerInfo = {
...personRnr.consignerInfo,
...formData
}
} else {
personRnr = {
...personRnr,
...formData
}
}
// 开始提交数据
const { h5LivenessUrl } = await submitRnr({
...personRnr,
contractPic: this.contractPic
})
// 将当前实名的值塞到缓存中
cache.set('rnr-result-condition', {
customerType: personRnr.customerType,
isConsigner: personRnr.isConsigner ? 1 : 0
})
// 跳转到活体认证页面
window.location.href = h5LivenessUrl
} catch (error) {
console.error(error)
}
// 关闭loading状态
this.loading = false
},
/**
* 打开协议管理
*/
async handleOpenSms() {
// 展示loading框
this.loading = true
try {
// 开始绘制canvas
const file = await this.$refs.painterRef.draw()
// 开始导出图片
const { uuid } = await fileUpload({ file })
// 记录当前照片
this.contractPic = [uuid]
// 展示短信验证码
this.showSms = true
} catch (error) {
console.error(error)
}
this.loading = false
},
/**
* 跳转到上一页
*/
handleToBefore() {
// 回退到上个页面
this.$router.back()
}
}
}
</script>
<style lang="scss">
@import "../rnr.scss";
.page-rnr-person-agreement {
.page-rnr-main {
margin-top: 30px;
.page-rnr-main-card {
padding: 24px 24px 168px;
height: calc(100vh - 450px);
overflow: auto;
.page-rnr-main-canvas {
width: 100%;
}
}
.page-rnr-sign-wrapper {
background: #ffffff;
bottom: 196px;
padding: 24px 32px;
position: fixed;
left: 24px;
right: 24px;
.page-rnr-sign {
align-items: center;
background: #F7F8FA;
border: 1px dashed rgba(7, 97, 243, 1);
border-radius: 12px;
color: #0761F3;
display: flex;
font-size: 24px;
font-weight: 400;
height: 120px;
justify-content: center;
}
.page-rnr-sign-fill {
align-items: center;
background: #F7F8FA;
border-radius: 12px;
bottom: 148px;
display: flex;
height: 120px;
justify-content: space-between;
padding: 0px 48px 0px 132px;
.page-rnr-sign-img {
width: auto;
height: 100px;
}
.page-rnr-sign-btn {
color: #0761F3;
font-size: 24px;
font-weight: 400;
}
}
}
.page-rnr-main-fixed-btn-group {
display: flex;
justify-content: space-between;
.page-rnr-main-btn-before {
color: #242424 !important;
flex: 1;
height: 96px;
}
.page-rnr-main-btn-next {
flex: 2;
height: 96px;
}
}
}
}
</style>
<template>
<Page class="page-rnr-person-base">
<template #slot-title>
<span>{{ currentFlow }}/{{ totalFlow }}</span>
<span>身份信息</span>
</template>
<UserInfo :value="formData" :cert-type="personRnr.certType" :show-phone="personRnr.isConsigner" ref="userRef" type="bluetooth" />
<template slot="slot-operation">
<van-button type="primary" class="page-rnr-main-btn-before" round color="linear-gradient(120deg, #EDF3FF 0%, #E9F0FF 97%)" @click="handleToBefore">上一步</van-button>
<van-button type="primary" class="page-rnr-main-btn-next" round color="linear-gradient(120deg, #4F4CFB 0%, #376FF4 97%)" @click="handleToNext">下一步</van-button>
</template>
</Page>
</template>
<script>
import { mapGetters } from 'vuex'
import Page from '@/components/Page'
import UserInfo from '@/components/UserInfo'
import flowMixin from '@/minxin/flow'
import { SET_PERSON_CARD } from '@/store/modules/rnr'
export default {
name: 'RnrPersonBase',
components: { Page, UserInfo },
mixins: [flowMixin],
data() {
return {
isConnect: false,
formData: {
certAddress: '',
certExpirationDate: '',
certNumber: '',
contactAddress: '',
fullName: '',
gender: ''
}
}
},
computed: {
...mapGetters(['isNFCDevice', 'personRnr'])
},
methods: {
/**
* 调到到下一页:腾讯的实名认证平台
*/
handleToNext() {
// 校验不通过的字段
try {
const formData = this.$refs.userRef.validate()
// 将当前数据保存到store中
this.$store.commit(`rnr/${SET_PERSON_CARD}`, formData)
// 取出当前是否是委托人字段
const { isConsigner, customerType } = this.$store.getters.personRnr
// 如果当前是委托人,则跳转到委托人
if (isConsigner) {
// 跳转到支付结果页
this.routerToNextPage('RnrPersonConsignerIdcard')
return
}
// 如果当前是二手车,则跳转到文件上传页,如果当前是新车,则直接去责任告知书
this.routerToNextPage(customerType === 1 ? 'RnrPersonFile' : 'RnrPersonNotification')
} catch (error) {
console.error('校验失败:', error)
}
},
/**
* 跳转到上一页
*/
handleToBefore() {
// 回退到上个页面
this.$router.back()
}
}
}
</script>
<style lang="scss">
.page-rnr-person-base {
.page-rnr-main-card {
.page-rnr-person-base-icon-idcard-reader {
background-image: url(../../../assets/rnr/ico_idcard_reader.png);
background-size: 100% 100%;
width: 654px;
height: 272px;
margin: 0 auto;
}
.page-rnr-person-base-step {
color: #242424;
font-size: 24px;
text-align: center;
font-weight: 400;
line-height: 34px;
margin-top: 10px;
&:first-child {
margin-top: 20px;
}
}
.page-rnr-person-base-btn-wrap {
margin-top: 56px;
.van-button {
font-size: 30px;
.page-rnr-person-base-icon-bluetooth {
background-image: url(../../../assets/rnr/ico_bluetooth.png);
background-size: 100% 100%;
display: inline-block;
width: 30px;
height: 30px;
margin-right: 12px;
margin-bottom: -4px;
}
}
.page-rnr-person-base-btn-block {
align-items: center;
border-radius: 50%;
color: #0761F3;
display: flex;
font-size: 30px;
height: 88px;
justify-content: center;
margin-top: 24px;
.page-rnr-person-base-icon-switch {
background-image: url(../../../assets/rnr/ico_switch.png);
background-size: 100% 100%;
display: inline-block;
width: 30px;
height: 30px;
margin-right: 12px;
margin-bottom: -4px;
}
}
}
&.base-intro {
padding: 26px 24px 40px !important;
}
}
.page-rnr-main-fixed-btn-group {
display: flex;
justify-content: space-between;
.page-rnr-main-btn-before {
color: #242424 !important;
flex: 1;
height: 96px;
}
.page-rnr-main-btn-next {
flex: 2;
margin-left: 40px;
height: 96px;
}
}
.van-cell__label {
.page-rnr-flex {
display: flex;
justify-content: space-between;
}
}
}
</style>
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