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
3b4e440d
Commit
3b4e440d
authored
Mar 05, 2025
by
songrui
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
随访详情
parent
8e6ad985
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
856 additions
and
4 deletions
+856
-4
atomic.less
src/assets/css/atomic.less
+2
-0
doc-down.svg
src/assets/icons/doc-down.svg
+3
-0
doc-pause.svg
src/assets/icons/doc-pause.svg
+5
-0
doc-play.svg
src/assets/icons/doc-play.svg
+3
-0
video-default.png
src/assets/image/video-default.png
+0
-0
DocAddress.vue
src/components/docAddress/DocAddress.vue
+0
-0
DocImage.vue
src/components/docImage/DocImage.vue
+157
-0
DocNavBar.vue
src/components/docNavBar/DocNavBar.vue
+62
-0
ImagePreview.vue
src/components/imagePreview/ImagePreview.vue
+67
-0
Mp3.vue
src/components/mediaPlay/Mp3.vue
+154
-0
Mp4.vue
src/components/mediaPlay/Mp4.vue
+129
-0
mp3.js
src/components/mediaPlay/mp3.js
+146
-0
register.js
src/register.js
+26
-0
index.js
src/router/index.js
+6
-1
Tumour.vue
src/tumour/Tumour.vue
+12
-0
visit.js
src/tumour/api/visit.js
+6
-0
base.vue
src/tumour/screening/simpleV2/form/base.vue
+1
-1
index.js
src/tumour/store/index.js
+6
-1
Detail.vue
src/tumour/visit/detail/Detail.vue
+0
-0
common.js
src/utils/common.js
+70
-0
vue.config.js
vue.config.js
+1
-1
No files found.
src/assets/css/atomic.less
View file @
3b4e440d
...
@@ -78,7 +78,9 @@
...
@@ -78,7 +78,9 @@
// 字体大小
// 字体大小
.text-16 { font-size: 16px; }
.text-16 { font-size: 16px; }
.text-12 { font-size: 12px; }
.text-12 { font-size: 12px; }
.text-start { text-align: start; }
.text-center { text-align: center; }
.text-center { text-align: center; }
.text-end { text-align: end; }
.text-black { color: #000; }
.text-black { color: #000; }
.text-green { color: #52C41A; }
.text-green { color: #52C41A; }
.text-red { color: #FF4D4F; }
.text-red { color: #FF4D4F; }
...
...
src/assets/icons/doc-down.svg
0 → 100644
View file @
3b4e440d
<svg
width=
"10"
height=
"6"
viewBox=
"0 0 10 6"
xmlns=
"http://www.w3.org/2000/svg"
>
<path
d=
"M4.99999 3.78145L8.29999 0.481445L9.24266 1.42411L4.99999 5.66678L0.757324 1.42411L1.69999 0.481445L4.99999 3.78145Z"
/>
</svg>
src/assets/icons/doc-pause.svg
0 → 100644
View file @
3b4e440d
<svg
width=
"8"
height=
"9"
viewBox=
"0 0 8 9"
xmlns=
"http://www.w3.org/2000/svg"
>
<rect
x=
"0.158203"
y=
"0.900391"
width=
"2.68262"
height=
"7.70361"
rx=
"1"
/>
<rect
x=
"5.1582"
y=
"0.900391"
width=
"2.68262"
height=
"7.70361"
rx=
"1"
/>
</svg>
\ No newline at end of file
src/assets/icons/doc-play.svg
0 → 100644
View file @
3b4e440d
<svg
width=
"8"
height=
"9"
viewBox=
"0 0 8 9"
xmlns=
"http://www.w3.org/2000/svg"
>
<path
d=
"M6.6432 3.90404C7.26987 4.29571 7.26987 5.20837 6.6432 5.60004L1.53 8.79579C0.863951 9.21207 0 8.73323 0 7.94779V1.55629C0 0.770851 0.863951 0.292008 1.53 0.708288L6.6432 3.90404Z"
/>
</svg>
src/assets/image/video-default.png
0 → 100644
View file @
3b4e440d
6.67 KB
src/
tumour/util
s/docAddress/DocAddress.vue
→
src/
component
s/docAddress/DocAddress.vue
View file @
3b4e440d
File moved
src/components/docImage/DocImage.vue
0 → 100644
View file @
3b4e440d
<
template
>
<div
class=
"doc-image"
>
<div
v-if=
"isPdf"
class=
"p-2 flex items-center view-pdf"
>
<doc-icon
type=
"doc-PDF"
style=
"font-size: .48rem"
class=
"shrink-0"
/>
<span
class=
"grow px-4 text-ellipsis"
>
{{
name
}}
</span>
<span
class=
"close-btn"
@
click
.
stop=
"removeBtn"
v-if=
"remove"
>
<doc-icon
type=
"close-circle"
/>
</span>
</div>
<div
class=
"view-img"
v-if=
"status==='success' && !isPdf"
>
<img
:src=
"src"
:alt=
"name"
:loading=
"loading"
>
</div>
<template
v-if=
"!isPdf"
>
<div
class=
"doc-image-wrapper"
v-if=
"status==='loading'"
>
<slot
name=
"placeholder"
>
<div
class=
"doc-image-default"
>
加载中...
</div>
</slot>
</div>
<div
class=
"doc-image-wrapper"
v-if=
"status==='fail'"
>
<slot
name=
"fail"
>
<div
class=
"doc-image-default"
>
加载失败
</div>
</slot>
</div>
<span
class=
"close-btn"
@
click
.
stop=
"removeBtn"
v-if=
"remove"
>
<doc-icon
type=
"close-circle"
/>
</span>
</
template
>
</div>
</template>
<
script
>
export
default
{
name
:
'doc-image'
,
props
:
{
src
:
String
,
// 浏览器应当如何加载该图像
// img标签中的属性 需要浏览器支持
// https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/img
// eager 立即加载图像
// lazy 延迟加载图像,直到它和视口接近到一个计算得到的距离
loading
:
String
,
// 开启删除功能
remove
:
Boolean
,
// 处理pdf预览
isPdf
:
Boolean
,
name
:
String
},
emits
:
[
'removeBtn'
],
data
()
{
return
{
// 图片加载状态 loading | fail | success
status
:
'loading'
,
imgStyle
:
{},
// viewer显示
visible
:
false
,
// 按键界面显示
btVisible
:
false
}
},
methods
:
{
loadImage
()
{
if
(
this
.
isPdf
)
{
this
.
status
=
'success'
return
}
const
image
=
new
Image
()
image
.
onload
=
()
=>
{
this
.
show
=
true
this
.
status
=
'success'
}
image
.
onerror
=
(
err
)
=>
{
console
.
warn
(
'doc-image'
,
err
)
this
.
show
=
false
this
.
status
=
'fail'
}
this
.
status
=
'loading'
image
.
src
=
this
.
src
},
removeBtn
()
{
this
.
btVisible
=
false
this
.
$emit
(
'onRemove'
,
this
.
src
)
}
},
watch
:
{
src
:
{
handler
(
val
)
{
if
(
val
)
{
this
.
loadImage
()
}
},
immediate
:
true
}
}
}
</
script
>
<
style
lang=
"less"
scoped
>
.doc-image {
display: inline-block;
width: 100%;
height: 100%;
position: relative;
.view-img {
width: 100%;
height: 100%;
min-height: 90px;
// border: 1px dashed #d9d9d9;
// background: #fafafa;
background: #EFF2F7;
img {
width: 100%;
height: 90px;
object-fit: contain;
}
}
.view-pdf {
width: 100%;
min-height: 48px;
overflow-y: hidden;
border-radius: 8px;
border: 1px solid #EEEEEE;
.close-btn {
top: 50%;
right: 8px;
transform: translateY(-50%);
}
}
.close-btn {
position: absolute;
font-size: 16px;
top: -8px;
right: -8px;
}
}
.doc-image-wrapper {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.doc-image-default {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
font-size: 14px;
background: #f5faf7;
color: #a8abb2;
vertical-align: middle;
user-select: none;
}
</
style
>
src/components/docNavBar/DocNavBar.vue
0 → 100644
View file @
3b4e440d
<
template
>
<div
class=
"px-3 py-3 flex items-center doc-nav-bar"
>
<div
class=
"shrink-0 left"
>
<slot
name=
"left"
>
<span
class=
"back-btn"
@
click=
"goBack"
v-if=
"!hideBack"
>
<doc-icon
type=
"doc-left"
style=
"color: #262626"
/>
</span>
</slot>
</div>
<div
class=
"grow text-center font-semibold title"
>
<slot>
{{
title
}}
</slot>
</div>
<div
class=
"shrink-0 right"
>
<slot
name=
"right"
></slot>
</div>
</div>
</
template
>
<
script
>
import
{
backHome
}
from
'@/utils/common.js'
export
default
{
name
:
'DocNavBar'
,
props
:
{
title
:
String
,
// 是否首页
home
:
Boolean
,
// 替换返回函数
backFunc
:
Function
,
// 隐藏返回按键
hideBack
:
Boolean
},
methods
:
{
goBack
()
{
if
(
this
.
backFunc
)
{
this
.
backFunc
()
return
}
if
(
this
.
home
)
{
backHome
()
return
}
this
.
$router
.
back
()
}
}
}
</
script
>
<
style
lang=
"less"
scoped
>
.doc-nav-bar {
background: transparent;
border-bottom: 1px solid #00000019;
.left {
min-width: 24px;
}
.title {
font-size: 16px;
}
}
</
style
>
src/components/imagePreview/ImagePreview.vue
0 → 100644
View file @
3b4e440d
<
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)'
class=
"flex gap-x-2.5"
>
<!--
<img
:style=
"
{width: imgSize.width, height: imgSize.height}" :src="url.trueDownloadUrl" /> -->
<DocImage
:style=
"
{width: imgSize.width, height: imgSize.height}" :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
>
import
DocImage
from
'../docImage/DocImage.vue'
export
default
{
name
:
'ImagePreview'
,
components
:
{
DocImage
},
props
:
{
imgList
:
Array
,
imgSize
:
{
default
:
()
=>
{
return
{
width
:
'.97rem'
,
height
:
'.97rem'
}
}}
},
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/components/mediaPlay/Mp3.vue
0 → 100644
View file @
3b4e440d
<
template
>
<div
class=
"p-1 flex flex-col mp3"
>
<div
v-if=
"file.annexName"
class=
"text-12 mb-1 text-ellipsis"
>
{{
file
.
annexName
}}
</div>
<div
class=
"flex items-center justify-between gap-x-2.5"
>
<div
class=
"shrink-0 play-bt"
@
click
.
stop=
"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>
<span
class=
"text-16 shrink-0 close-btn"
@
click
.
stop=
"removeBtn"
v-if=
"remove"
>
<doc-icon
type=
"close-circle"
/>
</span>
</div>
<audio
ref=
"audio"
type=
"audio/mpeg"
crossOrigin=
"anonymous"
preload=
"metadata"
style=
"display: none"
></audio>
</div>
</
template
>
<
script
>
import
{
musicPlayer
}
from
'./mp3.js'
import
{
showToast
}
from
'vant'
import
{
useStore
}
from
'@/tumour/store/index.js'
export
default
{
props
:
{
file
:
{
default
:
()
=>
({})
},
activeMediaUrl
:
{
default
:
''
},
remove
:
Boolean
},
emits
:
[
'play'
,
'onRemove'
],
data
()
{
return
{
store
:
useStore
(),
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.duration'
,
this
.
player
.
audioEl
.
duration
)
}
console
.
log
(
'this.player'
,
this
.
player
)
},
stop
()
{
this
.
player
.
audioEl
.
pause
()
this
.
player
.
playing
=
false
},
timeFormat
(
value
)
{
if
(
!
value
||
value
==
Infinity
)
{
return
'00:00'
}
let
date
=
Math
.
ceil
(
parseFloat
(
value
))
let
minutes
=
Math
.
floor
(
date
/
60
)
let
seconds
=
date
%
60
let
format
=
`
${
minutes
>=
10
?
minutes
:
'0'
+
minutes
.
toString
()}
:
${
seconds
>=
10
?
seconds
:
'0'
+
seconds
.
toString
()}
`
return
format
},
onProgress
(
value
)
{
this
.
player
.
progressChange
(
value
)
this
.
player
.
playing
=
true
},
removeBtn
()
{
this
.
$emit
(
'onRemove'
,
this
.
file
)
}
},
watch
:
{
activeMediaUrl
(
val
)
{
if
(
val
!==
this
.
file
.
annexUrl
)
{
this
.
stop
()
}
},
'store.documentHidden'
:
{
handler
(
val
)
{
if
(
val
&&
this
.
activeMediaUrl
==
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/components/mediaPlay/Mp4.vue
0 → 100644
View file @
3b4e440d
<
template
>
<div
class=
"mp4"
>
<div
class=
"flex flex-wrap justify-between video-list"
>
<div
v-for=
"item in files"
:key=
"item.annexId"
@
click
.
stop=
"start(item)"
>
<div
class=
"item"
>
<div
class=
"shrink-0 play-bt"
>
<doc-icon
type=
"doc-play"
/>
</div>
<span
class=
"close-btn"
@
click
.
stop=
"removeBtn(item)"
v-if=
"remove"
>
<doc-icon
type=
"close-circle"
/>
</span>
</div>
<div
v-if=
"item.annexName"
class=
"text-12 my-1 text-ellipsis"
>
{{
item
.
annexName
}}
</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"
ref=
"video"
>
<source
:src=
"activeVideo.annexUrl"
type=
"video/mp4"
/>
播放失败!
</video>
<van-icon
name=
"close"
class=
"close-icon"
@
click=
"visible = false"
/>
</div>
</van-overlay>
</div>
</
template
>
<
script
>
import
{
useStore
}
from
'@/tumour/store/index.js'
export
default
{
props
:
{
files
:
{
default
:
()
=>
[]
},
activeMediaUrl
:
{
default
:
''
},
remove
:
Boolean
},
emits
:
[
'play'
,
'onRemove'
],
data
()
{
return
{
visible
:
false
,
activeVideo
:
{},
store
:
useStore
()
}
},
methods
:
{
start
(
item
)
{
this
.
activeVideo
=
item
this
.
visible
=
true
this
.
$emit
(
'play'
,
item
)
},
removeBtn
(
item
)
{
this
.
$emit
(
'onRemove'
,
item
)
}
},
watch
:
{
activeMediaUrl
(
val
)
{
if
(
val
!==
this
.
activeVideo
.
annexUrl
)
{
const
dom
=
this
.
$refs
.
video
dom
&&
dom
.
pause
()
}
},
'store.documentHidden'
:
{
handler
(
val
)
{
if
(
val
&&
this
.
activeMediaUrl
==
this
.
activeVideo
.
annexUrl
)
{
const
dom
=
this
.
$refs
.
video
dom
&&
dom
.
pause
()
}
}
}
}
}
</
script
>
<
style
lang=
"less"
scoped
>
.video-list {
>div {
width: calc(50% - 5px);
.item {
position: relative;
background: url('@/assets/image/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;
color: var(--van-primary-color);
}
.close-btn {
position: absolute;
font-size: 16px;
top: -8px;
right: -8px;
}
}
.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/components/mediaPlay/mp3.js
0 → 100644
View file @
3b4e440d
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
this
.
audioEl
.
load
()
}
// 调整进度
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/register.js
View file @
3b4e440d
...
@@ -14,4 +14,30 @@ dayjs.locale('cn')
...
@@ -14,4 +14,30 @@ dayjs.locale('cn')
export
function
registe
(
app
)
{
export
function
registe
(
app
)
{
// 自定义组件
// 自定义组件
app
.
use
(
DocIcon
)
app
.
use
(
DocIcon
)
app
.
config
.
globalProperties
.
$idCardHide
=
idCardHide
app
.
config
.
globalProperties
.
$phoneHide
=
phoneHide
app
.
config
.
globalProperties
.
$addrJoin
=
addrJoin
}
// idCard 脱敏
function
idCardHide
(
idCard
)
{
if
(
!
idCard
||
idCard
.
length
<
18
)
{
return
idCard
}
return
idCard
.
substring
(
0
,
6
)
+
'******'
+
idCard
.
substring
(
14
)
}
// phone 脱敏
function
phoneHide
(
phone
)
{
if
(
!
phone
||
phone
.
length
<
11
)
{
return
phone
}
return
phone
.
substring
(
0
,
3
)
+
'******'
+
phone
.
substring
(
9
)
}
// 地址拼接显示
function
addrJoin
(
str1
=
''
,
str2
=
''
)
{
if
(
!
str1
&&
!
str2
)
return
'-'
return
(
str1
??
''
)
+
(
str2
??
''
)
}
}
src/router/index.js
View file @
3b4e440d
...
@@ -9,7 +9,12 @@ const routes = [
...
@@ -9,7 +9,12 @@ const routes = [
{
{
path
:
'screening/simple/form'
,
path
:
'screening/simple/form'
,
name
:
'tumour-screening-simple-form'
,
name
:
'tumour-screening-simple-form'
,
component
:
()
=>
import
(
/* webpackChunkName: "page-tumour" */
'@/tumour/screening/simpleV2/form/Index.vue'
)
component
:
()
=>
import
(
/* webpackChunkName: "page-tumour-screening" */
'@/tumour/screening/simpleV2/form/Index.vue'
)
},
{
path
:
'visit/detail'
,
name
:
'tumour-visit-detail'
,
component
:
()
=>
import
(
/* webpackChunkName: "page-tumour-visit" */
'@/tumour/visit/detail/Detail.vue'
)
}
}
]
]
}
}
...
...
src/tumour/Tumour.vue
View file @
3b4e440d
...
@@ -15,6 +15,8 @@ import { useStore } from './store/index.js'
...
@@ -15,6 +15,8 @@ import { useStore } from './store/index.js'
export
default
{
export
default
{
created
()
{
created
()
{
this
.
init
()
this
.
init
()
// 监听页面是否隐藏
document
.
addEventListener
(
'visibilitychange'
,
this
.
visibilitychange
)
},
},
setup
()
{
setup
()
{
const
store
=
useStore
()
const
store
=
useStore
()
...
@@ -25,7 +27,17 @@ export default {
...
@@ -25,7 +27,17 @@ export default {
getDict
().
then
(
res
=>
{
getDict
().
then
(
res
=>
{
this
.
store
.
$patch
({
dict
:
res
.
data
})
this
.
store
.
$patch
({
dict
:
res
.
data
})
})
})
},
visibilitychange
()
{
if
(
document
.
hidden
)
{
this
.
store
.
onDocumentHidden
(
true
)
}
else
{
this
.
store
.
onDocumentHidden
(
false
)
}
}
}
},
beforeUnmount
()
{
document
.
removeEventListener
(
'visibilitychange'
,
this
.
visibilitychange
)
}
}
}
}
</
script
>
</
script
>
...
...
src/tumour/api/visit.js
0 → 100644
View file @
3b4e440d
import
{
fetchBase
}
from
'@/utils/fetch.js'
// 简易筛查 新增
export
function
getVisitById
(
id
,
loading
=
true
)
{
return
fetchBase
({
url
:
`/tumour-admin/v1/h5-app/visit-details/
${
id
}
`
,
loading
})
}
src/tumour/screening/simpleV2/form/base.vue
View file @
3b4e440d
...
@@ -194,7 +194,7 @@ import { useStore } from '@/tumour/store/index.js'
...
@@ -194,7 +194,7 @@ import { useStore } from '@/tumour/store/index.js'
import
{
getResidentInfo
}
from
'@/tumour/api/base.js'
import
{
getResidentInfo
}
from
'@/tumour/api/base.js'
import
{
getDictValue
}
from
'@/tumour/utils/dictionaries.js'
import
{
getDictValue
}
from
'@/tumour/utils/dictionaries.js'
import
{
showToast
}
from
'vant'
import
{
showToast
}
from
'vant'
import
DocAddress
from
'@/
tumour/util
s/docAddress/DocAddress.vue'
import
DocAddress
from
'@/
component
s/docAddress/DocAddress.vue'
const
defaultForm
=
(
info
=
{})
=>
{
const
defaultForm
=
(
info
=
{})
=>
{
const
form
=
{
const
form
=
{
...
...
src/tumour/store/index.js
View file @
3b4e440d
...
@@ -4,7 +4,9 @@ export const useStore = defineStore('tumour', {
...
@@ -4,7 +4,9 @@ export const useStore = defineStore('tumour', {
state
:
()
=>
{
state
:
()
=>
{
return
{
return
{
// 字典
// 字典
dict
:
[]
dict
:
[],
// 页面是否处于隐藏状态
documentHidden
:
false
}
}
},
},
getters
:
{},
getters
:
{},
...
@@ -12,6 +14,9 @@ export const useStore = defineStore('tumour', {
...
@@ -12,6 +14,9 @@ export const useStore = defineStore('tumour', {
getDict
(
val
)
{
getDict
(
val
)
{
if
(
!
val
)
return
[]
if
(
!
val
)
return
[]
return
this
.
dict
[
val
]
||
[]
return
this
.
dict
[
val
]
||
[]
},
onDocumentHidden
(
value
)
{
this
.
documentHidden
=
value
}
}
}
}
})
})
src/tumour/visit/detail/Detail.vue
0 → 100644
View file @
3b4e440d
This diff is collapsed.
Click to expand it.
src/utils/common.js
View file @
3b4e440d
...
@@ -87,3 +87,72 @@ export function getInfoByIdCard(idCard) {
...
@@ -87,3 +87,72 @@ export function getInfoByIdCard(idCard) {
age
age
}
}
}
}
//原生方法调用 当前方法传参数两种 字符串或者map
export
function
callMobile
(
handlerInterface
,
parameters
)
{
let
classStr
=
Object
.
prototype
.
toString
.
call
(
parameters
);
if
(
classStr
===
'[object String]'
||
classStr
===
'[object Object]'
)
{
let
param
=
parameters
;
if
(
classStr
===
"[object Object]"
)
{
//判断传参是str ,还是object
//handlerInterface由iOS addScriptMessageHandler与andorid addJavascriptInterface 代码注入而来。
param
=
JSON
.
stringify
(
parameters
);
//参数必须转化成json格式
}
try
{
if
(
isIOSWebKit
())
{
//ios
if
(
window
.
webkit
!==
undefined
)
{
if
(
param
==
'{}'
)
{
window
.
webkit
.
messageHandlers
[
handlerInterface
].
postMessage
(
null
);
}
else
{
window
.
webkit
.
messageHandlers
[
handlerInterface
].
postMessage
(
param
);
}
}
}
else
if
(
isAndroid
())
{
//安卓传输不了js json对象,只能传输string
if
(
param
==
'{}'
)
{
window
[
'function'
][
handlerInterface
]();
}
else
{
window
[
'function'
][
handlerInterface
](
param
);
}
}
}
catch
(
e
)
{
}
}
}
// 判断是否是ios
export
function
isIOSWebKit
()
{
const
aa
=
window
.
navigator
.
userAgent
;
if
(
!!
aa
.
match
(
/
\(
i
[^
;
]
+;
(
U;
)?
CPU.+Mac OS X/
))
{
// ios端
return
true
;
}
}
// 判断是否安卓
export
function
isAndroid
()
{
const
aa
=
window
.
navigator
.
userAgent
;
if
(
aa
.
indexOf
(
'Android'
)
!==
-
1
||
aa
.
indexOf
(
'Adr'
)
!==
-
1
)
{
return
true
}
}
// 判断是否在微信中
export
function
isWeiXin
()
{
const
ua
=
window
.
navigator
.
userAgent
.
toLowerCase
()
return
/micromessenger/
.
test
(
ua
)
}
//关闭页面
export
function
backHome
()
{
if
(
isIOSWebKit
())
{
//ios
console
.
log
(
'ios'
)
callMobile
(
"onBack"
,
{})
}
else
if
(
isAndroid
())
{
console
.
log
(
'Android'
)
callMobile
(
"closePage"
,
{})
}
if
(
isWeiXin
())
{
// 微信中
console
.
log
(
'weixin'
)
WeixinJSBridge
.
call
(
'closeWindow'
)
}
}
\ No newline at end of file
vue.config.js
View file @
3b4e440d
...
@@ -22,7 +22,7 @@ module.exports = defineConfig({
...
@@ -22,7 +22,7 @@ module.exports = defineConfig({
// 设置代理
// 设置代理
proxy
:
{
proxy
:
{
'/tumour-admin'
:
{
'/tumour-admin'
:
{
target
:
'http://192.168.1.1
18
:8081'
,
target
:
'http://192.168.1.1
74
:8081'
,
// target: 'https://beta-tumour.zmnyjk.com',
// target: 'https://beta-tumour.zmnyjk.com',
changOrigin
:
true
,
changOrigin
:
true
,
pathRewrite
:
{
pathRewrite
:
{
...
...
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