Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
F
frontend-h5
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
songrui
frontend-h5
Commits
0f6d77b6
Commit
0f6d77b6
authored
Dec 02, 2024
by
gengchunlei
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
居民端小程序 v1.2 随访详情 组件引入
parent
8861fdc2
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
963 additions
and
266 deletions
+963
-266
generalFU.js
src/api/doctor/generalFU.js
+6
-0
imagePreview.vue
src/doctor/components/imagePreview/imagePreview.vue
+53
-0
Mp3.vue
src/doctor/components/mediaPlay/Mp3.vue
+137
-0
Mp4.vue
src/doctor/components/mediaPlay/Mp4.vue
+93
-0
mp3.js
src/doctor/components/mediaPlay/mp3.js
+145
-0
temDetail.vue
src/doctor/components/template/temDetail.vue
+14
-0
temList.vue
src/doctor/components/template/temList.vue
+21
-0
Detail.vue
src/doctor/followUp/generalFU/detail/Detail.vue
+426
-265
GeneralFUForm.vue
src/doctor/followUp/generalFU/form/GeneralFUForm.vue
+5
-1
common.less
src/doctor/utils/common.less
+63
-0
No files found.
src/api/doctor/generalFU.js
View file @
0f6d77b6
...
...
@@ -73,3 +73,8 @@ export function upLoadMultifile(params) {
contentType
:
'file'
})
}
//短信重发
export
function
messageResend
(
params
)
{
return
fetchBase
({
url
:
`/chronic-admin/v1/chronic-visit-currency/resend-sms`
,
body
:
params
,
loading
:
true
})
}
\ No newline at end of file
src/doctor/components/imagePreview/imagePreview.vue
0 → 100644
View file @
0f6d77b6
<
template
>
<div>
<div
class=
'list gap-x-2.5 gap-y-1 flex items-center flex-wrap'
>
<div
v-for=
"(url, index) in imgList"
:key=
"index"
@
click=
'toPreview(index)'
>
<img
style=
'width: 1.47rem;height: 2.04rem'
:src=
"url.trueDownloadUrl"
/>
</div>
</div>
<van-overlay
:show=
'imgShow'
@
click=
'imgShow = false'
>
<div
class=
'wrapper'
>
<van-swipe
class=
'block'
:initial-swipe=
'initSwipe'
>
<van-swipe-item
v-for=
'image in imgList'
:key=
'image'
>
<img
:src=
'image.trueDownloadUrl'
style=
'width: 100%;height: 100%'
/>
</van-swipe-item>
</van-swipe>
</div>
</van-overlay>
</div>
</
template
>
<
script
>
export
default
{
name
:
'imagePreview'
,
props
:
{
imgList
:
Array
,
},
data
()
{
return
{
imgShow
:
false
,
initSwipe
:
0
}
},
methods
:
{
//图片预览
toPreview
(
index
)
{
this
.
initSwipe
=
index
this
.
imgShow
=
true
},
}
}
</
script
>
<
style
scoped
lang=
'less'
>
.wrapper {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
.block {
width: 100%;
}
}
</
style
>
\ No newline at end of file
src/doctor/components/mediaPlay/Mp3.vue
0 → 100644
View file @
0f6d77b6
<
template
>
<div
class=
"p-1 flex flex-col mp3"
>
<div
v-if=
"file.annexFileName"
class=
"text-12 mb-1 text-ellipsis"
>
{{
file
.
annexFileName
}}
</div>
<div
class=
"flex items-center justify-between gap-x-2.5"
>
<div
class=
"shrink-0 play-bt"
@
click=
"start(file)"
>
<doc-icon
type=
"doc-play"
v-if=
"!player.playing"
/>
<doc-icon
type=
"doc-pause"
v-else
/>
</div>
<span
class=
"shrink-0 time"
>
{{
timeFormat
(
player
.
duration
)
}}
</span>
<div
class=
"grow progress"
>
<van-slider
v-model=
"player.currentTime"
:max=
"sliderMax"
:bar-height=
"6"
:button-size=
"0"
@
change=
"onProgress"
/>
<!--
<div
:style=
"`width: $
{progress}%`">
</div>
-->
</div>
<span
class=
"shrink-0 time"
:style=
"`opacity: $
{player.currentTime ? 1 : 0}`">
{{
timeFormat
(
player
.
currentTime
)
}}
</span>
</div>
<audio
ref=
"audio"
type=
"audio/mpeg"
crossOrigin=
"anonymous"
style=
"display: none"
></audio>
</div>
</
template
>
<
script
>
import
{
musicPlayer
}
from
'./mp3.js'
import
{
showToast
}
from
'vant'
export
default
{
props
:
{
file
:
{
default
:
()
=>
({})
},
activeMediaUrl
:
{
default
:
''
}
},
data
()
{
return
{
player
:
{},
// 正在播放的items
activeAudio
:
{},
}
},
computed
:
{
sliderMax
()
{
return
this
.
player
.
duration
?
Math
.
floor
(
this
.
player
.
duration
)
:
100
},
progress
()
{
if
(
!
this
.
player
.
currentTime
)
return
0
const
temp
=
this
.
player
.
currentTime
/
this
.
player
.
duration
return
Math
.
round
(
temp
*
1000
)
/
10
}
},
mounted
()
{
this
.
init
()
},
methods
:
{
init
()
{
this
.
player
=
new
musicPlayer
(
this
.
$refs
.
audio
)
this
.
player
.
init
()
this
.
player
.
setSrc
(
this
.
file
.
annexUrl
)
this
.
player
.
audioEl
.
onended
=
()
=>
{
console
.
log
(
'播放结束'
)
this
.
stop
()
}
},
start
(
item
)
{
if
(
!
item
||
!
item
.
annexUrl
)
{
showToast
(
'文件获取失败'
)
return
}
if
(
!
this
.
player
.
audioCtx
)
{
this
.
player
.
init
()
this
.
player
.
setSrc
(
item
.
annexUrl
)
}
if
(
this
.
player
.
playing
)
{
this
.
stop
()
}
else
{
this
.
player
.
audioEl
.
play
()
this
.
activeAudio
=
item
this
.
player
.
playing
=
true
this
.
$emit
(
'play'
,
item
)
}
console
.
log
(
'this.player'
,
this
.
player
)
},
stop
()
{
this
.
player
.
audioEl
.
pause
()
this
.
player
.
playing
=
false
},
timeFormat
(
value
)
{
if
(
!
value
)
{
return
'00:00'
}
let
date
=
Math
.
ceil
(
value
)
let
minutes
=
Math
.
floor
(
date
/
60
)
let
seconds
=
date
%
60
let
format
=
''
+
(
minutes
>=
10
?
minutes
:
'0'
+
minutes
)
+
':'
+
(
seconds
>=
10
?
seconds
:
'0'
+
seconds
)
return
format
},
onProgress
(
value
)
{
this
.
player
.
progressChange
(
value
)
this
.
player
.
playing
=
true
}
},
watch
:
{
activeMediaUrl
(
val
)
{
console
.
log
(
'activeMediaUrl'
,
val
)
if
(
val
!==
this
.
file
.
annexUrl
)
{
this
.
stop
()
}
}
}
}
</
script
>
<
style
lang=
"less"
scoped
>
.mp3 {
background-color: #fff;
.play-bt {
display: inline-flex;
width: 24px;
height: 24px;
align-items: center;
justify-content: center;
border-radius: 50%;
background-color: #E4F2F0;
font-size: 10px;
padding-left: 2px;
color: var(--van-primary-color);
}
.progress {
// height: 6px;
// border-radius: 4px;
// background: #EFF2F7;
// overflow: hidden;
// text-align: left;
// >div {
// height: 100%;
// background: #54CCBD;
// }
}
}
</
style
>
src/doctor/components/mediaPlay/Mp4.vue
0 → 100644
View file @
0f6d77b6
<
template
>
<div
class=
"mp4"
>
<div
class=
"flex flex-wrap justify-between video-list"
>
<div
v-for=
"item in files"
:key=
"item.annexId"
>
<div
class=
"item"
>
<div
class=
"shrink-0 play-bt"
@
click=
"start(item)"
>
<doc-icon
type=
"doc-play"
/>
</div>
</div>
<div
v-if=
"item.annexFileName"
class=
"text-12 my-1 text-ellipsis"
>
{{
item
.
annexFileName
}}
</div>
</div>
</div>
<!--
<van-popup
v-model:show=
"visible"
:close-on-click-overlay=
"false"
closeable
close-icon-position=
"top-right"
close-icon=
"clear"
>
<video
controls
v-if=
"visible"
style=
"width: calc(100vw - var(--van-padding-md) * 2)"
>
<source
:src=
"activeVideo.annexUrl"
type=
"video/mp4"
/>
播放失败!
</video>
</van-popup>
-->
<van-overlay
:show=
"visible"
>
<div
class=
"h-full flex items-center justify-center wrapper"
@
click
.
stop
>
<video
controls
v-if=
"visible"
>
<source
:src=
"activeVideo.annexUrl"
type=
"video/mp4"
/>
播放失败!
</video>
<van-icon
name=
"close"
class=
"close-icon"
@
click=
"visible = false"
/>
</div>
</van-overlay>
</div>
</
template
>
<
script
>
export
default
{
props
:
{
files
:
{
default
:
()
=>
[]
}
},
data
()
{
return
{
visible
:
false
,
activeVideo
:
{}
}
},
methods
:
{
start
(
item
)
{
this
.
activeVideo
=
item
this
.
visible
=
true
this
.
$emit
(
'play'
,
item
)
}
}
}
</
script
>
<
style
lang=
"less"
scoped
>
.video-list {
>div {
width: calc(50% - 5px);
.item {
background: url('@/assets/image/residentWX/video-default.png') no-repeat;
background-size: 100%;
height: .84rem;
display: flex;
align-items: center;
justify-content: center;
}
}
.play-bt {
display: inline-flex;
width: 36px;
height: 36px;
align-items: center;
justify-content: center;
border-radius: 50%;
background-color: #E4F2F0;
font-size: 15px;
padding-left: 2px;
}
}
.wrapper {
position: relative;
.close-icon {
position: absolute;
top: 16px;
right: 16px;
color: #ccc;
font-size: 24px;
}
video {
width: calc(100vw - var(--van-padding-md) * 2);
background-color: #fff;
}
}
</
style
>
src/doctor/components/mediaPlay/mp3.js
0 → 100644
View file @
0f6d77b6
export
class
musicPlayer
{
constructor
(
audioEl
)
{
this
.
audioEl
=
audioEl
// 音频上下文
this
.
audioCtx
=
null
// 音源
this
.
audioSource
=
null
// 时长
this
.
duration
=
0
// 当前播放时间
this
.
currentTime
=
0
// 播放进度
this
.
progress
=
0
// 声音
this
.
volume
=
20
// AnalyserNode 接口表示了一个可以提供实时频域和时域分析信息的节点
this
.
analyser
=
null
// 音量节点
this
.
gainNode
=
null
// 缓冲进度
this
.
timeRange
=
null
// 是否播放中
this
.
playing
=
false
}
init
()
{
// 音频上下文
this
.
audioCtx
=
new
(
window
.
AudioContext
||
window
.
webkitAudioContext
)()
if
(
!
this
.
audioCtx
)
{
throw
new
Error
(
'audioCtx is null'
)
}
// 获取音频数据的节点
this
.
analyser
=
this
.
audioCtx
.
createAnalyser
()
// 音量节点
this
.
gainNode
=
this
.
audioCtx
.
createGain
()
this
.
gainNode
.
gain
.
value
=
1
this
.
audioEl
.
volume
=
this
.
volume
/
100
// 从<audio>或<video>元素生成的音频源
this
.
audioSource
=
this
.
audioCtx
.
createMediaElementSource
(
this
.
audioEl
)
this
.
audioEl
.
ontimeupdate
=
()
=>
{
this
.
currentTime
=
this
.
audioEl
.
currentTime
if
(
this
.
progress
>=
this
.
duration
)
return
this
.
progress
=
this
.
currentTime
}
this
.
audioEl
.
onloadedmetadata
=
()
=>
{
// 时长
this
.
duration
=
this
.
audioEl
.
duration
console
.
log
(
'onloadedmetadata'
,
this
.
duration
)
}
this
.
audioEl
.
onprogress
=
()
=>
{
// 当浏览器正在下载音频/视频时
this
.
timeRange
=
this
.
audioEl
.
buffered
if
(
this
.
timeRange
&&
this
.
timeRange
.
length
>
0
)
{
console
.
log
(
'buffered'
,
this
.
audioEl
.
buffered
.
start
(
0
),
this
.
audioEl
.
buffered
.
end
(
0
)
)
}
}
this
.
audioEl
.
oncanplay
=
()
=>
{
console
.
log
(
'可播放'
)
setTimeout
(()
=>
{
this
.
getAudioSource
()
},
100
)
}
this
.
audioEl
.
onerror
=
(
e
)
=>
{
console
.
error
(
'加载出现错误'
,
e
)
this
.
onerror
(
e
)
}
}
onerror
()
{}
onended
()
{}
setSrc
(
src
)
{
this
.
progress
=
0
this
.
audioEl
.
src
=
src
}
// 调整进度
progressChange
(
value
)
{
this
.
audioEl
.
currentTime
=
value
}
// 调整音量
volumeChange
(
value
)
{
this
.
volume
=
value
this
.
audioEl
.
volume
=
this
.
volume
/
100
}
// 音频波形处理
getAudioSource
()
{
// 节点链接到音源
this
.
audioSource
.
connect
(
this
.
analyser
)
// 链接音量节点
this
.
analyser
.
connect
(
this
.
gainNode
)
this
.
gainNode
.
connect
(
this
.
audioCtx
.
destination
)
return
// 使用快速傅立叶变换(Fast Fourier Transform (FFT) )来捕获音频数据
// this.analyser.fftSize = 2048
this
.
analyser
.
fftSize
=
256
let
bufferLength
=
this
.
analyser
.
frequencyBinCount
let
dataArray
=
new
Uint8Array
(
bufferLength
)
let
c
=
this
.
boardEl
let
canvasWidth
=
c
.
width
let
canvasHeight
=
c
.
height
let
ctx
=
c
.
getContext
(
'2d'
)
let
left
=
this
ctx
.
strokeStyle
=
'rgba(81,167,255, .5)'
drawBar
()
function
drawBar
()
{
// 波形绘制
ctx
.
clearRect
(
0
,
0
,
canvasWidth
,
canvasHeight
)
let
barWidth
=
(
canvasWidth
/
bufferLength
)
*
1
let
barHeight
=
0
let
x
=
0
left
.
analyser
.
getByteFrequencyData
(
dataArray
)
for
(
let
i
=
0
;
i
<
bufferLength
;
i
++
)
{
barHeight
=
dataArray
[
i
]
/
2
let
tempColor
=
barHeight
*
3
>
255
?
255
:
barHeight
*
3
ctx
.
fillStyle
=
'rgba('
+
tempColor
+
', 160, 255, .5)'
ctx
.
fillRect
(
x
,
canvasHeight
-
barHeight
/
2
,
barWidth
,
barHeight
)
x
+=
barWidth
+
0.1
}
requestAnimationFrame
(
drawBar
)
}
}
}
src/doctor/components/template/temDetail.vue
0 → 100644
View file @
0f6d77b6
<
template
>
</
template
>
<
script
>
export
default
{
name
:
'temDetail'
}
</
script
>
<
style
scoped
>
</
style
>
\ No newline at end of file
src/doctor/components/template/temList.vue
0 → 100644
View file @
0f6d77b6
<
template
>
<van-popup
v-model:show=
"show"
position=
"right"
:style=
"
{ height: '100%' }" >
<div>
1111111
</div>
</van-popup>
</
template
>
<
script
>
export
default
{
name
:
'temList'
,
data
()
{
return
{
show
:
false
}
}
}
</
script
>
<
style
scoped
>
</
style
>
\ No newline at end of file
src/doctor/followUp/generalFU/detail/Detail.vue
View file @
0f6d77b6
<!--通用随访详情-->
<
template
>
<div
class=
'flex flex-col'
style=
'height: 100vh'
>
<div
class=
'p-3 text-black text-center shrink-0 doc-nav-bar'
>
<span
@
click=
'onBack'
class=
'text-12 back-bt'
>
<doc-icon
type=
'doc-left2'
/>
</span>
<span>
随访详情
</span>
</div>
<div
class=
'px-4 py-3 flex shrink-0 base-info'
>
<div
class=
'flex w-full'
>
<div
class=
'grow flex flex-col justify-between'
>
<div
class=
'flex justify-between'
>
<span
class=
'name'
>
{{
residentInfo
.
residentName
}}
</span>
</div>
<div
class=
'top-label'
>
<div
class=
'mt-3 flex'
>
<div><span>
随访方式:
</span><span
class=
'color-b'
>
{{
info
.
visitWayName
}}
</span></div>
<div
class=
'ml-4'
>
随访日期:
<span
class=
'color-b'
>
{{
info
.
visitDate
}}
</span></div>
</div>
<div><span>
下次随访日期:
</span><span
class=
'color-b'
>
{{
info
.
nextVisitDate
}}
</span></div>
</div>
</div>
</div>
</div>
<div
class=
'p-3 grow cont-box'
>
<div
class=
'p-3 h-full cont-inner'
>
<div
class=
'flex justify-between collapse-head mt-2'
>
<span
class=
'text-16 font-semibold'
>
全部内容
</span>
<span
@
click=
'toggleAll'
>
<span
v-if=
'!collapseAll'
>
展开全部
</span>
<span
v-else
>
收起全部
</span>
<span
:class=
"['ml-2 icon-down',
{ 'icon-down-expanded': collapseAll }]">
<doc-icon
type=
'doc-down'
/>
</span>
</span>
</div>
<van-collapse
:model-value=
'activeCollapse'
ref=
'collapse'
class=
'doc-collapse'
@
change=
'collapseChange'
>
<van-collapse-item
key=
'1'
title=
'居民信息'
name=
'1'
>
<template
#
right-icon
>
<doc-icon
type=
'doc-down'
/>
</
template
>
<div
class=
'list'
>
<div
v-for=
'item in columnsBase'
:key=
'item.key'
>
<div
class=
'flex justify-between py-1 border-bottom item'
>
<span
class=
'shrink-0 mr-2 label'
>
{{ item.title }}
</span>
<span
v-if=
"item.key === 'idCard'"
>
{{ $idCardHide(residentInfo.idCard) || '-'
}}
</span>
<span
class=
'text-end'
v-else
>
<span>
{{ residentInfo[item.key] || '-' }}
</span>
<span
v-if=
'item.unit'
class=
'ml-1'
>
{{ item.unit }}
</span>
</span>
</div>
</div>
</div>
</van-collapse-item>
<van-collapse-item
key=
'2'
title=
'随访人群'
name=
'2'
>
<
template
#
right-icon
>
<doc-icon
type=
'doc-down'
/>
</
template
>
<div
class=
'list'
>
<div
class=
'flex justify-between py-1 border-bottom item'
>
<span
class=
'shrink-0 mr-2 label'
>
随访人群
</span>
<span
class=
'text-end'
>
<span>
{{ info.groupsArraysName || '-' }}
</span>
</span>
</div>
</div>
</van-collapse-item>
<van-collapse-item
key=
'3'
title=
'随访方式'
name=
'3'
>
<
template
#
right-icon
>
<doc-icon
type=
'doc-down'
/>
</
template
>
<div
class=
'list'
>
<div
class=
'flex justify-between py-1 border-bottom item'
>
<span
class=
'shrink-0 mr-2 label'
>
随访方式
</span>
<span
class=
'text-end'
>
<span>
{{ info.visitWayName || '-' }}
</span>
</span>
</div>
</div>
</van-collapse-item>
<van-collapse-item
key=
'4'
title=
'随访类型'
name=
'4'
>
<
template
#
right-icon
>
<doc-icon
type=
'doc-down'
/>
</
template
>
<div
class=
'list'
>
<div
class=
'flex justify-between py-1 border-bottom item'
>
<span
class=
'shrink-0 mr-2 label'
>
随访类型
</span>
<span
class=
'text-end'
>
<span>
{{ info.visitWayRulesName || '-' }}
</span>
</span>
</div>
</div>
</van-collapse-item>
<van-collapse-item
key=
'5'
title=
'随访内容'
name=
'5'
v-if=
'showOne'
>
<
template
#
right-icon
>
<doc-icon
type=
'doc-down'
/>
</
template
>
<div
class=
'list'
>
<div
class=
'py-1 border-bottom item card'
:style=
"{textIndent: info.visitContent ? '2em' : '0'}"
>
<span>
{{ info.visitContent || '-' }}
</span>
</div>
</div>
</van-collapse-item>
<van-collapse-item
key=
'6'
title=
'处置意见'
name=
'6'
v-if=
'showOne'
>
<
template
#
right-icon
>
<doc-icon
type=
'doc-down'
/>
</
template
>
<div
class=
'list'
>
<div
class=
'py-1 border-bottom item card'
:style=
"{textIndent: info.disposalOpinion ? '2em' : '0'}"
>
<span>
{{ info.disposalOpinion || '-' }}
</span>
</div>
</div>
</van-collapse-item>
<van-collapse-item
key=
'7'
title=
'健康指导'
name=
'7'
v-if=
'showTwo'
>
<
template
#
right-icon
>
<doc-icon
type=
'doc-down'
/>
</
template
>
<div>
<van-nav-bar
title=
'随访详情'
left-text=
''
left-arrow
@
click-left=
'toBack'
></van-nav-bar>
<div
class=
'p-4 detail-info'
>
<div
class=
'title'
>
居民信息
</div>
<div
class=
'detail-div mt-3'
>
<!--
<div
class=
'flex items-center justify-between'
>
<div
class=
'label'
>
证件类型
</div>
<div>
{{
residentInfo
.
certificateTypeName
||
'-'
}}
</div>
</div>
<div
class=
'flex items-center justify-between mt-2'
>
<div
class=
'label'
>
证件号码
</div>
<div>
{{
residentInfo
.
idCard
||
'-'
}}
</div>
</div>
-->
<div
class=
'flex items-center justify-between mt-2'
>
<div
class=
'label'
>
姓名
</div>
<div>
{{
residentInfo
.
residentName
||
'-'
}}
</div>
</div>
<!--
<div
class=
'flex items-center justify-between mt-2'
>
<div
class=
'label'
>
性别
</div>
<div>
{{
residentInfo
.
genderName
||
'-'
}}
</div>
</div>
<div
class=
'flex items-center justify-between mt-2'
>
<div
class=
'label'
>
出生日期
</div>
<div>
{{
residentInfo
.
dataBirth
||
'-'
}}
</div>
</div>
-->
<div
class=
'flex items-center justify-between mt-2'
>
<div
class=
'label'
>
本人电话
</div>
<div>
{{
residentInfo
.
telephone
||
'-'
}}
</div>
</div>
<div
class=
'flex items-center justify-between mt-2'
>
<div
class=
'label'
>
民族
</div>
<div>
{{
residentInfo
.
nationalName
||
'-'
}}
</div>
</div>
<!--
<div
class=
'flex items-center justify-between mt-2'
>
<div
class=
'label'
>
年龄
</div>
<div>
{{
residentInfo
.
currentAge
||
'-'
}}
岁
</div>
</div>
-->
<div
class=
'flex flex-wrap justify-between mt-2'
>
<div
class=
'label'
>
现住址
</div>
<div
style=
'flex: 1'
>
{{
residentInfo
.
fullNowAddress
||
'-'
}}
</div>
</div>
<div
class=
'flex flex-wrap justify-between mt-2'
>
<div
class=
'label'
>
户籍地址
</div>
<div
style=
'flex: 1'
>
{{
residentInfo
.
fullPermanentAddress
||
'-'
}}
</div>
</div>
</div>
<div
class=
'title mt-3'
>
联系人信息
</div>
<div
class=
'detail-div mt-3'
>
<div
class=
'flex items-center justify-between'
>
<div
class=
'label'
>
联系人姓名
</div>
<div>
{{
residentInfo
.
contactName
||
'-'
}}
</div>
</div>
<div
class=
'flex items-center justify-between mt-2'
>
<div
class=
'label'
>
与居民关系
</div>
<div>
{{
residentInfo
.
relationName
||
'-'
}}
</div>
</div>
<div
class=
'flex items-center justify-between mt-2'
>
<div
class=
'label'
>
联系电话
</div>
<div>
{{
residentInfo
.
contactPhone
||
'-'
}}
</div>
</div>
</div>
<div
class=
'title mt-3'
>
随访信息
</div>
<div
class=
'detail-div mt-3'
>
<div
class=
'flex items-center justify-between'
>
<div>
本次随访情况
</div>
<div>
{{
info
.
visitSituationName
}}
</div>
</div>
<div
class=
'flex items-center justify-between mt-2'
v-if=
'info.visitSituation == 2'
>
<div>
失访原因
</div>
<div>
<span
v-if=
'info.lossReason != 9'
>
{{
info
.
lossReasonName
||
'-'
}}
</span>
<span
v-if=
'info.lossReason == 9'
>
{{
info
.
lossReasonOther
||
'-'
}}
</span>
</div>
</div>
<div
class=
'flex items-center justify-between mt-2'
v-if=
'info.lossReason == 3'
>
<div>
死亡原因
</div>
<div>
{{
info
.
deathReason
}}
</div>
</div>
<div
class=
'flex items-center justify-between mt-2'
v-if=
'info.visitSituation == 1'
>
<div>
随访方式
</div>
<div>
{{
info
.
visitWayName
}}
</div>
</div>
<div
class=
'white-b mt-2'
v-if=
'showOne && info.visitSituation == 1'
>
<span>
居民电话:
</span><span>
{{
residentInfo
.
telephone
||
'-'
}}
</span>
</div>
<div
class=
'white-b mt-2'
v-if=
'showThree && info.visitSituation == 1'
>
<div>
催检内容:
</div>
<div>
{{
info
.
urgentInsContent
}}
</div>
</div>
<div
class=
'mt-2'
v-if=
'showOne && info.visitSituation == 1'
>
<div>
随访内容
</div>
<div
class=
'white-b mt-2'
style=
'min-height: 60px'
>
<div>
{{
info
.
visitContent
}}
</div>
</div>
</div>
<div
class=
'mt-2'
v-if=
'showOne && info.visitSituation == 1'
>
<div>
处置意见
</div>
<div
class=
'white-b mt-2'
style=
'min-height: 60px'
>
<div>
{{
info
.
disposalOpinion
}}
</div>
</div>
</div>
<div
class=
'mt-2'
v-if=
'(showOne || showTwo) && info.visitSituation == 1 && info.isHealthGuide == 1'
>
<div>
健康指导
</div>
<div
class=
'white-b mt-2'
>
<div
class=
'flex flex-wrap mt-2'
v-for=
'(item, index) in healthInterventionsInfo.visitHealthGuideList'
>
<div
v-if=
"item.name != '无'"
class=
'label'
>
{{
item
.
name
}}
:
</div>
<div
style=
'flex: 1'
>
{{
item
.
templateContent
}}
</div>
</div>
<div
v-if=
'guideContentList.length'
class=
'flex flex-col card'
>
<!-- 文本 -->
<div
v-for=
'item in guideContentList'
:key=
'item.templateMode'
class=
'mb-1 flex'
:style=
'`order: ${item.templateMode}`'
>
<span
class=
'shrink-0 mr-1'
v-if=
"item.templateModeTrans != '无'"
>
{{ item.templateModeTrans }} :
</span>
<span>
{{ item.templateContent }}
</span>
</div>
</div>
<div
class=
'mt-2'
v-if=
'imgList1.length'
>
<div>
随访记录
</div>
<div
class=
'flex items-center'
style=
'flex-wrap: wrap'
>
<div
v-for=
'(item, index) in imgList1'
>
<!-- 图片-->
<div
v-if=
"item.imgFlag == 'img'"
class=
'mt-2'
>
<img
:src=
'item.trueDownloadUrl'
class=
'ml-2'
style=
'width: 95px;height: 95px;'
>
</div>
</div>
</div>
<!-- pdf-->
</van-collapse-item>
<van-collapse-item
key=
'8'
title=
'宣教内容'
name=
'8'
v-if=
'showThree'
>
<
template
#
right-icon
>
<doc-icon
type=
'doc-down'
/>
</
template
>
<div>
<div
v-for=
'item in imgList1'
>
<div
class=
'mt-2 pdf'
v-if=
"item.imgFlag == 'pdf'"
>
<div
class=
'flex items-center justify-between'
>
<div
class=
'flex items-center'
@
click
.
stop=
'toPdf(item)'
>
<div
class=
'flex flex-col card'
v-if=
'detailInfo?.publicizeType?.includes(1)'
>
<!-- 文本 -->
<div
v-for=
'item in contentList'
:key=
'item.templateMode'
class=
'mb-1 flex'
:style=
'`order: ${item.templateMode}`'
>
<span
class=
'shrink-0 mr-1'
v-if=
"item.templateModeTrans != '无'"
>
{{ item.templateModeTrans }} :
</span>
<span>
{{ item.templateContent }}
</span>
</div>
</div>
<div
class=
'card mt-2'
v-if=
'detailInfo?.publicizeType?.includes(3)'
>
<Mp4
:files=
'mp4List'
:activeMediaUrl=
'activeMediaUrl'
@
play=
'e => activeMediaUrl = e.annexUrl'
/>
</div>
<div
class=
'card flex flex-col mt-2'
style=
'row-gap: .06rem;'
v-if=
'detailInfo?.publicizeType?.includes(2)'
>
<Mp3
:file=
'item'
v-for=
'item in mp3List'
:key=
'item.annexId'
:activeMediaUrl=
'activeMediaUrl'
@
play=
'e => activeMediaUrl = e.annexUrl'
/>
</div>
</div>
</van-collapse-item>
<van-collapse-item
key=
'9'
title=
'催检内容'
name=
'9'
v-if=
'showFour'
>
<
template
#
right-icon
>
<doc-icon
type=
'doc-down'
/>
</
template
>
<div
class=
'list'
>
<div
class=
'py-1 border-bottom item card'
:style=
"{textIndent: info.urgentInsContent ? '2em' : '0'}"
>
<span>
{{ info.urgentInsContent || '-' }}
</span>
</div>
</div>
</van-collapse-item>
<van-collapse-item
key=
'10'
title=
'上传随访记录'
name=
'10'
v-if=
'showOne'
>
<
template
#
right-icon
>
<doc-icon
type=
'doc-down'
/>
</
template
>
<div>
<doc-icon
type=
'doc-PDF'
style=
'font-size: .48rem'
></doc-icon>
</div>
<div
class=
'ml-1'
>
{{
item
.
name
}}
</div>
</div>
</div>
</div>
</div>
<image-preview
:img-list=
'info.uploadVisitRecordImageList'
></image-preview>
</div>
</van-collapse-item>
<van-collapse-item
key=
'11'
title=
'现场随访照片'
name=
'11'
>
<
template
#
right-icon
>
<doc-icon
type=
'doc-down'
/>
</
template
>
<!-- <div class='list gap-x-2.5 gap-y-1 flex items-center flex-wrap'>
<div v-for="(url, index) in info.sceneVisitImageList" :key="index" >
<img style='width: 1.47rem;height: 2.04rem' :src="url.trueDownloadUrl" />
</div>
<div
class=
'mt-2'
v-if=
'imgList2.length'
>
<div>
现场随访照片
</div>
<div
class=
'flex items-center'
style=
'flex-wrap: wrap'
>
<div
v-for=
'(item, index) in imgList2'
>
<!-- 图片-->
<div
v-if=
"item.imgFlag == 'img'"
class=
'mt-2'
>
<img
:src=
'item.trueDownloadUrl'
class=
'ml-2'
style=
'width: 95px;height: 95px;'
>
</div>
</div>
</div>
<!-- pdf-->
<div>
<div
v-for=
'item in imgList2'
>
<div
class=
'mt-2 pdf'
v-if=
"item.imgFlag == 'pdf'"
>
<div
class=
'flex items-center justify-between'
>
<div
class=
'flex items-center'
@
click
.
stop=
'toPdf(item)'
>
</div>-->
<div>
<doc-icon
type=
'doc-PDF'
style=
'font-size: .48rem'
></doc-icon>
</div>
<div
class=
'ml-1'
>
{{
item
.
name
}}
</div>
<image-preview
:img-list=
'info.sceneVisitImageList'
></image-preview>
</div>
</van-collapse-item>
<van-collapse-item
key=
'12'
title=
'推送渠道'
name=
'12'
v-if=
'info?.visitWayRules?.includes(2) || info?.visitWayRules?.includes(3) || info?.visitWayRules?.includes(4)'
>
<
template
#
right-icon
>
<doc-icon
type=
'doc-down'
/>
</
template
>
<div
class=
'list'
>
<div
class=
'flex justify-between py-1 border-bottom item'
>
<span
class=
'shrink-0 mr-2 label'
>
推送渠道
</span>
<span
class=
'text-end'
>
<span
v-if=
'info.isSms == 1'
>
短信
</span><span
v-if=
'info.isSms == 1 && info.isWx == 1'
>
;
</span>
<span
v-if=
'info.isWx == 1'
>
微信
</span>
<span
v-if=
'info.isSms != 1 && info.isWx != 1'
>
-
</span>
</span>
</div>
<div
class=
'flex justify-between py-1 border-bottom item'
v-if=
'info.isSms == 1 && (info?.visitWayRules?.includes(2) || info?.visitWayRules?.includes(3) || info?.visitWayRules?.includes(4))'
>
<span
class=
'shrink-0 mr-2 label'
>
短信推送情况
</span>
<span
class=
'text-end'
>
<span>
{{ info?.serviceResidents?.messageStateName || '-' }}
</span>
<span
class=
'ml-4'
v-if=
'info?.serviceResidents?.messageState == 3'
style=
'font-size: 12px'
>
<van-button
ghost
type=
'primary'
size=
'small'
@
click=
'toReSend'
>
重发
</van-button>
</span>
</span>
</div>
</div>
</van-collapse-item>
<van-collapse-item
key=
'13'
title=
'随访机构'
name=
'13'
>
<
template
#
right-icon
>
<doc-icon
type=
'doc-down'
/>
</
template
>
<div
class=
'list'
>
<div
v-for=
'item in columnsOrg'
:key=
'item.key'
>
<div
class=
'flex justify-between py-1 border-bottom item'
>
<span
class=
'shrink-0 mr-2 label'
>
{{ item.title }}
</span>
<span
class=
'text-end'
>
<span>
{{ info[item.key] || '-' }}
</span>
</span>
</div>
</div>
</div>
</van-collapse-item>
</van-collapse>
</div>
</div>
</div>
</div>
</div>
</div>
<div
class=
'flex items-center justify-between mt-2'
v-if=
'info.visitSituation == 1'
>
<div>
下次随访日期
</div>
<div>
{{
info
.
nextVisitDate
||
'-'
}}
</div>
</div>
<div
class=
'flex items-center justify-between mt-2'
>
<div>
随访单位
</div>
<div>
{{
info
.
visitUnitName
||
'-'
}}
</div>
</div>
<div
class=
'flex items-center justify-between mt-2'
>
<div>
随访科室
</div>
<div>
{{
info
.
visitOfficeName
||
'-'
}}
</div>
</div>
<div
class=
'flex items-center justify-between mt-2'
>
<div>
随访医生
</div>
<div>
{{
info
.
visitDoctorName
||
'-'
}}
</div>
</div>
</div>
</div>
<div
class=
'px-5 flex align-center justify-around pt-2 pb-2'
>
<van-button
type=
'primary'
round
plain
style=
'width: 70%;background: #F0F3FF;border: 0px'
@
click=
'toBack'
>
返回
</van-button>
</div>
</div>
</template>
<
script
>
import
{
fetchCurrencyById
}
from
'@/api/doctor/generalFU'
import
{
showToast
}
from
'vant'
import
{
useStore
}
from
'@/doctor/store'
import
Mp3
from
'@/residentWX/components/mediaPlay/Mp3.vue'
import
Mp4
from
'@/residentWX/components/mediaPlay/Mp4'
import
ImagePreview
from
'@/residentWX/components/imagePreview/imagePreview'
import
{
fetchCurrencyById
,
messageResend
}
from
'@/api/doctor/generalFU'
export
default
{
name
:
'Detail'
,
props
:
{
id
:
[
String
,
Number
]
},
name
:
'CurrencyFUDetail.vue'
,
components
:
{
ImagePreview
,
Mp4
,
Mp3
},
inject
:
[
'showNav'
],
data
()
{
return
{
store
:
useStore
(),
activeCollapse
:
[],
detailInfo
:
{
publicizeType
:
[],
visitWayRules
:
[]
},
collapseList
:
[
{
title
:
'居民信息'
,
name
:
'1'
},
{
title
:
'随访人群'
,
name
:
'2'
},
{
title
:
'随访方式'
,
name
:
'3'
},
{
title
:
'随访类型'
,
name
:
'4'
},
{
title
:
'随访内容'
,
name
:
'5'
},
{
title
:
'处置意见'
,
name
:
'6'
},
{
title
:
'健康指导'
,
name
:
'7'
},
{
title
:
'宣教内容'
,
name
:
'8'
},
{
title
:
'催检内容'
,
name
:
'9'
},
{
title
:
'上传随访记录'
,
name
:
'10'
},
{
title
:
'现场随访照片'
,
name
:
'11'
},
{
title
:
'推送渠道'
,
name
:
'12'
},
{
title
:
'下次随访日期'
,
name
:
'13'
},
{
title
:
'随访机构'
,
name
:
'14'
}
],
// 全部展开、收起
collapseAll
:
false
,
info
:
{},
residentInfo
:
{}
columnsBase
:
[
{
title
:
'姓名'
,
key
:
'residentName'
},
{
title
:
'证件号码'
,
key
:
'idCard'
},
{
title
:
'性别'
,
key
:
'genderName'
},
{
title
:
'出生日期'
,
key
:
'dataBirth'
},
{
title
:
'年龄'
,
key
:
'currentAge'
},
{
title
:
'民族'
,
key
:
'nationalName'
},
{
title
:
'本人电话'
,
key
:
'telephone'
},
{
title
:
'现住址'
,
key
:
'presentCodeName'
},
{
title
:
'详细地址'
,
key
:
'nowAddress'
},
{
title
:
'户籍地址'
,
key
:
'registeredCodeName'
},
{
title
:
'详细地址'
,
key
:
'permanentAddress'
}
],
columnsOrg
:
[
{
title
:
'随访单位'
,
key
:
'visitUnitName'
},
{
title
:
'随访科室'
,
key
:
'visitOfficeName'
},
{
title
:
'随访医生'
,
key
:
'visitDoctorName'
}
],
activeMediaUrl
:
''
}
},
computed
:
{
routerDetail
()
{
return
this
.
$route
.
query
},
//复检指导
residentInfo
()
{
return
this
.
info
.
residentsRecord
||
{}
},
//复检
showOne
()
{
const
{
visitWay
}
=
this
.
info
const
{
visitWay
Rules
=
[]
}
=
this
.
info
let
res
=
false
if
(
visitWay
==
5
||
visitWay
==
6
||
visitWay
==
7
||
visitWay
==
8
)
{
if
(
visitWay
Rules
.
includes
(
1
)
)
{
res
=
true
}
return
res
},
//
微信、短信
指导
//指导
showTwo
()
{
const
{
visitWay
}
=
this
.
info
const
{
visitWay
Rules
=
[]
}
=
this
.
info
let
res
=
false
if
(
visitWay
==
9
||
visitWay
==
11
)
{
if
(
visitWay
Rules
.
includes
(
2
)
)
{
res
=
true
}
return
res
},
//
催检
//
宣教
showThree
()
{
const
{
visitWay
}
=
this
.
info
const
{
visitWay
Rules
=
[]
}
=
this
.
info
let
res
=
false
if
(
visitWay
==
10
||
visitWay
==
12
)
{
if
(
visitWay
Rules
.
includes
(
3
)
)
{
res
=
true
}
return
res
},
//健康指导
healthInterventionsInfo
()
{
const
modeArray
=
this
.
store
.
getDict
(
'DC00084'
)
let
visitHealthGuideList
=
[]
if
(
this
.
info
.
healthGuideContent
)
{
visitHealthGuideList
=
JSON
.
parse
(
this
.
info
.
healthGuideContent
)
}
const
res
=
{
visitHealthGuideList
:
modeArray
.
map
(
e
=>
{
const
item
=
visitHealthGuideList
.
find
(
i
=>
i
.
templateMode
===
e
.
value
)
return
{
templateMode
:
e
.
value
,
name
:
e
.
name
,
templateContent
:
item
?
item
.
templateContent
:
''
,
id
:
item
?
item
.
visitId
:
''
}
})
//催检
showFour
()
{
const
{
visitWayRules
=
[]
}
=
this
.
info
let
res
=
false
if
(
visitWayRules
.
includes
(
4
))
{
res
=
true
}
return
res
},
imgList1
()
{
const
{
uploadVisitRecordImageList
=
[]
}
=
this
.
info
uploadVisitRecordImageList
.
forEach
(
item
=>
{
item
[
'imgFlag'
]
=
''
if
(
item
.
fileType
==
'pdf'
)
{
item
[
'imgFlag'
]
=
'pdf'
}
if
(
item
.
fileType
==
'img'
)
{
item
[
'imgFlag'
]
=
'img'
}
})
return
uploadVisitRecordImageList
// 文本内容
guideContentList
()
{
return
this
.
info
?.
guide
?.
contentList
||
[]
},
imgList2
()
{
const
{
sceneVisitImageList
=
[]
}
=
this
.
info
sceneVisitImageList
.
forEach
(
item
=>
{
item
[
'imgFlag'
]
=
''
if
(
item
.
fileType
==
'pdf'
)
{
item
[
'imgFlag'
]
=
'pdf'
}
if
(
item
.
fileType
==
'img'
)
{
item
[
'imgFlag'
]
=
'img'
}
})
return
sceneVisitImageList
// 文本内容
contentList
()
{
return
this
.
info
?.
publicize
?.
contentList
||
[]
},
// 文件内容
annexList
()
{
return
this
.
info
?.
publicize
?.
annexList
||
[]
},
mp3List
()
{
return
this
.
annexList
.
filter
(
e
=>
e
.
type
==
2
)
},
mp4List
()
{
return
this
.
annexList
.
filter
(
e
=>
e
.
type
==
3
)
}
},
created
()
{
document
.
title
=
'通用随访详情'
this
.
load
()
},
methods
:
{
async
load
()
{
debugger
if
(
!
this
.
routerDetail
.
relationId
)
{
showToast
(
'未获取到信息'
)
return
...
...
@@ -305,50 +375,141 @@ export default {
fetchCurrencyById
(
par
).
then
(
res
=>
{
let
result
=
res
.
data
||
{}
this
.
info
=
result
this
.
residentInfo
=
result
.
residentsRecord
||
{}
this
.
dataHandle
()
}).
finally
(()
=>
{
})
},
toBack
()
{
//数据处理
dataHandle
()
{
const
{
visitWayRules
,
publicizeType
}
=
this
.
info
if
(
publicizeType
)
{
this
.
detailInfo
.
publicizeType
=
publicizeType
.
split
(
','
).
map
(
item
=>
Number
(
item
))
}
if
(
visitWayRules
)
{
this
.
detailInfo
.
visitWayRules
=
visitWayRules
.
split
(
','
).
map
(
item
=>
Number
(
item
))
}
},
//重新发送
toReSend
()
{
let
par
=
{
id
:
this
.
routerDetail
.
relationId
}
messageResend
(
par
).
then
(()
=>
{
this
.
load
()
})
},
// 折叠面板切换
collapseChange
(
val
)
{
if
(
val
&&
val
.
length
<=
2
)
{
this
.
activeCollapse
=
val
.
slice
(
val
.
length
-
1
)
}
else
{
if
(
this
.
activeCollapse
.
length
>
val
.
length
)
{
this
.
activeCollapse
=
val
}
if
(
this
.
activeCollapse
.
length
<
val
.
length
)
{
this
.
activeCollapse
=
val
.
slice
(
val
.
length
-
1
)
}
}
if
(
val
&&
val
.
length
===
this
.
collapseList
.
length
)
{
this
.
collapseAll
=
true
}
else
{
this
.
collapseAll
=
false
}
},
// 全部展开、收起
toggleAll
()
{
if
(
this
.
collapseAll
)
{
this
.
activeCollapse
=
[]
}
else
{
this
.
activeCollapse
=
this
.
collapseList
.
map
(
e
=>
e
.
name
)
}
this
.
collapseAll
=
!
this
.
collapseAll
},
onBack
()
{
this
.
$router
.
back
()
}
}
}
</
script
>
<
style
scoped
lang=
'less'
>
.title {
font-weight: bold;
}
<
style
lang=
'less'
scoped
>
@import url('../../../utils/common.less');
.mt-4 {
margin-top: 24px;
.base-info {
background: linear-gradient(to bottom, #DFF5F4, #fff 50%);
color: #8c8c8c;
.name {
font-weight: 600;
color: #000;
font-size: 18px;
}
.top-label {
font-size: 13px;
line-height: 22px;
}
.color-b {
color: #262626;
}
}
.detail-info {
height: calc(100vh - 110px);
overflow-y: auto;
.cont-box {
background-color: #f9f9f9;
.cont-inner {
background: linear-gradient(to bottom, #DFF5F4, #fff .6rem);
border-top-left-radius: .08rem;
border-top-right-radius: .08rem;
}
}
.detail-div {
padding: 12px;
border: 1px solid #EEEEEE;
background: #F8FAFC;
border-radius: 8px;
.collapse-head {
.icon-down {
vertical-align: middle;
font-size: .12rem;
.svg-icon {
transition: all .2s;
}
}
.icon-down-expanded {
.svg-icon {
transform: rotate(-180deg);
}
}
}
.white-b {
background: #FFFFFF;
padding: 12px;
border: 1px solid #EEEEEE;
border-radius: 8px;
table {
text-align: left;
border-bottom: 1px solid var(--van-cell-border-color);
> tr {
> td {
padding-left: 14px;
padding-bottom: 12px;
&:first-child {
text-align: right;
padding-left: 0;
}
}
}
}
.label {
width: 104px;
.list {
.label {
min-width: 5em;
}
}
:deep(.van-nav-bar .van-icon) {
color: #000000;
.card {
background-color: #F8FAFC;
padding: 4px 10px;
border-radius: 4px;
color: #4D5665;
}
</
style
>
src/doctor/followUp/generalFU/form/GeneralFUForm.vue
View file @
0f6d77b6
...
...
@@ -26,7 +26,11 @@
/>
</div>
<div
v-if=
'showTwo'
>
<div
class=
'no-req-label mt-5'
>
健康指导
</div>
<div
class=
'flex justify-between items-center'
>
<div
class=
'label-title mt-5'
>
健康指导
</div>
<van-button
class=
'doc-btn-primary'
>
选择内容
</van-button>
</div>
<div
class=
'health mt-2'
>
<div
class=
'health-cell mt-2'
v-for=
'item in form.visitHealthGuideList'
>
<div
class=
'no-req-label'
v-if=
"item.name != '无'"
>
{{
item
.
name
}}
</div>
...
...
src/doctor/utils/common.less
0 → 100644
View file @
0f6d77b6
:deep(.doc-tabs) {
border-bottom: 1px solid #EBEBEC;
.van-tab {
font-weight: 500;
}
.van-tabs__line {
border-radius: 0;
border-top-left-radius: 10px;
border-top-right-radius: 10px;
}
}
// 顶部导航栏
.doc-nav-bar {
position: relative;
border-bottom: 1px solid #3C3C435C;
font-size: 18px;
font-weight: 600;
.back-bt {
position: absolute;
left: .16rem;
top: 50%;
transform: translateY(-50%);
}
}
// 折叠面板
:deep(.doc-collapse) {
margin-top: .1rem;
&::after {
display: none;
}
.van-cell {
padding: .1rem 0;
color: #8C8C8C;
font-weight: 600;
background: transparent;
&::after {
display: none;
}
.svg-icon {
font-size: .12rem;
transition: all .2s;
}
}
.van-collapse-item {
.van-collapse-item__content {
padding: 0;
color: #262626;
}
&::after {
display: none;
}
}
// 展开
.van-collapse-item__title--expanded {
.svg-icon {
transform: rotate(-180deg);
}
}
}
\ No newline at end of file
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