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
Hide whitespace changes
Inline
Side-by-side
src/components/Device/components/photoStep/icon_clear.svg
0 → 100644
View file @
d2c4018b
<?xml version="1.0" encoding="UTF-8"?>
<svg
width=
"16px"
height=
"16px"
viewBox=
"0 0 16 16"
version=
"1.1"
xmlns=
"http://www.w3.org/2000/svg"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
>
<title>
ico_清除条件@2x
</title>
<g
id=
"车企实名制系统"
stroke=
"none"
stroke-width=
"1"
fill=
"none"
fill-rule=
"evenodd"
>
<g
id=
"入网协议-签字"
transform=
"translate(-945.000000, -242.000000)"
fill-rule=
"nonzero"
>
<g
id=
"编组-7"
transform=
"translate(407.000000, 155.000000)"
>
<g
id=
"Group-52"
transform=
"translate(522.000000, 78.000000)"
>
<g
id=
"清除"
transform=
"translate(16.000000, 9.000000)"
>
<rect
id=
"矩形"
fill=
"#000000"
opacity=
"0"
x=
"0"
y=
"0"
width=
"16"
height=
"16"
></rect>
<path
d=
"M14.0484375,13.5875 L13.2203125,8.8125 L13.5,8.8125 C13.725,8.8125 13.90625,8.63125 13.90625,8.40625 L13.90625,5.40625 C13.90625,5.18125 13.725,5 13.5,5 L9.65625,5 L9.65625,2.15625 C9.65625,1.93125 9.475,1.75 9.25,1.75 L6.75,1.75 C6.525,1.75 6.34375,1.93125 6.34375,2.15625 L6.34375,5 L2.5,5 C2.275,5 2.09375,5.18125 2.09375,5.40625 L2.09375,8.40625 C2.09375,8.63125 2.275,8.8125 2.5,8.8125 L2.7796875,8.8125 L1.9515625,13.5875 C1.946875,13.6109375 1.9453125,13.634375 1.9453125,13.65625 C1.9453125,13.88125 2.1265625,14.0625 2.3515625,14.0625 L13.6484375,14.0625 C13.671875,14.0625 13.6953125,14.0609375 13.7171875,14.05625 C13.9390625,14.01875 14.0875,13.8078125 14.0484375,13.5875 Z M3.1875,6.09375 L7.4375,6.09375 L7.4375,2.84375 L8.5625,2.84375 L8.5625,6.09375 L12.8125,6.09375 L12.8125,7.71875 L3.1875,7.71875 L3.1875,6.09375 Z M10.5,12.96875 L10.5,10.53125 C10.5,10.4625 10.44375,10.40625 10.375,10.40625 L9.625,10.40625 C9.55625,10.40625 9.5,10.4625 9.5,10.53125 L9.5,12.96875 L6.5,12.96875 L6.5,10.53125 C6.5,10.4625 6.44375,10.40625 6.375,10.40625 L5.625,10.40625 C5.55625,10.40625 5.5,10.4625 5.5,10.53125 L5.5,12.96875 L3.16875,12.96875 L3.8734375,8.90625 L12.125,8.90625 L12.8296875,12.96875 L10.5,12.96875 Z"
id=
"形状"
fill=
"#2A68FF"
></path>
</g>
</g>
</g>
</g>
</g>
</svg>
\ No newline at end of file
src/components/Device/components/photoStep/index.vue
0 → 100644
View file @
d2c4018b
<
template
>
<div
class=
"photo-steps"
>
<div
:style=
"
{margin}" class="step-list">
<div
v-for=
"(name, i) of data"
:key=
"i"
:class=
"
{finished: index >= i}" class="step-item">
{{
name
}}
</div>
</div>
</div>
</
template
>
<
script
>
export
default
{
name
:
'
Steps
'
,
props
:
{
data
:
{
type
:
Array
,
default
()
{
return
[]
}
},
index
:
{
type
:
Number
,
default
()
{
return
0
}
},
// 针对只有2个步骤两边需要填充更多白边时,如卡解绑UI稿
margin
:
{
type
:
String
,
default
()
{
return
'
0 0 0 0
'
}
}
}
}
</
script
>
<
style
lang=
"scss"
>
.photo-steps
{
width
:
260px
;
.step-list
{
display
:
flex
;
justify-content
:
space-between
;
align-items
:
center
;
position
:
relative
;
height
:
34px
;
&
:after
{
content
:
''
;
height
:
4px
;
background
:
radial-gradient
(
circle
at
1px
1px
,
#edeef0
2px
,
transparent
0
);
background-size
:
10px
10px
;
position
:
absolute
;
top
:
50%
;
left
:
0
;
right
:
0
;
margin-top
:
-2px
;
z-index
:
1
;
}
}
.step-item
{
padding
:
0
12px
0
34px
;
font-family
:
PingFangSC-Semibold
,
PingFang
SC
;
font-weight
:
600
;
background
:
#fff
url(./icon_arrow.svg)
no-repeat
12px
center
/
14px
14px
;
color
:
rgba
(
132
,
133
,
138
,
0
.6
);
position
:
relative
;
z-index
:
9
;
&
.finished
{
color
:
#212026
;
background
:
#fff
url(./icon_arrow_finished.svg)
no-repeat
12px
center
/
14px
14px
;
}
&
:first-child
{
padding-left
:
22px
;
background-position
:
0
center
;
}
}
}
</
style
>
src/components/Device/dialog.vue
0 → 100644
View file @
d2c4018b
<
template
>
<el-dialog
v-loading.fullscreen.lock=
"fullscreenLoading"
:visible.sync=
"showDialog"
:title=
"title"
destroy-on-close
width=
"750px"
top=
"10vh"
@
close=
"closeDialog"
>
<div
v-if=
"sign"
class=
"device-top"
>
<el-button
class=
"btn-clear"
size=
"small"
@
click=
"openSign"
>
{{
signList
.
length
===
0
?
'
签名
'
:
'
重签
'
}}
</el-button>
</div>
<div
class=
"preview-list"
>
<div
v-for=
"(item, i) of photoList"
:key=
"i"
class=
"preview-item"
>
<img
:src=
"item.accessUrl"
@
click=
"previewPhoto(i)"
>
<i
class=
"el-icon-delete"
@
click=
"removePhoto(i)"
/>
</div>
</div>
<div
v-loading=
"loading"
class=
"take-photo"
>
<canvas
v-show=
"stepIndex === 0 && !sign"
ref=
"photoCanvas"
:width=
"videoParams.video_frame_w"
:height=
"videoParams.video_frame_h"
class=
"canvas-phone"
/>
<div
v-if=
"sign"
:width=
"iWidth"
:height=
"iHeight"
class=
"canvas-sign"
>
<div
v-for=
"sign in signList"
:key=
"sign.accessUrl"
class=
"compose-area"
>
<img
:src=
"sign.agreement"
crossorigin=
"anonymous"
class=
"agreement-image"
>
<img
:src=
"sign.accessUrl"
class=
"sign-image"
>
<img
:src=
"attachmentUrl"
class=
"agreement-image"
>
</div>
<div
v-if=
"signList.length === 0"
class=
"tip"
>
点击“签名”按钮后,请在高拍仪上签名
</div>
</div>
</div>
<div
slot=
"footer"
class=
"dialog-footer"
>
<el-button
size=
"small"
@
click=
"closeDialog"
>
取消
</el-button>
<template
v-if=
"sign"
>
<el-button
:disabled=
"signList.length === 0"
:loading=
"showLoading"
size=
"small"
type=
"primary"
@
click=
"handleComposeSign"
>
完成
</el-button>
</
template
>
<
template
v-else
>
<el-button
:disabled=
"photoList.length >= limit"
size=
"small"
class=
"btn-camera"
@
click=
"takePhoto()"
>
拍摄
</el-button>
<el-button
:disabled=
"photoList.length === 0"
size=
"small"
type=
"primary"
@
click=
"uploadList"
>
完成
</el-button>
</
template
>
</div>
<image-viewer
v-if=
"showViewer"
:z-index=
"zIndex"
:initial-index=
"imageIndex"
:on-close=
"closeViewer"
:url-list=
"urlList"
/>
</el-dialog>
</template>
<
script
>
import
deviceService
from
'
@/components/Device/service
'
import
ImageViewer
from
'
@/components/Uploader/image-viewer
'
import
{
postVinUpload
,
cuscImageUpload
}
from
'
@/api/realname-enterprise
'
import
{
getToken
}
from
'
@/utils/auth
'
import
request
from
'
@/utils/request
'
import
photoStep
from
'
./components/photoStep
'
import
wzh
from
'
./wzh
'
import
{
imageViewer
}
from
'
@/utils/upload
'
import
{
jsPDF
as
JsPdf
}
from
'
jspdf
'
import
html2canvas
from
'
html2canvas
'
import
{
queryPotocolManage
}
from
'
@/api/management
'
export
default
{
name
:
'
DeviceHandle
'
,
components
:
{
ImageViewer
,
photoStep
},
props
:
{
// 展示弹窗
show
:
{
type
:
Boolean
,
default
:
false
},
// 是否签字
sign
:
{
type
:
Boolean
,
default
:
false
},
// 弹窗类型, photo: 图片, video: 视频
type
:
{
type
:
String
,
default
:
'
photo
'
},
// 图片个数
limit
:
{
type
:
Number
,
default
:
3
},
// 弹窗标题
title
:
{
type
:
String
,
default
:
'
拍照
'
},
// 图片列表
data
:
{
type
:
Array
,
default
:
()
=>
{
[]
}
},
// 是否加密上传
security
:
{
type
:
Boolean
,
default
:
false
},
// 需要签名的字段
signKey
:
{
type
:
String
,
default
:
''
},
// 附件
attachmentUrl
:
{
type
:
String
,
default
:
''
}
},
data
()
{
return
{
fullscreenLoading
:
false
,
loading
:
false
,
showDialog
:
false
,
stepIndex
:
0
,
stepData
:
[
'
拍摄
'
,
'
签字
'
],
openStatus
:
false
,
// 视频打开状态
cutStatus
:
0
,
// 0代表裁切,1代表不裁切
changeStatus
:
false
,
// 设备宽高
deviceWidth
:
0
,
deviceHeight
:
0
,
// 画板宽高
iWidth
:
800
,
iHeight
:
490
,
// 签字状态
startSign
:
false
,
isFirst
:
false
,
points
:
[],
beginPoint
:
null
,
videoParams
:
{
camera_type
:
0
,
// 0代表主摄像头, 1代表副摄像头
video_frame_w
:
0
,
video_frame_h
:
0
},
// 上传参数
uploadConf
:
{
url
:
this
.
security
?
cuscImageUpload
:
postVinUpload
,
headers
:
{
'
X-Requested-With
'
:
'
XMLHttpRequest
'
,
'
Content-Type
'
:
'
application/x-www-form-urlencoded;charset=utf-8
'
,
'
Authorization
'
:
`bearer
${
getToken
()}
`
},
data
:
{
rootPath
:
''
,
path
:
''
}
},
// 预览参数
photoList
:
[],
signList
:
[],
showViewer
:
false
,
zIndex
:
2000
,
imageIndex
:
0
,
prevOverflow
:
''
,
showLoading
:
false
}
},
computed
:
{
urlList
()
{
if
(
this
.
stepIndex
===
0
)
{
return
this
.
photoList
.
map
(
item
=>
{
return
item
.
accessUrl
})
}
else
{
return
this
.
signList
.
map
(
item
=>
{
return
item
.
accessUrl
})
}
}
},
watch
:
{
show
(
val
)
{
this
.
showDialog
=
val
if
(
val
)
{
// 如果当前需要签名,则直接打开签名页
if
(
!
this
.
sign
)
{
this
.
initList
(
this
.
data
)
this
.
$nextTick
(()
=>
{
this
.
openPhoto
()
})
}
}
else
{
this
.
closePhoto
()
if
(
this
.
stepIndex
===
1
)
{
this
.
closeSign
()
}
this
.
stepIndex
=
0
this
.
photoList
=
[]
this
.
signList
=
[]
this
.
startSign
=
false
}
}
},
methods
:
{
/**
* 初始化图片列表及签名列表数据
* @time 2022-05-12 21:03:29
*/
initList
(
list
)
{
list
.
forEach
(
item
=>
{
if
(
item
.
type
===
'
photo
'
||
!
item
.
type
)
{
this
.
photoList
.
push
(
item
)
}
else
if
(
item
.
type
===
'
sign
'
)
{
this
.
signList
.
push
(
item
)
}
})
},
/**
* 打开拍照
* @time 2022-05-10 15:51:55
*/
openPhoto
()
{
this
.
openStatus
=
false
this
.
videoParams
=
{
camera_type
:
0
,
video_frame_w
:
0
,
video_frame_h
:
0
}
this
.
loading
=
true
// 获取设备信息
deviceService
.
getVideoInfo
().
then
(
data
=>
{
if
(
data
.
length
===
2
)
{
// 主摄像头
const
masterCamera
=
data
.
find
(
item
=>
{
return
item
.
camera_type
===
this
.
videoParams
.
camera_type
})
const
resolutionInfo
=
masterCamera
.
resolution_info
||
[]
const
pixelIndex
=
parseInt
(
resolutionInfo
.
length
/
2
)
if
(
this
.
videoParams
.
video_frame_w
===
0
||
this
.
videoParams
.
video_frame_w
===
resolutionInfo
[
pixelIndex
].
width
)
{
this
.
videoParams
.
video_frame_w
=
resolutionInfo
[
pixelIndex
].
width
this
.
videoParams
.
video_frame_h
=
resolutionInfo
[
pixelIndex
].
height
}
const
ctx
=
this
.
$refs
.
photoCanvas
.
getContext
(
'
2d
'
)
const
image
=
new
Image
()
ctx
.
clearRect
(
0
,
0
,
this
.
videoParams
.
video_frame_w
,
this
.
videoParams
.
video_frame_h
)
// 打开主视频
deviceService
.
masterOpenVideo
(
this
.
videoParams
,
this
.
cutStatus
,
json
=>
{
if
(
!
this
.
changeStatus
)
{
this
.
openStatus
=
true
}
if
(
json
.
err_code
===
0
)
{
this
.
loading
=
false
image
.
src
=
'
data:image/jpeg;base64,
'
+
json
.
data
image
.
onload
=
function
()
{
ctx
.
drawImage
(
image
,
0
,
0
,
image
.
width
,
image
.
height
)
}
}
else
{
this
.
$message
.
error
(
json
.
err_msg
)
this
.
loading
=
false
}
})
}
}).
catch
(
err
=>
{
this
.
$message
.
error
(
err
)
})
},
/**
* 关闭拍照
* @time 2022-05-10 16:21:38
*/
closePhoto
()
{
deviceService
.
closeVideo
().
then
(()
=>
{
console
.
log
(
'
拍照关闭成功
'
)
}).
catch
(
err
=>
{
console
.
log
(
err
)
})
},
/**
* 主摄像头拍照
* @time 2022-05-10 15:54:58
*/
takePhoto
()
{
if
(
!
this
.
openStatus
)
{
this
.
$message
.
warning
(
'
摄像头正在加载中,请稍候
'
)
return
}
deviceService
.
masterTakePhoto
().
then
(
data
=>
{
if
(
data
)
{
const
content
=
'
data:image/png;base64,
'
+
data
const
blob
=
this
.
base64ToBlob
(
content
)
const
blobUrl
=
URL
.
createObjectURL
(
blob
)
this
.
photoList
.
push
({
type
:
'
photo
'
,
blob
,
accessUrl
:
blobUrl
})
}
else
{
this
.
closeDialog
()
}
}).
catch
(
err
=>
{
this
.
$message
.
error
(
err
)
})
},
/**
* 关闭弹窗
* @time 2022-05-10 16:21:17
*/
closeDialog
()
{
this
.
$emit
(
'
update:show
'
,
false
)
},
/**
* 下一步
* @time 2022-05-10 16:09:45
*/
onNextStep
()
{
this
.
loading
=
true
this
.
stepIndex
=
1
this
.
closePhoto
()
this
.
initSignCanvas
()
if
(
this
.
signList
.
length
===
0
)
{
this
.
openSign
()
}
},
/**
* 上一步
* @time 2022-05-10 16:09:36
*/
onPrevStep
()
{
this
.
stepIndex
=
0
this
.
startSign
=
false
this
.
signList
=
[]
this
.
initSignCanvas
()
this
.
closeSign
()
this
.
$nextTick
(()
=>
{
this
.
openPhoto
()
})
},
/**
* 初始化签名画布
* @time 2022-05-10 16:00:49
*/
initSignCanvas
()
{
this
.
loading
=
false
this
.
ctxSign
=
this
.
$refs
.
signCanvas
.
getContext
(
'
2d
'
)
this
.
ctxSign
.
fillStyle
=
'
#f9f9f9
'
this
.
ctxSign
.
fillRect
(
0
,
0
,
this
.
iWidth
,
this
.
iHeight
)
this
.
ctxSign
.
strokeStyle
=
'
#000
'
// 线条颜色
this
.
ctxSign
.
lineWidth
=
3
this
.
ctxSign
.
lineCap
=
'
round
'
// 线条末端添加圆形线帽,减少线条的生硬感
this
.
ctxSign
.
lineJoin
=
'
round
'
// 线条交汇时为原型边角
// 利用阴影,消除锯齿
this
.
ctxSign
.
shadowBlur
=
1
// 线条阴影大小
this
.
ctxSign
.
shadowColor
=
'
#000
'
// 线条阴影颜色
},
/**
* 页面点击重签
* @time 2022-05-10 16:49:47
*/
againSign
()
{
if
(
this
.
signList
.
length
>
0
)
{
this
.
signList
=
[]
this
.
startSign
=
true
this
.
initSignCanvas
()
this
.
openSign
()
return
}
if
(
!
this
.
startSign
)
{
return
}
this
.
againSignCallback
()
},
/**
* 外部设备重签
* @time 2022-05-10 16:09:57
*/
againSignCallback
()
{
this
.
startSign
=
false
this
.
initSignCanvas
()
},
/**
* 关闭签字
* @time 2022-05-10 16:10:07
*/
closeSign
()
{
deviceService
.
closeSign
().
then
(
data
=>
{
console
.
log
(
'
关闭签字成功
'
)
}).
catch
(
err
=>
{
console
.
log
(
err
)
})
},
/**
* 开始签名
* @time 2022-05-10 16:10:39
*/
async
openSign
()
{
// 请求接口
const
agreements
=
await
queryPotocolManage
({
orgId
:
this
.
$store
.
getters
.
organId
})
// 源url
const
originUrlLink
=
agreements
[
this
.
signKey
+
'
Vertical
'
]
// 源文件路径
const
originUrl
=
originUrlLink
?
originUrlLink
.
fileUrl
:
''
// 协议图片
const
agreementImage
=
new
Image
()
// 协议图片加载完成
agreementImage
.
onload
=
async
()
=>
{
// 创建canvas
const
cvs
=
document
.
createElement
(
'
canvas
'
)
// 获取绘图上下文
const
ctx
=
cvs
.
getContext
(
'
2d
'
)
// 创建canvas的大小
cvs
.
width
=
agreementImage
.
width
cvs
.
height
=
agreementImage
.
height
// 开始绘制图片
ctx
.
drawImage
(
agreementImage
,
0
,
0
,
agreementImage
.
width
,
agreementImage
.
height
)
// 获取base64地址
const
base64
=
cvs
.
toDataURL
(
'
image/jpeg
'
,
0.8
)
// 创建pdf对象
const
pdf
=
new
JsPdf
(
''
,
'
pt
'
,
'
a4
'
)
// 开始添加图片
pdf
.
addImage
(
base64
,
'
JPEG
'
,
0
,
0
,
595.28
,
(
595.28
/
agreementImage
.
width
)
*
agreementImage
.
height
)
// pdf的base64编码
const
pdfBase64
=
pdf
.
output
(
'
dataurlstring
'
)
// 开始预览签名
const
respData
=
await
wzh
.
previewSignT
(
pdfBase64
.
slice
(
pdfBase64
.
indexOf
(
'
base64,
'
)
+
7
))
// 将签名图片合
this
.
signList
=
[
{
accessUrl
:
`data:image/png;base64,
${
respData
.
signImage
}
`
,
agreement
:
originUrl
}
]
}
// 添加跨域
agreementImage
.
setAttribute
(
'
crossOrigin
'
,
'
anonymous
'
)
// 开始加载图片
agreementImage
.
src
=
originUrl
},
/**
* 将签名照片和协议照片组合在一起
*/
async
handleComposeSign
()
{
// 确定按钮展示loading
this
.
showLoading
=
true
try
{
// 将html抓换成canvas
const
canvas
=
await
html2canvas
(
document
.
querySelector
(
'
.compose-area
'
),
{
useCORS
:
true
})
// 导出图片文件
canvas
.
toBlob
(
async
blob
=>
{
try
{
// 将生成的图片传递给父组件
const
file
=
await
this
.
uploadPhoto
(
blob
)
// 关闭弹框
this
.
closeDialog
()
// 开始通知父组件
this
.
$emit
(
'
getPhoto
'
,
[
file
])
}
catch
(
error
)
{
console
.
error
(
error
)
}
// 关闭loading状态
this
.
showLoading
=
false
})
}
catch
(
error
)
{
console
.
error
(
error
)
this
.
showLoading
=
false
}
},
/**
* 签名获取坐标
* @time 2022-05-10 16:10:47
*/
getCoordinateCallback
(
res
)
{
if
(
res
.
err_code
===
0
)
{
const
signStatus
=
res
.
data
.
status
const
xInit
=
res
.
data
.
x
const
yInit
=
res
.
data
.
y
const
xSign
=
this
.
iWidth
*
xInit
/
this
.
deviceWidth
const
ySign
=
this
.
iHeight
*
yInit
/
this
.
deviceHeight
switch
(
signStatus
)
{
case
161
:
this
.
startSign
=
true
if
(
this
.
isFirst
)
{
this
.
points
.
push
({
xSign
:
xSign
,
ySign
:
ySign
})
if
(
this
.
points
.
length
>
3
)
{
const
lastTwoPoints
=
this
.
points
.
slice
(
-
2
)
const
controlPoint
=
lastTwoPoints
[
0
]
const
endPoint
=
{
xSign
:
(
lastTwoPoints
[
0
].
xSign
+
lastTwoPoints
[
1
].
xSign
)
/
2
,
ySign
:
(
lastTwoPoints
[
0
].
ySign
+
lastTwoPoints
[
1
].
ySign
)
/
2
}
this
.
drawSign
(
this
.
beginPoint
,
controlPoint
,
endPoint
)
this
.
beginPoint
=
endPoint
}
}
else
{
// 开始绘制
this
.
isFirst
=
true
this
.
points
.
push
({
xSign
:
xSign
,
ySign
:
ySign
})
this
.
beginPoint
=
{
xSign
,
ySign
}
}
break
case
128
:
this
.
points
.
push
({
xSign
:
xSign
,
ySign
:
ySign
})
if
(
this
.
points
.
length
>
3
)
{
var
lastTwoPoints
=
this
.
points
.
slice
(
-
2
)
var
controlPoint
=
lastTwoPoints
[
0
]
var
endPoint
=
lastTwoPoints
[
1
]
this
.
drawSign
(
this
.
beginPoint
,
controlPoint
,
endPoint
)
}
this
.
isFirst
=
false
this
.
beginPoint
=
null
this
.
points
=
[]
// 结束绘制
break
}
}
else
{
this
.
closeDialog
()
}
},
/**
* 签名方法
* @time 2022-05-10 16:11:01
*/
drawSign
(
beginPoint
,
controlPoint
,
endPoint
)
{
this
.
ctxSign
.
beginPath
()
this
.
ctxSign
.
moveTo
(
beginPoint
.
xSign
,
beginPoint
.
ySign
)
this
.
ctxSign
.
quadraticCurveTo
(
controlPoint
.
xSign
,
controlPoint
.
ySign
,
endPoint
.
xSign
,
endPoint
.
ySign
)
this
.
ctxSign
.
stroke
()
this
.
ctxSign
.
closePath
()
},
/**
* 下载文件
* @time 2022-05-10 15:56:04
*/
downloadFile
(
content
)
{
const
fileName
=
'
photo_
'
+
new
Date
().
getTime
()
const
link
=
document
.
createElement
(
'
a
'
)
const
blob
=
this
.
base64ToBlob
(
content
)
link
.
download
=
fileName
link
.
href
=
URL
.
createObjectURL
(
blob
)
link
.
click
()
},
/**
* base64转blob
* @param {str} base64code base64编码
* @time 2022-05-10 15:56:11
*/
base64ToBlob
(
base64code
)
{
const
parts
=
base64code
.
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
})
},
/**
* 关闭图片预览
* @time 2022-05-10 15:57:48
*/
closeViewer
()
{
document
.
body
.
style
.
overflow
=
this
.
prevOverflow
this
.
showViewer
=
false
},
/**
* 图片预览
* @param {num} index 图片索引
* @time 2022-05-10 15:57:17
*/
previewPhoto
(
index
)
{
this
.
imageIndex
=
index
this
.
prevOverflow
=
document
.
body
.
style
.
overflow
document
.
body
.
style
.
overflow
=
'
hidden
'
this
.
showViewer
=
true
},
/**
* 移除图片
* @param {num} index 图片索引
* @time 2022-05-10 15:58:17
*/
removePhoto
(
index
)
{
if
(
this
.
stepIndex
===
0
)
{
this
.
photoList
.
splice
(
index
,
1
)
}
else
{
this
.
signList
.
splice
(
index
,
1
)
}
},
/**
* 上传列表
* @time 2022-05-10 18:34:04
*/
uploadList
()
{
this
.
fullscreenLoading
=
true
const
blobList
=
[]
const
httpList
=
[]
this
.
photoList
.
forEach
(
item
=>
{
if
(
item
.
accessUrl
.
indexOf
(
'
blob:
'
)
===
0
)
{
blobList
.
push
(
item
)
}
else
{
httpList
.
push
(
item
)
}
})
this
.
signList
.
forEach
(
item
=>
{
if
(
item
.
accessUrl
.
indexOf
(
'
blob:
'
)
===
0
)
{
blobList
.
push
(
item
)
}
else
{
httpList
.
push
(
item
)
}
})
if
(
blobList
.
length
===
0
)
{
this
.
closeDialog
()
this
.
$emit
(
'
getPhoto
'
,
httpList
)
this
.
fullscreenLoading
=
false
return
}
const
photoList
=
[]
this
.
runQueue
(
blobList
,
async
(
item
,
next
)
=>
{
try
{
const
data
=
await
this
.
uploadPhoto
(
item
.
blob
)
photoList
.
push
({
type
:
item
.
type
,
uuid
:
data
.
uuid
,
accessUrl
:
data
.
accessUrl
})
next
()
}
catch
(
e
)
{
this
.
closeDialog
()
this
.
$emit
(
'
getPhoto
'
,
[...
httpList
])
this
.
fullscreenLoading
=
false
console
.
log
(
e
)
}
},
()
=>
{
this
.
closeDialog
()
this
.
$emit
(
'
getPhoto
'
,
[...
httpList
,
...
photoList
])
this
.
fullscreenLoading
=
false
})
},
/**
* promise阵列
* @time 2022-05-11 23:03:00
*/
runQueue
(
queue
,
fn
,
cb
)
{
const
step
=
function
(
index
)
{
if
(
index
>=
queue
.
length
)
{
cb
()
}
else
{
if
(
queue
[
index
])
{
fn
(
queue
[
index
],
function
()
{
step
(
index
+
1
)
})
}
else
{
step
(
index
+
1
)
}
}
}
step
(
0
)
},
/**
* 上传图片
* @param {str} blob 图片blob地址
* @time 2022-05-10 15:58:45
*/
uploadPhoto
(
blob
)
{
return
new
Promise
((
resolve
,
reject
)
=>
{
const
data
=
new
FormData
()
const
file
=
new
File
([
blob
],
`
${
new
Date
().
getTime
()}
.png`
,
{
type
:
'
image/png
'
})
const
opts
=
{
...
this
.
uploadConf
}
data
.
append
(
'
file
'
,
file
)
data
.
append
(
'
path
'
,
opts
.
data
.
path
)
data
.
append
(
'
rootPath
'
,
opts
.
data
.
rootPath
)
opts
.
data
=
data
return
request
(
opts
).
then
(
async
data
=>
{
// 如果当前需要加密
if
(
this
.
security
)
{
data
.
accessUrl
=
await
imageViewer
(
data
.
uuid
)
}
resolve
(
data
)
}).
catch
(
err
=>
{
reject
(
err
)
})
})
}
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
.device-top
{
margin-bottom
:
10px
;
display
:
flex
;
justify-content
:
space-between
;
}
.btn-camera
,
.btn-camera
:hover
{
color
:
#2A68FF
;
border
:
1px
solid
#B9CFFF
!
important
;
padding-left
:
30px
;
background
:
#F5F7FF
url(./components/photoStep/icon_camera.svg)
no-repeat
10px
center
/
16px
17px
;
}
.btn-clear
,
.btn-clear
:hover
{
color
:
#2A68FF
;
border
:
1px
solid
#B9CFFF
!
important
;
padding-left
:
30px
;
background
:
#F5F7FF
url(./components/photoStep/icon_clear.svg)
no-repeat
10px
center
/
16px
16px
;
}
.take-photo
{
height
:
400px
;
.canvas-phone
,
.canvas-sign
{
width
:
100%
;
height
:
100%
;
display
:
block
;
border
:
1px
dashed
#ddd
;
border-radius
:
4px
;
overflow
:
auto
;
.compose-area
{
width
:
600px
;
position
:
relative
;
margin
:
0
auto
;
.agreement-image
{
width
:
100%
;
height
:
auto
;
}
.sign-image
{
display
:
block
;
width
:
auto
;
height
:
80px
;
margin
:
-80px
0
0
52%
;
}
}
.tip
{
color
:
#666666
;
font-size
:
24px
;
text-align
:
center
;
line-height
:
380px
;
}
}
}
.preview-list
{
display
:
flex
;
.preview-item
{
position
:
relative
;
margin
:
0
8px
10px
0
;
height
:
68px
;
width
:
68px
;
border-radius
:
3px
;
overflow
:
hidden
;
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
flex
:
none
;
background
:
#f2f2f2
;
&
:hover
{
.el-icon-delete
{
opacity
:
1
;
}
}
.el-icon-delete
{
width
:
68px
;
height
:
20px
;
line-height
:
20px
;
background
:
rgba
(
0
,
0
,
0
,
0
.5
);
color
:
#ccc
;
text-align
:
center
;
cursor
:
pointer
;
position
:
absolute
;
bottom
:
0
;
left
:
0
;
font-size
:
12px
;
opacity
:
0
;
transition
:
opacity
.2s
ease
;
}
}
img
{
width
:
100%
;
position
:
relative
;
cursor
:
pointer
;
&
:last-child
{
margin-right
:
0
;
}
}
}
.dialog-footer
{
text-align
:
right
;
}
</
style
>
src/components/Device/ktService.js
0 → 100644
View file @
d2c4018b
const
baseUrl
=
'
http://127.0.0.1:6045
'
/**
* 列出所有读卡设备
*/
export
function
listCard
()
{
return
new
Promise
((
resolve
,
reject
)
=>
{
window
.
$
.
ajax
({
contentType
:
'
application/json;charset=UTF-8
'
,
dataType
:
'
jsonp
'
,
timeout
:
10000
,
jsonp
:
'
callback
'
,
url
:
`
${
baseUrl
}
/getCardReaderList`
,
success
:
function
(
resultInfo
,
status
)
{
// 取出错误信息
const
error
=
resultInfo
.
filter
(
r
=>
r
.
error
)
// 如果设备报错,且全都是错误信息,则取出第一个报错信息
if
(
error
.
length
>
0
&&
error
.
length
===
resultInfo
.
length
)
{
return
reject
(
error
.
map
(
e
=>
e
.
error
).
join
(
'
,
'
))
}
resolve
(
resultInfo
)
},
error
:
function
(
jqXHR
,
textStatus
,
errorThrown
)
{
reject
(
errorThrown
)
}
})
})
}
export
function
readCard
(
readerIndex
=
0
)
{
const
param
=
'
{"portType": 5}
'
return
new
Promise
((
resolve
,
reject
)
=>
{
window
.
$
.
ajax
({
contentType
:
'
application/json;charset=UTF-8
'
,
dataType
:
'
jsonp
'
,
timeout
:
10000
,
jsonp
:
'
callback
'
,
url
:
baseUrl
+
'
/readCard?param=
'
+
param
+
'
&index=
'
+
readerIndex
,
success
(
resultInfo
,
status
)
{
// 如果接口返回正确
if
(
resultInfo
&&
resultInfo
.
resultFlag
===
0
)
{
// 如果性别是中文,则转换成数值类型
resultInfo
.
resultContent
.
gender
=
resultInfo
.
resultContent
.
gender
===
'
男
'
?
'
1
'
:
'
2
'
resolve
(
resultInfo
.
resultContent
)
}
else
{
reject
(
resultInfo
?
resultInfo
.
errMsg
:
'
设备驱动失败,请重试
'
)
}
},
error
(
jqXHR
,
textStatus
,
errorThrown
)
{
reject
(
errorThrown
)
}
})
})
}
export
function
readCardNumber
(
readerIndex
=
1
)
{
return
new
Promise
((
resolve
,
reject
)
=>
{
window
.
$
.
ajax
({
contentType
:
'
application/json;charset=UTF-8
'
,
dataType
:
'
jsonp
'
,
timeout
:
10000
,
jsonp
:
'
callback
'
,
url
:
baseUrl
+
'
/readCardNo?index=
'
+
readerIndex
,
success
(
resultInfo
,
status
)
{
resolve
(
resultInfo
)
},
error
(
jqXHR
,
textStatus
,
errorThrown
)
{
reject
(
errorThrown
)
}
})
})
}
src/components/Device/readCert.js
0 → 100644
View file @
d2c4018b
/* eslint-disable */
import
cardutil
from
'
./cardWebsocket
'
var
readCert
=
{
// 一体式读证
rcOpenCertDevice
:
function
(
callback
)
{
if
(
cardutil
.
certWsStatus
)
{
cardutil
.
wsReadIntegratedCard
(
function
(
openCallback
)
{
console
.
log
(
'
openCallback
'
,
openCallback
)
callback
(
openCallback
)
})
}
else
{
readCert
.
rcReconnect
(
'
rcOpenCertDevice
'
,
function
(
resp
)
{
callback
(
resp
)
})
}
},
// 分离式获取秘钥
rcSetAppParamEx
:
function
(
appKey
,
appSecret
,
password
,
rcSetAppParamExCallback
)
{
if
(
cardutil
.
certWsStatus
)
{
console
.
log
(
appKey
,
appSecret
,
password
)
cardutil
.
setAppParamEx
(
appKey
,
appSecret
,
password
,
function
(
openCallback
)
{
console
.
log
(
'
openCallback
'
,
openCallback
)
rcSetAppParamExCallback
(
openCallback
)
})
}
else
{
cardutil
.
startWebSocket
(
function
(
res
)
{
console
.
log
(
'
读证读卡ws链接状态1111
'
,
res
)
if
(
res
)
{
cardutil
.
certWsStatus
=
true
readCert
.
rcSetAppParamEx
(
appKey
,
appSecret
,
password
,
rcSetAppParamExCallback
)
}
else
{
cardutil
.
certWsStatus
=
false
var
retcode
=
{
err_code
:
-
1
,
err_msg
:
'
ws连接失败,查看服务是否启动!!!
'
,
data
:
''
}
rcSetAppParamExCallback
(
retcode
)
}
})
}
},
// 分离式读证
rcReadCardEx
:
function
(
rcReadCardExCallback
)
{
if
(
cardutil
.
certWsStatus
)
{
cardutil
.
readCardEx
(
function
(
openCallback
)
{
console
.
log
(
'
openCallback
'
,
openCallback
)
rcReadCardExCallback
(
openCallback
)
})
}
else
{
readCert
.
rcReconnect
(
'
rcReadCardEx
'
,
function
(
resp
)
{
callback
(
resp
)
})
}
},
rcReconnect
:
function
(
params
,
rcReconnectCallback
)
{
cardutil
.
startWebSocket
(
function
(
res
)
{
console
.
log
(
'
读证读卡ws链接状态1111
'
,
res
)
if
(
res
)
{
cardutil
.
certWsStatus
=
true
if
(
params
==
'
rcOpenCertDevice
'
)
{
readCert
.
rcOpenCertDevice
(
rcReconnectCallback
)
}
if
(
params
==
'
rcReadCardEx
'
)
{
readCert
.
rcReadCardEx
(
rcReconnectCallback
)
}
}
else
{
cardutil
.
certWsStatus
=
false
var
retcode
=
{
err_code
:
-
1
,
err_msg
:
'
ws连接失败,查看服务是否启动!!!
'
,
data
:
''
}
rcReconnectCallback
(
retcode
)
}
})
}
}
export
default
readCert
src/components/Device/service.js
0 → 100644
View file @
d2c4018b
import
readCert
from
'
./readCert
'
import
readCard
from
'
./card
'
import
takePhoto
from
'
./takePhoto
'
import
sign
from
'
./sign
'
import
*
as
ktService
from
'
./ktService
'
const
service
=
{
// 一体式读证
readIntegratedCard
()
{
return
new
Promise
((
resolve
,
reject
)
=>
{
readCert
.
rcOpenCertDevice
((
json
)
=>
{
if
(
json
.
err_code
===
0
)
{
const
data
=
JSON
.
parse
(
json
.
data
)
||
{}
resolve
({
name
:
data
.
name
,
address
:
data
.
address
,
birthday
:
`
${
data
.
birthday
.
substr
(
0
,
4
)}
-
${
data
.
birthday
.
substr
(
4
,
2
)}
-
${
data
.
birthday
.
substr
(
6
)}
`
,
effectDate
:
`
${
data
.
effectDate
.
substr
(
0
,
4
)}
-
${
data
.
effectDate
.
substr
(
4
,
2
)}
-
${
data
.
effectDate
.
substr
(
6
)}
`
,
expireDate
:
data
.
expireDate
.
length
===
8
?
`
${
data
.
expireDate
.
substr
(
0
,
4
)}
-
${
data
.
expireDate
.
substr
(
4
,
2
)}
-
${
data
.
expireDate
.
substr
(
6
)}
`
:
data
.
expireDate
,
gender
:
data
.
gender
===
'
男
'
?
'
1
'
:
'
2
'
,
idNum
:
data
.
idNum
,
issueOrg
:
data
.
issueOrg
,
nation
:
data
.
nation
})
}
else
if
(
json
.
err_code
===
-
12104
)
{
reject
(
'
请检查读证设备上是否存在居民身份证
'
,
json
.
err_code
)
}
else
{
reject
(
json
.
err_msg
,
json
.
err_code
)
}
})
})
},
// 分离式读证秘钥
setAppParamEx
(
appKey
,
appSecret
,
password
)
{
return
new
Promise
((
resolve
,
reject
)
=>
{
readCert
.
rcSetAppParamEx
(
appKey
,
appSecret
,
password
,
(
json
)
=>
{
if
(
json
.
err_code
===
0
||
json
.
resultFlag
===
0
)
{
resolve
(
json
.
data
)
}
else
{
reject
(
json
.
err_msg
,
json
.
err_code
)
}
})
})
},
// 分离式读证
readCardEx
()
{
return
new
Promise
((
resolve
,
reject
)
=>
{
readCert
.
rcReadCardEx
(
function
(
json
)
{
if
(
json
.
err_code
===
0
)
{
resolve
(
json
.
data
)
}
else
{
reject
(
json
.
err_msg
,
json
.
err_code
)
}
})
})
},
// 获取设备
listCard
()
{
return
new
Promise
((
resolve
,
reject
)
=>
{
readCard
.
rdListCard
(
function
(
json
)
{
if
(
json
.
err_code
===
0
)
{
resolve
(
json
.
data
)
}
else
{
reject
(
json
.
err_msg
,
json
.
err_code
)
}
})
})
},
/**
* 获取卡尔的读卡设备
*/
async
listKtCard
()
{
try
{
return
await
ktService
.
listCard
()
}
catch
(
error
)
{
console
.
error
(
error
)
return
[]
}
},
/**
* 读取卡尔的身份证
*/
async
readKtCardEx
()
{
const
info
=
await
ktService
.
readCard
()
return
info
},
// 连接卡
connectCard
()
{
return
new
Promise
((
resolve
,
reject
)
=>
{
let
isSuccess
=
false
readCard
.
rdConnectCard
((
cert
)
=>
{
if
(
cert
.
err_code
!==
-
290
&&
isSuccess
!==
true
)
{
isSuccess
=
true
resolve
(
cert
)
}
else
{
readCard
.
rdListCard
((
cert
)
=>
{
resolve
(
cert
)
readCard
.
rdConnectCard
((
cert
)
=>
{
resolve
(
cert
)
})
})
}
})
})
},
// 发送APDU
transmitCard
(
Apdu
,
CardName
)
{
return
new
Promise
((
resolve
,
reject
)
=>
{
readCard
.
rdTransmitCard
(
Apdu
,
CardName
,
(
json
)
=>
{
if
(
json
.
err_code
===
0
)
{
resolve
(
json
.
data
)
}
else
{
reject
(
json
.
err_msg
,
json
.
err_code
)
}
})
})
},
// 断开卡
disconnectCard
()
{
return
new
Promise
((
resolve
,
reject
)
=>
{
readCard
.
rdDisconnectCard
((
json
)
=>
{
if
(
json
.
err_code
===
0
)
{
resolve
(
json
.
data
)
}
else
{
reject
(
json
.
err_msg
,
json
.
err_code
)
}
})
})
},
// 获取视频设备信息
getVideoInfo
()
{
return
new
Promise
((
resolve
,
reject
)
=>
{
takePhoto
.
tpGetVideoInfo
((
json
)
=>
{
if
(
json
.
err_code
===
0
)
{
resolve
(
json
.
data
)
}
else
{
resolve
([])
}
})
})
},
// 打开视频
masterOpenVideo
(
videoParams
,
cutStatus
,
callback
)
{
takePhoto
.
tpMasterOpenVideo
(
videoParams
,
cutStatus
,
function
(
json
)
{
callback
(
json
)
})
},
// 关闭视频
closeVideo
()
{
return
new
Promise
((
resolve
,
reject
)
=>
{
takePhoto
.
tpCloseVideo
((
json
)
=>
{
if
(
json
.
err_code
===
0
)
{
resolve
(
json
.
err_msg
)
}
else
{
reject
(
json
.
err_msg
,
json
.
err_code
)
}
})
})
},
// 主头拍照
masterTakePhoto
()
{
return
new
Promise
((
resolve
,
reject
)
=>
{
takePhoto
.
tpMasterTakePhoto
((
json
)
=>
{
if
(
json
.
err_code
===
0
)
{
resolve
(
json
.
data
)
}
else
{
reject
(
json
.
err_msg
,
json
.
err_code
)
}
})
})
},
// 副头拍照
slaveTakePhoto
()
{
return
new
Promise
((
resolve
,
reject
)
=>
{
takePhoto
.
tpslaveTakePhoto
((
json
)
=>
{
if
(
json
.
err_code
===
0
)
{
resolve
(
json
.
data
)
}
else
{
reject
(
json
.
err_msg
,
json
.
err_code
)
}
})
})
},
// 照片旋转角度
roteAngle
(
angleValue
)
{
takePhoto
.
tpRoteAngle
(
angleValue
)
},
// 签字获取设备在线状态
getSignStatus
()
{
return
new
Promise
((
resolve
,
reject
)
=>
{
sign
.
sGetSignStatus
((
json
)
=>
{
if
(
json
.
err_code
===
0
)
{
resolve
(
json
.
data
)
}
else
{
reject
(
json
.
err_msg
,
json
.
err_code
)
}
})
})
},
// 打开签字
signOpen
(
callback
)
{
sign
.
sSignOpen
(
function
(
cert
)
{
callback
(
cert
)
})
},
// 获取坐标
getCoordinate
(
callback
)
{
sign
.
sGetCoordinate
(
function
(
cert
)
{
callback
(
cert
)
})
},
// 签字
signFile
()
{
return
new
Promise
((
resolve
,
reject
)
=>
{
sign
.
sSignFile
((
json
)
=>
{
if
(
json
.
err_code
===
0
)
{
resolve
(
json
.
data
)
}
else
{
reject
(
json
.
err_msg
,
json
.
err_code
)
}
})
})
},
// 重签
resetSign
()
{
return
new
Promise
((
resolve
,
reject
)
=>
{
sign
.
sResetSign
((
json
)
=>
{
if
(
json
.
err_code
===
0
)
{
resolve
(
json
.
data
)
}
else
{
reject
(
json
.
err_msg
,
json
.
err_code
)
}
})
})
},
// 取消签名
closeSign
()
{
return
new
Promise
((
resolve
,
reject
)
=>
{
sign
.
sCloseSign
((
json
)
=>
{
if
(
json
.
err_code
===
0
)
{
resolve
(
json
.
data
)
}
else
{
reject
(
json
.
err_msg
,
json
.
err_code
)
}
})
})
}
}
export
default
service
src/components/Device/sign.js
0 → 100644
View file @
d2c4018b
import
signutil
from
'
./signWebsocket
'
var
sign
=
{
// 获取设备在线状态
sGetSignStatus
:
function
(
sGetSignStatuscallback
)
{
if
(
signutil
.
signWsStatus
)
{
signutil
.
getDeviceStatus
(
function
(
res
)
{
console
.
log
(
'
获取设备在线状态回调
'
,
res
)
var
retcode
=
{
err_code
:
res
.
result
,
err_msg
:
res
.
message
,
data
:
''
}
sGetSignStatuscallback
(
retcode
)
})
}
else
{
sign
.
sReconnect
(
'
sGetSignStatus
'
,
function
(
resp
)
{
sGetSignStatuscallback
(
resp
)
})
}
},
// 打开设备
sSignOpen
:
function
(
ssignOpencallback
)
{
if
(
signutil
.
signWsStatus
)
{
signutil
.
openDevice
(
function
(
res
)
{
console
.
log
(
'
打开签名回调
'
,
res
)
res
.
err_code
=
res
.
result
if
(
res
.
cmd
===
'
open_device
'
)
{
// 获取设备信息
signutil
.
getDeviceInfo
(
function
(
res
)
{
console
.
log
(
'
签名获取设备信息的返回
'
,
res
)
var
retcode
=
{
cmd
:
res
.
cmd
,
err_code
:
res
.
result
,
err_msg
:
res
.
message
,
resolution
:
res
.
resolution
}
ssignOpencallback
(
retcode
)
})
}
ssignOpencallback
(
res
)
})
}
else
{
sign
.
sReconnect
(
'
sSignOpen
'
,
function
(
resp
)
{
ssignOpencallback
(
resp
)
})
}
},
sGetCoordinate
:
function
(
sGoSignEventCallback
)
{
if
(
signutil
.
signWsStatus
)
{
// 连接签字通道
signutil
.
startWebSocketSc
(
function
(
connectSignCallback
)
{
console
.
log
(
'
连接签字通道连接状态
'
,
connectSignCallback
)
},
function
(
res
)
{
var
data
=
JSON
.
parse
(
res
.
data
)
// console.log('签字坐标返回', data)
var
recote
=
{
err_code
:
data
.
result
,
err_msg
:
data
.
message
,
data
:
data
.
resultContent
}
sGoSignEventCallback
(
recote
)
})
}
else
{
sign
.
sReconnect
(
'
sGetCoordinate
'
,
function
(
resp
)
{
sGoSignEventCallback
(
resp
)
})
}
},
// 确认签名获取图片
sSignFile
:
function
(
sSignFilecallback
)
{
if
(
signutil
.
signWsStatus
)
{
signutil
.
signConfirm
(
function
(
res
)
{
console
.
log
(
'
获取签名图片
'
,
res
)
var
retcode
=
{
err_code
:
res
.
result
,
err_msg
:
res
.
message
,
data
:
res
.
sign_pic_data
}
sSignFilecallback
(
retcode
)
})
}
else
{
sign
.
sReconnect
(
'
sSignFile
'
,
function
(
resp
)
{
sSignFilecallback
(
resp
)
})
}
},
// 重签清空画板
sResetSign
:
function
(
sResetSigncallback
)
{
if
(
signutil
.
signWsStatus
)
{
signutil
.
revivedSign
(
function
(
res
)
{
console
.
log
(
'
重签清空画板的回调
'
,
res
)
var
retcode
=
{
err_code
:
res
.
result
,
err_msg
:
res
.
message
,
data
:
''
}
sResetSigncallback
(
retcode
)
})
}
else
{
sign
.
sReconnect
(
'
sResetSign
'
,
function
(
resp
)
{
sResetSigncallback
(
resp
)
})
}
},
// 取消签名
sCloseSign
:
function
(
sCloseSigncallback
)
{
if
(
signutil
.
signWsStatus
)
{
signutil
.
signCancel
(
function
(
res
)
{
console
.
log
(
'
取消签名的回调
'
,
res
)
var
retcode
=
{
err_code
:
res
.
result
,
err_msg
:
res
.
message
,
data
:
''
}
sCloseSigncallback
(
retcode
)
})
}
else
{
sign
.
sReconnect
(
'
sCloseSign
'
,
function
(
resp
)
{
sCloseSigncallback
(
resp
)
})
}
},
sReconnect
:
function
(
params
,
sReconnectCallback
)
{
// 连接ws
signutil
.
startWebSocket
(
function
(
res
)
{
console
.
log
(
'
签名ws链接状态1111
'
,
res
)
if
(
res
)
{
signutil
.
signWsStatus
=
true
if
(
params
===
'
sGetSignStatus
'
)
{
sign
.
sGetSignStatus
(
sReconnectCallback
)
}
if
(
params
===
'
sSignOpen
'
)
{
sign
.
sSignOpen
(
sReconnectCallback
)
}
if
(
params
===
'
sGetCoordinate
'
)
{
sign
.
sGetCoordinate
(
sReconnectCallback
)
}
if
(
params
===
'
sSignFile
'
)
{
sign
.
sSignFile
(
sReconnectCallback
)
}
if
(
params
===
'
sResetSign
'
)
{
sign
.
sResetSign
(
sReconnectCallback
)
}
if
(
params
===
'
sCloseSign
'
)
{
sign
.
sCloseSign
(
sReconnectCallback
)
}
}
else
{
signutil
.
signWsStatus
=
false
var
retcode
=
{
err_code
:
-
1
,
err_msg
:
'
ws连接失败,查看服务是否启动!!!
'
,
data
:
''
}
sReconnectCallback
(
retcode
)
}
})
}
}
export
default
sign
src/components/Device/signWebsocket.js
0 → 100644
View file @
d2c4018b
var
clientId
=
'
1234567890
'
var
deviceName
=
'
SR236
'
var
deviceType
=
0
var
signutil
=
{
signWsStatus
:
false
,
// 主通道,用于打开设备、关闭设备等
websocket
:
null
,
wsUrl
:
'
ws://127.0.0.1:32561/
'
,
// wsUrl: 'ws://192.168.200.56:32561/',
// 用于签字坐标返回数据的通道
websocketSc
:
null
,
wsUrlSc
:
'
ws://127.0.0.1:42561/
'
,
// wsUrlSc: 'ws://192.168.200.56:42561/',
// 获取设备状态
deviceStatusParams
:
{
cmd
:
'
get_device_status
'
,
client_id
:
clientId
,
device_name
:
deviceName
,
device_type
:
1
},
// 打开设备
openParams
:
{
cmd
:
'
open_device
'
,
client_id
:
clientId
,
device_name
:
deviceName
,
device_type
:
1
,
recv_msg_port
:
42561
,
'
ui_type
'
:
2
,
'
x
'
:
0
,
'
y
'
:
0
,
'
show_text
'
:
0
,
'
time
'
:
0
},
// 获取设备信息
deviceInfoParams
:
{
cmd
:
'
get_device_info
'
,
client_id
:
clientId
,
device_name
:
deviceName
,
device_type
:
1
},
// 确认签字
signConfirmParams
:
{
cmd
:
'
sign_confirm
'
,
client_id
:
clientId
,
device_name
:
deviceName
,
device_type
:
deviceType
},
// 重签
againSignParams
:
{
cmd
:
'
revived_sign
'
,
client_id
:
clientId
,
device_name
:
deviceName
,
device_type
:
1
},
// 取消签字
signCancelParams
:
{
cmd
:
'
sign_cancel
'
,
client_id
:
clientId
,
device_name
:
deviceName
,
device_type
:
1
},
openDeviceCallback
:
null
,
// 打开设备
connectCallback
:
null
,
// 链接回调
getCoordinateCallback
:
null
,
deviceInfoCallback
:
null
,
// 设备信息回调
signConfirmCallback
:
null
,
revivedSignCallback
:
null
,
// 重签
getDeviceStatusCallback
:
null
,
// 获取设备状态
deviceTriggerCallback
:
null
,
//
logMessage
:
function
(
message
)
{
if
(
typeof
window
.
onHandleMessage
!==
'
undefined
'
)
{
window
.
onHandleMessage
(
message
)
}
else
{
console
.
log
(
message
)
}
},
// 连接主通道的websocket
startWebSocket
:
function
(
callback
)
{
signutil
.
connectCallback
=
callback
if
(
'
WebSocket
'
in
window
)
{
signutil
.
websocket
=
new
WebSocket
(
signutil
.
wsUrl
)
}
else
if
(
'
MozWebSocket
'
in
window
)
{
signutil
.
websocket
=
new
WebSocket
(
signutil
.
wsUrl
)
}
else
{
window
.
alert
(
'
浏览器不支持WebSocket
'
)
return
}
signutil
.
websocket
.
binaryType
=
'
arraybuffer
'
signutil
.
websocket
.
onopen
=
function
()
{
console
.
log
(
'
Connected 主通道的URL:
'
,
signutil
.
wsUrl
)
if
(
signutil
.
websocket
.
readyState
===
1
)
{
console
.
log
(
'
链接成功
'
)
signutil
.
connectCallback
(
true
)
}
}
signutil
.
websocket
.
onmessage
=
function
(
evt
)
{
signutil
.
wsMessage
(
evt
)
}
signutil
.
websocket
.
onclose
=
function
(
evt
)
{
if
(
signutil
.
websocket
.
readyState
===
3
)
{
console
.
log
(
'
链接关闭
'
,
evt
)
signutil
.
connectCallback
(
false
)
}
}
signutil
.
websocket
.
onerror
=
function
(
evt
)
{
if
(
signutil
.
websocket
.
readyState
===
3
)
{
console
.
log
(
'
链接报错
'
,
evt
)
signutil
.
connectCallback
(
false
)
}
}
},
// 连接签字坐标通道的websocket
startWebSocketSc
:
function
(
callback1
,
callback2
)
{
const
WebSocketScCallback
=
callback1
signutil
.
getCoordinateCallback
=
callback2
if
(
'
WebSocket
'
in
window
)
{
signutil
.
websocketSc
=
new
WebSocket
(
signutil
.
wsUrlSc
)
}
else
if
(
'
MozWebSocket
'
in
window
)
{
signutil
.
websocketSc
=
new
WebSocket
(
signutil
.
wsUrlSc
)
}
else
{
window
.
alert
(
'
浏览器不支持WebSocket
'
)
return
}
signutil
.
websocketSc
.
binaryType
=
'
arraybuffer
'
signutil
.
websocketSc
.
onopen
=
function
()
{
console
.
log
(
'
签字坐标URL链接成功ready
'
)
console
.
log
(
'
签字坐标URL链接成功
'
,
signutil
.
websocketSc
)
console
.
log
(
'
Connected 签字坐标URL:
'
,
signutil
.
wsUrlSc
)
if
(
signutil
.
websocketSc
.
readyState
===
1
)
{
console
.
log
(
'
签字坐标URL链接成功
'
)
WebSocketScCallback
(
true
)
}
}
signutil
.
websocketSc
.
onmessage
=
function
(
evt
)
{
signutil
.
wsMessageSc
(
evt
)
}
signutil
.
websocketSc
.
onclose
=
signutil
.
onSocketClose
signutil
.
websocketSc
.
onerror
=
signutil
.
onSocketError
},
// 发送信息
sendMsg
:
function
(
param
)
{
// console.log('发送信息', signutil.websocket, param)
if
(
signutil
.
websocket
&&
param
)
{
signutil
.
websocket
.
send
(
JSON
.
stringify
(
param
))
}
},
// websocket主通道的数据返回
wsMessage
:
function
(
res
)
{
res
=
JSON
.
parse
(
res
.
data
)
// console.log('主通道的返回', res)
var
cmd
=
res
.
cmd
switch
(
cmd
)
{
case
'
get_device_status
'
:
signutil
.
getDeviceStatusCallback
(
res
)
break
case
'
open_device
'
:
signutil
.
openDeviceCallback
(
res
)
break
case
'
get_device_info
'
:
signutil
.
deviceInfoCallback
(
res
)
break
case
'
sign_cancel
'
:
if
(
signutil
.
signCancelCallback
!=
null
)
{
signutil
.
signCancelCallback
(
res
)
}
else
{
signutil
.
openDeviceCallback
(
res
)
}
break
case
'
revived_sign
'
:
if
(
signutil
.
revivedSignCallback
!=
null
)
{
signutil
.
revivedSignCallback
(
res
)
}
else
{
signutil
.
openDeviceCallback
(
res
)
}
break
case
'
sign_pic
'
:
if
(
signutil
.
signConfirmCallback
!=
null
)
{
signutil
.
signConfirmCallback
(
res
)
}
else
{
signutil
.
openDeviceCallback
(
res
)
}
break
}
},
// 签字坐标通道的数据返回
wsMessageSc
:
function
(
res
)
{
// console.log('签字坐标通道的数据返回', res)
signutil
.
getCoordinateCallback
(
res
)
},
// 断开检测服务器连接
cwStopWebSocket
:
function
()
{
if
(
signutil
.
websocket
||
signutil
.
websocketSc
)
{
if
(
signutil
.
websocket
.
readyState
===
1
||
signutil
.
websocketSc
.
readyState
===
1
)
{
signutil
.
websocket
.
close
()
}
signutil
.
websocketSc
.
close
()
signutil
.
websocket
=
null
signutil
.
websocketSc
=
null
return
true
}
else
{
return
false
}
},
// 服务连接出错
onSocketError
:
function
(
evt
)
{
signutil
.
logMessage
(
'
连接检测服务有问题...
'
)
},
// 服务连接关闭onSocketClose
onSocketClose
:
function
(
evt
)
{
// websocket = null;
signutil
.
websocketSc
=
null
signutil
.
logMessage
(
'
服务已断开...
'
)
},
// 获取设备状态
getDeviceStatus
:
function
(
callback
)
{
signutil
.
getDeviceStatusCallback
=
callback
signutil
.
sendMsg
(
signutil
.
deviceStatusParams
)
},
// 打开设备
openDevice
:
function
(
callback
)
{
signutil
.
openDeviceCallback
=
callback
signutil
.
sendMsg
(
signutil
.
openParams
)
},
// 获取设备信息
getDeviceInfo
:
function
(
callback
)
{
signutil
.
deviceInfoCallback
=
callback
signutil
.
sendMsg
(
signutil
.
deviceInfoParams
)
},
// 取消签名
signCancel
:
function
(
callback
)
{
signutil
.
signCancelCallback
=
callback
signutil
.
sendMsg
(
signutil
.
signCancelParams
)
},
// 重签
revivedSign
:
function
(
callback
)
{
signutil
.
revivedSignCallback
=
callback
signutil
.
sendMsg
(
signutil
.
againSignParams
)
},
// 确认签名
signConfirm
:
function
(
callback
)
{
signutil
.
signConfirmCallback
=
callback
signutil
.
sendMsg
(
signutil
.
signConfirmParams
)
}
}
export
default
signutil
src/components/Device/takePhoto.js
0 → 100644
View file @
d2c4018b
/* eslint-disable */
import
videoutil
from
'
./videoWebsocket
'
var
takePhoto
=
{
videoParams
:
{
camera_type
:
0
,
camera_index
:
0
,
camera_name
:
''
,
camera_path
:
''
,
video_frame_w
:
0
,
video_frame_h
:
0
,
rotate_angle
:
0
},
cameraInfo
:
[],
cutStatus
:
0
,
// //0代表裁切,1代表不裁切
// 获取设备信息
tpGetVideoInfo
:
function
(
tpGetVideoInfocallback
)
{
if
(
videoutil
.
videoWsStatus
)
{
videoutil
.
getDeviceInfo
(
function
(
res
)
{
// console.log('获取设备信息返回', res)
if
(
res
.
statuCode
==
0
)
{
takePhoto
.
cameraInfo
=
res
.
camera_info
// console.log('sfsdfe sd s ', takePhoto.cameraInfo)
}
var
recote
=
{
err_code
:
res
.
statuCode
,
err_msg
:
res
.
message
,
data
:
res
.
camera_info
}
tpGetVideoInfocallback
(
recote
)
})
}
else
{
takePhoto
.
tpReconnect
(
'
tpGetVideoInfo
'
,
function
(
resp
)
{
tpGetVideoInfocallback
(
resp
)
})
}
},
tpMasterOpenVideo
:
function
(
videoParams
,
cutStatus
,
tpMasterOpenVideocallback
)
{
// 打开视频
takePhoto
.
cutStatus
=
cutStatus
takePhoto
.
videoParams
.
camera_type
=
videoParams
.
camera_type
takePhoto
.
videoParams
.
video_frame_w
=
videoParams
.
video_frame_w
takePhoto
.
videoParams
.
video_frame_h
=
videoParams
.
video_frame_h
var
cameraInfo
=
takePhoto
.
cameraInfo
for
(
var
i
=
0
;
i
<
cameraInfo
.
length
;
i
++
)
{
if
(
cameraInfo
[
i
].
camera_type
==
videoParams
.
camera_type
)
{
var
resIndex
=
i
takePhoto
.
videoParams
.
camera_index
=
cameraInfo
[
resIndex
].
device_index
takePhoto
.
videoParams
.
camera_name
=
cameraInfo
[
resIndex
].
camera_name
takePhoto
.
videoParams
.
camera_path
=
cameraInfo
[
resIndex
].
camera_path
break
}
}
console
.
log
(
'
打开视频videoParams
'
,
takePhoto
.
videoParams
)
if
(
videoutil
.
videoWsStatus
)
{
// console.log('1111', takePhoto.videoParams)
videoutil
.
singleVideoCheck
(
takePhoto
.
videoParams
,
function
(
singleVideoCheckCallback
)
{
console
.
log
(
'
打开视频的回调
'
,
singleVideoCheckCallback
)
if
(
singleVideoCheckCallback
&&
singleVideoCheckCallback
.
statuCode
==
0
)
{
videoutil
.
startWebSocketSc
(
function
(
startWebSocketCallback
)
{
console
.
log
(
'
34257ws连接回调
'
,
startWebSocketCallback
)
if
(
!
startWebSocketCallback
)
{
var
recote
=
{
err_code
:
-
1
,
err_msg
:
'
34257ws连接关闭
'
,
data
:
''
}
}
else
{
if
(
takePhoto
.
cutStatus
==
0
)
{
// 主头开启静态边缘检测
console
.
log
(
'
摄像头
'
,
takePhoto
.
videoParams
.
camera_type
)
if
(
takePhoto
.
videoParams
.
camera_type
==
0
)
{
videoutil
.
startEdgeCheck
(
takePhoto
.
videoParams
,
function
(
resp
)
{
console
.
log
(
'
打开静态边缘的回调
'
,
resp
)
})
}
}
}
},
function
(
playVideoCallback
)
{
// console.log('视频返回', playVideoCallback)
var
recote
=
{
err_code
:
0
,
err_msg
:
'
打开视频成功
'
,
data
:
playVideoCallback
.
data
}
tpMasterOpenVideocallback
(
recote
)
})
}
else
{
var
recote
=
{
err_code
:
singleVideoCheckCallback
.
statuCode
,
err_msg
:
singleVideoCheckCallback
.
message
,
data
:
''
}
tpMasterOpenVideocallback
(
recote
)
}
})
}
else
{
// 连接ws
videoutil
.
startWebSocket
(
function
(
res
)
{
console
.
log
(
'
打开视频ws链接状态1111
'
,
res
)
if
(
res
)
{
videoutil
.
videoWsStatus
=
true
takePhoto
.
tpMasterOpenVideo
(
takePhoto
.
videoParams
,
tpMasterOpenVideocallback
)
}
else
{
videoutil
.
videoWsStatus
=
false
var
retcode
=
{
err_code
:
-
1
,
err_msg
:
'
ws连接失败,查看服务是否启动!!!
'
,
data
:
''
}
tpMasterOpenVideocallback
(
retcode
)
}
})
}
},
// 主头拍照
tpMasterTakePhoto
:
function
(
tpMasterTakePhotocallback
)
{
if
(
videoutil
.
videoWsStatus
)
{
videoutil
.
takeCutPic
(
takePhoto
.
videoParams
,
function
(
openCallback
)
{
console
.
log
(
'
拍照
'
,
openCallback
)
var
recote
=
{
err_code
:
openCallback
.
statuCode
,
err_msg
:
openCallback
.
message
,
data
:
''
}
if
(
openCallback
.
statuCode
==
0
)
{
recote
.
data
=
openCallback
.
pic_data_arr
[
0
].
pic_data
}
tpMasterTakePhotocallback
(
recote
)
})
}
else
{
takePhoto
.
tpReconnect
(
'
tpMasterTakePhoto
'
,
function
(
resp
)
{
tpMasterTakePhotocallback
(
resp
)
})
}
},
// 副头拍照
tpslaveTakePhoto
:
function
(
tpslaveTakePhotocallback
)
{
if
(
videoutil
.
videoWsStatus
)
{
videoutil
.
takeCutPic
(
takePhoto
.
videoParams
,
function
(
openCallback
)
{
console
.
log
(
'
拍照
'
,
openCallback
)
var
recote
=
{
err_code
:
openCallback
.
statuCode
,
err_msg
:
openCallback
.
message
,
data
:
''
}
if
(
openCallback
.
statuCode
==
0
)
{
recote
.
data
=
openCallback
.
pic_data_arr
[
0
].
pic_data
}
tpslaveTakePhotocallback
(
recote
)
})
}
else
{
takePhoto
.
tpReconnect
(
'
tpslaveTakePhoto
'
,
function
(
resp
)
{
tpslaveTakePhotocallback
(
resp
)
})
}
},
// 旋转角度
tpRoteAngle
:
function
(
rotate_angle
)
{
console
.
log
(
'
角度
'
,
rotate_angle
)
if
(
rotate_angle
==
90
)
{
rotate_angle
=
1
}
if
(
rotate_angle
==
180
)
{
rotate_angle
=
2
}
if
(
rotate_angle
==
270
)
{
rotate_angle
=
3
}
takePhoto
.
videoParams
.
rotate_angle
=
rotate_angle
},
tpCloseVideo
:
function
(
tpCloseVideoCallback
)
{
if
(
videoutil
.
videoWsStatus
)
{
if
(
takePhoto
.
cutStatus
==
0
)
{
videoutil
.
stopEdgeCheck
(
takePhoto
.
videoParams
)
}
videoutil
.
stopVideo
(
takePhoto
.
videoParams
,
function
(
res
)
{
console
.
log
(
'
关闭视频回调
'
,
res
)
if
(
res
.
statuCode
==
0
)
{
if
(
videoutil
.
websocketSc
)
{
videoutil
.
websocketSc
.
close
()
}
}
var
recote
=
{
err_code
:
res
.
statuCode
,
err_msg
:
res
.
message
}
tpCloseVideoCallback
(
recote
)
})
}
else
{
takePhoto
.
tpReconnect
(
'
tpCloseVideo
'
,
function
(
resp
)
{
tpCloseVideoCallback
(
resp
)
})
}
},
tpReconnect
:
function
(
params
,
tpReconnectCallback
)
{
// 连接ws
videoutil
.
startWebSocket
(
function
(
res
)
{
console
.
log
(
'
读证读卡ws链接状态1111
'
,
res
)
if
(
res
)
{
videoutil
.
videoWsStatus
=
true
if
(
params
==
'
tpGetVideoInfo
'
)
{
takePhoto
.
tpGetVideoInfo
(
tpReconnectCallback
)
}
// if (params == 'tpMasterOpenVideo') {
// takePhoto.tpMasterOpenVideo(tpReconnectCallback);
// }
if
(
params
==
'
tpMasterTakePhoto
'
)
{
takePhoto
.
tpMasterTakePhoto
(
tpReconnectCallback
)
}
if
(
params
==
'
tpslaveTakePhoto
'
)
{
takePhoto
.
tpslaveTakePhoto
(
tpReconnectCallback
)
}
if
(
params
==
'
tpCloseVideo
'
)
{
takePhoto
.
tpCloseVideo
(
tpReconnectCallback
)
}
}
else
{
videoutil
.
videoWsStatus
=
false
var
retcode
=
{
err_code
:
-
1
,
err_msg
:
'
ws连接失败,查看服务是否启动!!!
'
,
data
:
''
}
tpReconnectCallback
(
retcode
)
}
})
}
}
export
default
takePhoto
src/components/Device/video.vue
0 → 100644
View file @
d2c4018b
<
template
>
<el-dialog
:visible=
"showDialog"
:title=
"title"
:close-on-press-escape=
"false"
:close-on-click-modal=
"false"
class=
"rnr-dialog"
width=
"480px"
top=
"10vh"
@
close=
"closeDialog"
>
<div
v-loading=
"loading"
class=
"take-camera"
>
<!-- 提示读取的数字,或者动作 -->
<div
class=
"random-num-wrapper"
>
<p
class=
"important-tips"
>
录制时请
{{
livenessType
===
LIVENESS_TYPE
.
ACTION
?
'
做出如下动作
'
:
'
用普通话大声读如下数字
'
}}
</p>
<p
class=
"random-num"
>
<i
v-if=
"status === VIDEO_STATUS.SUCCESS"
class=
"el-icon-success"
/>
{{
livenessType
===
LIVENESS_TYPE
.
ACTION
?
headAction
:
randomNum
}}
<span
v-if=
"status === VIDEO_STATUS.TAKING"
class=
"countdown"
>
{{
countdown
}}
</span>
</p>
</div>
<!-- 如果当前是录制前,或者录制中 -->
<video
v-show=
"status != VIDEO_STATUS.SUCCESS"
ref=
"video1"
name=
"video1"
autoplay=
"autoplay"
muted
/>
<!-- 如果当前是录制成功,则可以预览视频 -->
<div
v-show=
"status == VIDEO_STATUS.SUCCESS"
class=
"record-video-wrapper"
>
<video
ref=
"video2"
:muted=
"false"
name=
"video2"
/>
<i
class=
"btn-video"
:class=
"isPlaying ? 'el-icon-video-pause' : 'el-icon-video-play'"
@
click=
"handlePlayVideo"
/>
</div>
<div
class=
"take-camera-operation"
>
<el-button
v-if=
"status == VIDEO_STATUS.READY"
class=
"btn-record"
type=
"primary"
@
click.stop=
"handleStartRecording"
><i
class=
"imageicon-video-pause"
/>
开始录制
</el-button>
<el-button
v-if=
"status == VIDEO_STATUS.TAKING"
class=
"btn-record"
type=
"primary"
@
click=
"handleStopRecording"
><i
class=
"imageicon-video-pause"
/>
停止录制
</el-button>
<el-button
v-if=
"status == VIDEO_STATUS.SUCCESS"
class=
"btn-record"
type=
"primary"
@
click=
"handleStartRecording"
><i
class=
"imageicon-video-pause"
/>
重新录制
</el-button>
</div>
</div>
<div
slot=
"footer"
class=
"dialog-footer"
>
<el-button
size=
"small"
@
click=
"closeDialog"
>
取消
</el-button>
<el-button
:loading=
"isUploading"
size=
"small"
type=
"primary"
@
click=
"uploadPhoto"
>
确定
</el-button>
</div>
</el-dialog>
</
template
>
<
script
>
import
{
postVinUpload
}
from
'
@/api/realname-enterprise
'
import
{
getToken
}
from
'
@/utils/auth
'
import
{
getConnectDeviceId
}
from
'
@/utils/device
'
import
request
from
'
@/utils/request
'
import
'
@/styles/dialog.scss
'
const
LIVENESS_TYPE
=
{
NUMBER
:
'
LIP
'
,
ACTION
:
'
ACTION
'
}
// 视频状态
const
VIDEO_STATUS
=
{
// 准备状态
READY
:
0
,
// 录制中
TAKING
:
1
,
// 录制成功
SUCCESS
:
2
}
export
default
{
name
:
'
DeviceVideo
'
,
props
:
{
// 展示弹窗
show
:
{
type
:
Boolean
,
default
:
false
},
// 弹窗标题
title
:
{
type
:
String
,
default
:
'
拍摄视频
'
},
randomNum
:
{
type
:
String
,
default
:
''
},
// 验证方式
livenessType
:
{
type
:
String
,
default
:
''
}
},
data
()
{
return
{
VIDEO_STATUS
,
LIVENESS_TYPE
,
loading
:
false
,
showDialog
:
false
,
recordedBlobs
:
[],
mediaRecorder
:
null
,
// 初始化视频是等待录制
status
:
VIDEO_STATUS
.
READY
,
// 当前文件正在上传
isUploading
:
false
,
// 动作提示
actionTip
:
''
,
// 是否展示动画效果
showAnimation
:
false
,
// 是否初始化摄像头
initCameraSuccess
:
false
,
// 动作索引
actionIndex
:
0
,
// 倒计时
countdown
:
2
,
// 是否正在播放中
isPlaying
:
false
}
},
computed
:
{
/**
* 头部动作
*/
headAction
()
{
// 取出所有动作
const
actions
=
this
.
randomNum
.
split
(
'
,
'
)
// 活体序列
const
{
livenessActionSeq
}
=
this
.
$store
.
getters
.
dict
// 如果未开始录制
if
(
this
.
status
===
VIDEO_STATUS
.
READY
)
{
return
`请先
${
actions
.
map
(
action
=>
livenessActionSeq
.
find
(
seq
=>
`
${
seq
.
value
}
`
===
`
${
action
}
`
).
label
).
join
(
'
,再
'
)}
`
}
// 如果当前正在录制中,则展示需要展示的动作
if
(
this
.
status
===
VIDEO_STATUS
.
TAKING
)
{
// 当前需要做的动作
const
action
=
actions
[
this
.
actionIndex
]
return
action
?
`请
${
livenessActionSeq
.
find
(
seq
=>
`
${
seq
.
value
}
`
===
`
${
action
}
`
).
label
}
`
:
'
请停止录制
'
}
// 如果当前录制完成
if
(
this
.
status
===
VIDEO_STATUS
.
SUCCESS
)
{
return
'
已完成录制
'
}
return
''
}
},
watch
:
{
show
(
val
)
{
// 将内外状态同步
this
.
showDialog
=
val
// 如果当前是展示状态,且没有初始化过摄像头,则开始初始化摄像头
if
(
val
&&
!
this
.
initCameraSuccess
)
{
this
.
initCamera
()
}
}
},
destroyed
()
{
// 如果当前有流,则关闭流通道
if
(
window
.
stream
)
{
const
tracks
=
window
.
stream
.
getTracks
()
tracks
.
forEach
(
t
=>
t
.
stop
())
}
},
methods
:
{
/**
* 初始化摄像头
*/
async
initCamera
()
{
this
.
loading
=
true
try
{
// 获取设备id
const
deviceId
=
await
getConnectDeviceId
()
// 将视频流保存到window下
window
.
stream
=
await
navigator
.
mediaDevices
.
getUserMedia
({
audio
:
true
,
video
:
deviceId
?
{
deviceId
:
{
exact
:
deviceId
}}
:
true
})
if
(
window
.
URL
)
{
this
.
$refs
.
video1
.
srcObject
=
window
.
stream
}
else
{
this
.
$refs
.
video1
.
src
=
window
.
stream
}
// 标记当前初始化摄像头成功
this
.
initCameraSuccess
=
true
}
catch
(
error
)
{
console
.
error
(
'
Error accessing media devices.
'
,
error
)
}
this
.
loading
=
false
},
/**
* 关闭视频录制
*/
handleStopRecording
()
{
// 如果视频正在录制中,则关闭视频录制,并将状态置为成功
if
(
this
.
status
===
VIDEO_STATUS
.
TAKING
)
{
this
.
stopRecording
()
this
.
status
=
VIDEO_STATUS
.
SUCCESS
}
},
/**
* 开始录制视频
*/
handleStartRecording
()
{
// 如果当前是准备中|已经录完需要重新录制,则将状态置为录制中
if
([
VIDEO_STATUS
.
READY
,
VIDEO_STATUS
.
SUCCESS
].
includes
(
this
.
status
))
{
// 开始录制
this
.
startRecording
()
// 从第一个动作开始
this
.
actionIndex
=
0
// 如果当前是动作系统,则开始倒计时
if
(
this
.
livenessType
===
LIVENESS_TYPE
.
ACTION
)
{
this
.
startActionCountDown
()
}
// 将视频状态置为拍摄中
this
.
status
=
VIDEO_STATUS
.
TAKING
}
},
/**
* 录制视频
*/
startRecording
()
{
this
.
recordedBlobs
=
[]
let
options
=
{
mimeType
:
'
video/webm;codecs=vp9
'
}
if
(
!
MediaRecorder
.
isTypeSupported
(
options
.
mimeType
))
{
console
.
log
(
options
.
mimeType
+
'
is not Supported
'
)
options
=
{
mimeType
:
'
video/webm;codecs=vp8
'
}
if
(
!
MediaRecorder
.
isTypeSupported
(
options
.
mimeType
))
{
console
.
log
(
options
.
mimeType
+
'
is not Supported
'
)
options
=
{
mimeType
:
'
video/webm
'
}
if
(
!
MediaRecorder
.
isTypeSupported
(
options
.
mimeType
))
{
console
.
log
(
options
.
mimeType
+
'
is not Supported
'
)
options
=
{
mimeType
:
''
}
}
}
}
try
{
this
.
mediaRecorder
=
new
MediaRecorder
(
window
.
stream
,
options
)
}
catch
(
e
)
{
console
.
log
(
'
Exception while creating MediaRecorder:
'
+
e
+
'
. mimeType:
'
+
options
.
mimeType
)
return
}
console
.
log
(
'
Created MediaRecorder
'
,
this
.
mediaRecorder
,
'
with options
'
,
options
)
this
.
mediaRecorder
.
onstop
=
event
=>
console
.
log
(
'
Recorder stopped:
'
,
event
)
this
.
mediaRecorder
.
ondataavailable
=
this
.
handleDataAvailable
this
.
mediaRecorder
.
start
(
10
)
console
.
log
(
'
MediaRecorder started
'
,
this
.
mediaRecorder
)
},
/**
* 停止录制
*/
stopRecording
()
{
this
.
mediaRecorder
.
stop
()
const
buffer
=
new
Blob
(
this
.
recordedBlobs
,
{
type
:
'
video/mp4
'
})
this
.
$refs
.
video2
.
src
=
window
.
URL
.
createObjectURL
(
buffer
)
console
.
log
(
'
Recorded Blobs:
'
,
this
.
recordedBlobs
)
},
handleDataAvailable
(
event
)
{
if
(
event
.
data
&&
event
.
data
.
size
>
0
)
{
this
.
recordedBlobs
.
push
(
event
.
data
)
}
},
/**
* 播放已经录制的视频
*/
handlePlayVideo
()
{
// 如果当前是播放中,则停止
if
(
this
.
isPlaying
)
{
this
.
$refs
.
video2
.
pause
()
}
else
{
this
.
$refs
.
video2
.
play
()
// 视频播放方法
const
videoPlay
=
()
=>
{
// 移除监听事件
this
.
$refs
.
video2
.
removeEventListener
(
'
ended
'
,
videoPlay
)
// 关闭播放状态
this
.
isPlaying
=
false
}
// 如果播放结束,则重置
this
.
$refs
.
video2
.
addEventListener
(
'
ended
'
,
videoPlay
)
}
// 置反播放状态
this
.
isPlaying
=
!
this
.
isPlaying
},
/**
* 关闭弹窗
* @time 2022-05-10 16:21:17
*/
closeDialog
()
{
// 如果当前正在录制中
if
(
this
.
status
===
VIDEO_STATUS
.
TAKING
)
{
return
this
.
$message
({
message
:
'
视频正在录制中,请先停止录制
'
,
type
:
'
warning
'
})
}
// 将视频状态重置为准备状态
this
.
status
=
VIDEO_STATUS
.
READY
// 重置动作索引
this
.
actionIndex
=
0
// 关闭弹框
this
.
$emit
(
'
update:show
'
,
false
)
},
/**
* 开始呈现倒计时
*/
startActionCountDown
(
time
=
2
)
{
// 如果有倒计时,清空倒计时
this
.
timer
&&
clearTimeout
(
this
.
timer
)
// 取出当前动作
const
actions
=
this
.
randomNum
.
split
(
'
,
'
)
// 如果动作执行完成,则不继续进行定时器
if
(
this
.
actionIndex
>=
actions
.
length
)
{
return
}
// 记录当前倒计时
this
.
countdown
=
time
// 开始倒计时
this
.
timer
=
setTimeout
(()
=>
{
// 如果当前倒计时到1s,则动作索引累加
if
(
time
===
1
)
{
this
.
actionIndex
++
}
// 继续倒计时
this
.
startActionCountDown
(
time
===
1
?
2
:
1
)
},
1000
)
},
/**
* 上传视频
*/
async
uploadPhoto
()
{
// 如果当前正在录制中
if
(
this
.
status
===
VIDEO_STATUS
.
TAKING
)
{
return
this
.
$message
({
message
:
'
视频正在录制中,请先停止录制
'
,
type
:
'
warning
'
})
}
// 标记当前正在上传
this
.
isUploading
=
true
const
data
=
new
FormData
()
const
opts
=
{
url
:
postVinUpload
,
headers
:
{
'
X-Requested-With
'
:
'
XMLHttpRequest
'
,
'
Content-Type
'
:
'
application/x-www-form-urlencoded;charset=utf-8
'
,
'
Authorization
'
:
`bearer
${
getToken
()}
`
},
data
:
{
rootPath
:
''
,
path
:
''
}
}
data
.
append
(
'
file
'
,
new
File
([
new
Blob
(
this
.
recordedBlobs
,
{
type
:
'
video/mp4
'
})],
`
${
Date
.
now
()}
.mp4`
))
data
.
append
(
'
path
'
,
opts
.
data
.
path
)
data
.
append
(
'
rootPath
'
,
opts
.
data
.
rootPath
)
opts
.
data
=
data
try
{
const
respData
=
await
request
(
opts
)
this
.
$emit
(
'
upload-success
'
,
respData
)
// 关闭弹框
this
.
closeDialog
()
}
catch
(
error
)
{
console
.
error
(
'
上传错误:
'
,
error
)
}
// 标记上传结束
this
.
isUploading
=
false
}
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
.take-camera
{
position
:
relative
;
video
{
background-color
:
#000000
;
display
:
block
;
width
:
432px
;
height
:
220px
;
margin
:
0
auto
;
}
.record-video-wrapper
{
position
:
relative
;
.btn-video
{
color
:
#ffffff
;
font-size
:
48px
;
position
:
absolute
;
left
:
50%
;
top
:
50%
;
transform
:
translate
(
-50%
,
-50%
);
}
}
.take-camera-operation
{
align-items
:
center
;
display
:
flex
;
justify-content
:
center
;
margin-top
:
16px
;
.operation
{
color
:
#ffffff
;
cursor
:
pointer
;
font-size
:
20px
;
margin-left
:
30px
;
&
:first-child
{
margin-left
:
0px
;
}
}
.btn-record
{
height
:
32px
;
padding
:
0
16px
;
.imageicon-video-pause
{
background-image
:
url(../../assets/image/ico_video_pause.png)
;
background-size
:
100%
100%
;
display
:
inline-block
;
width
:
16px
;
height
:
16px
;
margin-right
:
2px
;
margin-bottom
:
-3px
;
}
}
}
.random-num-wrapper
{
.important-tips
{
color
:
#71747B
;
font-family
:
PingFangSC-Regular
,
PingFang
SC
;
font-size
:
14px
;
font-weight
:
400
;
line-height
:
20px
;
text-align
:
center
;
margin
:
0px
;
}
.random-num
{
align-items
:
center
;
color
:
#212026
;
display
:
flex
;
font-size
:
18px
;
font-family
:
PingFangSC-Semibold
,
PingFang
SC
;
font-weight
:
600
;
line-height
:
26px
;
height
:
26px
;
margin
:
4px
0
8px
;
justify-content
:
center
;
i
{
color
:
#25c343
;
font-size
:
20px
;
margin-right
:
4px
;
}
.countdown
{
align-items
:
center
;
background
:
#E7EBFF
;
border-radius
:
10px
;
color
:
#2A68FF
;
display
:
flex
;
font-size
:
14px
;
font-family
:
PingFangSC-Semibold
,
PingFang
SC
;
font-weight
:
600
;
width
:
20px
;
height
:
20px
;
justify-content
:
center
;
margin-left
:
8px
;
}
}
}
}
.dialog-footer
{
text-align
:
right
;
}
</
style
>
src/components/Device/videoWebsocket.js
0 → 100644
View file @
d2c4018b
/* eslint-disable */
var
clientId
=
'
1234567890
'
var
videoutil
=
{
videoWsStatus
:
false
,
// 主通道,用于打开设备、关闭设备等
websocket
:
null
,
wsUrl
:
'
ws://127.0.0.1:34256/
'
,
// wsUrl: 'ws://192.168.200.56:34256/',
connectCallback
:
null
,
// 用于视频图片返回数据的通道
websocketSc
:
null
,
wsUrlSc
:
'
ws://127.0.0.1:34257/
'
,
// wsUrlSc: 'ws://192.168.200.56:34257/',
WebSocketScCallback
:
null
,
// 拍照设备信息
videoDeviceParams
:
{
cmd
:
'
get_camera_info
'
,
client_id
:
clientId
},
// 打开视频
singleVideoCheckParams
:
{
cmd
:
'
playvideo
'
,
camera_type
:
0
,
camera_index
:
-
1
,
camera_name
:
''
,
client_id
:
clientId
,
camera_path
:
''
,
video_frame_w
:
''
,
video_frame_h
:
''
,
recv_video_port
:
34257
},
// 静态边缘检测
edgeParams
:
{
cmd
:
'
show_static_edge
'
,
camera_type
:
0
,
camera_index
:
-
1
,
camera_name
:
''
,
client_id
:
clientId
,
statuCode
:
1
,
camera_path
:
''
,
message
:
''
},
// 拍照
takeCutPicParams
:
{
cmd
:
'
take_pic
'
,
camera_type
:
0
,
camera_index
:
-
1
,
camera_name
:
''
,
client_id
:
clientId
,
camera_path
:
''
,
rotate_angle
:
0
},
// 关闭视频
stopvideoParams
:
{
cmd
:
'
stopvideo
'
,
camera_type
:
0
,
camera_index
:
-
1
,
camera_name
:
''
,
client_id
:
clientId
,
camera_path
:
''
},
deviceInfoCallback
:
null
,
// 获取设备信息
singleVideoCheckCallback
:
null
,
// 打开视频
startEdgeCheckCallback
:
null
,
// 静态边缘
takeCutPicCallback
:
null
,
// 拍照
videoConnectCallback
:
null
,
// 拍照连接回调
// 34257的链接回调
startWebSocketCallback
:
null
,
playVideoCallback
:
null
,
stopVideoCallback
:
null
,
// 停止拍照
logMessage
:
function
(
message
)
{
if
(
typeof
window
.
onHandleMessage
!==
'
undefined
'
)
{
window
.
onHandleMessage
(
message
)
}
else
{
console
.
log
(
message
)
}
},
// 连接主通道的websocket
startWebSocket
:
function
(
callback
)
{
videoutil
.
connectCallback
=
callback
if
(
'
WebSocket
'
in
window
)
{
videoutil
.
websocket
=
new
WebSocket
(
videoutil
.
wsUrl
)
}
else
if
(
'
MozWebSocket
'
in
window
)
{
videoutil
.
websocket
=
new
MozWebSocket
(
videoutil
.
wsUrl
)
}
else
{
window
.
alert
(
'
浏览器不支持WebSocket
'
)
return
}
videoutil
.
websocket
.
binaryType
=
'
arraybuffer
'
videoutil
.
websocket
.
onopen
=
function
()
{
console
.
log
(
'
Connected 主通道的URL:
'
,
videoutil
.
wsUrl
)
if
(
videoutil
.
websocket
.
readyState
==
1
)
{
console
.
log
(
'
链接成功
'
)
videoutil
.
connectCallback
(
true
)
}
}
videoutil
.
websocket
.
onmessage
=
function
(
evt
)
{
videoutil
.
wsMessage
(
evt
)
}
videoutil
.
websocket
.
onclose
=
function
(
evt
)
{
if
(
videoutil
.
websocket
.
readyState
==
3
)
{
console
.
log
(
'
链接关闭
'
,
evt
)
videoutil
.
connectCallback
(
false
)
}
}
videoutil
.
websocket
.
onerror
=
function
(
evt
)
{
if
(
videoutil
.
websocket
.
readyState
==
3
)
{
console
.
log
(
'
链接报错
'
,
evt
)
videoutil
.
connectCallback
(
false
)
}
}
},
// 连接34257通道的websocket
startWebSocketSc
:
function
(
callback1
,
callback2
)
{
var
WebSocketScCallback
=
callback1
videoutil
.
getCoordinateCallback
=
callback2
if
(
'
WebSocket
'
in
window
)
{
videoutil
.
websocketSc
=
new
WebSocket
(
videoutil
.
wsUrlSc
)
}
else
if
(
'
MozWebSocket
'
in
window
)
{
videoutil
.
websocketSc
=
new
MozWebSocket
(
videoutil
.
wsUrlSc
)
}
else
{
window
.
alert
(
'
浏览器不支持WebSocket
'
)
return
}
videoutil
.
websocketSc
.
binaryType
=
'
arraybuffer
'
videoutil
.
websocketSc
.
onopen
=
function
()
{
console
.
log
(
'
Connected 34257端口:
'
,
videoutil
.
wsUrlSc
)
if
(
videoutil
.
websocketSc
.
readyState
==
1
)
{
console
.
log
(
'
34257端口链接成功
'
)
WebSocketScCallback
(
true
)
}
}
videoutil
.
websocketSc
.
onmessage
=
function
(
evt
)
{
videoutil
.
wsMessageSc
(
evt
)
}
videoutil
.
websocketSc
.
onclose
=
videoutil
.
onSocketClose
videoutil
.
websocketSc
.
onerror
=
videoutil
.
onSocketError
},
// 发送信息
sendMsg
:
function
(
param
)
{
// console.log('发送信息', videoutil.websocket, param)
if
(
videoutil
.
websocket
&&
param
)
{
videoutil
.
websocket
.
send
(
JSON
.
stringify
(
param
))
}
},
// websocket主通道的数据返回
wsMessage
:
function
(
res
)
{
// console.log('主通道的返回', res)
var
res
=
JSON
.
parse
(
res
.
data
)
var
cmd
=
res
.
cmd
switch
(
cmd
)
{
case
'
get_camera_info
'
:
// 获取设备信息
videoutil
.
deviceInfoCallback
(
res
)
break
case
'
play_video_status
'
:
// 打开视频
if
(
videoutil
.
singleVideoCheckCallback
)
{
videoutil
.
singleVideoCheckCallback
(
res
)
}
break
case
'
show_static_edge
'
:
// 静态边缘
if
(
videoutil
.
startEdgeCheckCallback
)
{
videoutil
.
startEdgeCheckCallback
(
res
)
}
break
case
'
take_pic
'
:
videoutil
.
takeCutPicCallback
(
res
)
break
case
'
stopvideo
'
:
// 停止拍照
videoutil
.
stopVideoCallback
(
res
)
break
}
},
// 视频通道的数据返回
wsMessageSc
:
function
(
res
)
{
// console.log('视频通道的数据返回', res)
videoutil
.
getCoordinateCallback
(
res
)
},
// 断开检测服务器连接
cwStopWebSocket
:
function
()
{
if
(
videoutil
.
websocket
||
videoutil
.
websocketSc
)
{
if
(
videoutil
.
websocket
.
readyState
==
1
||
videoutil
.
websocketSc
.
readyState
==
1
)
{
videoutil
.
websocket
.
close
()
}
videoutil
.
websocketSc
.
close
()
videoutil
.
websocket
=
null
videoutil
.
websocketSc
=
null
return
true
}
else
{
return
false
}
},
// 服务连接出错
onSocketError
:
function
(
evt
)
{
videoutil
.
logMessage
(
'
连接检测服务有问题...
'
)
},
// 服务连接关闭onSocketClose
onSocketClose
:
function
(
evt
)
{
// websocket = null;
videoutil
.
websocketSc
=
null
videoutil
.
logMessage
(
'
服务已断开...
'
)
},
// 获取设备信息
getDeviceInfo
:
function
(
callback
)
{
videoutil
.
deviceInfoCallback
=
callback
videoutil
.
sendMsg
(
videoutil
.
videoDeviceParams
)
},
// 打开视频
singleVideoCheck
:
function
(
param
,
callback
)
{
console
.
log
(
'
ws打开视频参数
'
,
param
)
videoutil
.
singleVideoCheckCallback
=
callback
videoutil
.
singleVideoCheckParams
.
camera_type
=
param
.
camera_type
videoutil
.
singleVideoCheckParams
.
camera_index
=
param
.
camera_index
videoutil
.
singleVideoCheckParams
.
camera_name
=
param
.
camera_name
videoutil
.
singleVideoCheckParams
.
camera_path
=
param
.
camera_path
videoutil
.
singleVideoCheckParams
.
video_frame_w
=
parseInt
(
param
.
video_frame_w
)
videoutil
.
singleVideoCheckParams
.
video_frame_h
=
parseInt
(
param
.
video_frame_h
)
videoutil
.
sendMsg
(
videoutil
.
singleVideoCheckParams
)
},
// 开启静态边缘检测
startEdgeCheck
:
function
(
param
,
callback
)
{
videoutil
.
singleVideoCheckCallback
=
callback
videoutil
.
edgeParams
.
camera_type
=
param
.
camera_type
videoutil
.
edgeParams
.
camera_index
=
param
.
camera_index
videoutil
.
edgeParams
.
camera_name
=
param
.
camera_name
videoutil
.
edgeParams
.
camera_path
=
param
.
camera_path
videoutil
.
edgeParams
.
statuCode
=
1
videoutil
.
sendMsg
(
videoutil
.
edgeParams
)
videoutil
.
startEdgeCheckCallback
=
callback
},
// 关闭静态边缘检测
stopEdgeCheck
:
function
(
param
,
callback
)
{
videoutil
.
singleVideoCheckCallback
=
callback
videoutil
.
edgeParams
.
camera_type
=
param
.
camera_type
videoutil
.
edgeParams
.
camera_index
=
param
.
camera_index
videoutil
.
edgeParams
.
camera_name
=
param
.
camera_name
videoutil
.
edgeParams
.
camera_path
=
param
.
camera_path
videoutil
.
edgeParams
.
statuCode
=
0
videoutil
.
sendMsg
(
videoutil
.
edgeParams
)
videoutil
.
startEdgeCheckCallback
=
callback
},
// 停止摄像头
stopVideo
:
function
(
param
,
callback
)
{
videoutil
.
stopVideoCallback
=
callback
videoutil
.
stopvideoParams
.
camera_type
=
param
.
camera_type
videoutil
.
stopvideoParams
.
camera_index
=
param
.
camera_index
videoutil
.
stopvideoParams
.
camera_name
=
param
.
camera_name
videoutil
.
stopvideoParams
.
camera_path
=
param
.
camera_path
videoutil
.
sendMsg
(
videoutil
.
stopvideoParams
)
},
// 拍照
takeCutPic
:
function
(
param
,
callback
)
{
videoutil
.
takeCutPicCallback
=
callback
videoutil
.
takeCutPicParams
.
camera_type
=
param
.
camera_type
videoutil
.
takeCutPicParams
.
camera_index
=
param
.
camera_index
videoutil
.
takeCutPicParams
.
camera_name
=
param
.
camera_name
videoutil
.
takeCutPicParams
.
camera_path
=
param
.
camera_path
videoutil
.
takeCutPicParams
.
rotate_angle
=
param
.
rotate_angle
*
1
videoutil
.
sendMsg
(
videoutil
.
takeCutPicParams
)
}
}
export
default
videoutil
src/components/Device/wzh.js
0 → 100644
View file @
d2c4018b
var
wzh
=
{};
var
address
=
""
;
var
appSecret
=
"
30b5c231a8ea42c09c87f75d22ebc9ea
"
;
// appId对应的加密密钥
var
appId
=
"
1035
"
;
var
nonce
=
"
jfoiiuylkjljpohi
"
;
var
business
=
"
{'areaCode':'020','busiSerial':'12345','channelCode':'2001','clientIP':'','deviceModel':'llllllllsdfsdffsdfjka sdfjfsdfsdfsddddddddddd','deviceSerial':'','osType':'','srcSystem':'CRM','staffCode':'110011','teminalType':'PC'}
"
;
var
host
=
"
http://127.0.0.1:18889
"
wzh
.
getBase64PdfT
=
function
(
filePath
)
{
var
resultInfo
;
var
time
=
new
Date
();
var
tes
=
host
+
"
/api/getBase64file?time=
"
+
time
;
var
dataInfo
=
"
{
\"
filePath
\"
:
\"
"
+
filePath
+
"
\"
}
"
;
jQuery
.
support
.
cors
=
true
;
$
.
ajax
({
type
:
"
post
"
,
async
:
false
,
url
:
tes
,
data
:
dataInfo
,
jsonp
:
"
jsonpCallback
"
,
//服务端用于接收callback调用的function名的参数
success
:
function
(
result
)
{
if
(
result
.
indexOf
(
"
jsonpCallback
"
)
!=
-
1
)
{
resultInfo
=
result
.
substring
(
14
,
result
.
length
-
1
);
}
else
{
resultInfo
=
result
;
}
},
error
:
function
()
{
resultInfo
=
"
{
\"
resultFlag
\"
:-1,
\"
errorMsg
\"
:
\"
网络问题,请确认服务是否存在
\"
}
"
;
}
})
return
resultInfo
;
}
wzh
.
getStatusT
=
function
()
{
var
resultInfo
;
var
time
=
new
Date
();
var
tes
=
host
+
"
/api/getMutiStatus?time=
"
+
time
;
jQuery
.
support
.
cors
=
true
;
$
.
ajax
({
type
:
"
post
"
,
async
:
false
,
url
:
tes
,
jsonp
:
"
jsonpCallback
"
,
//服务端用于接收callback调用的function名的参数
success
:
function
(
result
)
{
if
(
result
.
indexOf
(
"
jsonpCallback
"
)
!=
-
1
)
{
resultInfo
=
result
.
substring
(
14
,
result
.
length
-
1
);
}
else
{
resultInfo
=
result
;
}
},
error
:
function
()
{
resultInfo
=
"
{
\"
resultFlag
\"
:-1,
\"
errorMsg
\"
:
\"
网络问题,请确认服务是否存在
\"
}
"
;
}
})
return
resultInfo
;
}
wzh
.
previewT
=
function
(
fileStr
,
filetype
)
{
var
resultInfo
;
var
time
=
new
Date
();
var
tes
=
host
+
"
/api/preview?time=
"
+
time
var
dataInfo
=
"
{
\"
fileStr
\"
:
\"
"
+
fileStr
+
"
\"
,
\"
filetype
\"
:
\"
"
+
filetype
+
"
\"
}
"
;
jQuery
.
support
.
cors
=
true
;
$
.
ajax
({
type
:
"
post
"
,
async
:
false
,
url
:
tes
,
timeout
:
10000
,
//超时时间设置,单位毫秒
data
:
dataInfo
,
jsonp
:
"
jsonpCallback
"
,
//服务端用于接收callback调用的function名的参数
success
:
function
(
result
)
{
if
(
result
.
indexOf
(
"
jsonpCallback
"
)
!=
-
1
)
{
resultInfo
=
result
.
substring
(
14
,
result
.
length
-
1
);
}
else
{
resultInfo
=
result
;
}
},
error
:
function
()
{
resultInfo
=
"
{
\"
resultFlag
\"
:-1,
\"
errorMsg
\"
:
\"
网络问题,请确认服务是否存在
\"
}
"
;
},
complete
:
function
(
XMLHttpRequest
,
status
)
{
//请求完成后最终执行参数
if
(
status
==
'
timeout
'
)
{
//超时,status还有success,error等值的情况
//ajaxTimeoutTest.abort();
wzh
.
closeSIGNT
();
}
}
})
return
resultInfo
;
}
wzh
.
previewSyncT
=
function
(
fileStr
,
filetype
)
{
var
resultInfo
;
var
time
=
new
Date
();
var
tes
=
host
+
"
/api/previewSync?time=
"
+
time
var
dataInfo
=
"
{
\"
fileStr
\"
:
\"
"
+
fileStr
+
"
\"
,
\"
filetype
\"
:
\"
"
+
filetype
+
"
\"
}
"
;
jQuery
.
support
.
cors
=
true
;
$
.
ajax
({
type
:
"
post
"
,
async
:
false
,
url
:
tes
,
timeout
:
10000
,
//超时时间设置,单位毫秒
data
:
dataInfo
,
jsonp
:
"
jsonpCallback
"
,
//服务端用于接收callback调用的function名的参数
success
:
function
(
result
)
{
if
(
result
.
indexOf
(
"
jsonpCallback
"
)
!=
-
1
)
{
resultInfo
=
result
.
substring
(
14
,
result
.
length
-
1
);
}
else
{
resultInfo
=
result
;
}
},
error
:
function
()
{
resultInfo
=
"
{
\"
resultFlag
\"
:-1,
\"
errorMsg
\"
:
\"
网络问题,请确认服务是否存在
\"
}
"
;
},
complete
:
function
(
XMLHttpRequest
,
status
)
{
//请求完成后最终执行参数
if
(
status
==
'
timeout
'
)
{
//超时,status还有success,error等值的情况
//ajaxTimeoutTest.abort();
wzh
.
closeSIGNT
();
}
}
})
return
resultInfo
;
}
wzh
.
setDialogTimeOutT
=
function
(
timeout
)
{
var
resultInfo
;
var
time
=
new
Date
();
var
tes
=
host
+
"
/api/setDialogTimeOut?time=
"
+
time
var
dataInfo
=
"
{
\"
timeout
\"
:
\"
"
+
timeout
+
"
\"
}
"
;
jQuery
.
support
.
cors
=
true
;
$
.
ajax
({
type
:
"
post
"
,
async
:
false
,
url
:
tes
,
timeout
:
10000
,
//超时时间设置,单位毫秒
data
:
dataInfo
,
jsonp
:
"
jsonpCallback
"
,
//服务端用于接收callback调用的function名的参数
success
:
function
(
result
)
{
if
(
result
.
indexOf
(
"
jsonpCallback
"
)
!=
-
1
)
{
resultInfo
=
result
.
substring
(
14
,
result
.
length
-
1
);
}
else
{
resultInfo
=
result
;
}
},
error
:
function
()
{
resultInfo
=
"
{
\"
resultFlag
\"
:-1,
\"
errorMsg
\"
:
\"
网络问题,请确认服务是否存在
\"
}
"
;
},
complete
:
function
(
XMLHttpRequest
,
status
)
{
//请求完成后最终执行参数
if
(
status
==
'
timeout
'
)
{
//超时,status还有success,error等值的情况
//ajaxTimeoutTest.abort();
wzh
.
closeSIGNT
();
}
}
})
return
resultInfo
;
}
wzh
.
getCameraT
=
function
()
{
var
resultInfo
;
var
time
=
new
Date
();
var
tes
=
host
+
"
/api/getCamera?time=
"
+
time
;
jQuery
.
support
.
cors
=
true
;
$
.
ajax
({
type
:
"
post
"
,
async
:
false
,
url
:
tes
,
jsonp
:
"
jsonpCallback
"
,
//服务端用于接收callback调用的function名的参数
success
:
function
(
result
)
{
if
(
result
.
indexOf
(
"
jsonpCallback
"
)
!=
-
1
)
{
resultInfo
=
result
.
substring
(
14
,
result
.
length
-
1
);
}
else
{
resultInfo
=
result
;
}
},
error
:
function
()
{
resultInfo
=
"
{
\"
resultFlag
\"
:-1,
\"
errorMsg
\"
:
\"
网络问题,请确认服务是否存在
\"
}
"
;
}
})
return
resultInfo
;
}
wzh
.
previewSignT
=
function
(
fileStr
,
filetype
=
'
pdf
'
,
location
=
'
0,1,50,50,1
'
,
ifPreview
=
'
1
'
)
{
jQuery
.
support
.
cors
=
true
;
return
new
Promise
((
resolve
,
reject
)
=>
{
$
.
ajax
({
type
:
"
post
"
,
async
:
false
,
url
:
host
+
"
/api/previewSign?time=
"
+
(
new
Date
()),
timeout
:
5000
,
//超时时间设置,单位毫秒
data
:
"
{
\"
fileStr
\"
:
\"
"
+
fileStr
+
"
\"
,
\"
filetype
\"
:
\"
"
+
filetype
+
"
\"
,
\"
location
\"
:
\"
"
+
location
+
"
\"
,
\"
ifPreview
\"
:
\"
"
+
ifPreview
+
"
\"
}
"
,
jsonp
:
"
jsonpCallback
"
,
//服务端用于接收callback调用的function名的参数
success
:
function
(
result
)
{
if
(
result
.
indexOf
(
"
jsonpCallback
"
)
!=
-
1
)
{
resolve
(
JSON
.
parse
(
result
.
substring
(
14
,
result
.
length
-
1
)).
resultEntity
)
}
else
{
resolve
(
result
)
}
},
error
:
function
()
{
reject
({
resultFlag
:
-
1
,
errorMsg
:
'
网络问题,请确认服务是否存在
'
})
},
complete
:
function
(
XMLHttpRequest
,
status
)
{
//请求完成后最终执行参数
if
(
status
==
'
timeout
'
)
{
//超时,status还有success,error等值的情况
//ajaxTimeoutTest.abort();
wzh
.
closeSIGNT
();
}
}
})
});
}
wzh
.
signFileT
=
function
(
fileStr
,
filetype
,
location
,
ifPreview
)
{
var
resultInfo
;
var
time
=
new
Date
();
var
tes
=
host
+
"
/api/signFile?time=
"
+
time
var
dataInfo
=
"
{
\"
fileStr
\"
:
\"
"
+
fileStr
+
"
\"
,
\"
filetype
\"
:
\"
"
+
filetype
+
"
\"
,
\"
location
\"
:
\"
"
+
location
+
"
\"
,
\"
ifPreview
\"
:
\"
"
+
ifPreview
+
"
\"
}
"
;
jQuery
.
support
.
cors
=
true
;
$
.
ajax
({
type
:
"
post
"
,
async
:
false
,
url
:
tes
,
timeout
:
10000
,
//超时时间设置,单位毫秒
data
:
dataInfo
,
jsonp
:
"
jsonpCallback
"
,
//服务端用于接收callback调用的function名的参数
success
:
function
(
result
)
{
if
(
result
.
indexOf
(
"
jsonpCallback
"
)
!=
-
1
)
{
resultInfo
=
result
.
substring
(
14
,
result
.
length
-
1
);
}
else
{
resultInfo
=
result
;
}
},
error
:
function
()
{
resultInfo
=
"
{
\"
resultFlag
\"
:-1,
\"
errorMsg
\"
:
\"
网络问题,请确认服务是否存在
\"
}
"
;
},
complete
:
function
(
XMLHttpRequest
,
status
)
{
//请求完成后最终执行参数
if
(
status
==
'
timeout
'
)
{
//超时,status还有success,error等值的情况
//ajaxTimeoutTest.abort();
wzh
.
closeSIGNT
();
}
}
})
return
resultInfo
;
}
var
getParam
;
wzh
.
signPoll
=
function
()
{
var
resultInfo
;
if
(
address
==
""
)
{
json
=
eval
(
'
(
'
+
wzh
.
getSystemIPT
()
+
'
)
'
);
address
=
json
.
IP
;
}
var
time
=
new
Date
();
var
tes
=
host
+
"
/api/intervalSign?time=
"
+
time
jQuery
.
support
.
cors
=
true
;
$
.
ajax
({
type
:
"
post
"
,
async
:
false
,
url
:
tes
,
jsonp
:
"
jsonpCallback
"
,
//服务端用于接收callback调用的function名的参数
success
:
function
(
result
)
{
if
(
result
==
""
)
{
return
result
;
}
if
(
result
.
indexOf
(
"
jsonpCallback
"
)
!=
-
1
)
{
resultInfo
=
result
.
substring
(
14
,
result
.
length
-
1
);
}
else
{
resultInfo
=
result
;
}
},
error
:
function
()
{
resultInfo
=
"
{
\"
resultFlag
\"
:-1,
\"
errorMsg
\"
:
\"
网络问题,请确认服务是否存在
\"
}
"
;
}
})
return
resultInfo
;
}
wzh
.
closeSIGNT
=
function
()
{
var
resultInfo
;
var
time
=
new
Date
();
var
tes
=
host
+
"
/api/closeSIGN?time=
"
+
time
;
jQuery
.
support
.
cors
=
true
;
$
.
ajax
({
type
:
"
post
"
,
async
:
false
,
url
:
tes
,
jsonp
:
"
jsonpCallback
"
,
//服务端用于接收callback调用的function名的参数
success
:
function
(
result
)
{
if
(
result
.
indexOf
(
"
jsonpCallback
"
)
!=
-
1
)
{
resultInfo
=
result
.
substring
(
14
,
result
.
length
-
1
);
}
else
{
resultInfo
=
result
;
}
},
error
:
function
()
{
resultInfo
=
"
{
\"
resultFlag
\"
:-1,
\"
errorMsg
\"
:
\"
网络问题,请确认服务是否存在
\"
}
"
;
}
})
return
resultInfo
;
}
wzh
.
closeVideoT
=
function
()
{
var
resultInfo
;
var
time
=
new
Date
();
var
tes
=
host
+
"
/api/closeVideo?time=
"
+
time
;
jQuery
.
support
.
cors
=
true
;
$
.
ajax
({
type
:
"
post
"
,
async
:
false
,
url
:
tes
,
jsonp
:
"
jsonpCallback
"
,
//服务端用于接收callback调用的function名的参数
success
:
function
(
result
)
{
if
(
result
.
indexOf
(
"
jsonpCallback
"
)
!=
-
1
)
{
resultInfo
=
result
.
substring
(
14
,
result
.
length
-
1
);
}
else
{
resultInfo
=
result
;
}
},
error
:
function
()
{
resultInfo
=
"
{
\"
resultFlag
\"
:-1,
\"
errorMsg
\"
:
\"
网络问题,请确认服务是否存在
\"
}
"
;
}
})
return
resultInfo
;
}
wzh
.
toMainScanT
=
function
()
{
var
resultInfo
;
var
dataInfo
=
"
{
\"
param
\"
:
\"
1600X1200;1; ;-1;0;0;0;0;-1;-1;Main;
\"
}
"
;
var
time
=
new
Date
();
var
tes
=
host
+
"
/api/toScan?time=
"
+
time
;
jQuery
.
support
.
cors
=
true
;
$
.
ajax
({
type
:
"
post
"
,
async
:
false
,
url
:
tes
,
data
:
dataInfo
,
jsonp
:
"
jsonpCallback
"
,
//服务端用于接收callback调用的function名的参数
success
:
function
(
result
)
{
if
(
result
.
indexOf
(
"
jsonpCallback
"
)
!=
-
1
)
{
resultInfo
=
result
.
substring
(
14
,
result
.
length
-
1
);
}
else
{
resultInfo
=
result
;
}
},
error
:
function
()
{
resultInfo
=
"
{
\"
resultFlag
\"
:-1,
\"
errorMsg
\"
:
\"
网络问题,请确认服务是否存在
\"
}
"
;
}
})
return
resultInfo
;
}
wzh
.
toSecScanT
=
function
()
{
var
resultInfo
;
var
dataInfo
=
"
{
\"
param
\"
:
\"
640X480;0; ;-1;0;0;0;0;-1;-1;Sec;
\"
}
"
;
var
time
=
new
Date
();
var
tes
=
host
+
"
/api/toScan?time=
"
+
time
;
jQuery
.
support
.
cors
=
true
;
$
.
ajax
({
type
:
"
post
"
,
async
:
false
,
url
:
tes
,
data
:
dataInfo
,
jsonp
:
"
jsonpCallback
"
,
//服务端用于接收callback调用的function名的参数
success
:
function
(
result
)
{
if
(
result
.
indexOf
(
"
jsonpCallback
"
)
!=
-
1
)
{
resultInfo
=
result
.
substring
(
14
,
result
.
length
-
1
);
}
else
{
resultInfo
=
result
;
}
},
error
:
function
()
{
resultInfo
=
"
{
\"
resultFlag
\"
:-1,
\"
errorMsg
\"
:
\"
网络问题,请确认服务是否存在
\"
}
"
;
}
})
return
resultInfo
;
}
wzh
.
getParam
=
function
(
param
)
{
getParam
=
param
;
return
getParam
;
}
wzh
.
toScanPollT
=
function
()
{
var
resultInfo
;
var
time
=
new
Date
();
var
tes
=
host
+
"
/api/toSurePoll?time=
"
+
time
;
jQuery
.
support
.
cors
=
true
;
$
.
ajax
({
type
:
"
post
"
,
async
:
false
,
url
:
tes
,
//data:dataInfo,
jsonp
:
"
jsonpCallback
"
,
//服务端用于接收callback调用的function名的参数
success
:
function
(
result
)
{
if
(
result
.
indexOf
(
"
jsonpCallback
"
)
!=
-
1
)
{
resultInfo
=
result
.
substring
(
14
,
result
.
length
-
1
);
json
=
eval
(
'
(
'
+
resultInfo
+
'
)
'
);
if
(
json
.
errorCode
!=
99
)
{
//alert(resultInfo)
clearInterval
(
getParam
);
}
}
else
{
resultInfo
=
result
;
}
},
error
:
function
()
{
resultInfo
=
"
{
\"
resultFlag
\"
:-1,
\"
errorMsg
\"
:
\"
网络问题,请确认服务是否存在
\"
}
"
;
}
})
return
resultInfo
;
}
wzh
.
GetICCIDT
=
function
()
{
var
time
=
new
Date
();
var
tes
=
host
+
"
/api/getCCID?time=
"
+
time
;
jQuery
.
support
.
cors
=
true
;
$
.
ajax
({
type
:
"
post
"
,
async
:
false
,
url
:
tes
,
//dataType : "jsonp",//数据类型为jsonp
jsonp
:
"
jsonpCallback
"
,
//服务端用于接收callback调用的function名的参数
success
:
function
(
result
)
{
if
(
result
.
indexOf
(
"
jsonpCallback
"
)
!=
-
1
)
{
resultInfo
=
result
.
substring
(
14
,
result
.
length
-
1
);
}
else
{
resultInfo
=
result
;
}
},
error
:
function
()
{
resultInfo
=
"
{
\"
resultFlag
\"
:-1,
\"
errorMsg
\"
:
\"
网络问题,请确认服务是否存在
\"
}
"
;
}
})
return
resultInfo
;
}
wzh
.
keyBoardPasswordT
=
function
(
limitLen
,
timeOut
)
{
var
time
=
new
Date
();
var
dataInfo
=
"
{
\"
limitLen
\"
:
"
+
limitLen
+
"
,
\"
timeOut
\"
:
"
+
timeOut
+
"
}
"
;
var
tes
=
host
+
"
/api/keyBoardPassword?time=
"
+
time
;
jQuery
.
support
.
cors
=
true
;
$
.
ajax
({
type
:
"
post
"
,
async
:
false
,
url
:
tes
,
data
:
dataInfo
,
//dataType : "jsonp",//数据类型为jsonp
jsonp
:
"
jsonpCallback
"
,
//服务端用于接收callback调用的function名的参数
success
:
function
(
result
)
{
if
(
result
.
indexOf
(
"
jsonpCallback
"
)
!=
-
1
)
{
resultInfo
=
result
.
substring
(
14
,
result
.
length
-
1
);
}
else
{
resultInfo
=
result
;
}
},
error
:
function
()
{
resultInfo
=
"
{
\"
resultFlag
\"
:-1,
\"
errorMsg
\"
:
\"
网络问题,请确认服务是否存在
\"
}
"
;
}
})
return
resultInfo
;
}
wzh
.
startSelectNumT
=
function
(
url
,
data
,
timeout
)
{
var
resultInfo
;
var
time
=
new
Date
();
var
dataInfo
=
{}
dataInfo
.
url
=
url
dataInfo
.
phone_numbers
=
data
dataInfo
.
timeout
=
timeout
dataInfo
=
JSON
.
stringify
(
dataInfo
)
var
tes
=
host
+
"
/api/StartSelectNum?time=
"
+
time
;
jQuery
.
support
.
cors
=
true
;
$
.
ajax
({
type
:
"
post
"
,
async
:
false
,
url
:
tes
,
data
:
dataInfo
,
//dataType : "jsonp",//数据类型为jsonp
jsonp
:
"
jsonpCallback
"
,
//服务端用于接收callback调用的function名的参数
success
:
function
(
result
)
{
if
(
result
.
indexOf
(
"
jsonpCallback
"
)
!=
-
1
)
{
resultInfo
=
result
.
substring
(
14
,
result
.
length
-
1
);
}
else
{
resultInfo
=
result
;
}
},
error
:
function
()
{
resultInfo
=
"
{
\"
resultFlag
\"
:-1,
\"
errorMsg
\"
:
\"
网络问题,请确认服务是否存在
\"
}
"
;
}
})
return
resultInfo
;
}
wzh
.
getSelectedNumT
=
function
(
callback
)
{
var
resultInfo
;
var
time
=
new
Date
();
var
tes
=
host
+
"
/api/GetSelectedNum?time=
"
+
time
;
jQuery
.
support
.
cors
=
true
;
$
.
ajax
({
type
:
"
post
"
,
async
:
false
,
url
:
tes
,
//dataType : "jsonp",//数据类型为jsonp
jsonp
:
"
jsonpCallback
"
,
//服务端用于接收callback调用的function名的参数
success
:
function
(
result
)
{
if
(
result
.
indexOf
(
"
jsonpCallback
"
)
!=
-
1
)
{
resultInfo
=
result
.
substring
(
14
,
result
.
length
-
1
);
}
else
{
resultInfo
=
result
;
}
callback
(
resultInfo
)
},
error
:
function
()
{
resultInfo
=
"
{
\"
resultFlag
\"
:-1,
\"
errorMsg
\"
:
\"
网络问题,请确认服务是否存在
\"
}
"
;
callback
(
resultInfo
)
}
})
return
resultInfo
;
}
wzh
.
cancelSelectNumT
=
function
()
{
var
time
=
new
Date
();
var
tes
=
host
+
"
/api/CancelSelectNum?time=
"
+
time
;
jQuery
.
support
.
cors
=
true
;
$
.
ajax
({
type
:
"
post
"
,
async
:
false
,
url
:
tes
,
jsonp
:
"
jsonpCallback
"
,
//服务端用于接收callback调用的function名的参数
success
:
function
(
result
)
{
if
(
result
.
indexOf
(
"
jsonpCallback
"
)
!=
-
1
)
{
resultInfo
=
result
.
substring
(
14
,
result
.
length
-
1
);
}
else
{
resultInfo
=
result
;
}
},
error
:
function
()
{
resultInfo
=
"
{
\"
resultFlag
\"
:-1,
\"
errorMsg
\"
:
\"
网络问题,请确认服务是否存在
\"
}
"
;
}
})
return
resultInfo
;
}
export
default
wzh
\ No newline at end of file
src/components/FileInfo/index.vue
0 → 100644
View file @
d2c4018b
<
template
>
<el-form
ref=
"form"
:rules=
"rules"
:model=
"form"
label-width=
"80px"
label-position=
"top"
size=
"small"
>
<el-row
:gutter=
"40"
>
<el-col
:span=
"24"
>
<el-form-item
:label=
"label"
prop=
"fileList"
>
<div
class=
"device-wrap"
>
<uploader
v-if=
"mode === 'preview'"
v-model=
"form.fileList"
list-type=
"picture-card"
mode=
"preview"
/>
<uploader
v-else
ref=
"fileUpload"
v-model=
"form.fileList"
:data=
"postData"
:action=
"upload.action"
:before-upload=
"onUploadBefore"
:limit=
"limit"
:placeholder=
"placeholder"
:accept=
"accept"
:upload-type=
"uploadType"
:sign-key=
"signKey"
:attachment-url=
"attachmentUrl"
list-type=
"picture-card"
@
on-error=
"onUploadError"
@
on-success=
"onUploadSuccess"
@
on-remove=
"onUploadRemove"
/>
<i
v-if=
"device.showTakePhoto && mode == 'upload'"
class=
"icon-device-video"
@
click=
"showDialog = true"
/>
</div>
</el-form-item>
</el-col>
</el-row>
<device-dialog
:show.sync=
"showDialog"
:data=
"form.fileList"
:sign=
"sign"
:attachment-url=
"attachmentUrl"
:sign-key=
"signKey"
:limit=
"limit"
@
getPhoto=
"getPhoto"
/>
</el-form>
</
template
>
<
script
>
import
{
mapGetters
}
from
'
vuex
'
import
{
getToken
}
from
'
@/utils/auth
'
import
{
postVinUpload
}
from
'
@/api/realname-enterprise
'
import
Uploader
from
'
@/components/Uploader
'
import
deviceDialog
from
'
@/components/Device/dialog
'
export
default
{
name
:
'
FileInfo
'
,
components
:
{
Uploader
,
deviceDialog
},
props
:
{
mode
:
{
type
:
String
,
default
:
'
upload
'
// upload/preview
},
sign
:
{
type
:
Boolean
,
default
:
false
},
limit
:
{
type
:
Number
,
default
:
5
},
label
:
{
type
:
String
,
default
:
'
文件信息
'
},
placeholder
:
{
type
:
String
,
default
:
'
上传文件
'
},
fileSize
:
{
type
:
Number
,
default
:
5
},
accept
:
{
type
:
String
,
default
:
'
image/png,image/jpeg,image/jpg,application/pdf
'
},
postData
:
{
type
:
Object
,
default
()
{
return
{
rootPath
:
''
,
path
:
''
}
}
},
data
:
{
type
:
Object
,
default
()
{
return
{}
}
},
uploadType
:
{
type
:
Array
,
default
:
undefined
},
signKey
:
{
type
:
String
,
default
:
''
},
attachmentUrl
:
{
type
:
String
,
default
:
''
}
},
data
()
{
const
checkFileList
=
(
rule
,
value
,
callback
)
=>
{
if
(
value
.
length
===
0
)
{
callback
(
new
Error
(
`请上传
${
this
.
label
}
`
))
}
else
{
callback
()
}
}
return
{
showDialog
:
false
,
upload
:
{
headers
:
{
'
Authorization
'
:
`bearer
${
getToken
()}
`
},
action
:
postVinUpload
},
form
:
{
fileList
:
[]
},
rules
:
{
fileList
:
[
{
required
:
true
,
validator
:
checkFileList
,
trigger
:
'
blur, change
'
}
]
}
}
},
computed
:
{
...
mapGetters
([
'
dict
'
,
'
device
'
]),
previewList
()
{
if
(
this
.
mode
===
'
preview
'
)
{
return
this
.
form
.
fileList
.
map
(
item
=>
{
return
item
.
accessUrl
})
}
return
[]
}
},
watch
:
{
data
()
{
this
.
updateInternalData
()
}
},
created
()
{
this
.
init
()
},
methods
:
{
init
()
{
this
.
updateInternalData
()
},
updateInternalData
()
{
if
(
typeof
this
.
data
===
'
object
'
&&
this
.
data
!==
null
)
{
this
.
form
.
fileList
=
this
.
data
.
fileList
||
[]
}
else
{
this
.
form
.
fileList
=
[]
}
},
/**
* 获取图片
* @time 2022-05-11 23:32:36
*/
getPhoto
(
data
)
{
this
.
form
.
fileList
=
data
},
/**
* 凭证上传校验
* @time 2022-04-11 09:16:44
*/
onUploadBefore
(
file
)
{
const
accept
=
this
.
accept
.
split
(
'
,
'
)
const
fileSize
=
file
.
size
/
1024
/
1024
<
this
.
fileSize
if
(
!
accept
.
includes
(
file
.
type
))
{
this
.
$message
.
error
(
`
${
this
.
label
}
格式不对`
)
return
false
}
if
(
!
fileSize
)
{
this
.
$message
.
error
(
`
${
this
.
label
}
大小不能超过5MB!`
)
return
false
}
},
/**
* 凭证上传成功
* @time 2022-04-09 17:22:21
*/
onUploadSuccess
()
{
this
.
$nextTick
(()
=>
{
this
.
$refs
.
form
.
validateField
(
'
fileList
'
)
})
},
/**
* 凭证上传失败
* @time 2022-04-09 17:22:21
*/
onUploadError
()
{
this
.
$message
.
error
(
'
文件上传失败
'
)
this
.
onUploadRemove
()
},
/**
* 移除上传凭证
* @time 2022-04-09 17:22:21
*/
onUploadRemove
()
{
this
.
$nextTick
(()
=>
{
this
.
$refs
.
form
.
validateField
(
'
fileList
'
)
})
},
/**
* 获取当前模块数据
* @time 2022-04-23 15:50:05
*/
async
validate
()
{
try
{
await
this
.
$refs
.
form
.
validate
()
return
true
}
catch
(
e
)
{
let
temp
=
{
anchor
:
()
=>
{
this
.
$refs
.
form
.
fields
.
filter
(
item
=>
item
.
validateState
===
'
error
'
)[
0
].
$el
.
scrollIntoView
(
true
)
temp
=
null
}
}
throw
temp
}
},
/**
* 获取表单数据
* @time 2022-04-23 18:02:02
*/
getFormData
()
{
return
this
.
form
},
getPendingCacheData
()
{
return
this
.
form
},
/**
* 清空校验值
*/
clearValidate
()
{
this
.
$refs
.
form
.
clearValidate
()
}
}
}
</
script
>
src/components/FormItemWrap/index.vue
0 → 100644
View file @
d2c4018b
<
template
>
<div
class=
"el-input-group"
>
<div
v-if=
"$slots.prepend"
class=
"el-input-group__prepend"
>
<slot
name=
"prepend"
/>
</div>
<div
class=
"el-input-group__content"
:class=
"
{ 'left-angle' : !!$slots.prepend, 'right-angle' : !!$slots.append }">
<el-select
v-if=
"type == 'el-select'"
v-bind=
"$attrs"
:value=
"value"
@
change=
"handleValueChange"
>
<el-option
v-for=
"(option, i) in options"
:key=
"`$
{option.value}_${i}`" v-bind="option" />
</el-select>
<component
:is=
"type"
v-else
v-bind=
"$attrs"
:options=
"options"
:value=
"value"
@
change=
"handleValueChange"
@
input=
"handleValueChange"
/>
</div>
<div
v-if=
"$slots.append"
class=
"el-input-group__append"
>
<slot
name=
"append"
/>
</div>
</div>
</
template
>
<
script
>
export
default
{
name
:
'
FormItemWrap
'
,
props
:
{
type
:
{
type
:
[
Object
,
String
],
default
:
null
},
options
:
{
type
:
Array
,
default
:
()
=>
([])
},
value
:
{
type
:
[
Object
,
String
,
Number
],
default
:
null
}
},
methods
:
{
/**
* 监听值变化
* @param value 当前变化的值
*/
handleValueChange
(
value
)
{
this
.
$emit
(
'
input
'
,
value
)
}
}
}
</
script
>
<
style
lang=
"scss"
>
.el-input-group__content
{
display
:
table-cell
;
&
.left-angle
.el-input__inner
{
border-top-left-radius
:
0
;
border-bottom-left-radius
:
0
;
}
&
.right-angle
.el-input__inner
{
border-top-right-radius
:
0
;
border-bottom-right-radius
:
0
;
}
}
</
style
>
src/components/FormRender/col.vue
0 → 100644
View file @
d2c4018b
<
template
>
<div
class=
"form-render"
>
<el-form
ref=
"formRender"
:disabled=
"disabled"
:model=
"formData"
v-bind=
"bindAttrs(formConfig, 'el-form')"
>
<el-row
:gutter=
"config.gutter"
>
<el-col
v-for=
"(s, key) in filterUnShowSchema(schema)"
:key=
"key"
:span=
"s.span || 6"
>
<el-form-item
:prop=
"key"
v-bind=
"bindAttrs(s, 'el-form-item')"
class=
"full-wrap"
>
<el-select
v-if=
"s.type == 'el-select'"
v-model=
"formData[key]"
v-bind=
"s.attrs"
:placeholder=
"placeholder(s)"
v-on=
"initBindFunction(s.on)"
@
change=
"value => handleFormDataChange(value, key)"
>
<template
v-if=
"formOptions[key]"
>
<el-option
v-for=
"(option, i) in formOptions[key]"
:key=
"`$
{option.value}_${i}`" v-bind="option" />
</
template
>
<
template
v-for=
"(slotName, takeSlot) in s.slotRender"
v-slot:
[
takeSlot
]
>
<slot
:name=
"slotName"
/>
</
template
>
</el-select>
<component
:is=
"s.type"
v-else
v-model=
"formData[key]"
v-bind=
"s.attrs"
:placeholder=
"placeholder(s)"
:options=
"formOptions[key]"
v-on=
"initBindFunction(s.on)"
@
change=
"value => handleFormDataChange(value, key)"
@
input=
"value => handleFormDataChange(value, key)"
>
<
template
v-for=
"(slotName, takeSlot) in s.slotRender"
v-slot:
[
takeSlot
]
>
<slot
:name=
"slotName"
/>
</
template
>
</component>
</el-form-item>
</el-col>
<div
class=
"operation-wrap"
>
<el-form-item
label-width=
"0"
>
<slot
v-if=
"!config.hideSearch"
name=
"slot-operation-search"
>
<el-button
round
size=
"small"
plain
type=
"primary"
icon=
"iconfont icon-search"
@
click=
"handleSubmit"
>
搜索
</el-button>
</slot>
<slot
v-if=
"!config.hideReset"
name=
"slot-operation-reset"
>
<el-button
round
size=
"small"
type=
"info"
icon=
"iconfont icon-clear"
@
click=
"handleReset"
>
重置
</el-button>
</slot>
<slot
name=
"slot-operation-extend"
/>
</el-form-item>
</div>
</el-row>
</el-form>
</div>
</template>
<
script
>
import
mixin
from
'
./mixin
'
export
default
{
mixins
:
[
mixin
]
}
</
script
>
<
style
lang=
"scss"
>
@import
url("./index.scss")
;
</
style
>
src/components/FormRender/index.scss
0 → 100644
View file @
d2c4018b
.form-render
.operation-wrap
{
display
:
inline-block
;
}
.form-render
.full-wrap
{
width
:
100%
;
}
.form-render
.el-form-item--small.el-form-item
{
margin-bottom
:
16px
;
}
.form-render
.el-input--prefix
.el-input__prefix
{
left
:
12px
;
}
.form-render
.el-input--prefix
.el-input__inner
{
padding-left
:
38px
;
}
.form-render
.el-form--inline
{
display
:
flex
;
align-items
:
center
;
}
.form-render
.el-form--inline
.el-form-item
{
margin-right
:
8px
;
}
.form-render
.mar-t-16
{
margin-top
:
16px
;
}
src/components/FormRender/index.vue
0 → 100644
View file @
d2c4018b
<
template
>
<div
class=
"form-render"
>
<el-form
ref=
"formRender"
:disabled=
"disabled"
:model=
"formData"
v-bind=
"bindAttrs(
{ inline: true, ...formConfig }, 'el-form')">
<el-form-item
v-for=
"(s, key) in filterUnShowSchema(schema)"
:key=
"key"
:prop=
"key"
:class=
"s.firstRow ? '' : 'mar-t-16'"
v-bind=
"bindAttrs(s, 'el-form-item')"
>
{{
s
.
firstRow
}}
<!-- 下拉选择需要单独拎出来,他的选项再el-option中 -->
<el-select
v-if=
"formType[key] == 'el-select'"
v-model=
"formData[key]"
v-bind=
"s.attrs"
:placeholder=
"placeholder(s)"
v-on=
"initBindFunction(s.on)"
@
change=
"value => handleFormDataChange(value, key)"
>
<template
v-if=
"formOptions[key]"
>
<el-option
v-for=
"option in formOptions[key]"
:key=
"option.value"
v-bind=
"option"
/>
</
template
>
<
template
v-for=
"(slotName, takeSlot) in s.slotRender"
v-slot:
[
takeSlot
]
>
<slot
:name=
"slotName"
/>
</
template
>
</el-select>
<!-- 渲染除el-select的其他任意组件,包括原生,element组件以及自定义组件 -->
<component
:is=
"formType[key]"
v-else
v-model=
"formData[key]"
v-bind=
"s.attrs"
:placeholder=
"placeholder(s)"
:options=
"formOptions[key]"
v-on=
"initBindFunction(s.on)"
@
change=
"value => handleFormDataChange(value, key)"
@
input=
"value => handleFormDataChange(value, key)"
>
<
template
v-for=
"(slotName, takeSlot) in s.slotRender"
v-slot:
[
takeSlot
]
>
<slot
:name=
"slotName"
/>
</
template
>
</component>
</el-form-item>
<el-form-item
v-if=
"showOperation"
label-width=
"0"
>
<slot
v-if=
"!config.hideSearch"
name=
"slot-operation-search"
>
<el-button
round
size=
"small"
plain
type=
"primary"
icon=
"iconfont icon-search"
@
click=
"handleSubmit"
>
搜索
</el-button>
</slot>
<slot
v-if=
"!config.hideReset"
name=
"slot-operation-reset"
>
<el-button
round
size=
"small"
type=
"info"
icon=
"iconfont icon-clear"
@
click=
"handleReset"
>
重置
</el-button>
</slot>
<slot
name=
"slot-operation-extend"
/>
</el-form-item>
</el-form>
</div>
</template>
<
script
>
import
mixin
from
'
./mixin
'
export
default
{
mixins
:
[
mixin
],
computed
:
{
showOperation
()
{
const
slots
=
[
'
slot-operation-search
'
,
'
slot-operation-reset
'
,
'
slot-operation-extend
'
]
const
show
=
slots
.
some
(
name
=>
{
return
this
.
$slots
[
`
${
name
}
`
]
})
return
show
}
}
}
</
script
>
<
style
lang=
"scss"
>
@import
url(./index.scss)
;
</
style
>
src/components/FormRender/mixin.js
0 → 100644
View file @
d2c4018b
import
{
Form
,
FormItem
}
from
'
element-ui
'
import
FormItemWrap
from
'
@/components/FormItemWrap
'
import
{
iterator
}
from
'
./shared
'
const
ISchema
=
{
type
:
Object
,
default
:
()
=>
({})
}
const
IConfig
=
{
type
:
Object
,
default
:
()
=>
({})
}
const
IValue
=
{
type
:
Object
,
default
:
()
=>
({})
}
// el-form组件props的key
const
EL_FORM_PROP_KEYS
=
Object
.
keys
(
Form
.
props
)
// el-form-item组件props的key
const
EL_FORM_ITEM_PROP_KEYS
=
Object
.
keys
(
FormItem
.
props
)
export
default
{
components
:
{
FormItemWrap
},
props
:
{
schema
:
ISchema
,
config
:
IConfig
,
value
:
IValue
,
disabled
:
{
type
:
Boolean
,
default
:
false
}
},
data
()
{
return
{
formData
:
{
...(
this
.
value
||
{})
},
formType
:
{},
formOptions
:
{},
formConfig
:
{
size
:
'
small
'
,
queryAfterReset
:
true
,
...(
this
.
config
||
{})
},
lastLinkageValue
:
{}
}
},
mounted
()
{
// 先初始化default的值
this
.
initDefault
()
// 初始化类型
this
.
initType
()
// 再初始化options的值
this
.
initOptions
()
},
watch
:
{
/**
* 监听value变化,如果value发生变化,引用地址发生变化,则覆盖formData
*/
value
:
{
handler
()
{
// 取出当前值
const
{
value
,
formData
}
=
this
// 如果值发生变化
if
(
value
===
formData
)
{
return
}
// 遍历数据
Object
.
keys
(
value
).
forEach
(
key
=>
{
// 如果当前项的值和传入的值不一致,则使用传入的值
if
(
formData
[
key
]
!==
value
[
key
])
{
formData
[
key
]
=
value
[
key
]
}
})
},
deep
:
true
}
},
methods
:
{
/**
* 先将default的值初始化至formData中
*/
initDefault
()
{
iterator
(
this
.
schema
,
(
schema
,
key
)
=>
{
this
.
$set
(
this
.
formData
,
key
,
(
this
.
value
[
key
]
===
undefined
||
this
.
value
[
key
]
===
null
)
?
schema
.
default
:
this
.
value
[
key
])
})
// 数据开始双向绑定
this
.
$emit
(
'
input
'
,
this
.
formData
)
// 触发change方法
this
.
$emit
(
'
change
'
,
this
.
formData
)
},
/**
* 初始化formType类型
*/
initType
()
{
iterator
(
this
.
schema
,
(
schema
,
key
)
=>
{
// 重新生成的类型
const
schemaType
=
schema
.
type
instanceof
Function
?
schema
.
type
(
this
.
formData
)
:
schema
.
type
// 如果当前和上一次的类型不一致,则重新赋值
if
(
this
.
formType
[
key
]
!==
schemaType
)
{
this
.
$set
(
this
.
formType
,
key
,
schemaType
)
}
})
},
/**
* 初始化select等的下拉选项
*/
initOptions
()
{
iterator
(
this
.
schema
,
async
(
schema
,
key
)
=>
{
// 如果当前是数组,则直接赋值
if
(
schema
.
options
instanceof
Array
)
{
this
.
$set
(
this
.
formOptions
,
key
,
schema
.
options
)
}
// 如果当前options是promise,则直接在then中获取结果
if
(
schema
.
options
instanceof
Promise
)
{
const
options
=
await
schema
.
options
this
.
$set
(
this
.
formOptions
,
key
,
options
)
}
// 如果当前是方法,则根据是否有联动项,判断是否立即执行
if
(
schema
.
options
instanceof
Function
)
{
const
options
=
await
schema
.
options
(
this
.
formData
)
this
.
$set
(
this
.
formOptions
,
key
,
options
)
}
})
},
/**
* 初始化绑定的方法
* @param schemaOn 当前组件上需要绑定的方法
*/
initBindFunction
(
schemaOn
)
{
// 如果没有需要绑定的方法
if
(
!
schemaOn
)
{
return
{}
}
// 将值绑定上formData
return
Object
.
keys
(
schemaOn
).
reduce
((
memo
,
key
)
=>
{
memo
[
key
]
=
schemaOn
[
key
].
bind
(
this
,
this
.
formData
)
return
memo
},
{})
},
/**
* 绑定属性
* @param {Object} attrs 当前属性值
* @param {String} type 当前组件类型
*/
bindAttrs
(
attrs
,
type
)
{
// 组件有的属性
let
componentAttrs
=
[]
// 判断类型
switch
(
type
)
{
case
'
el-form
'
:
componentAttrs
=
EL_FORM_PROP_KEYS
break
case
'
el-form-item
'
:
componentAttrs
=
EL_FORM_ITEM_PROP_KEYS
break
}
return
Object
.
keys
(
attrs
).
reduce
((
memo
,
current
)
=>
{
// 如果选择的属性,是组件的属性
if
(
componentAttrs
.
includes
(
current
))
{
memo
[
current
]
=
attrs
[
current
]
}
return
memo
},
{})
},
/**
* 过滤掉不需要显示的schema
*/
filterUnShowSchema
()
{
// 如果当前没有数据
if
(
!
this
.
schema
)
{
return
{}
}
// 当前需要显示的formSchema
const
formSchema
=
{}
// 便利原始数据
iterator
(
this
.
schema
,
(
value
,
key
)
=>
{
// 如果vif是方法
if
(
value
.
vif
instanceof
Function
)
{
// 如果当前vif返回结果是true,则需要直接展示
if
(
value
.
vif
(
this
.
formData
))
{
formSchema
[
key
]
=
value
}
}
else
{
formSchema
[
key
]
=
value
}
})
return
formSchema
},
/**
* 占位文案
* @param schema 当前schema对象
*/
placeholder
(
schema
)
{
// 如果当前设置了占位文案
if
(
schema
.
attrs
&&
schema
.
attrs
.
placeholder
)
{
return
schema
.
attrs
.
placeholder
}
// 如果当前时下拉或者级联组件,则展示选择,其他展示输入
return
`请
${[
'
el-select
'
,
'
el-cascader
'
].
includes
(
schema
.
type
)
?
'
选择
'
:
'
输入
'
}${
schema
.
label
||
''
}
`
},
/**
* 表单数据发生变化:触发一次options方法
* @param value 当前发生值变化的表单的值
* @param key 当前发生值变化的表单的key
*/
handleFormDataChange
(
value
,
key
)
{
const
{
lastLinkageValue
}
=
this
// 便利数据
iterator
(
this
.
schema
,
async
(
schema
,
schemaKey
)
=>
{
// 如果当前是方法,且配置了联动项,则当联动项发生变化才会触发options
if
(
schema
.
options
instanceof
Function
&&
schema
.
linkage
)
{
// 如果当前改变的值是联动项,则和上一次改变的值不一样,则执行options方法
if
(
schema
.
linkage
.
includes
(
key
)
&&
value
!==
lastLinkageValue
[
key
])
{
// 重新赋值,防止保留了上一次的记过
this
.
formData
[
schemaKey
]
=
schema
.
default
// 将options的值初始化为空
this
.
$set
(
this
.
formOptions
,
schemaKey
,
[])
// 开始执行options方法
const
options
=
await
schema
.
options
(
this
.
formData
)
// 开始绑定值,渲染页面
this
.
$set
(
this
.
formOptions
,
schemaKey
,
options
)
}
}
})
// 记录下当前的联动项的值
lastLinkageValue
[
key
]
=
value
// 开始初始化type
this
.
initType
()
// 开始双向绑定数据
this
.
$emit
(
'
input
'
,
this
.
formData
)
// 通过change方法,向上级暴露当前表单输入的值
this
.
$emit
(
'
change
'
,
this
.
formData
)
// 双向绑定数据
this
.
$emit
(
'
input
'
,
this
.
formData
)
},
/**
* 点击提交方法
*/
handleSubmit
()
{
this
.
$emit
(
'
submit
'
,
this
.
formData
)
},
/**
* 点击重置方法
*/
handleReset
()
{
// 去掉输入内容以及校验结果
this
.
$refs
.
formRender
.
resetFields
()
// 通知父组件
this
.
$emit
(
'
reset
'
)
// 如果当前需要点击重置后发起一起请求
this
.
formConfig
.
queryAfterReset
&&
this
.
handleSubmit
()
},
/**
* 拿到对应key的options
* @param fieldKey 字段key
*/
getOptions
(
fieldKey
)
{
return
this
.
formOptions
[
fieldKey
]
},
/**
* 拿到指定field的,具体值得option
* @param fieldKey 字段key
* @param optionValue 字段的值
*/
getOption
(
fieldKey
,
optionValue
)
{
return
this
.
formOptions
[
fieldKey
].
find
(
option
=>
option
.
value
===
optionValue
)
},
/**
* 重新加载options方法
*/
async
reloadOptions
(
key
,
data
)
{
// 生成options的方法
const
{
options
}
=
this
.
schema
[
key
]
// 如果当前是方法
if
(
options
instanceof
Function
)
{
// 开始调用方法
const
option
=
await
options
(
this
.
formData
,
data
)
// 开始赋值为默认值
this
.
formData
[
key
]
=
this
.
schema
[
key
].
default
// 开始绑定值,渲染页面
this
.
$set
(
this
.
formOptions
,
key
,
option
)
}
}
}
}
src/components/FormRender/shared.js
0 → 100644
View file @
d2c4018b
/**
* 对象迭代器,后期可扩展成对象数组迭代器
* @param target 需要迭代的对象
* @param callback 需要回调的方法
*/
export
function
iterator
(
target
,
callback
)
{
Object
.
keys
(
target
).
forEach
(
key
=>
{
callback
(
target
[
key
],
key
)
})
}
src/components/Layout/index.vue
0 → 100644
View file @
d2c4018b
<
template
>
<div
:class=
"isTablet ? 'tablet-adapter' : ''"
class=
"app-layout"
>
<TopNav
/>
<div
:class=
"
{'has-left-menu': showMenus}" class="app-main">
<div
v-if=
"showMenus"
class=
"app-menu"
>
<LeftMenu/>
</div>
<div
:class=
"showMenus ? 'fix-height' : ''"
class=
"app-content"
>
<keep-alive
:include=
"cachedViews"
>
<router-view
:key=
"key"
/>
</keep-alive>
</div>
</div>
</div>
</
template
>
<
script
>
import
TopNav
from
'
@/components/TopNav
'
import
LeftMenu
from
'
@/components/LeftMenu
'
export
default
{
name
:
'
Layout
'
,
components
:
{
TopNav
,
LeftMenu
},
data
()
{
return
{
isTablet
:
window
.
OS
.
isTablet
}
},
computed
:
{
cachedViews
()
{
return
this
.
$store
.
state
.
stepView
.
cachedViews
},
key
()
{
return
this
.
$route
.
path
},
showMenus
()
{
const
name
=
this
.
$route
.
name
return
[
'
CarAuth1
'
,
'
CarAuth2
'
,
'
DealerManagement
'
,
'
UserManagement
'
,
'
CarCardManagement
'
,
'
OrganizationManagement
'
,
'
AgreementManagement
'
,
'
SystemLog
'
,
'
CarInfoManagement
'
,
'
AuditList
'
,
'
WorkOrderRnrList
'
].
includes
(
name
)
}
}
}
</
script
>
<
style
lang=
"scss"
>
.app-layout
{
min-height
:
100%
;
height
:
100%
;
width
:
100%
;
.app-main
{
padding
:
0
;
display
:
flex
;
min-height
:
calc
(
100%
-
60px
);
&
.has-left-menu
{
border-top
:
1px
solid
#E5E6EC
;
}
.app-menu
{
position
:
relative
;
padding-top
:
12px
;
max-width
:
209px
;
border-right
:
1px
solid
#E5E6EC
;
background
:
#fff
;
flex
:
none
;
}
.app-content
{
flex
:
1
;
width
:
0
;
overflow
:
auto
;
&
.fix-height
{
height
:
calc
(
100vh
-
61px
);
}
}
.el-menu
{
border-right
:
0
none
;
.icon-menu
{
width
:
18px
;
height
:
18px
;
display
:
inline-block
;
&
.basic
{
background
:
url(../../assets/image/menu_basic.svg)
no-repeat
0
0
/
18px
18px
;
}
&
.count
{
background
:
url(../../assets/image/menu_count.svg)
no-repeat
0
0
/
18px
18px
;
}
}
}
.el-menu--collapse
{
width
:
60px
;
.icon-menu
{
width
:
24px
;
height
:
24px
;
display
:
inline-block
;
&
.basic
{
background
:
url(../../assets/image/menu_basic.svg)
no-repeat
0
0
/
24px
24px
;
&
:hover
{
background
:
url(../../assets/image/menu_basic_hover.svg)
no-repeat
0
0
/
24px
24px
;
}
}
&
.count
{
background
:
url(../../assets/image/menu_count.svg)
no-repeat
0
0
/
24px
24px
;
&
:hover
{
background
:
url(../../assets/image/menu_count_hover.svg)
no-repeat
0
0
/
24px
24px
;
}
}
}
.el-submenu__title
{
padding
:
0
18px
!
important
;
}
}
.el-submenu__title
{
padding
:
0
30px
!
important
;
&
:hover
{
background
:
#fff
;
color
:
#2A68FF
;
}
}
.el-submenu__title
,
.el-submenu
.el-menu-item
{
margin-top
:
8px
;
height
:
40px
;
line-height
:
40px
;
}
.el-submenu__icon-arrow
{
margin-top
:
-5px
;
}
.el-submenu
.el-menu-item
{
border-radius
:
2px
;
min-width
:
auto
;
margin
:
8px
18px
0
12px
;
font-size
:
14px
;
font-family
:
PingFangSC-Medium
,
PingFang
SC
;
font-weight
:
500
;
position
:
relative
;
&
.is-active
,
&
:hover
{
background
:
rgba
(
42
,
104
,
255
,
0
.08
);
color
:
#2A68FF
;
}
&
.is-active
{
&
:after
{
content
:
''
;
width
:
3px
;
height
:
24px
;
background
:
#2A68FF
;
position
:
absolute
;
top
:
50%
;
right
:
0
;
margin-top
:
-12px
;
}
}
}
}
&
.tablet-adapter
{
.page-home
{
.page-home-other-service
{
.page-home-row
{
width
:
100%
;
max-width
:
960px
;
.page-home-column-middle
{
width
:
33
.33%
;
}
.page-home-column-large
{
width
:
50%
;
}
}
}
}
.el-dialog
{
max-width
:
800px
;
}
.page
{
.vin-input-wrapper
{
width
:
100%
;
}
}
.page-steps
,
.page-module
{
width
:
100%
;
max-width
:
960px
;
}
.cbt-el-radio-group
{
.cbt-el-radio
{
width
:
100%
;
max-width
:
960px
;
}
}
}
}
</
style
>
Prev
1
…
7
8
9
10
11
12
13
14
15
…
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