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
import Big from 'big.js'
import fecha from 'element-ui/src/utils/date'
/**
* Created by PanJiaChen on 16/11/18.
*/
/**
* Parse the time to string
* @param {(Object|string|number)} time
* @param {string} cFormat
* @returns {string | null}
*/
export function parseTime(time, cFormat) {
if (arguments.length === 0 || !time) {
return null
}
const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
let date
if (typeof time === 'object') {
date = time
} else {
if ((typeof time === 'string')) {
if ((/^[0-9]+$/.test(time))) {
// support "1548221490638"
time = parseInt(time)
} else {
// support safari
// https://stackoverflow.com/questions/4310953/invalid-date-in-safari
time = time.replace(new RegExp(/-/gm), '/')
}
}
if ((typeof time === 'number') && (time.toString().length === 10)) {
time = time * 1000
}
date = new Date(time)
}
const formatObj = {
y: date.getFullYear(),
m: date.getMonth() + 1,
d: date.getDate(),
h: date.getHours(),
i: date.getMinutes(),
s: date.getSeconds(),
a: date.getDay()
}
const time_str = format.replace(/{([ymdhisa])+}/g, (result, key) => {
const value = formatObj[key]
// Note: getDay() returns 0 on Sunday
if (key === 'a') { return ['', '', '', '', '', '', ''][value ] }
return value.toString().padStart(2, '0')
})
return time_str
}
/**
* @param {number} time
* @param {string} option
* @returns {string}
*/
export function formatTime(time, option) {
if (('' + time).length === 10) {
time = parseInt(time) * 1000
} else {
time = +time
}
const d = new Date(time)
const now = Date.now()
const diff = (now - d) / 1000
if (diff < 30) {
return '刚刚'
} else if (diff < 3600) {
// less 1 hour
return Math.ceil(diff / 60) + '分钟前'
} else if (diff < 3600 * 24) {
return Math.ceil(diff / 3600) + '小时前'
} else if (diff < 3600 * 24 * 2) {
return '1天前'
}
if (option) {
return parseTime(time, option)
} else {
return (
d.getMonth() +
1 +
'' +
d.getDate() +
'' +
d.getHours() +
'' +
d.getMinutes() +
''
)
}
}
/**
* @param {string} url
* @returns {Object}
*/
export function param2Obj(url) {
const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ')
if (!search) {
return {}
}
const obj = {}
const searchArr = search.split('&')
searchArr.forEach(v => {
const index = v.indexOf('=')
if (index !== -1) {
const name = v.substring(0, index)
const val = v.substring(index + 1, v.length)
obj[name] = val
}
})
return obj
}
/**
* 检查是否为数字
* @param {any} str 待检查数据
* @return {boolean} true表示是有效的数字;false表示不是有效的数字
*/
export function isNum(str) {
const checkStr = String(str)
if (checkStr === '') {
return false
}
const reg = /^[-+]?\d*(?:\.\d+)?$/i
return reg.test(checkStr)
}
/**
* 格式化数字为金额格式
* @param {string|number} num 数字
* @param {string} thousandSep 千分隔符
* @param {string} fixed 保留的小数位数
* @param {number} roundMode 舍入模式
* @return {any} 格式化后的数字
*/
export function formatNum(num, thousandSep = ',', fixed = 2, roundMode = Big.roundDown) {
if (!isNum(num)) {
return num
}
const str = String(num)
const firstChar = str[0]
const sign = (firstChar === '+' || firstChar === '-' ? firstChar : '')
const handleStr = sign ? str.substring(1) : str
const bigInst = new Big(handleStr)
const fixedStr = bigInst.toFixed(fixed, roundMode)
const arr = fixedStr.split('.')
const zs = arr[0]
const xs = arr[1] || ''
const reg = /(\d)(?=(\d{3})+$)/g
const zsFmt = zs.replace(reg, `$1${thousandSep}`)
const xsFmt = xs ? `.${xs}` : ''
const completeFmt = `${sign}${zsFmt}${xsFmt}`
return completeFmt
}
/**
* 触发浏览器下载文件
* @param {Blob} blob 文件对象
* @param {string} fileName 文件名
*/
export function saveBlob(blob, fileName) {
const a = document.createElement('a')
a.style = 'display:none;'
document.body.appendChild(a)
const fileUrl = window.URL.createObjectURL(blob)
a.href = fileUrl
a.download = fileName
a.click()
window.URL.revokeObjectURL(fileUrl)
document.body.removeChild(a)
}
/**
* 解析日期字条串为日期对象
* @param {string} str 日期字符串
* @param {string} fmt 日期格式
* @return {obj} 日期对象
*/
export function parseDate(str, fmt) {
return fecha.parse(str, fmt)
}
/**
* 检查日期范围在指定的天数内
* @param {string} beginDate 开始日期字符串
* @param {string} beginDateFmt 开始日期格式字符串
* @param {string} endDate 结束日期字符串
* @param {string} endDateFmt 结束日期格式字符串
* @param {number} max 两个日期相隔的最大天数
* @return {boolean} true两个日期相隔的天数小于等于max;false两个日期相隔的天数大于max
*/
export function checkTimeRange(beginDate, beginDateFmt, endDate, endDateFmt, max) {
const start = parseDate(beginDate, beginDateFmt)
const stop = parseDate(endDate, endDateFmt)
const days = (stop.getTime() - start.getTime()) / (24 * 60 * 60 * 1000)
return days <= max
}
/**
* 检查值是否不为空
* @param {*} val
* @return {boolean} true不为空;false为空
*/
export function isNotBlank(val) {
return val !== null && val !== undefined && val !== '' && !isNaN(val)
}
export default class NiceScale {
constructor(min, max, maxTicks = 10) {
this.min = min
this.max = max
this.maxTicks = maxTicks
this.niceMin = 0
this.niceMax = 0
this.tickSpacing = 0
this.calculate()
}
calculate() {
const range = this.niceNum(this.max - this.min, false)
const tickSpacing = this.niceNum(range / (this.maxTicks - 1), true)
this.niceMin = Math.floor(this.min / tickSpacing) * tickSpacing
this.niceMax = Math.ceil(this.max / tickSpacing) * tickSpacing
this.tickSpacing = tickSpacing
}
niceNum(x, round) {
// exponent of x
const exponent = Math.floor(Math.log10(x))
// fractional part of x
const fraction = x / Math.pow(10, exponent)
// nice, rounded fraction
let niceFraction
if (round) {
if (fraction < 1.5) {
niceFraction = 1
} else if (fraction < 3) {
niceFraction = 2
} else if (fraction < 7) {
niceFraction = 5
} else {
niceFraction = 10
}
} else {
if (fraction <= 1) {
niceFraction = 1
} else if (fraction <= 2) {
niceFraction = 2
} else if (fraction <= 5) {
niceFraction = 5
} else {
niceFraction = 10
}
}
return niceFraction * Math.pow(10, exponent)
}
}
window.OS = (() => {
const ua = navigator.userAgent
const isWindowsPhone = /(?:Windows Phone)/.test(ua)
const isSymbian = /(?:SymbianOS)/.test(ua) || isWindowsPhone
const isAndroid = /(?:Android)/.test(ua)
const isFireFox = /(?:Firefox)/.test(ua)
const isChrome = /(?:Chrome|CriOS)/.test(ua)
const isTablet = /(?:iPad|PlayBook)/.test(ua) || (isAndroid && !/(?:Mobile)/.test(ua)) || (isFireFox && /(?:Tablet)/.test(ua))
const isPhone = /(?:iPhone)/.test(ua) && !isTablet
const isPc = !isPhone && !isAndroid && !isSymbian
return {
isTablet,
isPhone,
isAndroid,
isPc,
isChrome
}
})()
export const pickerOptions = {
shortcuts: [
{
text: '最近一天',
onClick(picker) {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24)
picker.$emit('pick', [start, end])
}
},
{
text: '最近三天',
onClick(picker) {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 3)
picker.$emit('pick', [start, end])
}
},
{
text: '最近一周',
onClick(picker) {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
picker.$emit('pick', [start, end])
}
}
]
}
import axios from 'axios'
import axiosRetry from 'axios-retry'
import contentDisposition from 'content-disposition'
import { Message } from 'element-ui'
import { getToken } from '@/utils/auth' // get token from cookie
import { saveBlob } from '@/utils/index'
import bridge, { isInApp } from '@/utils/bridge'
import store from '@/store'
axiosRetry(axios, {
retries: 3,
retryDelay: (retryCount) => 500 * retryCount,
retryCondition: (error) => error.message === 'Network Error' || error.code === 'ECONNABORTED' || false
})
const ajax = function(options) {
const NODE_ENV = process.env.NODE_ENV
const BASE_API = process.env.VUE_APP_BASE_API
const token = getToken()
const defaults = {
responseType: 'json',
method: 'post',
baseURL: BASE_API,
url: '',
data: {},
timeout: 30000,
withCredentials: true,
hideToast: false,
headers: {
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'application/json;charset=utf-8',
'Authorization': `bearer ${token}`
},
transformResponse: [
function(data) {
try {
return JSON.parse(data)
} catch (error) {
return data
}
}
]
}
if (!token) {
delete defaults.headers.Authorization
}
const clone = (target) => {
if (Object.prototype.toString.call(target) === '[object Object]' || Object.prototype.toString.call(target) === '[object Array]') {
const result = Array.isArray(target) ? [] : {}
for (const key in target) {
result[key] = clone(target[key])
}
return result
// 过滤入参前后空格
} else if (typeof target === 'string') {
return target.replace(/(^\s*)|(\s*$)/g, '')
} else {
return target
}
}
options = { ...defaults, ...options }
options.data = options.data ? clone(options.data) : {}
if (NODE_ENV !== 'production') {
console.log(JSON.stringify(options.data))
const url = options.url.indexOf('http') === 0 ? options.url : `${BASE_API}${options.url}`
console.log(`%c ${url}`, 'color: #207928')
}
return new Promise((resole, reject) => {
let data = {}
let code = 0
let message = ''
axios(options)
.then((response) => {
const json = response.data || {}
data = json.data || {}
code = json.code
message = json.msg || '接口异常,请稍后再试.'
// 文件下载
if (options.responseType === 'blob') {
const disposition = response.headers['content-disposition']
let fileName = 'default'
let cdResult = null
try {
cdResult = contentDisposition.parse(disposition)
} catch (e) {
console.log(e)
}
if (cdResult && cdResult.parameters && cdResult.parameters.filename) {
fileName = decodeURI(cdResult.parameters.filename)
}
const fileType = response.headers['content-type']
const fileData = new Blob([json], { type: fileType })
// 如果在app中,调用bridge下载
if (isInApp) {
const fileReader = new FileReader()
fileReader.onload = (e) => {
const base64 = e.target.result
bridge.saveFileByBase64(base64.slice(base64.indexOf(';base64,') + 8), fileName)
}
// readAsDataURL
fileReader.readAsDataURL(fileData)
fileReader.onerror = () => {
reject(new Error('blobToBase64 error'))
}
} else {
saveBlob(fileData, fileName)
}
resole(json)
return false
}
if (NODE_ENV === 'development' || NODE_ENV === 'debug') {
console.log(json)
} else if (NODE_ENV !== 'production') {
console.log(JSON.stringify(json, null, 2))
}
if (json.success) {
resole(data)
} else if (code === 1101 || code === 1102 || code === 1103 || code === 1104) {
// 1101 token无效或已过期
// 1102 已在其他终端登录 强制下线
// 1103 用户冻结 强制下线
// 1104 权限变更等原因 强制下线
store.dispatch('user/resetToken').then(() => {
window.location.href = `${process.env.VUE_APP_ROUTER}login?redirect=${encodeURIComponent(window.location.href)}`
})
} else {
reject({ code, message })
// hideToast=true或用户信息失效不展示报错信息
if (options.hideToast || options.url.indexOf('user/eiam/user/getCurrUserInfo') >= 0) {
return
}
Message({ message, type: 'error', duration: 3 * 1000 })
}
})
.catch((error) => {
if (NODE_ENV !== 'production') {
console.log(error.message)
}
if (error.response) {
code = error.response.status
message = error.response.statusText || error.response.data && error.response.data.msg
} else if (error.request && error.message === 'Network Error') {
// 网络异常
message = '连接似乎有问题,请检查网络.'
} else if (error.request && error.code === 'ECONNABORTED') {
// 请求超时
message = '接口异常,请稍后再试.'
} else if (error.__CANCEL__) {
// 取消请求
message = 'cancel request'
code = '_CANCEL_REQUEST_'
} else {
message = 'params setting error'
}
reject({ code, message })
if (options.hideToast) {
return
}
Message({ message, type: 'error', duration: 3 * 1000 })
})
})
}
export default ajax
const SM4 = require('gm-crypt').sm4
export function getJMJqueryParams(params, key) {
if (typeof (params) === 'undefined') {
params = null
}
const sm4Config = {
// 配置sm4参数
key, // 这里这个key值是跟后端要的
mode: 'ecb', // 加密的方式有两种,ecb和cbc两种,也是看后端如何定义的,不过要是cbc的话下面还要加一个iv的参数,ecb不用
cipherType: 'base64'
}
const sm4 = new SM4(sm4Config)
const encryptData = sm4.encrypt(params)
return encryptData.trim()
}
import request from './request'
import { ocrIdcard } from '@/api/user'
/**
* base64转文件流
* @param code 当前base编码
*/
const base64ToBlob = function(code) {
const parts = code.split(';base64,')
const contentType = parts[0].split(':')[1]
const raw = window.atob(parts[1])
const rawLength = raw.length
const uInt8Array = new Uint8Array(rawLength)
for (let i = 0; i < rawLength; ++i) {
uInt8Array[i] = raw.charCodeAt(i)
}
return new Blob([uInt8Array], {
type: contentType
})
}
/**
* 获取加密的图片原件
* @param uuid 文件id
* @returns 图片base64
*/
export const imageViewer = async(uuid) => {
const { base64 } = await request({
url: `${process.env.VUE_APP_BASIC_API}cuscImage/viewBase64`,
data: { uuid }
})
return URL.createObjectURL(base64ToBlob(`data:${uuid.indexOf('.mp4') ? 'video/mp4' : 'image/png'};base64,${base64}`))
}
/**
* 通过OCR获取身份证信息
* @param file 当前文件
*/
export const getIdcardInfoByOcr = file => {
// 获取FileReader实例
var reader = new FileReader()
// 读取文件
reader.readAsDataURL(file)
// 返回值
return new Promise((resolve, reject) => {
// 文件读取成功转换成base64
reader.onload = async function() {
// 转换完成输出该文件base64编码
const idcardInfo = await ocrIdcard({
ocrPic: this.result.slice(this.result.indexOf('base64,') + 7)
})
// 性别
idcardInfo.gender = idcardInfo.gender === '' ? '1' : '2'
// 数据回填
resolve(idcardInfo)
}
})
}
/**
* Created by PanJiaChen on 16/11/18.
*/
/**
* @param {string} path
* @returns {Boolean}
*/
export function isExternal(path) {
return /^(https?:|mailto:|tel:)/.test(path)
}
/**
* @param {string} str
* @returns {Boolean}
*/
export function validUsername(str) {
const valid_map = ['admin', 'editor']
return valid_map.indexOf(str.trim()) >= 0
}
export function validMail(str) {
return /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/.test(str)
}
export function validPhone(str) {
return /^1[0-9]{10}$/.test(str)
}
export function validId(idStr) {
const sId = String(idStr)
if (!/(^\d{15}$)|(^\d{17}(\d|X|x)$)/.test(sId)) {
return false
}
// 身份证省编码
const provinceCode = {
11: '北京',
12: '天津',
13: '河北',
14: '山西',
15: '内蒙古',
21: '辽宁',
22: '吉林',
23: '黑龙江',
31: '上海',
32: '江苏',
33: '浙江',
34: '安徽',
35: '福建',
36: '江西',
37: '山东',
41: '河南',
42: '湖北',
43: '湖南',
44: '广东',
45: '广西',
46: '海南',
50: '重庆',
51: '四川',
52: '贵州',
53: '云南',
54: '西藏',
61: '陕西',
62: '甘肃',
63: '青海',
64: '宁夏',
65: '新疆',
71: '台湾',
81: '香港',
82: '澳门',
91: '国外'
}
if (!provinceCode[sId.substring(0, 2)]) {
return false
}
// 出生日期验证
const yearStr = sId.substring(6, 10)
const monthStr = sId.substring(10, 12)
const dayStr = sId.substring(12, 14)
const dateObj = new Date(yearStr, monthStr - 1, dayStr)
const inputDateStr = `${yearStr}-${monthStr}-${dayStr}`
const calcuMonth = (dateObj.getMonth() + 1) >= 10 ? (dateObj.getMonth() + 1) : `0${dateObj.getMonth() + 1}`
const calcuDate = dateObj.getDate() >= 10 ? dateObj.getDate() : `0${dateObj.getDate()}`
const calcuDateStr = `${dateObj.getFullYear()}-${calcuMonth}-${calcuDate}`
if (inputDateStr !== calcuDateStr) {
return false
}
// 校验码校验
let sum = 0
const weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
const codes = '10X98765432'
for (let i = 0; i < sId.length - 1; i++) {
sum += sId[i] * weights[i]
}
const last = codes[sum % 11] // 计算出来的最后一位身份证号码
if (sId[sId.length - 1] !== last) {
return false
}
return true
}
<template>
<div class="wscn-http404-container">
<div class="wscn-http404">
<div class="pic-404">
<img :src="require('@/assets/404_images/404.png')" class="pic-404__parent" alt="404">
<img :src="require('@/assets/404_images/404_cloud.png')" class="pic-404__child left" alt="404">
<img :src="require('@/assets/404_images/404_cloud.png')" class="pic-404__child mid" alt="404">
<img :src="require('@/assets/404_images/404_cloud.png')" class="pic-404__child right" alt="404">
</div>
<div class="bullshit">
<div class="bullshit__oops">OOPS!</div>
<div class="bullshit__headline">{{ message }}</div>
<div class="bullshit__info">Please check that the URL you entered is correct, or click the button below to return to the homepage.</div>
<a :href="home" class="bullshit__return-home">Back to home</a>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'Page404',
data() {
return {
home: process.env.VUE_APP_STATIC
}
},
computed: {
message() {
return 'The webmaster said that you can not enter this page...'
}
}
}
</script>
<style lang="scss" scoped>
.wscn-http404-container{
transform: translate(-50%,-50%);
position: absolute;
top: 40%;
left: 50%;
}
.wscn-http404 {
position: relative;
width: 1200px;
padding: 0 50px;
overflow: hidden;
.pic-404 {
position: relative;
float: left;
width: 600px;
overflow: hidden;
&__parent {
width: 100%;
}
&__child {
position: absolute;
&.left {
width: 80px;
top: 17px;
left: 220px;
opacity: 0;
animation-name: cloudLeft;
animation-duration: 2s;
animation-timing-function: linear;
animation-fill-mode: forwards;
animation-delay: 1s;
}
&.mid {
width: 46px;
top: 10px;
left: 420px;
opacity: 0;
animation-name: cloudMid;
animation-duration: 2s;
animation-timing-function: linear;
animation-fill-mode: forwards;
animation-delay: 1.2s;
}
&.right {
width: 62px;
top: 100px;
left: 500px;
opacity: 0;
animation-name: cloudRight;
animation-duration: 2s;
animation-timing-function: linear;
animation-fill-mode: forwards;
animation-delay: 1s;
}
@keyframes cloudLeft {
0% {
top: 17px;
left: 220px;
opacity: 0;
}
20% {
top: 33px;
left: 188px;
opacity: 1;
}
80% {
top: 81px;
left: 92px;
opacity: 1;
}
100% {
top: 97px;
left: 60px;
opacity: 0;
}
}
@keyframes cloudMid {
0% {
top: 10px;
left: 420px;
opacity: 0;
}
20% {
top: 40px;
left: 360px;
opacity: 1;
}
70% {
top: 130px;
left: 180px;
opacity: 1;
}
100% {
top: 160px;
left: 120px;
opacity: 0;
}
}
@keyframes cloudRight {
0% {
top: 100px;
left: 500px;
opacity: 0;
}
20% {
top: 120px;
left: 460px;
opacity: 1;
}
80% {
top: 180px;
left: 340px;
opacity: 1;
}
100% {
top: 200px;
left: 300px;
opacity: 0;
}
}
}
}
.bullshit {
position: relative;
float: left;
width: 300px;
padding: 30px 0;
overflow: hidden;
&__oops {
font-size: 32px;
font-weight: bold;
line-height: 40px;
color: #1482f0;
opacity: 0;
margin-bottom: 20px;
animation-name: slideUp;
animation-duration: 0.5s;
animation-fill-mode: forwards;
}
&__headline {
font-size: 20px;
line-height: 24px;
color: #222;
font-weight: bold;
opacity: 0;
margin-bottom: 10px;
animation-name: slideUp;
animation-duration: 0.5s;
animation-delay: 0.1s;
animation-fill-mode: forwards;
}
&__info {
font-size: 13px;
line-height: 21px;
color: grey;
opacity: 0;
margin-bottom: 30px;
animation-name: slideUp;
animation-duration: 0.5s;
animation-delay: 0.2s;
animation-fill-mode: forwards;
}
&__return-home {
display: block;
float: left;
width: 110px;
height: 36px;
background: #1482f0;
border-radius: 100px;
text-align: center;
color: #ffffff;
opacity: 0;
font-size: 14px;
line-height: 36px;
cursor: pointer;
animation-name: slideUp;
animation-duration: 0.5s;
animation-delay: 0.3s;
animation-fill-mode: forwards;
}
@keyframes slideUp {
0% {
transform: translateY(60px);
opacity: 0;
}
100% {
transform: translateY(0);
opacity: 1;
}
}
}
}
</style>
<template>
<div class="page-audit-list page-auth-audit-list">
<SearchTable title="待审核列表查询" ref="searchTableRef" :immediately="true" 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 ? 24 : 12" :class="isTablet ? 'mt-16' : ''">
<el-form-item label="实名日期" prop="certificationTime" label-width="120px" :rules="START_TIME">
<el-date-picker v-model="searchForm.certificationTime" :editable="false" type="datetimerange" start-placeholder="请选择开始时间" end-placeholder="请选择结束时间" align="right" value-format="yyyy-MM-dd HH:mm:ss"> />
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="isTablet ? 12 : 6">
<el-form-item label="车主姓名" class="mt-16" prop="vinOwnerName" label-width="120px">
<el-input v-model="searchForm.vinOwnerName" placeholder="请输入车主姓名" clearable />
</el-form-item>
</el-col>
<el-col :span="isTablet ? 12 : 6">
<el-form-item label="车主手机" class="mt-16" prop="vinOwnerPhone" label-width="120px">
<el-input v-model="searchForm.vinOwnerPhone" placeholder="请输入车主手机号码" clearable />
</el-form-item>
</el-col>
<el-col :span="isTablet ? 12 : 6" class="mt-16">
<el-form-item label="业务类型" prop="rnrBizzType" label-width="120px">
<el-select v-model="searchForm.orderType" placeholder="请选择业务类型" clearable>
<el-option v-for="item in BUSINESS_TYPE" :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="vinCompanyName" label-width="120px">
<el-input v-model="searchForm.vinCompanyName" placeholder="请输入企业名称" clearable />
</el-form-item>
</el-col>
<el-col :span="isTablet ? 12 : 6" class="mt-16">
<el-form-item label="组织名称" prop="orgName" label-width="120px">
<el-input v-model="searchForm.orgName" placeholder="请输入组织名称" clearable />
</el-form-item>
</el-col>
</template>
<template #slot-table>
<el-table-column label="车辆VIN码" prop="vin" min-width="200" />
<el-table-column label="关联ICCID" prop="iccid" min-width="200" />
<el-table-column label="业务类型" prop="orderTypeName" min-width="180" />
<el-table-column label="审核状态" prop="orderStatus" width="130px">
<template slot-scope="scope">
<el-tag
:type="scope.row.orderStatus == 3 ? 'success' : 'warning'"
size="mini"
>{{ ['待审核', '待审核', '待审核', '审核通过', '审核不通过'][scope.row.orderStatus] || '' }}</el-tag>
</template>
</el-table-column>
<el-table-column label="车主姓名" prop="vinOwnerName" width="130px" />
<el-table-column label="车主手机" prop="vinOwnerPhone" width="130px" />
<el-table-column label="创建时间" prop="rnrDate" min-width="200" />
<el-table-column label="企业名称" prop="vinCompanyName" min-width="230" show-overflow-tooltip>
<template slot-scope="scope">
<span>{{ scope.row.vinCompanyName ? scope.row.vinCompanyName : '-' }}</span>
</template>
</el-table-column>
<el-table-column label="组织名称" prop="orgName" min-width="230" show-overflow-tooltip>
<template slot-scope="scope">
<span>{{ scope.row.orgName ? scope.row.orgName : '-' }}</span>
</template>
</el-table-column >
<el-table-column label="操作" width="106px" fixed="right">
<template slot-scope="scope">
<el-button type="text" @click="handleOpenDialog('0',scope.row)">查看</el-button>
</template>
</el-table-column>
</template>
</SearchTable>
<!-- 操作用户弹窗 start -->
<AuditDetailDialog :visible.sync="AuditDetailDialog.show" :data="AuditDetailDialog.data" @refresh="handleRefresh" />
<!-- 操作用户弹窗 end -->
</div>
</template>
<script>
import SearchTable from '@/components/SearchTable'
import AuditDetailDialog from './components/AuditDetailDialog.vue'
import { auditList } from '@/api/audit'
// 业务类型
const BUSINESS_TYPE = [
{ label: '自然人新车实名认证', value: '1' }, // 自然人
{ label: '自然人二手车实名认证', value: '2' }, // 自然人
{ label: '企业新车实名认证', value: '3' }, // 企业实名
{ label: '车企新车实名认证', value: '4' }, // 企业实名
{ label: '企业责任人变更', value: '5' }, // 企业负责人变更
{ label: '车主解绑', value: '6' }, // 自然人
{ label: '二手车主解绑', value: '7' }, // 自然人
{ label: '车企实名解绑', value: '8' },
{ label: '设备更换', value: '9' },
{ label: '一车多卡绑定', value: '10' },
{ label: '重新绑定', value: '11' }
]
const ORDER_TYPE = [
'',
'自然人实名认证',
'自然人代办人实名认证',
'自然人二手车实名认证',
'自然人二手车代办人实名认证',
'自然人二手车解绑',
'企业实名认证',
'企业责任人变更'
]
const START_TIME = { required: true, trigger: 'change', message: '请选择实名日期' }
export default {
name: 'AuditList',
components: {
SearchTable,
AuditDetailDialog
},
data() {
return {
totalCount: 0,
searchForm: {
vin: '',
iccid: '',
vinOwnerName: '',
vinOwnerPhone: '',
orderType: '',
vinCompanyName: '',
orgName: '',
rnrOrderInfoId: '',
certificationTime: []
},
START_TIME,
BUSINESS_TYPE,
ORDER_TYPE,
list: [],
// 查看
AuditDetailDialog: {
show: false,
type: '0',
data: {}
},
isTablet: window.OS.isTablet
}
},
created() {
this.searchForm.certificationTime[0] = this.dateFormat1()
this.searchForm.certificationTime[1] = this.dateFormat2()
},
methods: {
/**
* 当前日期
*/
dateFormat1() {
var date = new Date()
var y = date.getFullYear()
var m = date.getMonth() + 1
m = m < 10 ? '0' + m : m
var d = date.getDate()
d = d < 10 ? '0' + d : d
const time = y + '-' + m + '-' + d + ' ' + '00' + ':' + '00' + ':' + '00'
return time
},
/**
* 后30天日期
*/
dateFormat2() {
var date = new Date()
date.setDate(date.getDate() + 30)
var y = date.getFullYear()
var m = date.getMonth() + 1
m = m < 10 ? '0' + m : m
var d = date.getDate()
d = d < 10 ? '0' + d : d
const time = y + '-' + m + '-' + d + ' ' + '23' + ':' + '59' + ':' + '00'
return time
},
/**
* 获取数据
* @param formData 表格数据
* @param callback 回调函数
*/
async handleSubmit(formData, callback) {
const formDataCopy = { ...formData }
if (formData.certificationTime && formData.certificationTime.length > 0) {
formDataCopy.rnrStartDate = formData.certificationTime[0]
formDataCopy.rnrEndDate = formData.certificationTime[1]
}
const respData = await auditList(formDataCopy)
// 处理vin和list列表
respData.list.forEach(item => {
// 如果当前有vin码
if (item.vin) {
const vin = item.vin
item.vin = vin.split(',').slice(0, 5).join(',')
item.vin = `${item.vin}${item.vin === vin ? '' : '...'}`
}
// 如果当前有iccid
if (item.iccid) {
const iccid = item.iccid
item.iccid = iccid.split(',').slice(0, 5).join(',')
item.iccid = `${item.iccid}${item.iccid === iccid ? '' : '...'}`
}
})
console.log('调用待审核列表:', respData)
callback(respData)
},
/**
* 刷新页面
*/
handleRefresh() {
// 重新刷新页面
this.$refs.searchTableRef.handleSubmit()
},
/**
* 打开审核页面弹框
* @param type 打开弹框类型
* @param row 当前行数据
*/
handleOpenDialog(type = '0', row = {}) {
if (row.orderType) {
this.AuditDetailDialog = {
show: true,
type,
data: { ...row }
}
}
},
/**
* 重置方法
*/
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-audit-list {
.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;
&: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;
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>
<div class="user-operation">
<el-dialog
:visible="visible"
:title="`人工审核详情`"
:close-on-click-modal="false"
:close-on-press-escape="false"
class="audit-dialog"
width="1300px"
@close="$emit('update:visible', false)"
>
<RnrDetail :page-data="data" v-if="visible" @submit-click="handleSubmit" />
</el-dialog>
</div>
</template>
<script>
import RnrDetail from './rnr-detail'
export default {
components: {
RnrDetail
},
props: {
visible: {
type: Boolean,
default: false
},
data: {
type: Object,
default: () => {}
}
},
data() {
return {
isLoading: false
}
},
mounted() {
},
methods: {
/**
* 点击关闭方法
*/
handleClose() {
this.$emit('update:visible', false)
},
/**
* 点击审核方法
*/
handleSubmit(formData) {
if (formData.auditResult === 3) {
this.handleConfirm()
} else {
this.handleCancel(formData)
}
},
/**
* 通过事件3
* @time 2022-04-26 18:10:55
*/
handleConfirm() {
this.$confirm('审核通过操作成功', '提示', {
confirmButtonText: '确定',
showCancelButton: false,
showClose: false,
closeOnClickModal: false,
type: 'success'
}).then(() => {
this.$emit('update:visible', false)
this.$emit('refresh')
console.log('ok')
})
},
/**
* 拒绝事件4
* @time 2022-04-26 18:11:11
*/
handleCancel() {
this.$confirm('审核拒绝操作成功', '提示', {
confirmButtonText: '确定',
showCancelButton: false,
showClose: false,
closeOnClickModal: false,
type: 'success'
}).then(() => {
this.$emit('update:visible', false)
this.$emit('refresh')
console.log('ok')
})
}
}
}
</script>
<style lang="scss" scoped>
.audit-dialog{
margin-bottom: 10px;
}
</style>
<template>
<div>
<div v-if="formData.vinCardMsg && formData.vinCardMsg.length > 0" class="detail-group-box">
<div class="detail-group-title">
<img :src="require('@/assets/img/icon_marker.png')">
<span>车卡信息</span>
</div>
<el-row :gutter="14">
<el-col :span="24">
<div class="custom-table-info">
<el-table class="custom-table" :data="formData.vinCardMsg" border stripe >
<el-table-column type="index" label="序号" align="center" width="80" />
<el-table-column prop="vin" label="车辆VIN码" min-width="250" show-overflow-tooltip />
<el-table-column prop="iccid" label="ICCID" min-width="250" show-overflow-tooltip />
<el-table-column prop="status" label="车辆/设备/信息校验" min-width="250" show-overflow-tooltip />
</el-table>
</div>
</el-col>
</el-row>
</div>
<div v-if="formData.vinOwnerMsg && !formData.vinOwnerMsg.isCompany" class="detail-group-box">
<div class="detail-group-title">
<img :src="require('@/assets/img/icon_marker.png')">
<span>车主信息</span>
</div>
<el-row :gutter="14">
<el-col :span="24">
<table class="custom-table">
<tr>
<td class="custom-table-head"><span>姓名</span></td>
<td class="custom-table-td"><span>{{ formData.vinOwnerMsg.name }}</span></td>
<td class="custom-table-head"><span>性别</span></td>
<td class="custom-table-td"><span>{{ formData.vinOwnerMsg.sex }}</span></td>
<td class="custom-table-head"><span>证件类型</span></td>
<td class="custom-table-td"><span>{{ formData.vinOwnerMsg.idType }}</span></td>
</tr>
<tr>
<td class="custom-table-head"><span>证件号码</span></td>
<td class="custom-table-td"><span>{{ formData.vinOwnerMsg.idNo }}</span></td>
<td class="custom-table-head"><span>证件有效期</span></td>
<td class="custom-table-td"><span>{{ formData.vinOwnerMsg.idValidDate }}</span></td>
<td class="custom-table-head"><span>证件地址</span></td>
<td class="custom-table-td"><span>{{ formData.vinOwnerMsg.idAddress }}</span></td>
</tr>
<tr>
<td class="custom-table-head"><span>手机号</span></td>
<td class="custom-table-td"><span>{{ formData.vinOwnerMsg.phone }}</span></td>
<td class="custom-table-head"><span>通讯地址</span></td>
<td class="custom-table-td"><span>{{ formData.vinOwnerMsg.contactAddress }}</span></td>
<td class="custom-table-head"><span>证件照片</span></td>
<td class="custom-table-td">
<span>
<el-link type="primary" icon="iconfont icon-search" @click="handlePreview(auditImages.ownerImages)">点击查看</el-link>
</span>
</td>
</tr>
</table>
</el-col>
</el-row>
</div>
<div v-if="formData.vinLiaisonMsg" class="detail-group-box">
<div class="detail-group-title">
<img :src="require('@/assets/img/icon_marker.png')">
<span>代办人信息</span>
</div>
<el-row :gutter="14">
<el-col :span="24">
<table class="custom-table">
<tr>
<td class="custom-table-head"><span>姓名</span></td>
<td class="custom-table-td"><span>{{ formData.vinLiaisonMsg.name }}</span></td>
<td class="custom-table-head"><span>性别</span></td>
<td class="custom-table-td"><span>{{ formData.vinLiaisonMsg.sex }}</span></td>
<td class="custom-table-head"><span>证件类型</span></td>
<td class="custom-table-td"><span>{{ formData.vinLiaisonMsg.idType }}</span></td>
</tr>
<tr>
<td class="custom-table-head"><span>证件号码</span></td>
<td class="custom-table-td"><span>{{ formData.vinLiaisonMsg.idNo }}</span></td>
<td class="custom-table-head"><span>证件有效期</span></td>
<td class="custom-table-td"><span>{{ formData.vinLiaisonMsg.idValidDate }}</span></td>
<td class="custom-table-head"><span>证件地址</span></td>
<td class="custom-table-td"><span>{{ formData.vinLiaisonMsg.idAddress }}</span></td>
</tr>
<tr>
<td class="custom-table-head"><span>手机号</span></td>
<td class="custom-table-td"><span>{{ formData.vinLiaisonMsg.phone }}</span></td>
<td class="custom-table-head"><span>通讯地址</span></td>
<td class="custom-table-td"><span>{{ formData.vinLiaisonMsg.contactAddress }}</span></td>
<td class="custom-table-head"><span>证件照片</span></td>
<td class="custom-table-td">
<span>
<el-link type="primary" icon="iconfont icon-search" @click="handlePreview(auditImages.liaisonImages)">点击查看</el-link>
</span>
</td>
</tr>
</table>
</el-col>
</el-row>
</div>
<div v-if="formData.oldCompanyInfo" class="detail-group-box">
<div class="detail-group-title">
<img :src="require('@/assets/img/icon_marker.png')">
<span>原企业和责任人信息</span>
</div>
<el-row :gutter="14">
<el-col :span="24">
<table class="custom-table">
<tr>
<td class="custom-table-head"><span>企业名称</span></td>
<td class="custom-table-td"><span>{{ formData.oldCompanyInfo.companyName }}</span></td>
<td class="custom-table-head"><span>责任人姓名</span></td>
<td class="custom-table-td"><span>{{ formData.oldOwnerName }}</span></td>
</tr>
</table>
</el-col>
</el-row>
</div>
<div v-if="formData.newOwnerInfo" class="detail-group-box">
<div class="detail-group-title">
<img :src="require('@/assets/img/icon_marker.png')">
<span>新责任人信息</span>
</div>
<el-row :gutter="14">
<el-col :span="24">
<table class="custom-table">
<tr>
<td class="custom-table-head"><span>姓名</span></td>
<td class="custom-table-td"><span>{{ formData.newOwnerInfo.fullName }}</span></td>
<td class="custom-table-head"><span>性别</span></td>
<td class="custom-table-td"><span>{{ formData.newOwnerInfo.gender }}</span></td>
<td class="custom-table-head"><span>证件类型</span></td>
<td class="custom-table-td"><span>{{ formData.newOwnerInfo.certType }}</span></td>
</tr>
<tr>
<td class="custom-table-head"><span>证件号码</span></td>
<td class="custom-table-td"><span>{{ formData.newOwnerInfo.certNumber }}</span></td>
<td class="custom-table-head"><span>证件有效期</span></td>
<td class="custom-table-td"><span>{{ formData.newOwnerInfo.expiredDate }}</span></td>
<td class="custom-table-head"><span>证件地址</span></td>
<td class="custom-table-td"><span>{{ formData.newOwnerInfo.certAddress }}</span></td>
</tr>
<tr>
<td class="custom-table-head"><span>手机号</span></td>
<td class="custom-table-td"><span>{{ formData.newOwnerInfo.phone }}</span></td>
<td class="custom-table-head"><span>通讯地址</span></td>
<td class="custom-table-td"><span>{{ formData.newOwnerInfo.contactAddress }}</span></td>
<td class="custom-table-head"><span>证件照片</span></td>
<td class="custom-table-td">
<span>
<el-link type="primary" icon="iconfont icon-search" @click="handlePreview(formData.newOwnerInfo.newCertList)">点击查看</el-link>
</span>
</td>
</tr>
</table>
</el-col>
</el-row>
</div>
<div v-if="formData.companyInfoDetail" class="detail-group-box">
<div class="detail-group-title">
<img :src="require('@/assets/img/icon_marker.png')">
<span>企业信息</span>
</div>
<el-row :gutter="14">
<el-col :span="24">
<table class="custom-table">
<tr>
<td class="custom-table-head"><span>企业名称</span></td>
<td class="custom-table-td"><span>{{ formData.companyInfoDetail.companyName }}</span></td>
<td class="custom-table-head"><span>企业性质</span></td>
<td class="custom-table-td"><span>{{ formData.companyInfoDetail.companyType }}</span></td>
<td class="custom-table-head"><span>行业类型</span></td>
<td class="custom-table-td"><span>{{ formData.companyInfoDetail.industryType }}</span></td>
</tr>
<tr>
<td class="custom-table-head"><span>企业证件类型</span></td>
<td class="custom-table-td"><span>{{ formData.companyInfoDetail.companyCertType }}</span></td>
<td class="custom-table-head"><span>企业证件号码</span></td>
<td class="custom-table-td"><span>{{ formData.companyInfoDetail.companyCertNumber }}</span></td>
<td class="custom-table-head"><span>证件地址</span></td>
<td class="custom-table-td"><span>{{ formData.companyInfoDetail.companyCertAddress }}</span></td>
</tr>
<tr>
<td class="custom-table-head"><span>通讯地址</span></td>
<td class="custom-table-td"><span>{{ formData.companyInfoDetail.companyContactAddress }}</span></td>
<td class="custom-table-head"><span>企业证件照片</span></td>
<td class="custom-table-td" colspan="3">
<span>
<el-link type="primary" icon="iconfont icon-search" @click="handlePreview(auditImages.companyImages)">点击查看</el-link>
</span>
</td>
</tr>
</table>
</el-col>
</el-row>
</div>
<div v-if="formData.corporationInfoDetail && formData.corporationInfoDetail.isCompany" class="detail-group-box">
<div class="detail-group-title">
<img :src="require('@/assets/img/icon_marker.png')">
<span>责任人信息</span>
</div>
<el-row :gutter="14">
<el-col :span="24">
<table class="custom-table">
<tr>
<td class="custom-table-head"><span>姓名</span></td>
<td class="custom-table-td"><span>{{ formData.corporationInfoDetail.corporationName }}</span></td>
<td class="custom-table-head"><span>性别</span></td>
<td class="custom-table-td"><span>{{ formData.corporationInfoDetail.corporationGenderName || formData.corporationInfoDetail.corporationGender }}</span></td>
<td class="custom-table-head"><span>证件类型</span></td>
<td class="custom-table-td"><span>{{ formData.corporationInfoDetail.corporationCertType }}</span></td>
</tr>
<tr>
<td class="custom-table-head"><span>证件号码</span></td>
<td class="custom-table-td"><span>{{ formData.corporationInfoDetail.corporationCertNumber }}</span></td>
<td class="custom-table-head"><span>证件有效期</span></td>
<td class="custom-table-td"><span>{{ formData.corporationInfoDetail.corporationCertExpirationDate }}</span></td>
<td class="custom-table-head"><span>证件地址</span></td>
<td class="custom-table-td"><span>{{ formData.corporationInfoDetail.corporationCertAddress }}</span></td>
</tr>
<tr>
<td class="custom-table-head"><span>手机号</span></td>
<td class="custom-table-td"><span>{{ formData.corporationInfoDetail.corporationPhone }}</span></td>
<td class="custom-table-head"><span>通讯地址</span></td>
<td class="custom-table-td"><span>{{ formData.corporationInfoDetail.corporationContactAddress }}</span></td>
<td class="custom-table-head"><span>证件照片</span></td>
<td class="custom-table-td">
<span>
<el-link type="primary" icon="iconfont icon-search" @click="handlePreview(auditImages.corporationImages)">点击查看</el-link>
</span>
</td>
</tr>
</table>
</el-col>
</el-row>
</div>
<div v-if="showFileModule" class="detail-group-box">
<div class="detail-group-title">
<img :src="require('@/assets/img/icon_marker.png')">
<span>文件信息</span>
</div>
<el-row class="mb20" :gutter="14">
<el-col :span="24">
<el-image
v-for="(item, index) in auditImages.fileImages"
:key="index"
class="preview-photo"
:src="item"
:preview-src-list="auditImages.fileImages"
/>
<div
v-for="(item, index) in auditImages.filePdfs"
:key="index"
class="preview-photo preview-pdf"
@click="handleOpenPdf(item)"
>
<div class="pdf-container" />
</div>
</el-col>
</el-row>
</div>
<div v-if="auditImages.authInfoImages" class="detail-group-box">
<div class="detail-group-title">
<img :src="require('@/assets/img/icon_marker.png')">
<span>认证信息</span>
</div>
<el-row :gutter="14">
<el-col :span="24">
<table class="custom-table">
<tr>
<td class="custom-table-head"><span>活体照片/视频</span></td>
<td class="custom-table-td" colspan="3">
<el-image
v-for="(item, index) in auditImages.authInfoImages"
:key="index"
class="preview-photo"
:src="item"
:preview-src-list="auditImages.authInfoImages"
/>
<div v-for="(item, index) in auditImages.auditVideoList" :key="'td' + index" class="vedio-wrap">
<div class="video-item">
<i class="el-icon-video-play" @click="handlePlay(item)" />
<video preload="auto" class="cvp-file">
<source :src="item" type="video/mp4">
<p>暂不支持预览</p>
</video>
</div>
</div>
</td>
</tr>
<tr v-for="(item, index) in auditImages.tableList" :key="index">
<td
v-for="(ite, idx) in item"
:key="'t' + idx"
:class="ite.className"
:colspan="ite.colspan"
>
<span>{{ ite.name }}</span>
</td>
</tr>
</table>
</el-col>
</el-row>
</div>
<image-viewer v-if="showViewer" :on-close="closeViewer" :url-list="previewList" />
<el-dialog
:visible.sync="videoVisible"
width="50%"
:close-on-click-modal="false"
:center="true"
:append-to-body="true"
:before-close="handleClose"
>
<video-player v-if="videoVisible" :src="videoUrl" />
</el-dialog>
</div>
</template>
<script>
import ImageViewer from '@/components/Uploader/image-viewer.vue'
import VideoPlayer from '@/components/VideoPlayer/index.vue'
export default {
name: 'CompCertification',
components: {
ImageViewer,
VideoPlayer
},
props: {
formData: {
type: Object,
default: () => {}
},
auditImages: {
type: Object,
default: () => {}
}
},
data() {
return {
tableList: [],
previewList: [],
showViewer: false,
prevOverflow: '',
activityStatus: '',
videoVisible: false,
videoUrl: ''
}
},
computed: {
showFileModule() {
if (this.auditImages.fileImages && this.auditImages.fileImages.length > 0) {
return true
}
if (this.auditImages.filePdfs && this.auditImages.filePdfs.length > 0) {
return true
}
return false
}
},
mounted() {
},
methods: {
/**
* 打开图片预览
* @param {Array} imgList 需要预览的大图
* @time 2022-04-07 17:18:33
*/
handlePreview(imgList) {
if (imgList.length <= 0) {
this.$message.error('没有相关证件照片可预览')
return false
}
this.previewList = imgList
this.prevOverflow = document.body.style.overflow
document.body.style.overflow = 'hidden'
this.showViewer = true
},
/**
* 关闭图片预览
* @time 2022-04-07 17:18:20
*/
closeViewer() {
document.body.style.overflow = this.prevOverflow
this.showViewer = false
},
/**
* 视频播放
* @time 2022-04-26 00:04:00
*/
handlePlay(url) {
this.videoUrl = url
this.videoVisible = true
},
/**
* 视频播放关闭
* @time 2022-04-26 00:04:00
*/
handleClose() {
this.videoVisible = false
this.videoUrl = ''
},
/**
* 新窗口打开pdf
* @param url pdf的链接
*/
handleOpenPdf(url) {
window.open(url, '_blank')
}
}
}
</script>
<style lang="scss" >
.custom-table-info{
.el-table {
.cell {
padding: 0 10px;
}
}
}
.preview-photo, .cvp-file{
width: 68px;
height: 68px;
margin-right: 20px;
border-radius: 4px;
}
.preview-pdf {
align-items: center;
background: #F7F8FA;
border: 1px solid #CACCD0;
cursor: pointer;
display: flex;
justify-content: center;
.pdf-container {
align-items: center;
background: #FF5F61;
display: flex;
width: 24px;
height: 28px;
justify-content: center;
position: relative;
&:before {
color: #FFFFFF;
content: "P";
display: block;
font-weight: 900;
}
&:after {
background: linear-gradient(127deg, #FFE6E7 0%, #FFC5C6 100%);
box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.12);
content: "";
display: block;
width: 7px;
height: 6px;
position: absolute;
right: 0;
top: 0
}
}
}
.mb20{
margin-bottom: 10px;
}
.vedio-wrap, .video-item{
display: inline-block;
}
.video-item{
position: relative;
.el-icon-video-play{
position: absolute;
font-size: 30px;
color: #fff;
z-index: 1;
display: inline-block;
width: 68px;
height: 68px;
text-align: center;
line-height: 68px;
background-color: rgba(153, 153, 153, .4);
cursor: pointer;
border-radius: 4px;
}
}
.ite-button{
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
}
</style>
<template>
<div v-loading.fullscreen.lock="loading" element-loading-spinner="page-loading" class="app-container page-rnr-audit-detail">
<div v-if="orderDetail.bizDetail" class="detail-group-title matop0">
<page-module :path="iconPath" name="业务信息">
<table v-if="orderDetail.bizDetail" class="custom-table">
<tr>
<td class="custom-table-head"><span>业务类型</span></td>
<td class="custom-table-td"><span>{{ orderDetail.bizDetail.orderType | ORDER_TYPE }}</span></td>
<td class="custom-table-head"><span>实名日期</span></td>
<td class="custom-table-td"><span>{{ orderDetail.bizDetail.createTime }}</span></td>
</tr>
<tr>
<td class="custom-table-head"><span>认证进度</span></td>
<td class="custom-table-td" colspan="3"><span>{{ orderDetail.bizDetail.orderStatus | ORDER_STATUS }}</span></td>
</tr>
</table>
</page-module>
</div>
<page-module :path="iconPath" name="车卡信息">
<TableRender
:schema="SCHEMA"
:data="cardList"
:config="{pagination: { pageSizes: [10, 20, 50], layout: 'total, prev, pager, next, sizes' }}"
:pagination="pagination"
@size-change="handleSizeChange"
@current-change="handlePageChange"
/>
</page-module>
<div v-if="orderDetail.rnrDetail" class="detail-group-title">
<page-module :path="iconPath" name="新车主/责任人信息">
<table v-if="orderDetail.rnrDetail" class="custom-table">
<tr>
<td class="custom-table-head"><span>姓名</span></td>
<td class="custom-table-td"><span>{{ orderDetail.rnrDetail.fullName }}</span></td>
<td class="custom-table-head"><span>性别</span></td>
<td class="custom-table-td"><span>{{ { 1: '', 2: '' }[orderDetail.rnrDetail.gender] }}</span></td>
</tr>
<tr>
<td class="custom-table-head"><span>证件类型</span></td>
<td class="custom-table-td"><span>{{ orderDetail.rnrDetail.certTypeName }}</span></td>
<td class="custom-table-head"><span>证件号码</span></td>
<td class="custom-table-td"><span>{{ orderDetail.rnrDetail.certNumber }}</span></td>
</tr>
<tr>
<td class="custom-table-head"><span>手机号</span></td>
<td class="custom-table-td"><span>{{ orderDetail.rnrDetail.phone }}</span></td>
<td class="custom-table-head"><span>证件有效期</span></td>
<td class="custom-table-td"><span>{{ orderDetail.rnrDetail.expiredDate }}</span></td>
</tr>
<tr>
<td class="custom-table-head"><span>证件照片</span></td>
<td class="custom-table-td" colspan="3"><el-link @click="handlePreviewImage(orderDetail.rnrDetail.rnrInfoFile)">点击查看</el-link></td>
</tr>
</table>
</page-module>
</div>
<div v-if="orderDetail.liaisonDetail" class="detail-group-title">
<page-module :path="iconPath" name="代办人信息">
<table v-if="orderDetail.liaisonDetail" class="custom-table">
<tr>
<td class="custom-table-head"><span>姓名</span></td>
<td class="custom-table-td"><span>{{ orderDetail.liaisonDetail.fullName }}</span></td>
<td class="custom-table-head"><span>性别</span></td>
<td class="custom-table-td"><span>{{ { 1: '', 2: '' }[orderDetail.liaisonDetail.gender] }}</span></td>
</tr>
<tr>
<td class="custom-table-head"><span>证件类型</span></td>
<td class="custom-table-td"><span>{{ orderDetail.liaisonDetail.certTypeName }}</span></td>
<td class="custom-table-head"><span>证件号码</span></td>
<td class="custom-table-td"><span>{{ orderDetail.liaisonDetail.certNumber }}</span></td>
</tr>
<tr>
<td class="custom-table-head"><span>手机号</span></td>
<td class="custom-table-td"><span>{{ orderDetail.liaisonDetail.phone }}</span></td>
<td class="custom-table-head"><span>证件有效期</span></td>
<td class="custom-table-td"><span>{{ orderDetail.liaisonDetail.expiredDate }}</span></td>
</tr>
<tr>
<td class="custom-table-head"><span>证件照片</span></td>
<td class="custom-table-td" colspan="3"><el-link @click="handlePreviewImage(orderDetail.liaisonDetail.rnrInfoFile)">点击查看</el-link></td>
</tr>
</table>
</page-module>
</div>
<div v-if="orderDetail.companyDetail" class="detail-group-title">
<page-module :path="iconPath" name="企业信息">
<table v-if="orderDetail.companyDetail" class="custom-table">
<tr>
<td class="custom-table-head"><span>企业名称</span></td>
<td class="custom-table-td"><span>{{ orderDetail.companyDetail.companyName }}</span></td>
<td class="custom-table-head"><span>企业性质</span></td>
<td class="custom-table-td"><span>{{ orderDetail.companyDetail.companyTypeName }}</span></td>
</tr>
<tr>
<td class="custom-table-head"><span>行业类型</span></td>
<td class="custom-table-td"><span>{{ orderDetail.companyDetail.industryTypeName }}</span></td>
<td class="custom-table-head"><span>企业证件类型</span></td>
<td class="custom-table-td"><span>{{ orderDetail.companyDetail.companyCertTypeName }}</span></td>
</tr>
<tr>
<td class="custom-table-head"><span>企业证件号码</span></td>
<td class="custom-table-td"><span>{{ orderDetail.companyDetail.companyCertNumber }}</span></td>
<td class="custom-table-head"><span>证件地址</span></td>
<td class="custom-table-td"><span>{{ orderDetail.companyDetail.companyCertAddress }}</span></td>
</tr>
<tr>
<td class="custom-table-head"><span>通讯地址</span></td>
<td class="custom-table-td"><span>{{ orderDetail.companyDetail.companyContactAddress }}</span></td>
<td class="custom-table-head"><span>企业证件照片</span></td>
<td class="custom-table-td" :colspan="3"><el-link @click="handlePreviewImage(orderDetail.companyDetail.companyFile)">点击查看</el-link></td>
</tr>
</table>
</page-module>
</div>
<div v-if="orderDetail.authenticationList && orderDetail.authenticationList.length > 0" class="detail-group-title">
<page-module :path="iconPath" name="认证信息">
<table v-if="orderDetail.authenticationList && orderDetail.authenticationList.length > 0" class="custom-table">
<tr v-for="(authentication, index) in orderDetail.authenticationList" :key="index">
<td class="custom-table-head"><span>{{ { LIVENESS: '活体', OCR: '光符识别', CERT_CHECK: '身份信息核查', ID_COMPARE: '人证比对', FACE_COMPARE: '人脸比对' }[authentication.authWayType] }}</span></td>
<td class="custom-table-td"><span>{{ authentication.authResultMsg }}</span></td>
</tr>
<tr>
<td class="custom-table-head">活体照片/视频</td>
<td class="custom-table-td">
<el-image
v-for="(item, index) in orderDetail.authMap"
:key="index"
:src="item"
:preview-src-list="orderDetail.authMap"
fit="contain"
class="preview-photo"
/>
<div v-for="video in orderDetail.authVideo" :key="video" class="video-wrapper">
<div class="video-item">
<i class="el-icon-video-play" @click="handlePlay(video)" />
<video preload="auto" class="cvp-file">
<source :src="video" type="video/mp4">
<p>暂不支持预览</p>
</video>
</div>
</div>
</td>
</tr>
</table>
</page-module>
</div>
<div v-if="orderDetail.fileMap" class="detail-group-title">
<page-module :path="iconPath" name="文件信息">
<el-image
v-for="(item, index) in orderDetail.fileMap"
:key="index"
:src="item"
:preview-src-list="orderDetail.fileMap"
fit="contain"
class="preview-photo"
/>
</page-module>
</div>
<div v-if="orderDetail.auditDetail" class="detail-group-title">
<page-module :path="iconPath" name="人工审核信息" >
<table v-if="orderDetail.auditDetail" class="custom-table">
<tr>
<td class="custom-table-head"><span>审核人员</span></td>
<td class="custom-table-td"><span>{{ orderDetail.auditDetail.operatorName }}</span></td>
<td class="custom-table-head"><span>审核日期</span></td>
<td class="custom-table-td"><span>{{ orderDetail.auditDetail.auditTime }}</span></td>
</tr>
<tr>
<td class="custom-table-head"><span>审核意见</span></td>
<td class="custom-table-td" colspan="3"><span>{{ orderDetail.auditDetail.content }}</span></td>
</tr>
</table>
</page-module>
</div>
<image-viewer v-if="showViewer" :z-index="2010" :on-close="handleCloseViewer" :url-list="urlList" />
<el-dialog
:visible.sync="videoVisible"
width="50%"
:close-on-click-modal="false"
:center="true"
:append-to-body="true"
:before-close="handleClose"
>
<video-player v-if="videoVisible" :src="videoUrl" />
</el-dialog>
</div>
</template>
<script>
import { queryCardPageByOrderId, queryOrderDetail } from '@/api/audit'
import TableRender from '@/components/TableRender'
import ImageViewer from '@/components/Uploader/image-viewer'
import VideoPlayer from '@/components/VideoPlayer'
import { imageViewer } from '@/utils/upload'
// 认证进度
const ORDER_STATUS = [
{ label: '已提交', value: 0 },
{ label: '待分派/认领', value: 1 },
{ label: '待审核', value: 2 },
{ label: '审核通过', value: 3 },
{ label: '未通过', value: 4 },
{ label: '作废', value: 9 }
]
// 业务类型
const ORDER_TYPE = [
{ label: '自然人新车实名认证', value: 1 },
{ label: '自然人二手车实名认证', value: 2 },
{ label: '企业新车实名认证', value: 3 },
{ label: '车企新车实名认证', value: 4 },
{ label: '企业责任人变更', value: 5 },
{ label: '车主解绑', value: 6 },
{ label: '二手车主解绑', value: 7 },
{ label: '车企实名解绑', value: 8 },
{ label: '设备更换', value: 9 },
{ label: '一车多卡绑定', value: 10 },
{ label: '重新绑定', value: 11 },
{ label: '企业解绑', value: 12 }
]
export default {
name: 'RnrDetail',
components: { TableRender, ImageViewer, VideoPlayer },
filters: {
ORDER_STATUS(value) {
try {
return ORDER_STATUS.find(item => +item.value === +value).label
} catch (error) {
console.log(error)
return ''
}
},
ORDER_TYPE(value) {
try {
return ORDER_TYPE.find(item => +item.value === +value).label
} catch (error) {
console.log(error)
return ''
}
}
},
props: {
orderId: {
type: String,
default: ''
}
},
data() {
return {
ORDER_STATUS,
ORDER_TYPE,
loading: false,
cardList: [],
orderDetail: {},
pagination: {
total: 0,
currentPage: 1,
pageSize: 10
},
urlList: [],
fileList: [],
showViewer: false,
SCHEMA: [
{ type: 'index', label: '序号', width: '100px' },
{ label: 'VIN', prop: 'vin' },
{ label: 'ICCID', prop: 'iccid' }
],
cacheImages: {},
videoUrl: '',
videoVisible: false,
iconPath: require('@/assets/audit/icon_marker.png')
}
},
mounted() {
// 分页查询车卡数据接口
this.queryCardPageByOrderId()
// 查询订单详情接口
this.queryOrderDetail()
},
methods: {
/**
* 预览照片
* @param {Array} fileList 文件列表
* @time 2022-09-19 17:25:46
*/
async handlePreviewImage(fileList) {
// 增加loading
this.loading = true
try {
// 获取的图片url
this.urlList = await Promise.all(
fileList.map(({ fileId }) => {
// 如果当前有缓存的文件,则直接展示
if (this.cacheImages[fileId]) {
return this.cacheImages[fileId]
}
return imageViewer(fileId).then(url => {
this.cacheImages[fileId] = url
return url
})
})
)
// 打开图片预览
this.showViewer = true
} catch (error) {
console.error(error)
}
// 关闭loading
this.loading = false
},
/**
* 尺寸变化方法
* @param pageSize 每页展示条数
*/
handleSizeChange(pageSize) {
this.pagination.pageSize = pageSize
this.queryCardPageByOrderId()
},
/**
* 页码改变方法
* @param page 页码
*/
handlePageChange(page) {
this.pagination.currentPage = page
this.queryCardPageByOrderId()
},
/**
* 分页查询车卡信息
*/
async queryCardPageByOrderId() {
// 展示loading框
this.loading = true
try {
// 开始请求接口
const { list, totalCount } = await queryCardPageByOrderId({
orderId: this.orderId,
currPage: this.pagination.currentPage,
pageSize: this.pagination.pageSize
})
// 表格数据
this.cardList = list
// 分页的数据
this.pagination.total = totalCount
} catch (error) {
console.error(error)
}
// 展示loading框
this.loading = false
},
/**
* 查询订单详情
*/
async queryOrderDetail() {
// 开始请求订单详情接口
const respData = await queryOrderDetail({ orderId: this.orderId }) || {}
// 订单详情
this.orderDetail = respData
// 获取的图片url
if (respData.fileList && respData.fileList.length > 0) {
// 文件列表
const fileMap = []
const authMap = []
const authVideo = []
// 将文件保存到上面的变量中
const setFileMap = ({ fileId, fileType }) => {
// 如果当前是活体相关的
if ([6].includes(fileType)) {
authVideo.push(this.cacheImages[fileId])
} else if ([3, 4].includes(fileType)) {
authMap.push(this.cacheImages[fileId])
} else {
fileMap.push(this.cacheImages[fileId])
}
}
// 查询接口
await Promise.all(
respData.fileList.map(({ fileId, fileType }) => {
// 如果当前有缓存的文件,则直接展示
if (this.cacheImages[fileId]) {
setFileMap({ fileId, fileType })
return this.cacheImages[fileId]
}
return imageViewer(fileId).then(url => {
// 保存到缓存中
this.cacheImages[fileId] = url
// 开始赋值
setFileMap({ fileId, fileType })
return url
}).catch(err => {
console.error(err)
return ''
})
})
)
// 文件列表
this.$set(this.orderDetail, 'fileMap', fileMap)
this.$set(this.orderDetail, 'authMap', authMap)
this.$set(this.orderDetail, 'authVideo', authVideo)
}
},
/**
* 视频播放
* @time 2022-04-26 00:04:00
*/
handlePlay(url) {
this.videoUrl = url
this.videoVisible = true
},
/**
* 关闭预览的视图
* @time 2022-09-19 19:04:53
*/
handleCloseViewer() {
this.showViewer = false
},
/**
* 关闭视频播放弹框
* @time 2022-09-19 19:05:00
*/
handleClose() {
this.videoVisible = false
}
}
}
</script>
<style lang="scss">
.page-rnr-audit-detail {
.detail-group-title{
font-size: 14px;
font-weight: 400;
color: #333333;
line-height: 20px;
margin: 10px 0;
&.matop0{
margin-top: 0px;
}
img{
width: 18px;
vertical-align: -4px;
}
}
.custom-table {
width: 100%;
border-collapse: collapse;
border-bottom: 1px solid #F0F0F0;
border-left: 1px solid #F0F0F0;
margin-bottom: 10px;
tr{
height: 40px;
}
td{
border-right: 1px solid #F0F0F0;
border-top: 1px solid #F0F0F0;
}
.custom-table-head{
font-size: 14px;
font-weight: 400;
color: #494B53;
width: 140px;
background-color: rgba(247, 248, 250, 0.7);
padding-left: 20px;
}
.custom-table-td{
font-size: 14px;
font-weight: 400;
color: #333841;
padding: 10px 20px 10px;
}
.w180{
width: 180px;
}
}
.el-pagination {
text-align: right;
margin-top: 12px;
}
.preview-photo, .cvp-file {
width: 68px;
height: 68px;
margin-right: 20px;
border-radius: 4px;
.el-image__preview {
width: 100%;
height: 100%;
}
}
.video-wrapper {
display: inline-block;
.video-item{
display: inline-block;
position: relative;
.el-icon-video-play{
position: absolute;
font-size: 30px;
color: #fff;
z-index: 1;
display: inline-block;
width: 68px;
height: 68px;
text-align: center;
line-height: 68px;
background-color: rgba(153, 153, 153, .4);
cursor: pointer;
border-radius: 4px;
}
}
}
img.module-icon {
width: 22px;
height: 22px
}
}
</style>
<template>
<div class="rnr-aduit-module">
<div class="aduit-title-box">
<div class="aduit-title">
<span>审核信息</span>
</div>
<div v-if="formData.verifyMsg" class="create-box">
<span style="margin-right: 20px;">审核人员: {{ formData.verifyMsg.currentUserName }}</span>
<span>审核日期: {{ formData.verifyMsg.currentDate }}</span>
</div>
</div>
<el-form ref="aduitForm" :model="aduitForm" size="small" label-width="70px" label-position="right">
<el-row :gutter="14">
<el-col :span="24">
<el-form-item label="审核意见">
<el-checkbox-group v-model="aduitForm.reason">
<el-checkbox label="证件信息不全" name="reason" />
<el-checkbox label="证件信息不一致" name="reason" />
<el-checkbox label="查不到证件信息" name="reason" />
<el-checkbox label="照片格式不正确" name="reason" />
<el-checkbox label="照片不清晰" name="reason" />
</el-checkbox-group>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="14">
<el-col :span="24">
<el-form-item label="其他">
<el-input
v-model.trim="aduitForm.remark"
type="textarea"
placeholder="其他补充意见"
:rows="3"
autocomplete="off"
maxlength="250"
show-word-limit
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="14">
<el-col :span="24">
<el-form-item style="text-align: center;">
<el-button round type="primary" @click="handleConfirm(3)">审核通过</el-button>
<el-button class="reject-btn" round @click="handleConfirm(4)">审核拒绝</el-button>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
</template>
<script>
export default {
name: 'RnrAuditForm',
props: {
formData: {
type: Object,
default: () => {}
},
pageData: {
type: Object,
default: () => {}
}
},
data() {
return {
auditor: '',
auditDate: '',
aduitForm: {
reason: [],
remark: ''
}
}
},
computed: {
},
mounted() {
},
methods: {
/**
* 提交审核
* COMMIT(0, "已提交 ,待确认"),
* ASSIGNMENT(1, "待分派/认领"),
* TO_EXAMINE(2, "待审核"),
* PASS(3, "审核通过"),
* NOT_PASS(4, "未通过"),
* CANCEL(9, "作废");
* @time 2022-06-13 21:08:28
*/
handleConfirm(val) {
if (val === 4) {
if (this.aduitForm.reason.length <= 0 && this.aduitForm.remark === '') {
this.$message.error('审核拒绝需填写意见')
return false
}
}
const content = this.aduitForm.reason.join(', ')
let otherComments = ''
if (this.aduitForm.remark !== '') {
otherComments = this.aduitForm.remark
}
const formData = {
userId: '',
userName: '',
rnrOrderInfoId: this.pageData.rnrOrderInfoId,
otherComments: otherComments,
auditResult: val,
auditNote: content
}
console.log('ok', formData)
this.$emit('submit-audit-click', formData)
}
}
}
</script>
<style lang="scss" scoped>
.rnr-aduit-module{
border-top: 12px solid #F7F8FA;
padding: 10px 24px;
.aduit-title-box{
display: flex;
justify-content: space-between;
font-size: 12px;
font-weight: 400;
color: #A5ACB9;
line-height: 28px;
margin-bottom: 10px;
}
.aduit-title{
font-size: 16px;
font-weight: 600;
color: #3F3F59;
line-height: 28px;
}
.reject-btn{
color: #2A68FF;
border-color: #2A68FF;
}
}
</style>
<template>
<div v-loading.fullscreen.lock="fullscreenLoading" class="app-container aduit-detail">
<div class="aduit-top">
<div class="detail-basic">
<div class="basic-left">
<img :src="require('@/assets/img/natural_person.png')">
</div>
<div class="basic-right">
<div class="basic-main">
<div class="aduit-name">
<span>{{ pageData.orderTypeName + '审核' }}</span>
<!-- <span>'审核'</span> -->
<span class="status-tag">
<el-tag :type="pageData.orderStatus == 3 ? 'success' : 'warning'" size="mini">{{ form.verifyMsg ? form.verifyMsg.statusStr:'' }}</el-tag>
</span>
</div>
</div>
<div v-if="pageData" class="display-flex">
<div class="after-line">车企/经销商名称: {{ pageData.orgName }}</div>
<div class="after-line">业务类型: {{ pageData.orderTypeName }}</div>
<div>实名时间: {{ pageData.rnrDate }}</div>
</div>
</div>
</div>
</div>
<div class="aduit-bottom">
<comp-certification ref="compCertification" :form-data="form" :audit-images="auditImages"/>
</div>
<audit-form
ref="auditForm"
v-if="form.verifyMsg && [0, 1, 2].includes(form.verifyMsg.orderStatus)"
@submit-audit-click="handleSubmit"
:form-data="form"
:page-data="pageData"
/>
</div>
</template>
<script>
import CompCertification from './certification'
import { queryPersonDetailAuditDetail, queryEnterpriseAuditDetail, queryEnterprisePersonAuditDetail, queryAuditsubmit, queryBase64List } from '@/api/audit'
import AuditForm from './rnr-audit-form'
export default {
name: 'RnrDetail',
components: {
CompCertification,
AuditForm
},
props: {
pageData: {
type: Object,
default: () => {}
}
},
data() {
return {
fullscreenLoading: false,
form: {},
auditImages: {
ownerImages: [],
liaisonImages: [],
fileImages: [],
authInfoImages: [],
companyImages: [],
corporationImages: [],
auditVideoList: [],
tableList: []
}
}
},
mounted() {
if ([1, 2, 6, 7].includes(+this.pageData.orderType)) { // 自然人
this.handlePersonAuditData()
} else if ([3, 4, 5, 8].includes(+this.pageData.orderType)) { // 企业认证
this.handleEnterpriseAuditData()
} else { // 车企负责人
}
},
methods: {
getInItData() {
},
/**
* 提交数据
* @time 2022-06-09
*/
handleSubmit(formData) {
this.fullscreenLoading = true
queryAuditsubmit(formData)
.then((res) => {
this.fullscreenLoading = false
this.$emit('submit-click', formData)
})
.catch(() => {
this.fullscreenLoading = false
})
},
/**
* 获取详情-自然人认证
* @time 2022-06-09
*/
handlePersonAuditData() {
this.fullscreenLoading = true
queryPersonDetailAuditDetail({
rnrOrderInfoId: this.pageData.rnrOrderInfoId
})
.then((res) => {
this.fullscreenLoading = false
// console.log('我是自然人详情====' + JSON.stringify(res))
res.verifyMsg.statusStr = this.setOrderStatus(res.verifyMsg.orderStatus)
// 车主信息
if (res.vinOwnerMsg) {
res.vinOwnerMsg.isCompany = false
// res.vinOwnerMsg.newCertList = []
const tempImageIds = []
tempImageIds[0] = res.vinOwnerMsg.idImageFace
tempImageIds[1] = res.vinOwnerMsg.idImageEmblem
const fileImages = {
fileSystemIds: tempImageIds
}
console.log(fileImages)
this.handleImageData(fileImages, 'owner')
}
// 代办人信息
if (res.vinLiaisonMsg) {
const tempImageIds = []
tempImageIds[0] = res.vinLiaisonMsg.idImageFace
tempImageIds[1] = res.vinLiaisonMsg.idImageEmblem
const fileImages = {
fileSystemIds: tempImageIds
}
this.handleImageData(fileImages, 'liaison')
}
// 认证信息
if (res.verifyLivingMsg) {
const newAuthList = []
const faceImages = res.verifyLivingMsg.faceImage
// 认证信息-图片相关
for (const key in faceImages) {
newAuthList[key] = faceImages[key]
}
const fileImages = {
fileSystemIds: newAuthList
}
this.handleImageData(fileImages, 'auth')
// 认证信息-视频相关
if (res.verifyLivingMsg.livingVideo) {
this.auditImages.auditVideoList.push(res.verifyLivingMsg.livingVideo)
}
}
// 认证结果
if (res.authResultInfo.length > 0) {
this.auditImages.tableList = this.handleTableData(res.authResultInfo)
}
// 文件信息
var imageList = []
const pdfList = []
// 需要处理的照片数据
const keys = ['networkAccessContractImage', 'attorneyImage', 'buyBillImage', 'buyContractImage', 'transferOwnershipProveImage']
// 处理数据
keys.forEach(key => {
// 当前图片对象
const image = res.verifyFileMsg[key]
for (const key in image) {
if (image[key].indexOf('.pdf') > 0) {
pdfList.push(image[key])
} else {
imageList.push(image[key])
}
}
})
this.handleImageData({ fileSystemIds: imageList }, 'newFile')
this.handleImageData({ fileSystemIds: pdfList }, 'newFile', true)
this.form = {
...res
}
})
.catch(() => {
this.fullscreenLoading = false
})
},
/**
* 获取详情-企业认证
* @time 2022-06-09
*/
handleEnterpriseAuditData() {
this.fullscreenLoading = true
queryEnterpriseAuditDetail({
uuid: this.pageData.rnrOrderInfoId
})
.then((result) => {
this.fullscreenLoading = false
var res = result.data
// console.log('我是企业详情:=========' + JSON.stringify(res))
res.verifyMsg.statusStr = this.setOrderStatus(res.verifyMsg.orderStatus)
res.verifyMsg.currentDate = res.verifyMsg.reviewDate
res.verifyMsg.currentUserName = res.verifyMsg.reviewer
// 企业信息
if (res.companyInfoDetail) {
res.companyInfoDetail.newCertList = []
const fileMap = res.companyInfoDetail.companyLicenseFiles
const tempImageIds = []
for (const key in fileMap) {
if (Object.hasOwnProperty.call(fileMap, key)) {
tempImageIds[key] = fileMap[key].fileSystemId
}
}
const OwnerFileImages = {
fileSystemIds: tempImageIds
}
this.handleImageData(OwnerFileImages, 'company')
}
// 企业责任人
if (res.corporationInfoDetail) {
res.corporationInfoDetail.isCompany = true
var newCertList = []
// 正面
const BackPic = res.corporationInfoDetail.corporationCertFrontPic
if (BackPic !== '') {
newCertList.push(BackPic.fileSystemId)
}
// // 反面
const FrontPic = res.corporationInfoDetail.corporationCertBackPic
if (res.corporationInfoDetail.corporationCertBackPic) {
newCertList.push(FrontPic.fileSystemId)
}
const corporationImages = {
fileSystemIds: newCertList
}
this.handleImageData(corporationImages, 'corporation')
// 文件信息
const comFileList = res.corporationInfoDetail.fileSystemList
const comFiles = {
fileSystemIds: comFileList
}
this.handleImageData(comFiles, 'comFiles')
// 认证信息
if (res.verifyLivingMsg) {
if (res.verifyLivingMsg.livingVideo) {
this.auditImages.auditVideoList.push(res.verifyLivingMsg.livingVideo.fileBase64)
}
const newAuthList = []
const faceImages = res.verifyLivingMsg.faceImages
// 认证信息-图片相关
for (const key in faceImages) {
newAuthList[key] = faceImages[key].fileSystemId
}
const fileImages = {
fileSystemIds: newAuthList
}
this.handleImageData(fileImages, 'auth')
}
// 认证结果
if (res.authResultInfo.length > 0) {
if (res.authResultInfo.length > 0) {
this.auditImages.tableList = this.handleTableData(res.authResultInfo)
}
}
}
this.form = {
...res
}
})
.catch(() => {
this.fullscreenLoading = false
})
},
/**
* 获取企业负责人变更审核详情
* @time 2022-06-09
*/
handleEnterprisePersonAuditData() {
this.fullscreenLoading = true
queryEnterprisePersonAuditDetail({
uuid: this.pageData.rnrOrderInfoId
})
.then((res) => {
this.fullscreenLoading = false
// console.log(res)
this.form = {
...res.data
}
})
.catch(() => {
this.fullscreenLoading = false
})
},
/**
*COMMIT(0, "已提交 ,待确认"),
* ASSIGNMENT(1, "待分派/认领"),
* TO_EXAMINE(2, "待审核"),
* PASS(3, "审核通过"),
* NOT_PASS(4, "未通过"),
* CANCEL(9, "作废");
* @status
*/
setOrderStatus(status) {
var statusStr = ''
if (status === 0 || status === 1 || status === 2) {
statusStr = '待审核'
} else if (status === 4) {
statusStr = '审核不通过'
} else if (status === 3) {
statusStr = '审核通过'
} else {
statusStr = '作废'
}
return statusStr
},
/**
* 数据处理
*/
async handleImageData(data, type, isPdf = false) {
await queryBase64List(data)
.then((res) => {
var list = []
for (const key in res) {
list.push('data:image/jpeg;base64,' + res[key].base64)
}
if (type === 'owner') {
this.auditImages.ownerImages = list
} else if (type === 'liaison') {
this.auditImages.liaisonImages = list
} else if (type === 'newFile') {
if (isPdf) {
this.auditImages.filePdfs = list
} else {
this.auditImages.fileImages = list
}
} else if (type === 'auth') {
this.auditImages.authInfoImages = list
} else if (type === 'company') {
this.auditImages.companyImages = list
} else if (type === 'corporation') {
this.auditImages.corporationImages = list
} else if (type === 'comFiles') {
this.auditImages.fileImages = list
}
})
.catch(() => {
})
},
/**
* 处理认证结果信息
*/
handleTableData(data) {
var authInfoArr = []
var tempOCRArr = []
var tableList = []
for (const key in data) {
const item = data[key]
if (item.tpAction === 'OCR') {
tempOCRArr.push({
tpActionName: 'OCR',
success: item.success,
message: item.message
})
}
}
for (const key in data) {
const item = data[key]
if (item.tpAction === 'LIVENESS') {
authInfoArr.push({
tpActionName: '人脸识别',
success: item.success,
message: item.message
})
} else if (item.tpAction === 'FACE_COMPARE') {
authInfoArr.push({
tpActionName: '人脸比对相似度',
success: item.success,
message: item.message
})
} else if (item.tpAction === 'CERT_CHECK') {
authInfoArr.push({
tpActionName: '人脸比对',
success: item.success,
message: item.message
})
} else if (item.tpAction === 'ID_COMPARE') {
authInfoArr.push({
tpActionName: '人证比对',
success: item.success,
message: item.message
})
}
}
authInfoArr.push(...tempOCRArr)
let tempArr = []
for (let i = 0; i < authInfoArr.length; i++) {
if (i % 2 === 0) {
tempArr = []
tableList.push(tempArr)
}
tempArr.push({
name: authInfoArr[i].tpActionName + '结果',
className: 'custom-table-head w180'
})
tempArr.push({
name: authInfoArr[i].success ? '成功' : authInfoArr[i].message,
className: 'custom-table-td'
})
}
// 最后一行需要判断是否只有两个td,是需要加上colspan
const len = tableList.length - 1
if (tableList[len].length === 2) {
tableList[len][1].colspan = 3
}
return tableList
}
}
}
</script>
<style lang="scss">
.aduit-detail{
padding: 0px;
.aduit-top{
padding: 10px 24px;
}
.aduit-bottom{
border-top: 12px solid #F7F8FA;
padding: 10px 24px;
}
}
.detail-basic{
display: flex;
font-size: 14px;
font-weight: 400;
color: #778094;
line-height: 20px;
.el-image-viewer__close{
color: #000;
}
.basic-left{
margin-right: 20px;
img{
width: 60px;
}
}
.basic-right{
flex: 1;
}
.aduit-name{
font-size: 18px;
font-weight: 600;
color: #333333;
line-height: 25px;
}
.basic-main{
margin-bottom: 16px;
}
.display-flex{
display: flex;
}
.status-tag{
font-size: 12px;
margin-left: 10px;
}
.after-line{
&::after{
display: inline-block;
content: " ";
margin: 0 16px;
width: 1px;
height: 12px;
background-color: #E8E8E8;
vertical-align: middle;
}
}
}
.detail-group-box{
.detail-group-title{
font-size: 14px;
font-weight: 400;
color: #333333;
line-height: 20px;
margin-bottom: 12px;
img{
width: 18px;
vertical-align: -4px;
}
}
.detail-item-box{
display: flex;
border: 1px solid #F0F0F0;
border-right: none;
max-width: 747px;
margin-bottom: 20px;
}
.detail-item{
display: flex;
font-size: 14px;
font-weight: 400;
line-height: 42px;
}
.detail-item-title{
width: 138px;
padding-left: 20px;
background-color: rgba(247, 248, 250, 0.7);
border-radius: 3px 0px 0px 3px;
color: #1D2129;
border-right: 1px solid #F0F0F0;
}
.detail-item-info{
color: #333841;
width: 215px;
margin-left: 20px;
border-right: 1px solid #F0F0F0;
}
}
.custom-table{
width: 100%;
border-collapse: collapse;
border-bottom: 1px solid #F0F0F0;
border-left: 1px solid #F0F0F0;
margin-bottom: 10px;
tr{
height: 40px;
}
td{
border-right: 1px solid #F0F0F0;
border-top: 1px solid #F0F0F0;
}
.custom-table-head{
font-size: 14px;
font-weight: 400;
color: #494B53;
width: 140px;
background-color: rgba(247, 248, 250, 0.7);
padding-left: 20px;
}
.custom-table-td{
width: 200px;
font-size: 14px;
font-weight: 400;
color: #333841;
padding: 10px 20px 10px;
}
.w180{
width: 180px;
}
}
</style>
<template>
<div class="workorder-rnr-list">
<SearchTable
v-model="searchForm"
ref="searchTableRef"
title="平台车辆认证查询"
:immediately="true"
@submit="handleSubmit"
>
<template #slot-form>
<el-col :span="isTablet ? 12 : 6">
<el-form-item label="车辆VIN码" prop="vin" label-width="140px">
<el-input v-model="searchForm.vin" placeholder="请输入车辆VIN码" clearable />
</el-form-item>
</el-col>
<el-col :span="isTablet ? 12 : 6">
<el-form-item :class="isTablet ? 'mt-16' : ''" label="ICCID" prop="iccid" label-width="140px">
<el-input v-model="searchForm.iccid" placeholder="请输入ICCID" clearable />
</el-form-item>
</el-col>
<el-col :span="isTablet ? 12 : 6">
<el-form-item :class="isTablet ? 'mt-16' : ''" label="业务类型" prop="orderType" label-width="140px">
<el-select v-model="searchForm.orderType" placeholder="请输入业务类型" clearable>
<el-option v-for="type in ORDER_TYPE" v-bind="type" :key="type.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="isTablet ? 12 : 6">
<el-form-item :class="isTablet ? 'mt-16' : ''" label="认证进度" prop="orderStatus" label-width="140px">
<el-select v-model="searchForm.orderStatus" placeholder="请输入认证进度" clearable>
<el-option v-for="status in ORDER_STATUS" v-bind="status" :key="status.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="isTablet ? 12 : 6">
<el-form-item label="企业名称" prop="companyName" label-width="140px" class="mt-16">
<el-input v-model="searchForm.companyName" placeholder="请输入企业名称" clearable />
</el-form-item>
</el-col>
<el-col :span="isTablet ? 24 : 12">
<el-form-item label="认证日期" prop="createTimeQuery" label-width="140px" class="mt-16">
<el-date-picker
v-model="searchForm.createTimeQuery"
type="daterange"
value-format="timestamp"
start-placeholder="开始时间"
end-placeholder="结束时间"
clearable
/>
</el-form-item>
</el-col>
<el-col :span="isTablet ? 12 : 6">
<el-form-item label="车主/责任人姓名" prop="fullName" label-width="140px" class="mt-16">
<el-input v-model="searchForm.fullName" placeholder="请输入车主/责任人姓名" clearable />
</el-form-item>
</el-col>
<el-col :span="isTablet ? 12 : 6">
<el-form-item label="车主/责任人手机" prop="phone" label-width="140px" class="mt-16">
<el-input v-model="searchForm.phone" placeholder="请输入车主/责任人手机" clearable />
</el-form-item>
</el-col>
<el-col :span="isTablet ? 12 : 6">
<el-form-item label="车主/责任人证件号" prop="certNumber" label-width="140px" class="mt-16">
<el-input v-model="searchForm.certNumber" placeholder="请输入车主/责任人证件号" clearable />
</el-form-item>
</el-col>
</template>
<template #slot-table>
<el-table-column label="认证进度" prop="orderStatus" fixed="left" width="140px">
<template #default="{ row }">
<el-link type="primary" @click="handleOpenRnrOrderDetail(row)">{{ ORDER_STATUS.find(status => +status.value === +row.orderStatus).label }}</el-link>
</template>
</el-table-column>
<el-table-column label="车辆VIN" prop="vin" fixed="left" min-width="200px" />
<el-table-column label="ICCID" prop="iccid" min-width="200px" />
<el-table-column label="企业名称" prop="companyName" min-width="220px" />
<el-table-column label="车主/责任人" prop="fullName" min-width="140px" />
<el-table-column label="车主/责任人手机" prop="phone" min-width="160px" />
<el-table-column label="认证日期" prop="createTime" min-width="180px" />
<el-table-column label="业务类型" prop="orderType" width="180px">
<template #default="{ row }">{{ businessType(row) }}</template>
</el-table-column>
<el-table-column label="证件号" prop="certNumber" width="160px" />
<el-table-column label="审核人" prop="operatorName" width="140px" />
<el-table-column label="审核日期" prop="auditTime" width="180px" />
</template>
</SearchTable>
<el-drawer
:visible.sync="rnrDetail.show"
:before-close="() => (rnrDetail.show = false)"
title="审核详情"
direction="rtl"
size="1000px">
<RnrAuditDetail v-if="rnrDetail.show" :order-id="rnrDetail.data" />
</el-drawer>
</div>
</template>
<script>
import { pageListQuery } from '@/api/audit'
import SearchTable from '@/components/SearchTable'
import RnrAuditDetail from './components/rnr-audit-detail'
// 认证进度
const ORDER_STATUS = [
{ label: '已提交', value: 0 },
{ label: '待分派/认领', value: 1 },
{ label: '待审核', value: 2 },
{ label: '审核通过', value: 3 },
{ label: '未通过', value: 4 },
{ label: '作废', value: 9 }
]
// 业务类型
const ORDER_TYPE = [
{ label: '自然人新车实名认证', value: 1 },
{ label: '自然人二手车实名认证', value: 2 },
{ label: '企业新车实名认证', value: 3 },
{ label: '车企新车实名认证', value: 4 },
{ label: '企业责任人变更', value: 5 },
{ label: '车主解绑', value: 6 },
{ label: '二手车主解绑', value: 7 },
{ label: '车企实名解绑', value: 8 },
{ label: '设备更换', value: 9 },
{ label: '一车多卡绑定', value: 10 },
{ label: '重新绑定', value: 11 },
{ label: '企业解绑', value: 12 }
]
export default {
name: 'WorkOrderRnrList',
components: { SearchTable, RnrAuditDetail },
data() {
return {
rnrDetail: {
show: false,
data: ''
},
searchForm: {},
ORDER_STATUS,
ORDER_TYPE
}
},
methods: {
/**
* 提交方法
* @param formData 表单数据
* @param callback 控制页面显示的回调
*/
async handleSubmit(formData, callback) {
try {
// 如果当前选择了认证时间
if (formData.createTimeQuery) {
const [createTimeQueryStart, createTimeQueryEnd] = formData.createTimeQuery
formData.createTimeQueryStart = createTimeQueryStart
formData.createTimeQueryEnd = createTimeQueryEnd + 1000 * 60 * 60 * 24 - 1
delete formData.createTimeQuery
}
// 开始查询接口
const { list, totalCount } = await pageListQuery(formData)
// 渲染界面
callback({ list, totalCount })
} catch (error) {
callback([], 0)
console.error(error)
}
},
/**
* 跳转到工单详情页面
* @param row 当前行数据
*/
handleOpenRnrOrderDetail(row) {
// 打开弹框
this.rnrDetail.show = true
// 记录当前订单编号
this.rnrDetail.data = row.orderId
},
/**
* 业务类型
* @param {Object} row 当前行数据
* @time 2022-09-15 16:27:19
*/
businessType(row) {
try {
return ORDER_TYPE.find(status => +status.value === +row.orderType).label
} catch (error) {
return ''
}
}
}
}
</script>
<style lang="scss">
.workorder-rnr-list {
.mt-16 {
margin-top: 16px;
}
.el-col {
&:last-child {
margin-top: 16px;
}
}
}
</style>
<template>
<div v-loading.fullscreen.lock="fullscreenLoading" class="page-home">
<div class="container">
<div class="page-home-banner page-category-bg">
<div class="page-home-banner-title">{{ companyName }}欢迎您</div>
<!-- <div class="page-home-banner-subtitle">致力于成为一流的汽车数字化运营服务提供商</div> -->
</div>
<div class="page-home-realname page-category-bg">
<div v-if="!disabledClass('PersonRealnameStep1')" class="page-home-column" @click="handleToPage('PersonRealnameStep1')">
<div class="page-home-column-imageicon person" />
<div class="page-home-column-name">自然人实名认证</div>
<div class="page-home-column-desc">个人用户实名信息登记</div>
<div class="page-home-column-btn">立即认证</div>
</div>
<div v-if="!disabledClass('EnterpriseRealnameStep1')" class="page-home-column" @click="handleToPage('EnterpriseRealnameStep1')">
<div class="page-home-column-imageicon company" />
<div class="page-home-column-name">企业实名认证</div>
<div class="page-home-column-desc">单位用户实名信息登记</div>
<div class="page-home-column-btn">立即认证</div>
</div>
<div v-if="!disabledClass('CarEnterpriseRealname')" class="page-home-column" @click="handleToPage('CarEnterpriseRealname')">
<div class="page-home-column-imageicon vehicle" />
<div class="page-home-column-name">车企实名认证</div>
<div class="page-home-column-desc">车辆研发/测试期的企业实名</div>
<div class="page-home-column-btn">立即认证</div>
</div>
<div v-if="!disabledClass('PersonChangeStep1')" class="page-home-column" @click="handleToPage('PersonChangeStep1')">
<div class="page-home-column-imageicon change" />
<div class="page-home-column-name">企业责任人变更</div>
<div class="page-home-column-desc">单位用户实名责任人变更</div>
<div class="page-home-column-btn">立即认证</div>
</div>
</div>
<div class="page-home-other-service page-category-bg">
<div class="page-home-row">
<div :class="disabledClass('CardBindingStepOne') && 'disabled'" class="page-home-column-middle" @click="handleToPage('CardBindingStepOne')">
<div class="page-home-column-container">
<div class="page-home-column-imageicon multicard-bind" />
<div class="page-home-column-wrap">
<div class="page-home-column-name">一车多卡绑定</div>
<div class="page-home-column-desc">支持已实名车辆新增卡绑定,无需重复认证</div>
</div>
</div>
<div class="page-home-column-bind">立即绑定 >></div>
</div>
<div :class="disabledClass('CardUnbindingStepOne') && 'disabled'" class="page-home-column-middle" @click="handleToPage('CardUnbindingStepOne')">
<div class="page-home-column-container">
<div class="page-home-column-imageicon card-unbind" />
<div class="page-home-column-wrap">
<div class="page-home-column-name">卡解绑</div>
<div class="page-home-column-desc">支持误绑、退/换车等场景下的卡解绑</div>
</div>
</div>
<div class="page-home-column-bind">立即解绑 >></div>
</div>
<div :class="disabledClass('ReplacementStepOne') && 'disabled'" class="page-home-column-middle no-border-right" @click="handleToPage('ReplacementStepOne')">
<div class="page-home-column-container">
<div class="page-home-column-imageicon iccid-change" />
<div class="page-home-column-wrap">
<div class="page-home-column-name">换件</div>
<div class="page-home-column-desc">支持硬件设备更换场景下的卡解绑及卡绑定,无需重复认证</div>
</div>
</div>
<div class="page-home-column-bind">立即换件 >></div>
</div>
<div :class="disabledClass('CarUnbindingStepOne') && 'disabled'" class="page-home-column-large" @click="handleToPage('CarUnbindingStepOne')">
<div class="page-home-column-large-container">
<div class="page-home-column-imageicon vehicle-unbind" />
<div class="page-home-column-large-wrap">
<div class="page-home-column-large-name">车企实名解绑</div>
<div class="page-home-column-large-desc">支持车企研发、制造期的批量解绑,降低安全风险</div>
</div>
</div>
<div class="page-home-column-large-bind">立即解绑 >></div>
</div>
<div :class="disabledClass('EnterpriseUnbindingStepOne') && 'disabled'" class="page-home-column-large no-border-right" @click="handleToPage('EnterpriseUnbindingStepOne')">
<div class="page-home-column-large-container">
<div class="page-home-column-imageicon company-unbind" />
<div class="page-home-column-large-wrap">
<div class="page-home-column-large-name">企业实名解绑</div>
<div class="page-home-column-large-desc">支持单位用户实名的卡解绑</div>
</div>
</div>
<div class="page-home-column-large-bind">立即解绑 >></div>
</div>
</div>
</div>
</div>
<footer>Copyright 2017-2019 联通智网科技股份有限公司 版权所有 京ICP备16005440号-1</footer>
</div>
</template>
<script>
import { queryCarEnterpriseDetail } from '@/api/realname-car-enterprise'
export default {
name: 'Home',
data() {
return {
companyName: this.$store.getters.companyName,
fullscreenLoading: false,
isTablet: window.OS.isTablet
}
},
methods: {
/**
* 跳转页面
*/
handleToPage(name) {
// 如果当前是禁用的菜单
if (this.disabledClass(name)) {
return
}
if (name === 'CarEnterpriseRealname') {
// 车企实名
this.queryCarEnterpriseRealnameState()
return
}
// 如果当前是企业实名
if (name === 'EnterpriseRealnameStep1') {
// 如果当前是平板,且非一体机
if (this.isTablet && this.$store.getters.deviceType !== 'aio') {
this.$router.push({ name: 'EnterpriseRealnameStepPad1' })
return
}
}
this.$router.push({ name })
},
async queryCarEnterpriseRealnameState() {
this.fullscreenLoading = true
try {
const respData = await queryCarEnterpriseDetail({})
if (respData.vehicleEnterpriseId) {
this.$router.push({ name: 'CarEnterpriseRealnameFlow1' })
} else {
this.$router.push({ name: 'CarEnterpriseRealnameStep1' })
}
} catch (e) {
console.log(e)
}
this.fullscreenLoading = false
},
/**
* 检测是否是禁用的class
* @param routerName 路由名称
*/
disabledClass(routerName) {
// 是否在路由中包括
let isEnable = false
// 取出当前所有的路由
this.$store.getters.addRoutes.forEach(route => {
// 如果一级目录匹配上了
if (route.name === routerName) {
isEnable = true
}
// 如果孩子节点中有此目录
if (route.children && route.children.some(child => child.name === routerName)) {
isEnable = true
}
})
return !isEnable
}
}
}
</script>
<style lang="scss" scoped>
.page-home {
.page-category-bg {
background-size: 100% auto;
background-position: top center;
background-repeat: no-repeat;
}
.page-home-banner {
background-image: url(../../assets/img/pic_banner.png);
background-size: auto 100%;
color: #FFFFFF;
height: 300px;
padding: 128px 0 0;
text-align: center;
.page-home-banner-title {
font-size: 40px;
font-weight: bold;
height: 40px;
line-height: 40px;
}
.page-home-banner-subtitle {
font-size: 20px;
font-weight: 400;
line-height: 30px;
letter-spacing: 2px;
margin-top: 28px;
}
}
.page-home-realname {
background-image: url(../../assets/img/realname-pic.png);
background-size: auto 100%;
background-position: center;
background-repeat: no-repeat;
display: flex;
padding: 146px 0 60px;
position: relative;
justify-content: center;
.page-home-column {
align-items: center;
background-color: rgba(255, 255, 255, 0);
border-radius: 4px;
cursor: pointer;
display: flex;
flex-direction: column;
width: 232px;
height: 290px;
justify-content: center;
margin-left: 12px;
transition: all 500ms ease;
.page-home-column-imageicon {
background-size: 100% 100%;
background-repeat: no-repeat;
background-position: center;
width: 102px;
height: 116px;
&.person {
background-image: url(../../assets/img/icon-person.png);
}
&.company {
background-image: url(../../assets/img/icon-company.png);
}
&.vehicle {
background-image: url(../../assets/img/icon-vehicle.png);
}
&.change {
background-image: url(../../assets/img/icon-change.png);
}
}
.page-home-column-name {
color: #191C28;
font-size: 20px;
text-align: center;
font-weight: 600;
line-height: 28px;
margin-top: 18px;
}
.page-home-column-desc {
color: #9DA6BB;
font-size: 14px;
font-weight: 400;
text-align: center;
line-height: 20px;
margin-top: 6px;
}
.page-home-column-btn {
align-items: center;
background: #2A68FF;
box-shadow: 0 7px 13px 0 rgba(42,104,255,0.20);
border-radius: 4px;
color: #FFFFFF;
display: flex;
font-size: 14px;
font-weight: 500;
width: 88px;
justify-content: center;
margin-top: 16px;
height: 20px;
opacity: 0;
overflow: hidden;
transition: all 300ms ease;
}
&:first-child {
margin-left: 0px;
}
&:hover {
background: #FFFFFF;
box-shadow: 0 8px 22px 0 rgba(111,119,171,0.10);
transform: translateY(-12px);
.page-home-column-btn {
opacity: 1;
height: 32px;
}
}
}
&:after {
background-image: url(../../assets/img/text_realname.png);
background-size: 100% auto;
background-repeat: no-repeat;
content: "";
display: block;
width: 432px;
height: 52px;
position: absolute;
top: 50px;
left: 50%;
transform: translateX(-50%);
}
}
.page-home-other-service {
background-image: url(../../assets/img/other-service-pic.png);
background-size: auto 260px;
padding: 134px 0 0;
position: relative;
.page-home-row {
background: #FFFFFF;
box-shadow: 0 8px 24px 0 rgba(112,118,150,0.19);
border-radius: 4px;
display: flex;
width: 960px;
margin: 0 auto;
flex-wrap: wrap;
justify-content: center;
.page-home-column-imageicon {
background-size: 100% auto;
background-position: center;
background-repeat: no-repeat;
flex-shrink: 0;
width: 60px;
height: 60px;
&.multicard-bind {
background-image: url(../../assets/img/icon-multicard-unbind.png);
}
&.card-unbind {
background-image: url(../../assets/img/icon-card-unbind.png);
}
&.iccid-change {
background-image: url(../../assets/img/icon-change-iccid.png);
}
&.vehicle-unbind {
background-image: url(../../assets/img/icon-vehicle-unbind.svg);
}
&.company-unbind {
background-image: url(../../assets/img/icon-enterprise-unbind.svg);
}
}
.page-home-column-middle {
border-right: 1px solid #eeeeee;
box-sizing: border-box;
cursor: pointer;
flex-shrink: 0;
width: 320px;
height: 262px;
position: relative;
overflow: hidden;
.page-home-column-container {
align-items: center;
display: flex;
flex-direction: column;
padding: 40px 60px 0px;
.page-home-column-wrap {
text-align: center;
.page-home-column-name {
color: #0A1D30;
font-size: 18px;
line-height: 26px;
font-weight: 600;
margin-top: 24px;
}
.page-home-column-desc {
color: #757F92;
font-size: 14px;
line-height: 20px;
font-weight: 400;
margin-top: 12px;
}
}
}
.page-home-column-bind {
background: #FFFFFF;
align-items: center;
bottom: 0;
color: #FFFFFF;
display: flex;
font-size: 14px;
font-weight: 500;
position: absolute;
left: 0px;
right: 0px;
height: 40px;
justify-content: center;
transform: translateY(40px);
transition: all 500ms ease;
}
&:hover {
box-shadow: 0 8px 24px 0 rgba(66, 72, 109, 0.10);
.page-home-column-bind {
background: #2A68FF;
transform: translateY(0px);
}
}
&.no-border-right {
border-right: 0;
}
&.disabled {
cursor: not-allowed;
.page-home-column-container {
opacity: 0.3;
.page-home-column-imageicon {
filter: grayscale(100%);
}
}
&:hover {
box-shadow: none;
.page-home-column-bind {
display: none;
}
}
}
}
.page-home-column-large {
border-top: 1px solid #eeeeee;
border-right: 1px solid #eeeeee;
box-sizing: border-box;
cursor: pointer;
flex-shrink: 0;
width: 480px;
height: 200px;
position: relative;
overflow: hidden;
.page-home-column-large-container {
display: flex;
padding: 60px 70px 0px 60px;
.page-home-column-large-wrap {
padding-left: 30px;
.page-home-column-large-name {
color: #0A1D30;
font-size: 18px;
line-height: 26px;
font-weight: 600;
}
.page-home-column-large-desc {
color: #757F92;
font-size: 14px;
line-height: 20px;
font-weight: 400;
margin-top: 12px;
}
}
}
.page-home-column-large-bind {
background: #FFFFFF;
align-items: center;
bottom: 0;
color: #FFFFFF;
display: flex;
font-size: 14px;
font-weight: 500;
position: absolute;
left: 0px;
right: 0px;
height: 40px;
justify-content: center;
transform: translateY(40px);
transition: all 500ms ease;
}
&:hover {
box-shadow: 0 8px 24px 0 rgba(66, 72, 109, 0.10);
.page-home-column-large-bind {
background: #2A68FF;
transform: translateY(0px);
}
}
&.no-border-right {
border-right: 0;
}
&.disabled {
cursor: not-allowed;
.page-home-column-large-container {
opacity: 0.3;
.page-home-column-large-imageicon {
filter: grayscale(100%);
}
}
&:hover {
box-shadow: none;
.page-home-column-large-bind {
display: none;
}
}
}
}
}
&:after {
background-image: url(../../assets/img/text_other_service.png);
background-size: 100% auto;
background-repeat: no-repeat;
content: "";
display: block;
width: 275px;
height: 52px;
left: 50%;
position: absolute;
top: 50px;
transform: translateX(-50%);
}
}
footer {
align-items: center;
background: #1D2229;
color: rgba(255, 255, 255, 0.4);
display: flex;
font-size: 14px;
font-weight: 400;
height: 80px;
margin-top: 40px;
justify-content: center;
}
}
</style>
<template>
<div class="login-tab">
<div class="login-tabs">
<div :class="active === 'msg'? 'tab-active': ''" class="login-tab-pane" @click="active = 'msg'">短信登录</div>
<div class="tab-line"/>
<div :class="active === 'password'? 'tab-active': ''" class="login-tab-pane" @click="active = 'password'">账号登录</div>
</div>
<!-- 验证码登录 -->
<div v-show="active === 'msg'">
<MsgValidate ref="msgValidateRef" />
<el-button :loading="loading" type="primary" class="btn-login" @click.native.prevent="handleLogin">立即登录</el-button>
</div>
<!-- 密码登录 -->
<el-form v-show="active === 'password'" ref="loginPassForm" :model="loginForm" :rules="loginRules" class="login-form" autocomplete="off" label-position="left">
<el-form-item prop="userName">
<el-input v-model="loginForm.userName" placeholder="请输入用户名" autocomplete="off" type="text" auto-complete="on" />
</el-form-item>
<el-form-item prop="password">
<el-input v-model="loginForm.password" placeholder="请输入密码" autocomplete="off" type="password" auto-complete="on" />
</el-form-item>
<el-form-item prop="captchaCode">
<div class="phone-captcha">
<el-input v-model="loginForm.captchaCode" placeholder="图形验证码" autocomplete="off" type="text" maxlength="6" auto-complete="on">
<img slot="suffix" :src="captchaImg" class="captch-img" alt="验证码" @click="fetchVerifyGraphic">
</el-input>
</div>
</el-form-item>
<div class="forget-password">
<el-button type="text" @click="forgetPassword">忘记密码</el-button>
</div>
<el-button :loading="loading" type="primary" class="btn-login" @click.native.prevent="handleLogin">立即登录</el-button>
</el-form>
</div>
</template>
<script>
import SvgIcon from '@/components/SvgIcon'
import { getToken } from '@/utils/auth'
import cloneDeep from 'lodash/cloneDeep'
import MsgValidate from './MsgValidate.vue'
import { getLoginSecretKey, getGraphic } from '@/api/user'
import { getJMJqueryParams } from '@/utils/sm4'
export default {
name: 'LoginTab',
components: { SvgIcon, MsgValidate },
data() {
return {
active: 'msg',
loginForm: {
userName: '',
password: '',
requestId: '', // 登录密码加密的请求id
platformSource: 'Web',
captchaCode: ''
},
loginRules: {
userName: [
{ required: true, message: '请输入用户名', trigger: 'blur' }
],
captchaCode: [
{ required: true, message: '请输入图片验证码', trigger: 'blur' }
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' }
]
},
captchaImg: '',
loading: false,
redirect: undefined
}
},
watch: {
$route: {
handler: function(route) {
this.redirect = route.query && route.query.redirect
},
immediate: true
}
},
mounted() {
this.fetchVerifyGraphic()
},
methods: {
/**
* 查询图片验证码
*/
async fetchVerifyGraphic() {
// 获取图片验证码
const { captchaImg, requestId } = await getGraphic({ platformSource: 'Web' })
// 记录当前图片验证码
this.captchaImg = captchaImg
// 请求id
this.loginForm.captchaId = requestId
},
/**
* 点击登录方法
*/
handleLogin() {
let params
if (this.active === 'msg') {
params = this.$refs.msgValidateRef.getData()
this.logIn(params)
} else if (this.active === 'password') {
this.$refs.loginPassForm.validate(async valid => {
if (valid) {
params = cloneDeep(this.loginForm)
// 获取随机请求id-登录密码加密
await this.getSecretKey(params)
this.logIn(params)
} else {
params = false
}
})
}
},
// 登录
logIn(params) {
if (params) {
params = { ...params, ...{ type: this.active }}
this.loading = true
this.$store.dispatch('user/login', params)
.then(() => {
if (getToken()) {
location.href = this.redirect || process.env.VUE_APP_ROUTER
}
this.loading = false
})
.catch(() => {
// 失败,清空验证码们,并重新获取图形验证码
this.$refs.msgValidateRef && this.$refs.msgValidateRef.clearInit()
this.fetchVerifyGraphic()
this.loading = false
})
}
},
// 获取随机请求id-登录密码加密
async getSecretKey(params) {
const { requestId, secretKey } = await getLoginSecretKey()
params.requestId = requestId
params.password = getJMJqueryParams(params.password, secretKey)
},
// 忘记密码
forgetPassword() {
this.$emit('forgetPassword')
}
}
}
</script>
<style lang="scss">
.login-tab{
.login-tabs {
display: flex;
flex-direction: row;
justify-content: space-between;
.login-tab-pane {
font-size: 20px;
font-weight: 600;
color: #212026;
line-height: 28px;
cursor: pointer;
// &:first-child {
// padding-right: 62px;
// border-right: 1px dashed #ccc;
// }
}
.tab-line {
width: 1px;
height: 34px;
background: url(../../../assets/img/login-line.svg) no-repeat 0 0;
background-size: 100% 100%;
}
.tab-active {
padding-bottom: 8px;
border-bottom: 2px solid #2A68FF;
color: #2A68FF;
}
}
.login-form {
width: 100%;
.btn-send-sms {
background-color: #ffffff;
border-color: #2A68FF;
color: #2A68FF;
height: 36px;
padding: 0;
width: 120px;
}
.phone-captcha {
display: flex;
.captcha-img-wrap {
align-items: center;
display: flex;
margin-top: 1px;
.captch-img {
flex-shrink: 0;
width: 90px;
height: 40px;
}
.refresh-captcha {
cursor: pointer;
font-size: 20px;
width: 20px;
height: 20px;
margin-left: 4px;
}
}
.el-button {
margin-left: 10px;
flex: none;
width: 120px;
}
.captch-img {
width: 90px;
height: 40px;
margin-top: -6px;
}
}
.input-wrap {
display: flex;
}
.forget-password {
display: flex;
justify-content: flex-end;
.el-button {
padding: 24px 0 0;
}
}
}
.btn-login {
background: #3269FF;
border-radius: 4px;
font-size: 16px;
width: 100%;
height: 48px;
margin-top: 46px;
}
}
</style>
<template>
<el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" autocomplete="off" label-position="left">
<el-form-item prop="phone">
<el-input v-model="loginForm.phone" placeholder="手机号码" autocomplete="off" type="text" maxlength="11" auto-complete="on" />
</el-form-item>
<slot name="password"/>
<el-form-item prop="captcha">
<div class="phone-captcha">
<el-input v-model="loginForm.captcha" placeholder="图形验证码" autocomplete="off" type="text" maxlength="6" auto-complete="on">
<img slot="suffix" :src="captchaImg" class="captch-img" alt="验证码" @click="fetchVerifyGraphic">
</el-input>
</div>
</el-form-item>
<el-form-item prop="sms">
<div class="input-wrap">
<el-input v-model="loginForm.sms" placeholder="验证码" autocomplete="off" type="text" maxlength="6" auto-complete="on">
<el-button slot="suffix" :disabled="time > 0" type="text" @click="getSmsCaptcha">{{ captchaBtnText }}</el-button>
</el-input>
</div>
</el-form-item>
</el-form>
</template>
<script>
import { validPhone } from '@/utils/validate'
import SvgIcon from '@/components/SvgIcon'
import { sendSmsCaptcha, getGraphic } from '@/api/user'
export default {
name: 'Msg',
components: { SvgIcon },
data() {
const validateUsername = (rule, value, callback) => {
if (!validPhone(value)) {
callback(new Error('请输入手机号码'))
} else {
callback()
}
}
const validatePassword = (rule, value, callback) => {
if (value.length < 6) {
callback(new Error('请输入短信验证码'))
} else {
callback()
}
}
const validateCaptcha = (rule, value, callback) => {
if (value.length !== 4) {
callback(new Error('请输入验证码'))
} else {
callback()
}
}
return {
loginForm: {
phone: '',
captcha: '',
sms: ''
},
loginRules: {
phone: [
{ trigger: 'blur', validator: validateUsername }
],
captcha: [
{ trigger: 'blur', validator: validateCaptcha }
],
sms: [
{ trigger: 'blur', validator: validatePassword }
]
},
// 图片验证码
captchaImg: '',
// 请求图片验证码返回的请求id
requestId: '',
captchaBtnText: '发送验证码',
timer: null,
time: 0
}
},
watch: {
$route: {
handler: function(route) {
this.redirect = route.query && route.query.redirect
},
immediate: true
}
},
mounted() {
// 默认查询图片验证码
this.fetchVerifyGraphic()
},
methods: {
/**
* 查询图片验证码
*/
async fetchVerifyGraphic() {
// 获取图片验证码
const { captchaImg, requestId } = await getGraphic({ platformSource: 'Web' })
// 记录当前图片验证码
this.captchaImg = captchaImg
// 请求id
this.requestId = requestId
},
/**
* 获取短信验证码
*/
getSmsCaptcha() {
// 校验结果
const validResult = []
this.$refs.loginForm.validateField(
['phone', 'captcha'],
(errorMsg) => {
if (!errorMsg) {
validResult.push(errorMsg)
// 没有校验完全
if (validResult.length !== 2) {
return
}
clearTimeout(this.timer)
sendSmsCaptcha({
phone: this.loginForm.phone,
captchaImage: this.loginForm.captcha,
requestId: this.requestId,
platformSource: 'Web'
}).then(data => {
this.time = 60
this.captchaBtnText = `${this.time - 1}S后重发`
this.countdown()
}).catch(() => {
// 如果接口报错了,则刷新二维码
this.fetchVerifyGraphic()
this.captchaBtnText = '重新获取'
})
}
})
},
/**
* 开始倒计时
*/
countdown() {
this.timer = setTimeout(() => {
if (this.time > 1) {
this.time--
this.captchaBtnText = `${this.time}S后重发`
this.countdown()
} else {
this.time = 0
clearTimeout(this.timer)
this.captchaBtnText = '重新获取'
}
}, 1000)
},
getData() {
// 校验结果
let result
const validResult = []
this.$refs.loginForm.validateField(
['phone', 'sms'],
(errorMsg) => {
if (!errorMsg) {
validResult.push(errorMsg)
// 没有校验完全
if (validResult.length !== 2) {
result = false
return
}
result = this.loginForm
}
})
return result
},
// 失败,清空验证码们,并重新获取图形验证码
clearInit() {
this.fetchVerifyGraphic()
this.loginForm.captcha = ''
this.loginForm.sms = ''
}
}
}
</script>
<style lang="scss">
.login-form {
width: 100%;
.btn-send-sms {
background-color: #ffffff;
border-color: #2A68FF;
color: #2A68FF;
height: 36px;
padding: 0;
width: 120px;
}
.phone-captcha {
display: flex;
.captcha-img-wrap {
align-items: center;
display: flex;
margin-top: 1px;
.captch-img {
flex-shrink: 0;
width: 90px;
height: 40px;
}
.refresh-captcha {
cursor: pointer;
font-size: 20px;
width: 20px;
height: 20px;
margin-left: 4px;
}
}
.el-button {
margin-left: 10px;
flex: none;
width: 120px;
}
.captch-img {
width: 90px;
height: 40px;
margin-top: -6px;
}
}
.input-wrap {
display: flex;
}
.forget-password {
display: flex;
justify-content: flex-end;
.el-button {
padding: 24px 0 0;
}
}
}
</style>
<template>
<div class="reset-result">
<div v-if="result === 'NetworkError'">
<div class="result-text">服务器异常,请重试</div>
<img :src="require('@/assets/img/reset-network-error.svg')" alt="network-error" class="result-ico">
<el-button type="primary" class="result-btn" @click="toReset">重试</el-button>
</div>
<div v-if="result === 'success'">
<div class="result-text">恭喜,重置密码成功</div>
<img :src="require('@/assets/img/reset-success.svg')" alt="success" class="result-ico">
<el-button type="primary" class="result-btn" @click="toLogin">去登录</el-button>
</div>
</div>
</template>
<script>
export default {
name: 'ResetResult',
props: {
result: {
type: String,
default: ''
}
},
data() {
return {
}
},
watch: {
},
mounted() {
},
methods: {
toReset() {
location.reload()
},
toLogin() {
this.$router.push({ name: 'Login' })
}
}
}
</script>
<style lang="scss">
.reset-result {
text-align: center;
padding-top: 140px;
.result-text {
height: 28px;
font-size: 20px;
font-weight: 600;
color: #212026;
line-height: 28px;
margin-bottom: 48px;
}
.result-ico {
width: 72px;
height: 72px;
margin: 0 auto 156px;
display: block;
}
.result-btn {
width: 286px;
height: 44px;
background: #3269FF;
border-radius: 4px;
font-size: 16px;
}
}
</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