Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
聂康
cusc-realname-private-pc-master
Commits
d2c4018b
Commit
d2c4018b
authored
Jun 17, 2025
by
kang.nie@inzymeits.com
Browse files
初始化代码
parent
de8a8ae5
Pipeline
#3105
failed with stages
in 0 seconds
Changes
393
Pipelines
1
Show whitespace changes
Inline
Side-by-side
src/assets/img/text_other_service.png
0 → 100644
View file @
d2c4018b
14.5 KB
src/assets/img/text_realname.png
0 → 100644
View file @
d2c4018b
16.1 KB
src/assets/rnr/ico_fail.png
0 → 100644
View file @
d2c4018b
25.4 KB
src/assets/rnr/ico_success.png
0 → 100644
View file @
d2c4018b
23.6 KB
src/assets/special-business/bindImg.png
0 → 100644
View file @
d2c4018b
106 KB
src/assets/special-business/course.png
0 → 100644
View file @
d2c4018b
126 KB
src/assets/special-business/new_car_owner@2x.png
0 → 100644
View file @
d2c4018b
33.8 KB
src/assets/special-business/tbox.png
0 → 100644
View file @
d2c4018b
117 KB
src/assets/special-business/used_car_new_owner@2x.png
0 → 100644
View file @
d2c4018b
39 KB
src/components/CarCompany/index.vue
0 → 100644
View file @
d2c4018b
<
template
>
<el-select
:value=
"value"
:placeholder=
"placeholder"
clearable
@
change=
"handleCarCompanyChange"
>
<el-option
v-for=
"item in list"
v-bind=
"item"
:key=
"item.value"
/>
</el-select>
</
template
>
<
script
>
import
{
queryOrgByList
}
from
'
@/api/management
'
export
default
{
name
:
'
CarCompany
'
,
props
:
{
value
:
{
type
:
[
String
,
Number
],
default
:
''
},
placeholder
:
{
type
:
String
,
default
:
'
请选择
'
},
// 默认选中第一项
defaultSelectFirst
:
{
type
:
Boolean
,
default
:
false
}
},
data
()
{
return
{
list
:
[]
}
},
mounted
()
{
this
.
queryOrgByList
()
},
methods
:
{
/**
* 查询车厂列表
*/
async
queryOrgByList
()
{
const
data
=
await
queryOrgByList
()
// 如果查询出来了车企
if
(
data
&&
data
.
length
>
0
)
{
this
.
list
=
data
.
map
(
item
=>
{
return
{
value
:
item
.
organCode
,
label
:
item
.
organName
}
})
}
// 如果当前需要默认选中第一项
this
.
defaultSelectFirst
&&
this
.
handleCarCompanyChange
(
this
.
list
[
0
].
value
)
},
/**
* 车厂切换方法
* @param v 当前方法
*/
handleCarCompanyChange
(
v
)
{
this
.
$emit
(
'
input
'
,
v
)
this
.
$emit
(
'
change
'
,
v
)
}
}
}
</
script
>
src/components/Common/index.js
0 → 100644
View file @
d2c4018b
export
default
{
computed
:
{
cacheKey
()
{
return
this
.
$route
.
name
}
},
methods
:
{
cacheSetStepData
(
key
,
data
)
{
window
.
sessionStorage
.
setItem
(
key
,
JSON
.
stringify
(
data
))
},
cacheGetStepData
(
key
)
{
try
{
const
ret
=
JSON
.
parse
(
window
.
sessionStorage
.
getItem
(
key
))
return
ret
}
catch
(
e
)
{
return
null
}
},
cacheDelStepData
(
key
)
{
window
.
sessionStorage
.
removeItem
(
key
)
},
isValidObject
(
obj
)
{
return
typeof
obj
===
'
object
'
&&
obj
!==
null
},
cloneObject
(
obj
)
{
return
JSON
.
parse
(
JSON
.
stringify
(
obj
))
}
}
}
src/components/CompAttachment/index.vue
0 → 100644
View file @
d2c4018b
<
script
>
import
html2canvas
from
'
html2canvas
'
export
default
{
name
:
'
CompAttachment
'
,
props
:
{
vin
:
{
type
:
[
String
,
Array
],
default
:
null
},
iccid
:
{
type
:
Array
,
default
:
null
},
fileId
:
{
type
:
String
,
default
:
''
}
},
mounted
()
{
this
.
exportAttachmentUrl
()
},
methods
:
{
/**
* 导出图片链接
*/
async
exportAttachmentUrl
()
{
// 导出图片
const
cvs
=
await
html2canvas
(
document
.
querySelector
(
'
.component-attachment-wrapper
'
))
// 导出图片
this
.
$emit
(
'
change
'
,
cvs
.
toDataURL
())
}
},
render
()
{
return
(
<
div
class
=
'
component-attachment-wrapper
'
>
<
h1
>*
附件
<
/h1
>
{
typeof
this
.
vin
===
'
string
'
?
(
<
div
>
<
div
class
=
'
vin-title
'
>
VIN
:
{
this
.
vin
}
<
/div
>
<
div
class
=
'
vin-title
'
>
ICCID
:
{
this
.
iccid
.
join
(
'
,
'
)}
<
/div
>
<
/div
>
)
:
(
this
.
fileId
?
(
<
div
>
<
div
class
=
'
vin-title
'
>
文件id
:
{
this
.
fileId
}
<
/div
>
<
div
class
=
'
vin-content
'
><
/div
>
<
/div
>
)
:
(
<
div
>
{
this
.
vin
.
map
(
vin
=>
(
<
div
style
=
'
border-top: 1px solid #666666;
'
>
<
p
>
VIN
:
{
vin
.
vin
}
<
/p
>
<
p
>
ICCID
:
{
vin
.
iccidList
.
join
(
'
,
'
)}
<
/p
>
<
/div
>
))
}
<
/div
>
)
)
}
<
/div
>
)
}
}
</
script
>
<
style
lang=
"scss"
>
.component-attachment-wrapper
{
background-color
:
#ffffff
;
width
:
750px
;
height
:
500px
;
padding
:
20px
40px
;
position
:
fixed
;
top
:
0px
;
left
:
100vw
;
h1
{
font-size
:
22px
;
}
.vin-title
{
font-size
:
20px
;
margin
:
16px
0
12px
;
}
}
</
style
>
src/components/CompBasicInfo/index.vue
0 → 100644
View file @
d2c4018b
<
template
>
<div
class=
"comp-basic-info"
>
<el-form
ref=
"formRef"
:model=
"form"
:rules=
"formRules"
size=
"small"
label-position=
"top"
>
<el-row
v-if=
"type === 'person' && showVin"
:gutter=
"40"
>
<el-col
:span=
"12"
>
<el-form-item
label=
"车辆VIN码"
prop=
"vin"
>
<el-input
v-model=
"form.vin"
disabled
/>
</el-form-item>
</el-col>
</el-row>
<el-row
:gutter=
"40"
>
<el-col
:span=
"12"
>
<el-form-item
label=
"姓名"
prop=
"name"
>
<el-input
v-model=
"form.name"
placeholder=
"请输入姓名"
clearable
maxlength=
"50"
/>
</el-form-item>
</el-col>
<el-col
:span=
"12"
>
<el-form-item
label=
"性别"
prop=
"sex"
>
<el-select
v-model=
"form.sex"
placeholder=
"请选择性别"
clearable
>
<el-option
key=
"1"
label=
"男"
value=
"1"
/>
<el-option
key=
"2"
label=
"女"
value=
"2"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
</
template
>
<
script
>
export
default
{
name
:
'
CompBasicInfo
'
,
props
:
{
type
:
{
type
:
String
,
default
:
'
person
'
// person: 自然人, enterprise: 企业
},
data
:
{
type
:
Object
,
default
:
()
=>
({})
},
showVin
:
{
type
:
Boolean
,
default
:
true
}
},
data
()
{
return
{
form
:
{
vin
:
''
,
name
:
''
,
sex
:
''
},
formRules
:
{
name
:
[
{
required
:
true
,
message
:
`请输入姓名`
,
trigger
:
'
blur
'
}
],
sex
:
[
{
required
:
true
,
message
:
`请选择性别`
,
trigger
:
'
change
'
}
]
}
}
},
watch
:
{
data
:
{
handler
()
{
this
.
updateInternalData
()
},
deep
:
true
,
immediate
:
true
}
},
created
()
{
this
.
init
()
},
methods
:
{
init
()
{
this
.
updateInternalData
()
},
updateInternalData
()
{
if
(
typeof
this
.
data
===
'
object
'
&&
this
.
data
!==
null
)
{
this
.
form
.
vin
=
this
.
data
.
vin
||
''
this
.
form
.
name
=
this
.
data
.
name
||
''
this
.
form
.
sex
=
this
.
data
.
sex
||
'
1
'
if
(
this
.
data
.
sex
&&
this
.
data
.
name
)
{
this
.
validate
()
}
}
else
{
this
.
form
.
vin
=
''
this
.
form
.
name
=
''
this
.
form
.
sex
=
'
1
'
}
},
// 校验
async
validate
(
isErrorAnchor
=
false
)
{
try
{
await
this
.
$refs
.
formRef
.
validate
()
return
true
}
catch
(
e
)
{
if
(
isErrorAnchor
)
{
this
.
$refs
.
formRef
.
fields
.
filter
(
item
=>
item
.
validateState
===
'
error
'
)[
0
].
$el
.
scrollIntoView
(
true
)
}
let
temp
=
{
anchor
:
()
=>
{
this
.
$refs
.
formRef
.
fields
.
filter
(
item
=>
item
.
validateState
===
'
error
'
)[
0
].
$el
.
scrollIntoView
(
true
)
temp
=
null
}
}
throw
temp
}
},
// 获取数据
getFormData
()
{
return
{
vin
:
this
.
form
.
vin
,
name
:
this
.
form
.
name
,
sex
:
this
.
form
.
sex
}
},
// 获取待缓存数据
getPendingCacheData
()
{
return
this
.
getFormData
()
},
/**
* 清空校验结果
*/
clearValidate
()
{
this
.
$refs
.
formRef
.
clearValidate
()
}
}
}
</
script
>
src/components/CompBusType/index.vue
0 → 100644
View file @
d2c4018b
<
template
>
<div
class=
"comp-bus-type"
>
<el-form
ref=
"formRef"
:model=
"form"
:rules=
"formRules"
size=
"small"
label-position=
"top"
>
<el-row>
<el-col
:span=
"24"
>
<el-form-item
label=
" "
prop=
"userType"
>
<el-radio-group
v-model=
"form.userType"
class=
"cbt-el-radio-group"
@
change=
"handleUserTypeChange"
>
<el-row
:gutter=
"40"
>
<el-col
:span=
"10"
>
<el-radio
label=
"new"
border
class=
"cbt-el-radio new"
>
<div
class=
"cbt-radio-block"
>
<div
class=
"cbt-rb-title"
>
新车车主
</div>
<div
class=
"cbt-rb-desc"
>
针对未实名/已解绑的车辆
</div>
</div>
</el-radio>
</el-col>
<el-col
:span=
"10"
>
<el-radio
label=
"old"
border
class=
"cbt-el-radio old"
>
<div
class=
"cbt-radio-block"
>
<div
class=
"cbt-rb-title"
>
二手车新车主
</div>
<div
class=
"cbt-rb-desc"
>
针对未解绑的车辆
</div>
</div>
</el-radio>
</el-col>
</el-row>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col
:span=
"24"
>
<el-form-item
label-width=
"0"
prop=
"isDelegate"
>
<el-checkbox
v-model=
"form.isDelegate"
>
是否委托人代办
</el-checkbox>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
</
template
>
<
script
>
export
default
{
name
:
'
CompBusType
'
,
props
:
{
data
:
{
type
:
Object
,
default
:
()
=>
({})
}
},
data
()
{
return
{
form
:
{
userType
:
'
new
'
,
isDelegate
:
false
},
formRules
:
{
isDelegate
:
[
{
required
:
true
,
message
:
'
请选择是否委托人代办
'
,
trigger
:
[
'
change
'
,
'
blur
'
]
}
]
},
isTablet
:
window
.
OS
.
isTablet
}
},
watch
:
{
data
()
{
this
.
updateInternalData
()
}
},
created
()
{
this
.
init
()
},
methods
:
{
init
()
{
this
.
updateInternalData
()
},
updateInternalData
()
{
if
(
typeof
this
.
data
===
'
object
'
&&
this
.
data
!==
null
)
{
this
.
form
.
userType
=
(
this
.
data
.
userType
===
'
new
'
||
this
.
data
.
userType
===
'
old
'
)
?
this
.
data
.
userType
:
'
new
'
this
.
form
.
isDelegate
=
typeof
this
.
data
.
isDelegate
===
'
boolean
'
?
this
.
data
.
isDelegate
:
false
}
else
{
this
.
form
.
userType
=
'
new
'
this
.
form
.
isDelegate
=
false
}
},
// 校验
async
validate
(
isErrorAnchor
=
false
)
{
try
{
await
this
.
$refs
.
formRef
.
validate
()
return
true
}
catch
(
e
)
{
if
(
isErrorAnchor
)
{
this
.
$refs
.
formRef
.
fields
.
filter
(
item
=>
item
.
validateState
===
'
error
'
)[
0
].
$el
.
scrollIntoView
(
true
)
}
let
temp
=
{
anchor
:
()
=>
{
this
.
$refs
.
formRef
.
fields
.
filter
(
item
=>
item
.
validateState
===
'
error
'
)[
0
].
$el
.
scrollIntoView
(
true
)
temp
=
null
}
}
throw
temp
}
},
// 获取数据
getFormData
()
{
return
{
userType
:
this
.
form
.
userType
,
isDelegate
:
this
.
form
.
isDelegate
}
},
// 获取待缓存数据
getPendingCacheData
()
{
return
this
.
getFormData
()
},
/**
* 监听用户类型改变的方法
*/
handleUserTypeChange
()
{
this
.
$emit
(
'
change
'
,
this
.
form
.
userType
)
}
}
}
</
script
>
<
style
lang=
"scss"
>
.comp-bus-type
{
.cbt-el-radio-group
{
width
:
100%
;
}
.cbt-el-radio
{
position
:
relative
;
box-sizing
:
border-box
;
display
:
flex
;
align-items
:
center
;
width
:
346px
;
height
:
106px
;
padding
:
0
24px
;
border-radius
:
4px
;
border-color
:
#f0f0f0
;
&
.is-checked
{
background
:
rgba
(
42
,
104
,
255
,
0
.04
);
}
&
:hover
{
border-color
:
#2a68ff
;
}
.el-radio__inner
{
width
:
16px
;
height
:
16px
;
}
.el-radio__input
{
flex
:
0
0
auto
;
}
.el-radio__label
{
padding-left
:
16px
;
}
.cbt-radio-block
{
display
:
inline-flex
;
flex-direction
:
column
;
position
:
relative
;
z-index
:
1
;
.cbt-rb-title
{
font-size
:
16px
;
color
:
#212026
;
}
.cbt-rb-desc
{
margin-top
:
5px
;
font-size
:
12px
;
color
:
#84858a
;
}
}
&
:after
{
content
:
''
;
position
:
absolute
;
top
:
0
;
right
:
0
;
bottom
:
0
;
display
:
block
;
width
:
156px
;
height
:
100%
;
background-repeat
:
no-repeat
;
background-size
:
cover
;
background-position
:
right
center
;
}
&
.new
{
&
:after
{
background-image
:
url('../../assets/image/new_car_owner@2x.png')
;
}
}
&
.old
{
&
:after
{
background-image
:
url('../../assets/image/used_car_new_owner@2x.png')
;
}
}
}
}
</
style
>
src/components/CompCarCard/index.vue
0 → 100644
View file @
d2c4018b
<
template
>
<div
class=
"comp-car-card"
>
<el-form
ref=
"formRef"
:model=
"form"
:rules=
"formRules"
size=
"small"
label-position=
"top"
@
submit.native.prevent
>
<el-row>
<el-col
:span=
"24"
>
<el-form-item
label=
"车辆VIN码"
prop=
"vin"
>
<div
class=
"el-input-wrapper"
>
<el-input
:value=
"form.vin"
clearable
maxlength=
"50"
placeholder=
"请输入您的VIN码"
class=
"ccc-vin-input"
@
input=
"onVinInput"
@
focus=
"onVinFocus"
@
blur=
"onVinBlur"
/>
<!--
<el-button
v-if=
"isInApp"
class=
"ccc-add-vin-btn"
type=
"primary"
icon=
"el-icon-camera"
plain
size=
"small"
@
click.stop=
"handleTakeScan"
>
扫码添加
</el-button>
-->
</div>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col
:span=
"24"
>
<div
class=
"add-iccid-btn-wrapper"
>
<el-form-item
label=
"ICCID列表"
prop=
"iccidList"
>
<el-button
:disabled=
"!enableAddBtn"
class=
"ccc-add-iccid-btn"
type=
"primary"
icon=
"el-icon-plus"
plain
size=
"small"
@
click.stop=
"clickAddIccid"
>
添加ICCID卡
</el-button>
</el-form-item>
</div>
<div
class=
"iccid-table-wrapper"
>
<el-table
v-loading=
"loading"
:data=
"iccidList"
style=
"width: 100%"
>
<el-table-column
type=
"index"
label=
"序号"
width=
"180"
/>
<el-table-column
prop=
"iccid"
label=
"ICCID"
min-width=
"320"
>
<template
slot-scope=
"scope"
>
<template
v-if=
"scope.row.state === 'readonly'"
>
{{
scope
.
row
.
iccid
}}
</
template
>
<
template
v-else-if=
"scope.row.state === 'edit'"
>
<el-form
:ref=
"scope.row._formId"
:model=
"scope.row"
:rules=
"iccidRules"
size=
"small"
label-width=
"0"
@
submit.native.prevent
>
<el-form-item
prop=
"iccid"
class=
"ccc-el-form-item"
>
<el-input
:ref=
"scope.row._inputId"
:value=
"scope.row.iccid"
clearable
maxlength=
"50"
class=
"ccc-iccid-el-input"
@
input=
"onIccidInput($event, scope.row)"
/>
</el-form-item>
</el-form>
</
template
>
</template>
</el-table-column>
<el-table-column
label=
"操作"
width=
"120"
>
<
template
slot-scope=
"scope"
>
<el-link
v-if=
"canDelIccidRecord(scope)"
class=
"ccc-el-link-del"
@
click.stop=
"clickIccidItemDel(scope)"
>
删除
</el-link>
</
template
>
</el-table-column>
</el-table>
</div>
</el-col>
</el-row>
</el-form>
<comp-confirm
:show.sync=
"showDelConfirm"
:desc=
"delConfirmDesc"
:show-cancel-btn=
"true"
@
on-sure=
"onDelSure"
/>
<comp-confirm
:show.sync=
"showTipConfirm"
:desc=
"tipConfirmDesc"
/>
</div>
</template>
<
script
>
import
bridge
,
{
isInApp
}
from
'
@/utils/bridge
'
import
{
CancelToken
}
from
'
axios
'
import
{
queryUnBindCardByVin
,
queryBindCardByVin
}
from
'
@/api/iccid
'
import
CompConfirm
from
'
@/components/CompConfirm
'
let
gid
=
0
export
default
{
name
:
'
CompCarCard
'
,
components
:
{
CompConfirm
},
props
:
{
data
:
{
type
:
Object
,
default
:
()
=>
({})
},
maxIccidLength
:
{
type
:
Number
,
default
:
5
},
// 特殊业务卡解绑重新封装依据vin获取iccid等信息 SPECIAL
soucePage
:
{
type
:
String
,
default
:
()
=>
''
},
// 是否查询绑定的iccid true:已绑定 false:未绑定
isBind
:
{
type
:
Boolean
,
default
:
false
}
},
data
()
{
const
checkVin
=
(
rule
,
value
,
callback
)
=>
{
if
(
value
===
''
)
{
callback
(
new
Error
(
'
请输入您的vin码
'
))
}
else
if
(
!
this
.
checkVin
(
value
))
{
callback
(
new
Error
(
'
vin码格式不正确
'
))
}
else
{
callback
()
}
}
const
checkIccid
=
(
rule
,
value
,
callback
)
=>
{
if
(
value
!==
''
)
{
if
(
this
.
checkIccid
(
value
))
{
callback
()
}
else
{
callback
(
new
Error
(
'
iccid格式不正确
'
))
}
}
else
{
if
(
this
.
validIccidList
.
length
)
{
callback
()
}
else
{
callback
(
new
Error
(
'
请输入iccid
'
))
}
}
}
return
{
form
:
{
vin
:
''
,
iccidList
:
[]
},
formRules
:
{
vin
:
[
{
required
:
true
,
validator
:
checkVin
,
trigger
:
'
blur
'
}
],
iccidList
:
[
{
type
:
'
array
'
,
required
:
true
,
message
:
'
请添加ICCID数据
'
,
trigger
:
''
}
]
},
iccidRules
:
{
iccid
:
[
{
required
:
true
,
validator
:
checkIccid
,
trigger
:
'
blur
'
}
]
},
isInApp
,
iccidList
:
[],
loading
:
false
,
showDelConfirm
:
false
,
delConfirmDesc
:
'
确认删除当前行吗?
'
,
showTipConfirm
:
false
,
tipConfirmDesc
:
''
,
inputIsFocus
:
false
}
},
computed
:
{
newAddedIccidList
()
{
return
this
.
iccidList
.
filter
(
item
=>
item
.
state
===
'
edit
'
)
},
validIccidList
()
{
return
this
.
iccidList
.
filter
(
item
=>
(
item
.
state
===
'
edit
'
?
this
.
checkIccid
(
item
.
iccid
)
:
(
item
.
iccid
!==
''
)))
},
enableAddBtn
()
{
const
ret
=
(
!
this
.
inputIsFocus
&&
!
this
.
loading
)
||
(
this
.
inputIsFocus
&&
!
this
.
form
.
vin
)
this
.
$emit
(
'
on-canenable
'
,
ret
)
return
ret
}
},
watch
:
{
data
()
{
this
.
updateInternalData
()
},
iccidList
(
val
)
{
if
(
this
.
_iccidListInitMount
)
{
this
.
_iccidListInitMount
=
false
return
}
if
(
val
.
length
)
{
this
.
$refs
.
formRef
.
clearValidate
(
'
iccidList
'
)
}
else
{
this
.
$refs
.
formRef
.
validateField
(
'
iccidList
'
)
}
}
},
created
()
{
this
.
_iccidListInitMount
=
true
this
.
init
()
},
methods
:
{
/**
* 扫码功能
*/
handleTakeScan
()
{
bridge
.
scanCode
(
true
,
code
=>
{
this
.
form
.
vin
=
code
this
.
onVinBlur
()
})
},
errorTips
(
errMsg
)
{
this
.
showTipConfirm
=
true
this
.
tipConfirmDesc
=
errMsg
},
init
()
{
this
.
updateInternalData
()
},
updateInternalData
()
{
if
(
typeof
this
.
data
===
'
object
'
&&
this
.
data
!==
null
)
{
this
.
form
.
vin
=
this
.
data
.
vin
||
''
this
.
form
.
iccidList
=
[]
this
.
iccidList
=
Array
.
isArray
(
this
.
data
.
iccidList
)
?
[...
this
.
data
.
iccidList
]
:
this
.
getDefaultIccidList
()
}
else
{
this
.
form
.
vin
=
''
this
.
form
.
iccidList
=
[]
this
.
iccidList
=
this
.
getDefaultIccidList
()
}
},
getDefaultIccidList
()
{
return
[]
},
// 点击添加 ICCID 按钮
clickAddIccid
()
{
if
(
this
.
iccidList
.
length
>=
this
.
maxIccidLength
)
{
this
.
errorTips
(
`最多只能添加
${
this
.
maxIccidLength
}
条ICCID数据`
)
return
}
const
newIccid
=
this
.
makeIccidTemplate
()
newIccid
.
state
=
'
edit
'
this
.
iccidList
.
push
(
newIccid
)
this
.
$nextTick
(()
=>
{
this
.
$refs
[
`
${
newIccid
.
_inputId
}
`
].
focus
()
})
},
// 点击删除 ICCID 记录按钮
clickIccidItemDel
(
scope
)
{
this
.
showDelConfirm
=
true
this
.
_curDelIndex
=
scope
.
$index
},
// 确认删除 ICCID
onDelSure
()
{
this
.
iccidList
.
splice
(
this
.
_curDelIndex
,
1
)
},
onIccidInput
(
$event
,
cur
)
{
if
(
$event
===
''
||
$event
.
length
<=
20
)
{
cur
.
iccid
=
$event
}
},
canDelIccidRecord
(
scope
)
{
// 卡解绑查询出来的数据不能删除
if
(
this
.
$route
.
name
===
'
CardUnbindingStepOne
'
)
{
if
(
scope
.
row
.
state
===
'
readonly
'
)
{
return
false
}
}
return
true
},
onVinFocus
()
{
this
.
inputIsFocus
=
true
},
// 光标移开 vin 码输入框时的动作
onVinBlur
()
{
this
.
inputIsFocus
=
false
this
.
$refs
.
formRef
.
validateField
(
'
vin
'
,
errorMsg
=>
{
if
(
!
errorMsg
)
{
this
.
onVinBlurHandler
()
}
else
{
if
(
this
.
_req
)
{
this
.
_req
.
cancel
()
}
}
})
},
// 光标移开 vin 码输入框处理
async
onVinBlurHandler
()
{
this
.
loading
=
true
const
retData
=
await
this
.
getIccidListByVin
()
this
.
loading
=
false
if
(
retData
===
'
cancel
'
)
{
return
}
const
pendingAdd
=
retData
.
iccidList
||
[]
this
.
iccidList
=
[
...
this
.
normalizeIccidList
(
pendingAdd
.
slice
(
0
,
this
.
maxIccidLength
))
]
this
.
prevIsBind
=
this
.
isBind
this
.
_preVin
=
this
.
form
.
vin
},
// vin 码输入长度限制
onVinInput
(
$event
)
{
if
(
$event
===
''
||
$event
.
length
<=
17
)
{
this
.
form
.
vin
=
$event
}
},
checkVin
(
vin
)
{
return
vin
.
length
===
17
},
checkIccid
(
iccid
)
{
return
typeof
iccid
===
'
string
'
&&
iccid
!==
''
&&
iccid
.
length
===
20
},
async
getIccidListByVin
()
{
if
(
this
.
_req
)
{
this
.
_req
.
cancel
()
}
this
.
_req
=
CancelToken
.
source
()
let
retData
=
null
const
searchParams
=
{
vin
:
this
.
form
.
vin
}
try
{
// 接口请求方法
const
reqFuction
=
this
.
isBind
?
queryBindCardByVin
:
queryUnBindCardByVin
// 开始请求接口
const
respData
=
await
reqFuction
({
data
:
{
...
searchParams
,
...(
this
.
soucePage
===
'
BIND
'
?
{
filter
:
true
}
:
{})
},
cancelToken
:
this
.
_req
.
token
,
hideToast
:
true
})
retData
=
respData
||
{}
}
catch
(
e
)
{
if
(
e
.
code
===
'
_CANCEL_REQUEST_
'
)
{
retData
=
'
cancel
'
}
else
{
// 其他错误需要提示
this
.
errorTips
(
e
.
message
||
'
系统异常
'
)
}
}
return
retData
||
{}
},
// ICCID 记录数据模板
makeIccidTemplate
()
{
return
{
iccid
:
''
,
state
:
'
readonly
'
,
_formId
:
gid
++
,
_inputId
:
gid
++
}
},
// 标准化远程获取的 ICCID 记录数据
normalizeIccidList
(
list
=
[])
{
return
list
.
map
(
item
=>
{
const
newIccid
=
this
.
makeIccidTemplate
()
newIccid
.
iccid
=
item
newIccid
.
state
=
'
readonly
'
return
newIccid
})
},
async
validateForm1
(
isErrorAnchor
=
false
)
{
this
.
form
.
iccidList
=
JSON
.
parse
(
JSON
.
stringify
(
this
.
iccidList
))
try
{
await
this
.
$refs
.
formRef
.
validate
()
return
true
}
catch
(
e
)
{
if
(
isErrorAnchor
)
{
this
.
$refs
.
formRef
.
fields
.
filter
(
item
=>
item
.
validateState
===
'
error
'
)[
0
].
$el
.
scrollIntoView
(
true
)
}
let
temp
=
{
anchor
:
()
=>
{
this
.
$refs
.
formRef
.
fields
.
filter
(
item
=>
item
.
validateState
===
'
error
'
)[
0
].
$el
.
scrollIntoView
(
true
)
temp
=
null
}
}
throw
temp
}
},
async
validateIccidListForm2
(
isErrorAnchor
=
false
)
{
const
validateIccidList
=
this
.
newAddedIccidList
for
(
let
i
=
0
,
len
=
validateIccidList
.
length
;
i
<
len
;
i
++
)
{
const
item
=
validateIccidList
[
i
]
try
{
await
this
.
$refs
[
item
.
_formId
].
validate
()
}
catch
(
e
)
{
if
(
isErrorAnchor
)
{
this
.
$refs
[
item
.
_inputId
].
$el
.
scrollIntoView
(
true
)
}
let
temp
=
{
anchor
:
()
=>
{
this
.
$refs
[
item
.
_inputId
].
$el
.
scrollIntoView
(
true
)
temp
=
null
}
}
throw
temp
}
}
return
true
},
// 校验
async
validate
(
isErrorAnchor
=
false
)
{
try
{
await
Promise
.
all
([
this
.
validateForm1
(),
this
.
validateIccidListForm2
()
])
return
true
}
catch
(
e
)
{
throw
e
}
},
// 获取数据
getFormData
()
{
return
{
vin
:
this
.
form
.
vin
,
iccidList
:
this
.
iccidList
.
map
(
item
=>
item
.
iccid
)
}
},
// 获取待缓存数据
getPendingCacheData
()
{
return
{
vin
:
this
.
form
.
vin
,
iccidList
:
JSON
.
parse
(
JSON
.
stringify
(
this
.
iccidList
))
}
}
}
}
</
script
>
<
style
lang=
"scss"
>
.comp-car-card
{
.ccc-vin-input
{
width
:
44%
;
}
.ccc-iccid-el-input
{
width
:
60%
;
}
.ccc-el-form-item
{
.el-form-item__error
{
left
:
62%
;
top
:
50%
;
transform
:
translateY
(
-50%
);
}
}
.add-iccid-btn-wrapper
{
margin-bottom
:
8px
;
.ccc-add-iccid-btn
{
border-color
:
#B9CFFF
;
color
:
#2A68FF
;
background
:
#F5F7FF
;
&
:hover
{
border-color
:
#5489FF
;
background
:
#F5F7FF
;
color
:
#5489FF
;
}
}
}
.iccid-table-wrapper
{
.el-form-item
{
margin-bottom
:
0
!
important
;
}
.ccc-el-link-del
{
font-size
:
14px
;
color
:
#2A68FF
;
&
:hover
{
&
:after
{
display
:
none
;
}
}
}
}
.el-input-wrapper
{
display
:
flex
;
.ccc-add-vin-btn
{
margin-left
:
12px
;
}
}
}
</
style
>
src/components/CompCertificateInfo/index.vue
0 → 100644
View file @
d2c4018b
<
template
>
<div
class=
"comp-certificate-info"
>
<div
class=
"device-list"
>
<i
v-if=
"device.showReadCard && form.type === 'IDCARD'"
class=
"icon-device-card"
@
click=
"getCertData"
/>
</div>
<el-form
ref=
"formRef"
:model=
"form"
:rules=
"formRules"
size=
"small"
label-position=
"top"
>
<el-row
:gutter=
"40"
>
<el-col
:span=
"12"
>
<el-form-item
label=
"证件类型"
prop=
"type"
>
<el-select
v-model=
"form.type"
placeholder=
"请选择证件类型"
clearable
filterable
@
change=
"onTypeChange"
>
<el-option
v-for=
"item in dict.certType"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<template
v-if=
"form.type !== ''"
>
<el-row
:gutter=
"40"
>
<el-col
:span=
"24"
>
<el-form-item
v-if=
"form.photoUrls && form.photoUrls.length > 0"
label=
"上传证件照片"
prop=
"photoUrls"
class=
"cci-form-item"
>
<template
v-if=
"form.type === 'IDCARD'"
>
<el-row
:gutter=
"18"
>
<el-col
:span=
"6"
style=
"margin-right:40px"
>
<comp-certificate-upload
v-model=
"form.photoUrls[0].url"
:limit=
"1"
:certs=
"[form.photoUrls[0]]"
:bg-img-url=
"positiveBgUrl"
:face=
"true"
desc=
"请上传人像面"
@
on-cert=
"data => formatCardInfo(data, CERT_FRONT)"
@
take-photo-success=
"(data)=>takePhotoSuccess(data, 0)"
@
input=
"uploadAutoValidate"
/>
</el-col>
<el-col
:span=
"6"
>
<comp-certificate-upload
v-model=
"form.photoUrls[1].url"
:limit=
"1"
:certs=
"[form.photoUrls[1]]"
:bg-img-url=
"negativeBgUrl"
:face=
"false"
desc=
"请上传国徽面"
@
on-cert=
"data => formatCardInfo(data, CERT_BACK)"
@
take-photo-success=
"(data)=>takePhotoSuccess(data, 1)"
@
input=
"uploadAutoValidate"
/>
</el-col>
</el-row>
</
template
>
<
template
v-else
>
<el-row>
<el-col
v-for=
"(item, index) in form.photoUrls"
:span=
"4"
:key=
"item.id"
>
<comp-certificate-upload
v-model=
"item.url"
:limit=
"maxCertImgCount"
:certs=
"[form.photoUrls[0]]"
:bg-img-url=
"positiveBgUrl"
desc=
"请上传证件照片"
card-type=
"other"
@
take-photo-success=
"(data)=>takePhotoSuccess(data)"
@
input=
"uploadAutoValidate"
@
on-success=
"onUploadItemSuccess(index)"
@
on-del=
"onUploadItemDel(index)"
/>
</el-col>
</el-row>
</
template
>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col
:span=
"24"
>
<div
class=
"cci-upload-tips"
>
文件类型为图片文件,扩展名要求使用小写字母,允许支持的照片格式包括bmp、jpg/jpeg、png,小于500K
</div>
</el-col>
</el-row>
</template>
<el-row
:gutter=
"40"
>
<el-col
:span=
"12"
>
<el-form-item
label=
"证件号码"
prop=
"no"
>
<el-input
v-model=
"form.no"
placeholder=
"请输入证件号码"
clearable
maxlength=
"50"
@
blur=
"() => (form.no = form.no.toUpperCase())"
/>
</el-form-item>
</el-col>
<el-col
:span=
"12"
>
<el-form-item
label=
"证件地址"
prop=
"address"
>
<el-input
v-model=
"form.address"
placeholder=
"请输入证件地址"
clearable
maxlength=
"50"
/>
</el-form-item>
</el-col>
</el-row>
<el-row
:gutter=
"40"
>
<el-col
:span=
"12"
>
<el-form-item
label=
"证件起始时间"
prop=
"certEffectiveDate"
>
<!-- 日期 -->
<el-date-picker
v-model=
"form.certEffectiveDate"
:picker-options=
"startTimePickerOptions"
:editable=
"false"
type=
"date"
placeholder=
"请选择证件有效期"
clearable
value-format=
"yyyy-MM-dd"
/>
</el-form-item>
</el-col>
<el-col
:span=
"12"
>
<el-form-item
label=
"通讯地址"
prop=
"connectAddress"
>
<el-input
v-model=
"form.connectAddress"
placeholder=
"请输入通讯地址"
clearable
maxlength=
"50"
/>
</el-form-item>
</el-col>
<el-col
:span=
"12"
>
<el-form-item
label=
"证件有效期"
prop=
"validDate"
>
<!-- 长期 -->
<el-input
v-if=
"form.validDate && form.validDate.length === 2"
v-model=
"form.validDate"
:readonly=
"true"
placeholder=
"请填写证件有效期"
clearable
maxlength=
"2"
@
change=
"handleValidDateChange"
/>
<!-- 日期 -->
<el-date-picker
v-else
v-model=
"form.validDate"
:picker-options=
"pickerOptions"
:editable=
"false"
type=
"date"
placeholder=
"请选择证件有效期"
clearable
value-format=
"yyyy-MM-dd"
/>
<!-- 是否长期有效 -->
<el-checkbox
v-model=
"longTerm"
@
change=
"handleChangeValidData"
>
长期有效
</el-checkbox>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
</template>
<
script
>
import
dayjs
from
'
dayjs
'
import
bridge
,
{
isInApp
}
from
'
@/utils/bridge
'
import
{
mapGetters
}
from
'
vuex
'
import
{
validId
}
from
'
@/utils/validate
'
import
deviceService
from
'
@/components/Device/service
'
import
{
FIRM
}
from
'
@/store/modules/user
'
import
CompCertificateUpload
from
'
@/components/CompCertificateUpload
'
import
positiveBgUrl
from
'
@/assets/image/id_positive@2x.png
'
import
negativeBgUrl
from
'
@/assets/image/id_negative@2x.png
'
let
gid
=
0
// 证件信息正面
const
CERT_FRONT
=
'
CERT_FRONT
'
// 证件信息背面
const
CERT_BACK
=
'
CERT_BACK
'
export
default
{
name
:
'
CompCertificateInfo
'
,
components
:
{
CompCertificateUpload
},
props
:
{
data
:
{
type
:
Object
,
default
:
()
=>
({})
},
maxCertImgCount
:
{
type
:
Number
,
default
:
2
}
},
data
()
{
const
checkphotoUrlsForId
=
(
rule
,
value
,
callback
)
=>
{
if
(
!
Array
.
isArray
(
this
.
form
.
photoUrls
)
||
this
.
form
.
photoUrls
.
length
===
0
)
{
callback
(
new
Error
(
'
请上传人像面
'
))
}
else
if
(
this
.
form
.
photoUrls
[
0
].
url
.
id
===
null
)
{
callback
(
new
Error
(
'
请上传人像面
'
))
}
else
if
(
this
.
form
.
photoUrls
[
1
].
url
.
id
===
null
)
{
callback
(
new
Error
(
'
请上传国徽面
'
))
}
else
{
callback
()
}
}
const
checkphotoUrlsForOther
=
(
rule
,
value
,
callback
)
=>
{
if
(
!
Array
.
isArray
(
this
.
form
.
photoUrls
)
||
this
.
form
.
photoUrls
.
length
===
0
)
{
callback
(
new
Error
(
'
请上传证件图片
'
))
}
else
if
(
this
.
form
.
photoUrls
[
0
].
url
.
id
===
null
)
{
callback
(
new
Error
(
'
请上传证件图片
'
))
}
else
{
callback
()
}
}
const
checkphotoUrls
=
(
rule
,
value
,
callback
)
=>
{
if
(
this
.
form
.
type
===
'
IDCARD
'
)
{
checkphotoUrlsForId
(
rule
,
value
,
callback
)
}
else
{
checkphotoUrlsForOther
(
rule
,
value
,
callback
)
}
}
const
checkNo
=
(
rule
,
value
,
callback
)
=>
{
if
(
value
===
''
)
{
callback
(
new
Error
(
'
请输入证件号码
'
))
}
else
if
(
this
.
form
.
type
===
'
IDCARD
'
&&
!
validId
(
value
))
{
callback
(
new
Error
(
'
证件号码格式不正确
'
))
}
else
{
callback
()
}
}
return
{
CERT_FRONT
,
CERT_BACK
,
showDialog
:
false
,
form
:
{
type
:
''
,
photoUrls
:
[],
no
:
''
,
address
:
''
,
validDate
:
''
,
certEffectiveDate
:
''
,
connectAddress
:
''
},
formRules
:
{
type
:
[
{
required
:
true
,
message
:
'
请选择证件类型
'
,
trigger
:
'
change
'
}
],
photoUrls
:
[
{
required
:
true
,
validator
:
checkphotoUrls
,
trigger
:
'
change
'
}
],
no
:
[
{
required
:
true
,
validator
:
checkNo
,
trigger
:
'
blur
'
}
],
address
:
[
{
required
:
true
,
message
:
'
请输入证件地址
'
,
trigger
:
'
blur
'
}
],
certEffectiveDate
:
[
{
required
:
true
,
message
:
'
请选择证件起始时间
'
,
trigger
:
'
change
'
}
],
validDate
:
[
{
required
:
true
,
message
:
'
请选择证件有效期
'
,
trigger
:
'
change
'
}
]
},
longTerm
:
false
,
positiveBgUrl
,
negativeBgUrl
}
},
computed
:
{
...
mapGetters
([
'
dict
'
,
'
device
'
]),
/**
* 时间选择器的选项(当前天之前不让选中)
*/
pickerOptions
()
{
return
{
disabledDate
(
time
)
{
return
time
.
getTime
()
<
dayjs
().
startOf
(
'
date
'
).
valueOf
()
}
}
},
/**
* 时间选择器的选项(当前天之前不让选中)
*/
startTimePickerOptions
()
{
return
{
disabledDate
(
time
)
{
return
time
.
getTime
()
>=
dayjs
().
endOf
(
'
date
'
).
valueOf
()
}
}
}
},
watch
:
{
data
()
{
this
.
updateInternalData
()
}
},
created
()
{
this
.
init
()
},
methods
:
{
// 获取证件信息
getCertData
()
{
if
(
this
.
form
.
type
!==
'
IDCARD
'
)
{
return
}
// 如果当前在app中
if
(
isInApp
)
{
return
new
Promise
((
resolve
,
reject
)
=>
{
bridge
.
readIDCardByOTG
(
data
=>
{
data
.
gender
=
data
.
gender
===
'
男
'
?
'
1
'
:
'
2
'
this
.
formatCardInfo
(
data
)
this
.
validate
()
resolve
()
})
})
}
// 设备回调
let
deviceCallback
// 如果当前是卡尔的
if
(
this
.
device
.
firm
===
FIRM
.
KT
)
{
deviceCallback
=
deviceService
.
readKtCardEx
()
}
else
{
deviceCallback
=
deviceService
.
readIntegratedCard
()
}
return
deviceCallback
.
then
(
data
=>
{
this
.
formatCardInfo
(
data
)
this
.
validate
()
}).
catch
(
err
=>
{
this
.
$message
.
error
(
err
)
})
},
/**
* 格式化身份证证件信息
* @param data 读取的信息
*/
formatCardInfo
(
data
,
type
=
''
)
{
// 如果当前是证件信息背面(国徽面)
if
(
!
type
||
type
===
CERT_BACK
)
{
// 过期时间
const
expireDate
=
dayjs
(
data
.
expireDate
,
'
YYYYMMDD
'
)
// 开始时间
const
effectDate
=
dayjs
(
data
.
effectDate
,
'
YYYYMMDD
'
)
// 如果当前是非长期身份证
if
(
expireDate
.
isValid
())
{
if
(
expireDate
.
isBefore
(
dayjs
().
startOf
(
'
date
'
)))
{
this
.
$message
.
error
(
'
当前身份证已过期,请注意更换
'
)
data
.
expireDate
=
''
}
else
{
data
.
expireDate
=
expireDate
.
format
(
'
YYYY-MM-DD
'
)
}
}
// 设置身份证生效时间
data
.
certEffectiveDate
=
effectDate
.
format
(
'
YYYY-MM-DD
'
)
this
.
form
.
validDate
=
data
.
expireDate
this
.
form
.
certEffectiveDate
=
data
.
certEffectiveDate
this
.
longTerm
=
data
.
expireDate
===
'
长期
'
}
// 如果当前是证件信息正面(人像面)
if
(
!
type
||
type
===
CERT_FRONT
)
{
this
.
form
.
no
=
data
.
idNum
this
.
form
.
address
=
data
.
address
this
.
$emit
(
'
read-cert
'
,
data
)
}
},
init
()
{
this
.
updateInternalData
()
},
updateInternalData
()
{
if
(
typeof
this
.
data
===
'
object
'
&&
this
.
data
!==
null
)
{
// 如果当前是长期
this
.
longTerm
=
this
.
form
.
validDate
===
'
长期
'
this
.
form
.
type
=
this
.
data
.
type
||
this
.
getDefaultType
()
this
.
form
.
photoUrls
=
this
.
data
.
photoUrls
||
this
.
getDefaultPhotoUrls
()
this
.
form
.
no
=
this
.
data
.
no
||
''
this
.
form
.
address
=
this
.
data
.
address
||
''
this
.
form
.
validDate
=
this
.
data
.
validDate
||
''
this
.
form
.
connectAddress
=
this
.
data
.
connectAddress
||
''
}
else
{
this
.
form
.
type
=
this
.
getDefaultType
()
this
.
form
.
photoUrls
=
this
.
getDefaultPhotoUrls
()
this
.
form
.
no
=
''
this
.
form
.
address
=
''
this
.
form
.
validDate
=
''
this
.
form
.
connectAddress
=
''
}
},
getDefaultType
()
{
return
'
IDCARD
'
},
getDefaultPhotoUrls
()
{
if
(
this
.
form
.
type
===
'
IDCARD
'
)
{
return
[
this
.
makeUploadDataTemplate
(),
this
.
makeUploadDataTemplate
()
]
}
return
[
this
.
makeUploadDataTemplate
()]
},
// 高拍仪拍照上传成功回调
// index=0正面, index=1反面
takePhotoSuccess
(
data
,
index
)
{
if
(
data
.
length
<=
0
)
{
return
}
// 如果当前是身份证
if
(
typeof
index
===
'
number
'
)
{
this
.
form
.
photoUrls
.
splice
(
index
,
1
,
{
id
:
gid
++
,
url
:
{
url
:
data
[
0
].
accessUrl
,
id
:
data
[
0
].
uuid
}
})
}
else
{
this
.
form
.
photoUrls
=
data
.
map
(
item
=>
{
return
{
id
:
gid
++
,
url
:
{
url
:
item
.
accessUrl
,
id
:
item
.
uuid
}
}
})
}
},
// 上传图片变化后自动校验
uploadAutoValidate
()
{
this
.
validatePhoto
()
},
// 校验图片
validatePhoto
()
{
if
(
this
.
$refs
.
formRef
)
{
this
.
$nextTick
(()
=>
{
this
.
$refs
.
formRef
.
validateField
(
'
photoUrls
'
)
})
}
},
// 上传成功自动添加空上传控件
onUploadItemSuccess
(
index
)
{
if
(
this
.
form
.
photoUrls
.
length
>=
this
.
maxCertImgCount
)
{
return
}
// 最后一个控件上传成功后,添加新的
if
(
index
===
this
.
form
.
photoUrls
.
length
-
1
)
{
this
.
form
.
photoUrls
.
push
(
this
.
makeUploadDataTemplate
())
}
},
// 删除上传控件
onUploadItemDel
(
index
)
{
if
(
this
.
form
.
photoUrls
.
length
<=
1
)
{
return
}
this
.
form
.
photoUrls
.
splice
(
index
,
1
)
this
.
addPendingUploadItem
()
},
// 添加待上传控件
addPendingUploadItem
()
{
if
(
this
.
form
.
photoUrls
[
this
.
form
.
photoUrls
.
length
-
1
].
url
.
id
!==
null
)
{
this
.
form
.
photoUrls
.
push
(
this
.
makeUploadDataTemplate
())
}
},
// 上传控件数据模板
makeUploadDataTemplate
()
{
return
{
id
:
gid
++
,
url
:
{
id
:
null
,
url
:
''
}
}
},
onTypeChange
()
{
this
.
form
.
photoUrls
=
this
.
getDefaultPhotoUrls
()
// 如果当前选择的是户口本,将则过期时间替换成长期
this
.
form
.
validDate
=
this
.
form
.
type
===
'
HOUSEHOLD
'
?
'
长期
'
:
this
.
form
.
validDate
this
.
validatePhoto
()
},
// 校验
async
validate
(
isErrorAnchor
=
false
)
{
try
{
await
this
.
$refs
.
formRef
.
validate
()
return
true
}
catch
(
e
)
{
if
(
isErrorAnchor
)
{
this
.
$refs
.
formRef
.
fields
.
filter
(
item
=>
item
.
validateState
===
'
error
'
)[
0
].
$el
.
scrollIntoView
(
true
)
}
let
temp
=
{
anchor
:
()
=>
{
this
.
$refs
.
formRef
.
fields
.
filter
(
item
=>
item
.
validateState
===
'
error
'
)[
0
].
$el
.
scrollIntoView
(
true
)
temp
=
null
}
}
throw
temp
}
},
// 获取数据
getFormData
()
{
return
{
type
:
this
.
form
.
type
,
no
:
this
.
form
.
no
,
address
:
this
.
form
.
address
,
validDate
:
this
.
form
.
validDate
,
certEffectiveDate
:
this
.
form
.
certEffectiveDate
,
connectAddress
:
this
.
form
.
connectAddress
,
photoUrls
:
this
.
form
.
photoUrls
}
},
// 获取待缓存数据
getPendingCacheData
()
{
return
this
.
getFormData
()
},
/**
* 当前长期选项改变时
*/
handleChangeValidData
()
{
this
.
form
.
validDate
=
this
.
longTerm
?
'
长期
'
:
''
},
/**
* 日期改变时
*/
handleValidDateChange
()
{
// 如果当前是清空操作
if
(
!
this
.
form
.
validDate
)
{
this
.
longTerm
=
false
}
},
/**
* 清空校验值
*/
clearValidate
()
{
this
.
$refs
.
formRef
.
clearValidate
()
}
}
}
</
script
>
<
style
lang=
"scss"
>
.comp-certificate-info
{
position
:
relative
;
.device-list
{
position
:
absolute
;
top
:
-50px
;
right
:
0
;
}
.icon-device-card
,
.icon-device-video
{
margin-left
:
16px
;
}
.cci-upload-tips
{
margin-bottom
:
22px
;
font-size
:
12px
;
color
:
rgba
(
132
,
133
,
138
,
0
.7
);
}
.cci-form-item
{
margin-bottom
:
10px
;
.el-form-item__error
{
top
:
calc
(
100%
+
24px
);
}
}
}
</
style
>
src/components/CompCertificateUpload/index.vue
0 → 100644
View file @
d2c4018b
<
template
>
<div
class=
"comp-certificate-upload-wrap"
>
<PadBridge>
<el-upload
ref=
"uploadRef"
:auto-upload=
"true"
:show-file-list=
"false"
:multiple=
"false"
:on-success=
"onSuccess"
:on-error=
"onUploadError"
:before-upload=
"onBeforeUpload"
:on-progress=
"onProgress"
:data=
"reqParams"
:headers=
"reqHeaders"
:action=
"actionUrl"
class=
"comp-certificate-upload"
name=
"file"
accept=
".jpg,.jpeg,.png,.bmp"
>
<template
v-if=
"state === 'init'"
>
<div
class=
"su-icon"
>
<img
:src=
"bgImgUrl"
>
</div>
<div
class=
"su-text"
>
{{
desc
}}
</div>
</
template
>
<
template
v-else-if=
"state === 'uploading'"
>
<div
class=
"su-loading-text"
>
文件上传中
</div>
<div
class=
"su-loading-bar"
>
<div
:style=
"
{width: uploadPercent}" class="su-loading-bar-progress" />
</div>
</
template
>
<
template
v-else-if=
"state === 'success'"
>
<img
:src=
"fileRemoteUrl.url"
alt=
""
class=
"su-img"
>
<div
class=
"su-success-operate-wrapper"
>
<i
class=
"el-icon-delete su-operate-btn"
@
click.stop.prevent=
"clickDel"
/>
<i
class=
"el-icon-zoom-in su-operate-btn zoom"
@
click.stop.prevent
>
<el-image
:src=
"fileRemoteUrl.url"
:preview-src-list=
"[fileRemoteUrl.url]"
/>
</i>
</div>
</
template
>
<
template
v-else-if=
"state === 'error'"
>
<div
class=
"su-text"
>
上传失败
</div>
<div
class=
"su-success-operate-wrapper"
>
<i
class=
"el-icon-delete su-operate-btn"
@
click.stop.prevent=
"clickDel"
/>
</div>
</
template
>
</el-upload>
</PadBridge>
<div
class=
"device-wrapper"
>
<i
v-if=
"device.showTakePhoto"
class=
"icon-device-video"
@
click.stop=
"showDialog = true"
/>
</div>
<device-dialog
:show.sync=
"showDialog"
:security=
"true"
:data=
"photoList"
:limit=
"limit"
@
getPhoto=
"getPhoto"
/>
</div>
</template>
<
script
>
import
PadBridge
from
'
@/components/PadBridge
'
import
{
mapGetters
}
from
'
vuex
'
import
CompressImg
from
'
@/components/CompressImg
'
import
BlobUtil
from
'
@/components/CompressImg/blobutil
'
import
{
getToken
}
from
'
@/utils/auth
'
import
{
getIdcardInfoByOcr
}
from
'
@/utils/upload
'
import
{
imageViewer
}
from
'
@/utils/upload
'
import
defaultBgImgUrl
from
'
@/assets/image/id_positive@2x.png
'
import
deviceDialog
from
'
@/components/Device/dialog
'
export
default
{
name
:
'
CompCertificateUpload
'
,
components
:
{
deviceDialog
,
PadBridge
},
props
:
{
value
:
{
type
:
Object
,
default
:
()
=>
({})
},
maxSize
:
{
type
:
Number
,
default
:
0.5
},
rootPath
:
{
type
:
String
,
default
:
'
common/imgs
'
},
bgImgUrl
:
{
type
:
String
,
default
:
defaultBgImgUrl
},
desc
:
{
type
:
String
,
default
:
'
请上传人像面
'
},
limit
:
{
type
:
Number
,
default
:
1
},
certs
:
{
type
:
Array
,
default
:
()
=>
([])
}
},
data
()
{
return
{
showDialog
:
false
,
file
:
null
,
fileRemoteUrl
:
null
,
state
:
'
init
'
,
uploadPercent
:
'
0%
'
,
actionUrl
:
`
${
process
.
env
.
VUE_APP_BASIC_API
}
cuscImage/upload`
,
reqParams
:
{
rootPath
:
this
.
rootPath
},
reqHeaders
:
{
'
Authorization
'
:
''
}
}
},
computed
:
{
...
mapGetters
([
'
device
'
]),
photoList
()
{
const
list
=
[]
this
.
certs
.
forEach
(
item
=>
{
if
(
item
.
url
.
url
)
{
list
.
push
({
type
:
'
photo
'
,
accessUrl
:
item
.
url
.
url
,
uuid
:
item
.
url
.
id
})
}
})
return
list
}
},
watch
:
{
'
fileRemoteUrl.id
'
(
v
)
{
if
(
this
.
_fileRemoteUrlInitMount
)
{
this
.
_fileRemoteUrlInitMount
=
false
return
}
this
.
$emit
(
'
input
'
,
this
.
fileRemoteUrl
)
},
value
(
v
)
{
if
(
v
&&
v
.
id
!==
this
.
fileRemoteUrl
.
id
)
{
this
.
updateInternalData
()
}
}
},
created
()
{
this
.
_fileRemoteUrlInitMount
=
true
this
.
init
()
},
methods
:
{
/**
* 获取图片
* @time 2022-05-11 23:32:36
*/
getPhoto
(
data
)
{
if
(
data
.
length
>
0
)
{
this
.
$emit
(
'
take-photo-success
'
,
data
)
this
.
state
=
'
success
'
this
.
$emit
(
'
on-success
'
)
}
},
errorTips
(
msg
)
{
this
.
$message
.
error
(
msg
)
},
init
()
{
this
.
updateInternalData
()
},
updateInternalData
()
{
if
(
typeof
this
.
value
===
'
object
'
&&
this
.
value
!==
null
)
{
const
fileRemoteUrl
=
this
.
makeFileRemoteUrlTemplate
()
fileRemoteUrl
.
id
=
this
.
value
.
id
||
null
fileRemoteUrl
.
url
=
this
.
value
.
url
||
''
if
(
fileRemoteUrl
.
id
===
null
)
{
this
.
resetState
()
return
}
this
.
file
=
null
this
.
fileRemoteUrl
=
fileRemoteUrl
this
.
state
=
'
success
'
this
.
uploadPercent
=
'
0%
'
}
else
{
this
.
resetState
()
}
},
resetState
()
{
this
.
file
=
null
this
.
fileRemoteUrl
=
this
.
makeFileRemoteUrlTemplate
()
this
.
state
=
'
init
'
this
.
uploadPercent
=
'
0%
'
},
// 点击删除
clickDel
()
{
this
.
$emit
(
'
on-del
'
)
this
.
resetState
()
},
makeExceedSizeTips
()
{
if
(
this
.
maxSize
>=
1
)
{
return
`上传文件大小不能超过
${
this
.
maxSize
}
M`
}
return
`上传文件大小不能超过
${
this
.
maxSize
*
1000
}
K`
},
// 上传前
onBeforeUpload
(
file
)
{
// 检查文件格式
if
(
!
/jpg|jpeg|png|bmp/i
.
test
(
file
.
type
))
{
this
.
errorTips
(
'
上传文件格式不正确
'
)
return
false
}
if
(
file
.
size
>
60
*
1024
*
1024
)
{
this
.
errorTips
(
this
.
makeExceedSizeTips
())
return
false
}
if
(
file
.
size
>
this
.
maxSize
*
1024
*
1024
)
{
return
new
Promise
((
resolve
,
reject
)
=>
{
// 压缩
CompressImg
(
file
,
{
size
:
850
,
quality
:
70
,
cb
:
(
dataURL
)
=>
{
const
abData
=
BlobUtil
.
base64ToArrayBuffer
(
dataURL
)
if
(
abData
.
length
>
this
.
maxSize
*
1024
*
1024
)
{
this
.
errorTips
(
this
.
makeExceedSizeTips
())
reject
(
false
)
}
else
{
// 如果当前有正在上传的请求,取消这些请求
if
(
this
.
state
===
'
uploading
'
)
{
this
.
$refs
.
uploadRef
.
abort
()
}
// 设置token
this
.
reqHeaders
[
'
Authorization
'
]
=
`bearer
${
getToken
()}
`
this
.
state
=
'
uploading
'
// 设置上传文件为压缩后的文件
const
compressedFile
=
BlobUtil
.
Blob
([
abData
],
{
type
:
'
image/jpeg
'
})
resolve
(
new
File
([
compressedFile
],
file
.
name
||
'
压缩后的文件.jpeg
'
))
}
}
})
})
}
// 如果当前有正在上传的请求,取消这些请求
if
(
this
.
state
===
'
uploading
'
)
{
this
.
$refs
.
uploadRef
.
abort
()
}
// 设置token
this
.
reqHeaders
[
'
Authorization
'
]
=
`bearer
${
getToken
()}
`
this
.
state
=
'
uploading
'
return
true
},
// 上传中
onProgress
(
ev
,
file
)
{
if
(
ev
.
lengthComputable
)
{
this
.
uploadPercent
=
`
${(
ev
.
loaded
/
ev
.
total
)
*
100
}
%`
}
},
// 上传成功
async
onSuccess
(
res
,
file
)
{
this
.
uploadPercent
=
'
0%
'
try
{
res
.
data
.
accessUrl
=
await
imageViewer
(
res
.
data
.
uuid
)
}
catch
(
error
)
{
console
.
error
(
'
加密图片加载失败:
'
,
error
)
}
if
(
res
&&
res
.
success
&&
res
.
data
&&
res
.
data
.
accessUrl
)
{
const
fileRemoteUrl
=
this
.
makeFileRemoteUrlTemplate
()
fileRemoteUrl
.
id
=
res
.
data
.
uuid
fileRemoteUrl
.
url
=
res
.
data
.
accessUrl
// 上传成功
this
.
state
=
'
success
'
this
.
fileRemoteUrl
=
fileRemoteUrl
this
.
file
=
file
this
.
$emit
(
'
on-success
'
)
}
else
{
// 上传失败
this
.
state
=
'
error
'
this
.
fileRemoteUrl
=
this
.
makeFileRemoteUrlTemplate
()
this
.
file
=
null
this
.
$emit
(
'
on-error
'
)
}
},
// 上传失败
onUploadError
(
e
)
{
this
.
uploadPercent
=
'
0%
'
this
.
state
=
'
error
'
this
.
fileRemoteUrl
=
this
.
makeFileRemoteUrlTemplate
()
this
.
file
=
null
this
.
$emit
(
'
on-error
'
)
},
// 生成远程数据模板
makeFileRemoteUrlTemplate
()
{
return
{
id
:
null
,
url
:
''
}
},
/**
* 身份证ocr识别
*/
async
handleIdcardOcr
()
{
// 通过ocr读取证件信息
const
respData
=
await
getIdcardInfoByOcr
(
this
.
file
.
raw
)
// 返回读取的证件信息
this
.
$emit
(
'
on-cert
'
,
respData
)
}
}
}
</
script
>
<
style
lang=
"scss"
>
.comp-certificate-upload-wrap
{
position
:
relative
;
width
:
140px
;
.device-wrapper
{
position
:
absolute
;
bottom
:
0
;
right
:
-36px
;
}
}
.comp-certificate-upload
{
width
:
140px
;
.el-upload
{
box-sizing
:
border-box
;
position
:
relative
;
overflow
:
hidden
;
display
:
flex
;
flex-direction
:
column
;
justify-content
:
center
;
align-items
:
center
;
width
:
140px
;
height
:
96px
;
border
:
1px
dashed
#DCDFE6
;
border-radius
:
8px
;
background
:
#fff
;
.su-icon
{
width
:
86px
;
height
:
52px
;
margin
:
0
auto
7px
;
>
img
{
display
:
block
;
width
:
100%
;
height
:
100%
;
}
}
.su-text
,
.su-loading-text
{
font-size
:
12px
;
line-height
:
17px
;
color
:
#84858A
;
text-align
:
center
;
}
.su-img
{
display
:
block
;
max-width
:
100%
;
max-height
:
100%
;
}
.su-loading-bar
{
position
:
relative
;
width
:
100%
;
height
:
2px
;
.su-loading-bar-progress
{
position
:
absolute
;
left
:
0
;
top
:
0
;
bottom
:
0
;
width
:
0
;
background
:
blue
;
}
}
.su-success-operate-wrapper
{
position
:
absolute
;
left
:
0
;
right
:
0
;
bottom
:
0
;
display
:
flex
;
justify-content
:
center
;
align-items
:
center
;
height
:
22px
;
border-radius
:
0
0
8px
8px
;
background
:
rgba
(
0
,
0
,
0
,
0
.5
);
transition
:
opacity
.3s
ease-out
;
opacity
:
0
;
pointer-events
:
none
;
>
.su-operate-btn
{
width
:
50%
;
text-align
:
center
;
color
:
#fff
;
opacity
:
0
.7
;
&
.zoom
{
position
:
relative
;
overflow
:
hidden
;
border-left
:
1px
solid
#fff
;
.el-image
{
position
:
absolute
;
left
:
0
;
top
:
0
;
width
:
100%
;
height
:
100%
;
opacity
:
0
;
}
}
}
}
&
:hover
{
.su-success-operate-wrapper
{
pointer-events
:
auto
;
opacity
:
1
;
}
}
}
}
</
style
>
src/components/CompClientConfirm/index.vue
0 → 100644
View file @
d2c4018b
<
template
>
<div
class=
"comp-client-confirm"
>
<el-form
ref=
"form"
:model=
"form"
label-width=
"80px"
label-position=
"top"
size=
"small"
>
<page-module
name=
"确认步骤"
icon=
"step"
>
<el-row
:gutter=
"40"
>
<el-col
:span=
"24"
>
<div
class=
"SMS-confirm-course"
>
<img
:src=
"courseImg"
>
</div>
</el-col>
</el-row>
</page-module>
<page-module
name=
"信息内容"
icon=
"content"
>
<div
class=
"SMS-confirm-content"
>
<el-row
:gutter=
"40"
>
<el-col
:span=
"12"
>
<div
class=
"SMS-confirm-content-row marginTop0"
>
<div
class=
"SMS-confirm-content-title"
>
车主手机号
</div>
<div
class=
"SMS-confirm-content-content"
>
{{
turnHidePwd
(
form
.
mobile
)
}}
</div>
</div>
</el-col>
</el-row>
<el-row>
<el-col
:span=
"24"
>
<div
class=
"SMS-confirm-content-row"
>
<div
class=
"SMS-confirm-content-title"
>
短信内容
</div>
<div
class=
"SMS-confirm-content-content"
>
{{
form
.
vin
}}
</div>
</div>
</el-col>
</el-row>
</div>
</page-module>
</el-form>
<!-- 操作等待 -->
<operation-wait-dialog
:wait-visible=
"msgVisible"
:break-timer=
"breakTimer"
:prompt-info=
"promptInfo"
@
updateWaitVisible=
"updateWaitVisible"
/>
<!-- 成功 -->
<comp-confirm
:show.sync=
"tipVisible"
:desc=
"desc"
:show-cancel-btn=
"false"
:type=
"msgType"
@
on-sure=
"closeVisible"
/>
</div>
</
template
>
<
script
>
import
{
postIccidsByVin
,
postPollCardUnbindStatus
,
surplusCardResult
,
getUnBindIccidList
}
from
'
@/api/special-business
'
import
CompConfirm
from
'
@/components/CompConfirm
'
import
OperationWaitDialog
from
'
@/components/OperationWaitDialog
'
export
default
{
name
:
'
CompClientConfirm
'
,
components
:
{
CompConfirm
,
OperationWaitDialog
},
props
:
{
formData
:
{
type
:
Object
,
default
:
()
=>
{}
},
waitVisible
:
{
type
:
Boolean
,
default
:
()
=>
false
},
type
:
{
type
:
String
,
default
:
()
=>
''
},
promptInfo
:
{
type
:
String
,
default
:
()
=>
''
},
opreatorUuid
:
{
type
:
String
,
default
:
()
=>
''
}
},
data
()
{
return
{
courseImg
:
require
(
'
@/assets/special-business/course.png
'
),
tboxImg
:
require
(
'
@/assets/special-business/tbox.png
'
),
bindImg
:
require
(
'
@/assets/special-business/bindImg.png
'
),
unbindImg
:
require
(
'
@/assets/special-business/course.png
'
),
form
:
{
mobile
:
''
,
vin
:
''
},
rnrInfo
:
{},
rnrId
:
''
,
tipVisible
:
false
,
msgType
:
'
info
'
,
desc
:
''
,
carUnbindMsg
:
{
3
:
'
卡解绑成功
'
,
4
:
'
客户已取消操作
'
,
9
:
'
已超时, 如需操作请重试
'
},
enterpriserUnbindMsg
:
{
3
:
'
企业解绑成功
'
,
4
:
'
客户已取消操作
'
,
9
:
'
已超时, 如需操作请重试
'
},
tboxMsg
:
{
3
:
'
换件成功
'
,
4
:
'
客户已取消操作
'
,
9
:
'
已超时, 如需操作请重试
'
},
bindMsg
:
{
// 2等待中 3成功 4用户取消 9超时
3
:
'
卡绑定成功
'
,
4
:
'
客户已取消操作
'
,
9
:
'
已超时, 如需操作请重试
'
},
intervals
:
null
,
breakTimer
:
false
,
msgVisible
:
false
}
},
watch
:
{
formData
:
{
handler
(
val
,
oldVal
)
{
if
(
val
&&
val
!==
oldVal
)
{
this
.
displaySmsTxt
()
}
},
deep
:
true
,
immediate
:
true
},
waitVisible
:
{
handler
(
val
,
oldVal
)
{
if
(
val
&&
val
!==
oldVal
)
{
this
.
msgVisible
=
val
// 轮询是否发送了短信
this
.
handleStatus
()
}
}
}
},
methods
:
{
/**
* 展示短信内容
* @time 2022-04-24 06:49:47
*/
displaySmsTxt
()
{
let
smsMsg
=
''
const
curVin
=
this
.
formData
.
vin
instanceof
Array
?
this
.
formData
.
vin
.
map
(
vin
=>
this
.
turnHidePwd
(
vin
,
'
vin
'
))
:
this
.
turnHidePwd
(
this
.
formData
.
vin
,
'
vin
'
)
const
iccidTxtArr
=
this
.
formData
.
iccidList
?
this
.
formData
.
iccidList
.
map
((
item
)
=>
{
return
this
.
type
===
'
TBOX
'
?
`
${
this
.
turnHidePwd
(
item
.
iccid
,
'
iccid
'
)}
换为
${
this
.
turnHidePwd
(
item
.
newiccid
,
'
iccid
'
)}
`
:
this
.
turnHidePwd
(
item
.
iccid
,
'
iccid
'
)
})
:
[]
if
(
this
.
type
===
'
TBOX
'
)
{
// 换件
smsMsg
=
`尊敬的*先生/女士: 您正在对VIN号为
${
curVin
}
的车进行换件操作, 如下卡号:
${
iccidTxtArr
.
join
(
'
,
'
)}
。确定更换请回复“Y”, 放弃更换请回复“N”`
this
.
courseImg
=
this
.
tboxImg
}
if
(
this
.
type
===
'
UNBIND
'
)
{
// 卡解绑
smsMsg
=
`尊敬的*先生/女士: 您正在对VIN号为
${
curVin
}
的车进行解绑操作,解绑如下卡号:
${
iccidTxtArr
.
join
(
'
,
'
)}
。确定解绑请回复“Y”, 放弃解绑请回复“N”。解绑后该车将无法享受我们提供的联网服务, 请谨慎操作, 并确认您对该车的所属权。`
this
.
courseImg
=
this
.
unbindImg
}
if
(
this
.
type
===
'
BIND
'
||
this
.
type
===
''
)
{
// 卡绑定
smsMsg
=
`尊敬的*先生/女士: 您正在对VIN号为
${
curVin
}
的车进行一车多卡绑定操作, 绑定如下卡号:
${
iccidTxtArr
.
join
(
'
,
'
)}
。确定绑定请回复“Y”, 放弃绑定请回复“N”`
this
.
courseImg
=
this
.
bindImg
}
if
(
this
.
type
===
'
ENTERPRISE_UNBIND
'
)
{
smsMsg
=
`尊敬的*先生/女士:您作为企业责任人,正在对本企业
${
curVin
.
length
}
台车辆进行解绑操作。确定解绑请回复“Y”,放弃解绑请回复“N”。解绑后这批车辆将无法享受我们提供的联网服务,请谨慎操作,并确认本企业对该批车辆的所属权。`
}
this
.
form
.
vin
=
smsMsg
// 企业解绑不需要查询
if
(
this
.
type
!==
'
ENTERPRISE_UNBIND
'
)
{
this
.
getRnrInfoByVinFn
()
}
else
{
this
.
form
.
mobile
=
this
.
formData
.
mobile
console
.
clear
()
console
.
log
(
'
mobile:
'
,
this
.
formData
,
this
.
form
)
}
},
/**
* 加 * 号,置换首尾数字
* @param {String} val 手机号
* @time 2022-04-23 13:39:47
*/
turnHidePwd
(
val
,
type
)
{
const
curVal
=
''
+
val
if
(
type
===
'
vin
'
)
{
return
curVal
.
replace
(
/^
(\w{6})\w{8}(\w{3})
$/
,
'
$1********$2
'
)
}
else
if
(
type
===
'
iccid
'
)
{
return
curVal
.
replace
(
/^
(\w{6})\w{8}(\w{6})
$/
,
'
$1********$2
'
)
}
else
{
return
curVal
.
replace
(
/^
(\w{3})\w{4}(\w{4})
$/
,
'
$1****$2
'
)
}
},
/**
* 获取实名ID以及手机号
* @time 2022-04-23 15:26:33
*/
getRnrInfoByVinFn
()
{
if
(
this
.
type
===
'
BIND
'
)
{
getUnBindIccidList
({
data
:
{
vin
:
this
.
formData
.
vin
}
})
.
then
((
res
)
=>
{
this
.
rnrId
=
res
.
rnrId
this
.
form
.
mobile
=
res
.
phone
})
}
else
{
postIccidsByVin
({
data
:
{
vin
:
this
.
formData
.
vin
}
}).
then
(
res
=>
{
this
.
rnrInfo
=
res
.
mgRnrInfoDTO
this
.
rnrId
=
res
.
vehicleCardRnrDTO
.
rnrId
this
.
form
.
mobile
=
this
.
rnrInfo
.
phone
})
}
},
/**
* 操作等待弹出关闭后事件
* @time 2022-04-23 14:29:04
*/
updateWaitVisible
(
val
)
{
clearTimeout
(
this
.
intervals
)
// 在倒计时结束后, 延迟200毫秒发出最后一次请求
setTimeout
(()
=>
{
this
.
postStatusFuc
(
true
)
},
200
)
this
.
$emit
(
'
update:waitVisible
'
,
false
)
},
/**
* 关闭解绑成功弹出
* @time 2022-04-23 15:59:13
*/
closeVisible
()
{
if
(
this
.
msgType
===
'
success
'
)
{
// 成功 - 前往首页
this
.
$router
.
replace
({
name
:
'
Home
'
})
}
else
{
// 失败 - 关闭弹出
this
.
tipVisible
=
false
}
},
/**
* 查询定时器
* @time 2022-04-23 15:59:13
*/
handleStatus
()
{
this
.
intervals
=
setTimeout
(()
=>
{
this
.
postStatusFuc
()
},
6000
)
},
/**
* 查询是否发送短信
* @time 2022-04-23 15:59:13
*/
postStatusFuc
(
last
)
{
let
reqFuc
=
postPollCardUnbindStatus
let
reqData
=
{
uuid
:
this
.
opreatorUuid
}
if
(
this
.
type
===
'
BIND
'
)
{
reqFuc
=
surplusCardResult
reqData
=
{
orderId
:
this
.
opreatorUuid
}
}
reqFuc
(
reqData
)
.
then
((
res
)
=>
{
if
(
this
.
type
===
'
UNBIND
'
)
{
this
.
desc
=
this
.
carUnbindMsg
[
res
.
orderStatus
]
||
'
卡解绑失败
'
}
if
(
this
.
type
===
'
ENTERPRISE_UNBIND
'
)
{
this
.
desc
=
this
.
enterpriserUnbindMsg
[
res
.
orderStatus
]
||
'
企业解绑失败
'
}
if
(
this
.
type
===
'
TBOX
'
)
{
this
.
desc
=
this
.
tboxMsg
[
res
.
orderStatus
]
||
'
换件失败
'
}
if
(
this
.
type
===
'
BIND
'
)
{
this
.
desc
=
this
.
bindMsg
[
res
.
orderStatus
]
||
'
卡绑定失败
'
}
if
(
res
.
orderStatus
===
3
)
{
this
.
msgType
=
'
success
'
if
(
last
)
{
this
.
msgVisible
=
false
this
.
tipVisible
=
true
}
else
{
this
.
breakTimer
=
true
}
}
else
{
this
.
msgType
=
'
info
'
if
(
last
)
{
this
.
msgVisible
=
false
this
.
tipVisible
=
true
}
else
{
if
(
res
.
orderStatus
===
2
||
res
.
orderStatus
===
1
)
{
this
.
handleStatus
()
}
else
{
this
.
breakTimer
=
true
}
}
}
})
.
catch
((
err
)
=>
{
console
.
log
(
err
)
if
(
last
)
{
this
.
msgVisible
=
false
this
.
tipVisible
=
true
}
else
{
this
.
breakTimer
=
true
}
this
.
msgType
=
'
info
'
this
.
desc
=
err
.
message
||
'
操作失败
'
})
}
}
}
</
script
>
<
style
scoped
lang=
"scss"
>
.SMS-confirm-course
{
img
{
width
:
100%
;
}
}
.marginTop0
{
margin-top
:
0
!
important
;
}
.SMS-confirm-content-row
{
margin-top
:
23px
;
.SMS-confirm-content-title
{
font-size
:
14px
;
color
:
#212026
;
font-weight
:
700
;
}
.SMS-confirm-content-content
{
background
:
#F2F3F5
;
border-radius
:
4px
;
font-size
:
16px
;
color
:
#212026
;
line-height
:
24px
;
font-weight
:
400
;
padding
:
12px
;
margin-top
:
13px
;
text-align
:
left
;
word-break
:
break-all
;
}
}
</
style
>
src/components/CompConcatInfo/index.vue
0 → 100644
View file @
d2c4018b
<
template
>
<div
class=
"comp-concat-info"
>
<el-form
ref=
"formRef"
:model=
"form"
:rules=
"formRules"
size=
"small"
label-position=
"top"
>
<el-row
:gutter=
"40"
>
<el-col
:span=
"12"
>
<el-form-item
label=
"手机号"
prop=
"phone"
>
<el-input
v-model=
"form.phone"
placeholder=
"请输入手机号"
clearable
maxlength=
"11"
/>
</el-form-item>
</el-col>
<el-col
v-if=
"needVcode"
:span=
"12"
>
<el-row
:gutter=
"8"
>
<el-col
:span=
"16"
>
<el-form-item
label=
"验证码"
prop=
"veCode"
>
<el-input
v-model=
"form.veCode"
clearable
maxlength=
"6"
placeholder=
"请输入验证码"
/>
</el-form-item>
</el-col>
<el-col
:span=
"8"
>
<el-form-item
label=
"验证码"
class=
"cci-hidden-form-item-label"
>
<el-button
:disabled=
"disableSendBtn"
type=
"primary"
size=
"small"
@
click.stop=
"clickSendVeCode"
>
{{
sendBtnText
}}
</el-button>
</el-form-item>
</el-col>
</el-row>
</el-col>
</el-row>
</el-form>
</div>
</
template
>
<
script
>
import
{
validPhone
}
from
'
@/utils/validate
'
import
{
sendSmsCaptcha
}
from
'
@/api/realname-person
'
export
default
{
name
:
'
CompConcatInfo
'
,
props
:
{
data
:
{
type
:
Object
,
default
:
()
=>
({})
},
needVcode
:
{
type
:
Boolean
,
default
:
true
},
bizType
:
{
type
:
String
,
default
:
'
rnr
'
}
},
data
()
{
const
checkPhone
=
(
rule
,
value
,
callback
)
=>
{
if
(
value
===
''
)
{
callback
(
new
Error
(
`请输入手机号`
))
}
else
if
(
!
validPhone
(
value
))
{
callback
(
new
Error
(
`手机号格式不正确`
))
}
else
{
callback
()
}
}
return
{
form
:
{
phone
:
''
,
veCode
:
''
},
formRules
:
{
phone
:
[
{
required
:
true
,
validator
:
checkPhone
,
trigger
:
'
blur
'
}
],
veCode
:
[
{
required
:
true
,
message
:
'
请输入验证码
'
,
trigger
:
'
change
'
}
]
},
sendBtnText
:
'
发送验证码
'
,
countingDown
:
false
}
},
computed
:
{
disableSendBtn
()
{
return
this
.
countingDown
||
(
this
.
form
.
phone
===
''
||
!
validPhone
(
this
.
form
.
phone
))
}
},
watch
:
{
data
()
{
this
.
updateInternalData
()
}
},
created
()
{
this
.
init
()
},
methods
:
{
init
()
{
this
.
updateInternalData
()
},
updateInternalData
()
{
if
(
typeof
this
.
data
===
'
object
'
&&
this
.
data
!==
null
)
{
this
.
form
.
phone
=
this
.
data
.
phone
||
''
this
.
form
.
veCode
=
this
.
data
.
veCode
||
''
}
else
{
this
.
form
.
phone
=
''
this
.
form
.
veCode
=
''
this
.
countingDown
=
false
this
.
sendBtnText
=
'
发送验证码
'
}
},
// 点击发送验证码
clickSendVeCode
()
{
if
(
this
.
countingDown
)
{
return
}
this
.
countingDown
=
true
this
.
sendVeCode
()
this
.
startCountingDown
()
},
// 倒计时
startCountingDown
()
{
clearTimeout
(
this
.
_ctTid
)
let
ctNum
=
59
this
.
sendBtnText
=
`
${
ctNum
--
}
S后重发`
const
countingDownHandler
=
()
=>
{
if
(
ctNum
>
0
)
{
this
.
sendBtnText
=
`
${
ctNum
--
}
S后重发`
this
.
_ctTid
=
setTimeout
(
countingDownHandler
,
1000
)
}
else
{
this
.
sendBtnText
=
'
发送验证码
'
this
.
countingDown
=
false
}
}
this
.
_ctTid
=
setTimeout
(
countingDownHandler
,
1000
)
},
async
sendVeCode
()
{
let
ret
=
null
try
{
ret
=
await
sendSmsCaptcha
({
phone
:
this
.
form
.
phone
,
bizType
:
this
.
bizType
})
}
catch
(
e
)
{
ret
=
{}
}
return
ret
||
{}
},
// 校验
async
validate
(
isErrorAnchor
=
false
)
{
try
{
await
this
.
$refs
.
formRef
.
validate
()
return
true
}
catch
(
e
)
{
if
(
isErrorAnchor
)
{
this
.
$refs
.
formRef
.
fields
.
filter
(
item
=>
item
.
validateState
===
'
error
'
)[
0
].
$el
.
scrollIntoView
(
true
)
}
let
temp
=
{
anchor
:
()
=>
{
this
.
$refs
.
formRef
.
fields
.
filter
(
item
=>
item
.
validateState
===
'
error
'
)[
0
].
$el
.
scrollIntoView
(
true
)
temp
=
null
}
}
throw
temp
}
},
// 获取数据
getFormData
()
{
return
{
phone
:
this
.
form
.
phone
,
veCode
:
this
.
form
.
veCode
}
},
// 获取待缓存数据
getPendingCacheData
()
{
return
this
.
getFormData
()
},
/**
* 清空校验值
*/
clearValidate
()
{
this
.
$refs
.
formRef
.
clearValidate
()
}
}
}
</
script
>
<
style
lang=
"scss"
>
.comp-concat-info
{
.cci-hidden-form-item-label
{
.el-form-item__label
{
visibility
:
hidden
;
}
}
}
</
style
>
src/components/CompConfirm/index.vue
0 → 100644
View file @
d2c4018b
<
template
>
<div
:class=
"
{show}" class="comp-confirm">
<div
class=
"cc-content-wrapper"
>
<div
class=
"cc-content-main"
>
<div
class=
"cc-icon"
>
<svg
v-if=
"type === 'success'"
width=
"100%"
height=
"100%"
viewBox=
"0 0 28 28"
version=
"1.1"
xmlns=
"http://www.w3.org/2000/svg"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
>
<g
fill=
"#25C343"
>
<path
d=
"M14,0.875 C21.2487373,0.875 27.125,6.75126266 27.125,14 C27.125,21.2487373 21.2487373,27.125 14,27.125 C6.75126266,27.125 0.875,21.2487373 0.875,14 C0.875,6.75126266 6.75126266,0.875 14,0.875 Z M19.5344115,9.30436434 C19.3836132,9.15373919 19.1422439,9.14871835 18.9854074,9.28930183 L18.9694917,9.30436434 L11.9156158,16.3501294 L8.81175831,13.2499302 C8.66095994,13.0993051 8.41959062,13.0942842 8.26275419,13.2348677 L8.24683845,13.2499302 L7.11699873,14.3784721 C6.96620037,14.5290973 6.96117375,14.7701894 7.1019189,14.9268456 L7.11699873,14.9427431 L10.4381346,18.2601477 C10.4501112,18.2794965 10.4638977,18.2980447 10.4794941,18.3155504 L10.4956938,18.3326996 L11.6255335,19.4612415 C11.7440613,19.579633 11.9185436,19.6080705 12.0639378,19.5466213 C12.1068259,19.529948 12.1474116,19.5055961 12.1835744,19.4735657 L12.2012775,19.4569107 L13.3311172,18.3283688 C13.3407696,18.3187274 13.3498248,18.3087154 13.3582828,18.2983786 L13.3705217,18.2826356 L20.6642513,10.9971772 C20.8150496,10.846552 20.8200762,10.60546 20.6793311,10.4488037 L20.6642513,10.4329062 L19.5344115,9.30436434 Z"
/>
</g>
</svg>
<svg
v-if=
"type === 'info'"
width=
"100%"
height=
"100%"
viewBox=
"0 0 28 28"
version=
"1.1"
xmlns=
"http://www.w3.org/2000/svg"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
>
<g
stroke=
"none"
stroke-width=
"1"
fill=
"none"
fill-rule=
"evenodd"
>
<g
transform=
"translate(-587.000000, -74.000000)"
fill=
"#FF9C00"
>
<g
transform=
"translate(587.000000, 74.000000)"
>
<path
d=
"M14,0.875 C21.2487373,0.875 27.125,6.75126266 27.125,14 C27.125,21.2487373 21.2487373,27.125 14,27.125 C6.75126266,27.125 0.875,21.2487373 0.875,14 C0.875,6.75126266 6.75126266,0.875 14,0.875 Z M14.875,18.375 L13.125,18.375 C12.8906974,18.375 12.6994132,18.5591841 12.6880354,18.7906643 L12.6875,18.8125 L12.6875,20.5625 C12.6875,20.7968026 12.8716841,20.9880868 13.1031643,20.9994646 L13.125,21 L14.875,21 C15.1093026,21 15.3005868,20.8158159 15.3119646,20.5843357 L15.3125,20.5625 L15.3125,18.8125 C15.3125,18.5781974 15.1283159,18.3869132 14.8968357,18.3755354 L14.875,18.375 Z M14.875,7.984375 L13.125,7.984375 C12.8906974,7.984375 12.6994132,8.16855905 12.6880354,8.40003934 L12.6875,8.421875 L12.6875,16.1875 C12.6875,16.4218026 12.8716841,16.6130868 13.1031643,16.6244646 L13.125,16.625 L14.875,16.625 C15.1093026,16.625 15.3005868,16.4408159 15.3119646,16.2093357 L15.3125,16.1875 L15.3125,8.421875 C15.3125,8.18757238 15.1283159,7.99628825 14.8968357,7.98491042 L14.875,7.984375 Z"
/>
</g>
</g>
</g>
</svg>
</div>
<div
class=
"cc-desc"
>
{{
desc
}}
</div>
</div>
<div
class=
"cc-content-footer"
>
<el-button
v-if=
"showCancelBtn"
size=
"small"
@
click.stop=
"clickCancel"
>
取消
</el-button>
<el-button
type=
"primary"
size=
"small"
@
click.stop=
"clickSure"
>
确定
</el-button>
</div>
</div>
</div>
</
template
>
<
script
>
export
default
{
name
:
'
CompConfirm
'
,
props
:
{
show
:
{
type
:
Boolean
,
default
:
false
},
desc
:
{
type
:
String
,
default
:
''
},
showCancelBtn
:
{
type
:
Boolean
,
default
:
false
},
type
:
{
type
:
String
,
default
:
'
info
'
}
},
mounted
()
{
document
.
body
.
appendChild
(
this
.
$el
)
},
destroyed
()
{
document
.
body
.
removeChild
(
this
.
$el
)
},
methods
:
{
clickCancel
()
{
this
.
$emit
(
'
update:show
'
,
false
)
this
.
$emit
(
'
on-cancel
'
)
},
clickSure
()
{
this
.
$emit
(
'
update:show
'
,
false
)
this
.
$emit
(
'
on-sure
'
)
}
}
}
</
script
>
<
style
lang=
"scss"
>
.comp-confirm
{
position
:
fixed
;
left
:
0
;
top
:
0
;
z-index
:
9999
;
display
:
flex
;
justify-content
:
center
;
align-items
:
center
;
width
:
100%
;
height
:
100%
;
background
:
rgba
(
0
,
0
,
0
,
0
.5
);
opacity
:
0
;
transition
:
opacity
.3s
ease-out
;
pointer-events
:
none
;
.cc-content-wrapper
{
box-sizing
:
border-box
;
width
:
480px
;
padding
:
24px
;
border-radius
:
4px
;
font-size
:
16px
;
color
:
#111
;
background
:
#fff
;
transform
:
translate3d
(
0
,
-20px
,
0
);
transition
:
transform
.3s
ease-out
;
.cc-content-main
{
display
:
flex
;
.cc-icon
{
flex
:
0
0
auto
;
width
:
28px
;
height
:
28px
;
margin-right
:
9px
}
.cc-desc
{
line-height
:
28px
;
word-break
:
break-all
;
}
}
.cc-content-footer
{
margin-top
:
26px
;
text-align
:
right
;
}
}
&
.show
{
opacity
:
1
;
pointer-events
:
auto
;
.cc-content-wrapper
{
transform
:
translate3d
(
0
,
0
,
0
);
}
}
}
</
style
>
Prev
1
…
5
6
7
8
9
10
11
12
13
…
20
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment