Commit c50e0a88 authored by gengchunlei's avatar gengchunlei

Merge branch 'chronic-dev' into chronic-master

parents 1485572f 616fb46f
...@@ -7,6 +7,7 @@ module.exports = { ...@@ -7,6 +7,7 @@ module.exports = {
'postcss-pxtorem': { 'postcss-pxtorem': {
rootValue: 100, rootValue: 100,
propList: ['*'], propList: ['*'],
minPixelValue: 2,
} }
} }
} }
\ No newline at end of file
...@@ -6,6 +6,7 @@ export function getDict() { ...@@ -6,6 +6,7 @@ export function getDict() {
return fetchBase({ url: `/tumour-admin/v1/h5-app/dict`, loading: true }) return fetchBase({ url: `/tumour-admin/v1/h5-app/dict`, loading: true })
} }
// 区划编码查询下级 // 区划编码查询下级
export function getAreaChild(parentCode, loading = true) { export function getAreaChild(parentCode, loading = true) {
const key = 'chronic-area-cache' const key = 'chronic-area-cache'
...@@ -33,4 +34,21 @@ export function getResidentInfo(idCard) { ...@@ -33,4 +34,21 @@ export function getResidentInfo(idCard) {
// 居民idCard或者tel查询居民信息 // 居民idCard或者tel查询居民信息
export function getResidentByInfo(params) { export function getResidentByInfo(params) {
return fetchBase({ url: `/chronic-resident/v1/chronic-residents-record/query-resident-info-by-id-card`, body: params, loading: true }) return fetchBase({ url: `/chronic-resident/v1/chronic-residents-record/query-resident-info-by-id-card`, body: params, loading: true })
} }
\ No newline at end of file
// 文件上传
export function fileUpload(params) {
return fetchBase({ url: `/chronic-admin/v1/pictures-info/qiniu`, body: params, contentType: 'file' })
}
// 获取字典管理数据
export function getTemplateList() {
return fetchBase({ url: `/tumour-admin/v1/h5-app/dict`, loading: true })
}
//字典数据主键查询
export function getTemplateById() {
return fetchBase({ url: `/tumour-admin/v1/h5-app/dict`, loading: true })
}
import {fetchBase} from '@/api/doctor/doctorFetch'
//列表查询 疾病信息相关 诊断列表、治疗方案、随访方案
export function fetchDiseaseTypeList(params, loading) {
return fetchBase({ url: `/chronic-admin/v1/chronic-diagnose-record/manage-record`, body: params, loading })
}
// 查询随访列表
export function getVisitManageList(params, loading) {
return fetchBase({ url: `/chronic-admin/v1/chronic-visit-record/page`, body: params, loading })
}
\ No newline at end of file
...@@ -13,27 +13,27 @@ export function getChronicResidentsId(residentInfoId) { ...@@ -13,27 +13,27 @@ export function getChronicResidentsId(residentInfoId) {
loading: true loading: true
}) })
} }
//获取居民是否存在微信电话
export function getResidentWX(params) {
return fetchBase({ url: `/chronic-admin/v1/chronic-residents-record/query-resident-is-wx`, body: params, loading: true})
}
// 主键查询 // 主键查询
export function fetchCurrencyById(params) { export function fetchCurrencyById(params) {
return fetchBase({ url: `/chronic-admin/v1/chronic-visit-currency/record`, body: params, loading: true }) return fetchBase({ url: `/chronic-admin/v1/chronic-visit-currency/record`, body: params, loading: true })
} }
// 慢性病管理列表查询
export function getResidentByPage(params) {
return fetchBase({ url: `/chronic-admin/v1/chronic-residents-record/page`, body: params, loading: true })
}
// 查询待随访列表
export function getVisitAll(params, loading = true) {
return fetchBase({ url: `/chronic-admin/v1/chronic-visit-task/query-all-list`, body: params, loading })
}
// 根据单位名称模糊查询单位信息 // 根据单位名称模糊查询单位信息
export function getUnitByName(orgName) { export function getUnitByName(orgName) {
return fetchBase({ url: `/tumour-admin/v1/sys-user/org-by-name/${orgName}` }) return fetchBase({ url: `/tumour-admin/v1/sys-user/org-by-name/${orgName}` })
} }
// 拼音码查询药品信息
export function getDrug(code) {
return fetchBase({ url: `/tumour-admin/v1/remote-system/drugs/${code}` })
}
// 根据单位id查询科室 // 根据单位id查询科室
export function getOfficeList(unitId) { export function getOfficeList(unitId) {
return fetchBase({ url: `/tumour-admin/v1/sys-user/org-office/${unitId}` }) return fetchBase({ url: `/tumour-admin/v1/sys-user/org-office/${unitId}` })
...@@ -54,14 +54,14 @@ export function updateCurrency(params) { ...@@ -54,14 +54,14 @@ export function updateCurrency(params) {
return fetchBase({ url: `/chronic-admin/v1/chronic-visit-currency/update`, body: params, loading: true }) return fetchBase({ url: `/chronic-admin/v1/chronic-visit-currency/update`, body: params, loading: true })
} }
// 删除随访 // 列表查询
export function deleteVisit(params) { export function fetchCurrencyList(params, loading) {
return fetchBase({ url: `/chronic-admin/v1/chronic-visit-record/delete`, body:params, loading: true }) return fetchBase({ url: `/chronic-admin/v1/chronic-visit-currency/page`, body: params, loading })
} }
// 查询随访列表 //删除通用随访
export function queryVisitByPage(params, loading) { export function delCurrencyById(params) {
return fetchBase({ url: `/chronic-admin/v1/chronic-visit-record/page`, body: params, loading }) return fetchBase({ url: `/chronic-admin/v1/chronic-visit-currency/delete`, body: params, loading: true })
} }
...@@ -73,4 +73,9 @@ export function upLoadMultifile(params) { ...@@ -73,4 +73,9 @@ export function upLoadMultifile(params) {
loading: false, loading: false,
contentType: 'file' 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
...@@ -8,4 +8,34 @@ export function queryResidentInfo(params) { ...@@ -8,4 +8,34 @@ export function queryResidentInfo(params) {
//更新居民基本信息 //更新居民基本信息
export function updateResident(params) { export function updateResident(params) {
return fetchBase({ url: `/chronic-admin/v1/chronic-residents-record/update`, body: params, loading: true }) return fetchBase({ url: `/chronic-admin/v1/chronic-residents-record/update`, body: params, loading: true })
}
// 慢性病管理列表查询
export function getResidentByPage(params) {
return fetchBase({ url: `/chronic-admin/v1/chronic-residents-record/page`, body: params, loading: true })
}
//转诊列表查询
export function getReferralList(params, loading) {
return fetchBase({ url: `/chronic-admin/v1/base-info/referral-list`, body: params, loading })
}
// 会诊列表查询
export function getConsultationList(params, loading) {
return fetchBase({ url: `/chronic-admin/v1/base-info/consultation-list`, body: params, loading })
}
// 获取用户配置
export function getUserConfig() {
return fetchBase({ url: `/tumour-admin/v1/sys-user-config/query-by-user`, loading: true })
}
// 添加个性化配置
export function addUserConfig(params, loading = true) {
return fetchBase({ url: `/tumour-admin/v1/sys-user-config/add-config`, body: params, loading })
}
// 修改个性化配置
export function updateUserConfig(params, loading = true) {
return fetchBase({ url: `/tumour-admin/v1/sys-user-config/update-config`, body: params, loading })
} }
\ No newline at end of file
import {fetchBase} from '@/api/doctor/doctorFetch'
//查初筛和复筛列表
export function getScreenAllList(residentInfoId, loading) {
return fetchBase({ url: `/chronic-admin/v1/chronic-screening-record/screen-list`,body:{residentInfoId},loading})
}
// 慢病高危筛查详情
export function firstScreenDetail(params) {
return fetchBase({ url: `/chronic-resident/v1/chronic-screening-record/screening-detail`, body: params, loading: true })
}
// 慢病专病筛查详情
export function secondScreenDetail(params) {
return fetchBase({ url: `/chronic-resident/v1/chronic-screening-record/rescreen-detail`, body: params, loading: true })
}
\ No newline at end of file
import {fetchBase} from '@/api/doctor/doctorFetch'
//获取高危随访列表v1.2
export function getHighVisitList(params, loading) {
return fetchBase({ url: `/chronic-admin/v1/chronic-high-visit-collect/page`, body: params, loading})
}
\ No newline at end of file
import {fetchBase} from '@/api/doctor/doctorFetch'
// 查询最近工作记录
export function getWorkByPage(params, loading) {
return fetchBase({ url: `/chronic-admin/v1/chronic-workbench/lately-service`, body: params, loading })
}
// 查询待随访列表
export function getVisitByPage(params, loading) {
return fetchBase({ url: `/chronic-admin/v1/chronic-visit-task/page`, body: params, loading })
}
// 待随访列表忽略
export function delVisit(params) {
return fetchBase({ url: `/chronic-admin/v1/chronic-visit-task/delete`, body: params, loading: true })
}
// 模板 分页查询
export function getTemplateByPage(params) {
return fetchBase({ url: `/tumour-admin/v1/template/page`, body: params, loading: true })
}
// 模板 主键查询
export function getTemplateDetail(params, loading = true) {
return fetchBase({ url: `/tumour-admin/v1/template/query-id/${params.id}`, loading })
}
// 待接诊列表
export function getReceiveByPage(params) {
return fetchBase({ url: `/chronic-admin/v1/chronic-referral-task/page`, body: params })
}
// 待接诊列表 忽略
export function ignoreReceive(params) {
return fetchBase({ url: `/chronic-admin/v1/chronic-referral-task/update`, body: params, loading: true })
}
// 筛查高危记录表 初筛高危待复筛1 复筛高危待诊断2
export function getBeSecondScreenByPage(params) {
return fetchBase({ url: `/chronic-admin/v1/chronic-workbench/be-second-page`, body: params })
}
// 筛查高危记录表 初筛高危待复筛1 复筛高危待诊断2
export function getDiagnoseByPage(params) {
return fetchBase({ url: `/chronic-admin/v1/chronic-workbench/be-diagnose-page`, body: params })
}
// 待复筛和高危待诊断忽略
export function addIgnoreRecord(params) {
return fetchBase({ url: `/chronic-admin/v1/chronic-ignore-record/save`, body: params, loading: true })
}
...@@ -11,7 +11,7 @@ export function queryMajorFUDetail(params) { ...@@ -11,7 +11,7 @@ export function queryMajorFUDetail(params) {
//查询专病高危随访详情 //查询专病高危随访详情
export function querySpecificFUDetail(params) { export function querySpecificFUDetail(params) {
return fetchBase({ url: `/chronic-resident/v1/chronic-visit-record/high-major-detail`, body: params, loading: true }) return fetchBase({ url: `/chronic-resident/v1/chronic-visit-record/high-specific-detail`, body: params, loading: true })
} }
// 查询通用随访详情 // 查询通用随访详情
......
...@@ -75,6 +75,7 @@ ...@@ -75,6 +75,7 @@
.w-1\/3 { width: 33.3%; } .w-1\/3 { width: 33.3%; }
.w-1\/2 { width: 50%; } .w-1\/2 { width: 50%; }
.h-full { height: 100%; } .h-full { height: 100%; }
.min-h-0 { min-height: 0px; }
// 字体大小 // 字体大小
.text-16 { font-size: 16px; } .text-16 { font-size: 16px; }
......
...@@ -27,6 +27,34 @@ body { ...@@ -27,6 +27,34 @@ body {
opacity: 0; opacity: 0;
} }
// 下拉框 消失隐藏动画
.viewer-fade-enter-active {
animation: viewer-fade-in .3s;
}
.viewer-fade-leave-active {
animation: viewer-fade-out .2s;
}
@keyframes viewer-fade-in {
0% {
transform: translate3d(0, -20px, 0);
opacity: 0;
}
100% {
transform: translate3d(0, 0, 0);
opacity: 1;
}
}
@keyframes viewer-fade-out {
0% {
transform: translate3d(0, 0, 0);
opacity: 1;
}
100% {
transform: translate3d(0, -20px, 0);
opacity: 0;
}
}
*, :after, :before { *, :after, :before {
box-sizing: border-box; box-sizing: border-box;
} }
......
<svg width="19" height="19" viewBox="0 0 19 19" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.6675 9.27291C11.6675 10.5326 10.6465 11.5536 9.38677 11.5536C8.12707 11.5536 7.10571 10.5326 7.10571 9.27291C7.10571 8.01321 8.12707 6.99219 9.38677 6.99219C10.6465 6.99219 11.6675 8.01321 11.6675 9.27291Z" stroke="currentColor" stroke-width="1.2"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M16.7508 8.14H14.9998C14.9913 8.14 14.9835 8.09478 14.975 8.09512C14.8285 7.42362 14.5629 6.77388 14.2032 6.21356C14.21 6.2071 14.2175 6.19112 14.2243 6.18466L15.4622 4.94026C15.8264 4.57612 15.8264 3.98282 15.4622 3.61868L15.0444 3.19912C14.6802 2.83498 14.0897 2.8343 13.7255 3.19844L12.4872 4.43604C12.4808 4.44284 12.4764 4.45032 12.4702 4.45678C11.9096 4.0974 11.2364 3.83152 10.5649 3.68498C10.5652 3.67648 10.52 3.66866 10.52 3.66016V1.90916C10.52 1.39406 10.1973 1 9.68224 1H9.09098C8.57588 1 8.14 1.39406 8.14 1.90916V3.66016C8.14 3.66866 8.15156 3.67648 8.1519 3.68498C7.4804 3.83152 6.85888 4.09706 6.29856 4.45678C6.2921 4.44998 6.29006 4.4425 6.2836 4.4357L5.04668 3.19776C4.68254 2.83362 4.09264 2.83362 3.7285 3.19776L3.31064 3.61562C2.9465 3.97976 2.9465 4.57034 3.31098 4.93448L4.54892 6.17276C4.55572 6.17922 4.56354 6.1833 4.57 6.18976C4.21028 6.75042 3.94474 7.42362 3.7982 8.09512C3.7897 8.09478 3.78188 8.14 3.77338 8.14H2.02238C1.50728 8.14 1 8.46266 1 8.97776V9.56902C1 10.0838 1.50728 10.52 2.02238 10.52H3.77338C3.78188 10.52 3.7897 10.5084 3.7982 10.5081C3.94474 11.1796 4.21028 11.8011 4.57 12.3614C4.56354 12.3679 4.55572 12.3699 4.54926 12.3764L3.31098 13.6133C2.94684 13.9775 2.94684 14.5674 3.31098 14.9315L3.72884 15.3494C4.09332 15.7135 4.68356 15.7135 5.0477 15.349L6.28598 14.1107C6.29244 14.1043 6.29686 14.0965 6.30298 14.09C6.86364 14.4497 7.4804 14.7153 8.1519 14.8618C8.15156 14.8703 8.14 14.8781 8.14 14.8866V16.6376C8.14 17.1527 8.57588 17.66 9.09098 17.66H9.68224C10.1973 17.66 10.52 17.1527 10.52 16.6376V14.8866C10.52 14.8781 10.5652 14.8703 10.5649 14.8618C11.2364 14.7153 11.8858 14.4497 12.4464 14.09C12.4529 14.0965 12.4689 14.1043 12.4753 14.1107L13.7197 15.349C14.0839 15.7132 14.6772 15.7132 15.0413 15.349L15.4609 14.9312C15.825 14.5667 15.8257 13.9764 15.4616 13.6123L14.224 12.374C14.2172 12.3676 14.2097 12.3631 14.2029 12.357C14.5626 11.7964 14.8285 11.1796 14.975 10.5081C14.9835 10.5084 14.9913 10.52 14.9998 10.52H16.7508C17.2659 10.52 17.66 10.0838 17.66 9.56902V8.97776C17.66 8.46266 17.2659 8.14 16.7508 8.14Z" stroke="currentColor" stroke-width="1.2"/>
</svg>
<svg width="14" height="15" viewBox="0 0 14 15" xmlns="http://www.w3.org/2000/svg">
<path d="M1.75 12.7496H2.8105L9.796 5.76407L8.7355 4.70357L1.75 11.6891V12.7496ZM13.75 14.2496H0.25V11.0673L10.3263 0.991074C10.4669 0.850471 10.6576 0.771484 10.8565 0.771484C11.0554 0.771484 11.2461 0.850471 11.3868 0.991074L13.5085 3.11282C13.6491 3.25347 13.7281 3.4442 13.7281 3.64307C13.7281 3.84195 13.6491 4.03268 13.5085 4.17332L4.93225 12.7496H13.75V14.2496ZM9.796 3.64307L10.8565 4.70357L11.917 3.64307L10.8565 2.58257L9.796 3.64307Z"/>
</svg>
<svg width="9" height="15" viewBox="0 0 9 15" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg width="9" height="15" viewBox="0 0 9 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7.5 13.689L1.5 7.68896L7.5 1.68896" stroke="#262626" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/> <path d="M7.5 13.689L1.5 7.68896L7.5 1.68896" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/>
</svg> </svg>
<svg width="18" height="16" viewBox="0 0 18 16" xmlns="http://www.w3.org/2000/svg">
<path d="M0 0H18V2H0V0ZM0 7H18V9H0V7ZM0 14H18V16H0V14Z"/>
</svg>
<svg width="18" height="18" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
<path d="M12 0H18V5H16V2H12V0ZM6 0V2H2V5H0V0H6ZM12 18V16H16V13H18V18H12ZM6 18H0V13H2V16H6V18ZM0 8H18V10H0V8Z"/>
</svg>
<svg width="8" height="9" viewBox="0 0 8 9" fill="none" xmlns="http://www.w3.org/2000/svg"> <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" fill="#5FC3B7"/> <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> </svg>
<template> <template>
<van-config-provider :theme-vars='themeVars' class="h-full"> <van-config-provider :theme-vars='themeVars' style="height: 100vh">
<div class='h-full resident-home'> <div class='h-full resident-home'>
<router-view v-slot='{ Component }'> <router-view v-slot='{ Component, route }'>
<Transition name='route' mode='out-in'> <Transition name='route' mode='out-in'>
<component :is='Component' v-if='visible' /> <KeepAlive :include="['Workbench', 'PatientDetail']">
<component :is='Component' :key="route.name" v-if='visible' />
</KeepAlive>
</Transition> </Transition>
</router-view> </router-view>
</div> </div>
...@@ -35,7 +37,8 @@ export default { ...@@ -35,7 +37,8 @@ export default {
cellVerticalPadding: '.15rem', cellVerticalPadding: '.15rem',
cellTextColor: '#262626', cellTextColor: '#262626',
cellBorderColor: '#d9d9d9', cellBorderColor: '#d9d9d9',
navBarIconColor: '#262626' navBarIconColor: '#262626',
} }
} }
}, },
...@@ -45,6 +48,8 @@ export default { ...@@ -45,6 +48,8 @@ export default {
}, },
created() { created() {
this.init() this.init()
// 监听页面是否隐藏
document.addEventListener('visibilitychange', this.visibilitychange)
}, },
methods: { methods: {
async init() { async init() {
...@@ -52,7 +57,7 @@ export default { ...@@ -52,7 +57,7 @@ export default {
if (!token) { if (!token) {
token = sessionStorage.getItem('token') token = sessionStorage.getItem('token')
if (process.env.NODE_ENV !== 'production') { if (process.env.NODE_ENV !== 'production') {
token = '4ef7a32e-c217-44b6-ac5d-8ad9a91d38a0' token = '80fa0d29-73b2-4593-87b8-fc46b53bf49e'
} }
} }
if (token) { if (token) {
...@@ -61,17 +66,128 @@ export default { ...@@ -61,17 +66,128 @@ export default {
this.store.$patch({ dict: res.data || {} }) this.store.$patch({ dict: res.data || {} })
const user = await getAuthInfo() const user = await getAuthInfo()
this.store.$patch({authInfo: user.data || {}}) this.store.$patch({authInfo: user.data || {}})
this.visible = true this.visible = true
} else { } else {
backHome() backHome()
} }
},
visibilitychange() {
if (document.hidden) {
this.store.onDocumentHidden(true)
} else {
this.store.onDocumentHidden(false)
}
} }
},
beforeUnmount() {
document.removeEventListener('visibilitychange', this.visibilitychange)
} }
} }
</script> </script>
<style lang='less' scoped> <style lang='less'>
// 按钮样式
.doc-btn {
border: 0;
padding: 4px 12px;
height: 26px;
}
.doc-btn-primary {
.doc-btn();
color: var(--van-primary-color);
background: #F0F3FF;
}
.doc-btn-red {
.doc-btn();
color: #FF4D4F;
background: #FFF3F0;
}
// tab 样式
.doc-tab-round {
.van-tabs__nav--card {
column-gap: 10px;
border: 0;
margin: 0;
background: transparent;
}
.van-tab--card {
border: 0;
border-radius: 40px;
background: #fff;
color: #262626;
font-size: 14px;
line-height: 28px;
padding: 0 10px;
transition: all .2s;
}
.van-tab--card.van-tab--active {
color: #fff;
background: var(--van-primary-color);
font-weight: 500;
}
}
.doc-tab-round[line] {
.van-tab--card {
border: 1px solid #fff;
line-height: 1;
}
.van-tab--card.van-tab--active {
color: var(--van-primary-color);
border: 1px solid var(--van-primary-color);
background: #E6F0FF;
font-weight: 500;
}
}
// 底部细线
.bottom-small-line {
height: 1px;
box-shadow: 0 0.5Px #D7DADE;
}
// list列表中的card
.doc-list-card {
border-radius: 12px;
background-color: #fff;
.name {
font-size: 16px;
font-weight: 600;
}
.tag {
background: #F0F3FF;
padding: 4px 8px;
border-radius: 8px;
font-size: 12px;
line-height: 1;
}
.label {
display: inline-block;
color: #8C8C8C;
min-width: 104px;
}
.divider {
.bottom-small-line()
// border-bottom: 1px solid #D7DADE;
// transform: scaleY(.5);
// height: 1px;
// box-shadow: 0 0 0.5Px #e5e5e5;
}
.bt-group {
display: flex;
justify-content: flex-end;
column-gap: 10px;
}
}
// 输入框
.doc-input {
border-radius: 50px;
background-color: #FAFAFA !important;
padding: 5px 0 5px 12px !important;
&::after {
display: none;
}
}
</style> </style>
<template> <template>
<div> <div>
<van-nav-bar title='修改居民信息' left-text='' left-arrow <!-- <van-nav-bar title='修改居民信息' left-text='' left-arrow
@click-left='toBack'></van-nav-bar> @click-left='toBack'></van-nav-bar> -->
<DocNavBar title="修改居民信息" class="shrink-0"></DocNavBar>
<div class='p-4 h-overflow'> <div class='p-4 h-overflow'>
<van-form ref='form'> <van-form ref='form'>
<div class='title'>居民信息</div> <div class='title'>居民信息</div>
...@@ -14,14 +15,14 @@ ...@@ -14,14 +15,14 @@
class='input-back mt-2 form-input' class='input-back mt-2 form-input'
:rules='rules.certificateTypeName' :rules='rules.certificateTypeName'
/>--> />-->
<!-- <div class='label-title mt-5'>证件号码</div> <div class='label-title mt-5'>证件号码</div>
<van-field <van-field
v-model='form.idCard' v-model='form.idCard'
readonly readonly
placeholder='证件号码' placeholder='证件号码'
class='input-back mt-2 form-input' class='input-back mt-2 form-input'
:rules='rules.idCard' :rules='rules.idCard'
/>--> />
<div class='label-title mt-5'>姓名</div> <div class='label-title mt-5'>姓名</div>
<van-field <van-field
v-model='form.residentName' v-model='form.residentName'
...@@ -30,7 +31,7 @@ ...@@ -30,7 +31,7 @@
class='input-back mt-2 form-input' class='input-back mt-2 form-input'
:rules='rules.residentName' :rules='rules.residentName'
/> />
<!-- <div class='label-title mt-5'>性别</div> <div class='label-title mt-5'>性别</div>
<van-field <van-field
v-model='form.genderName' v-model='form.genderName'
is-link is-link
...@@ -38,8 +39,8 @@ ...@@ -38,8 +39,8 @@
placeholder='性别' placeholder='性别'
class='input-back mt-2 form-input' class='input-back mt-2 form-input'
:rules='rules.genderName' :rules='rules.genderName'
/>--> />
<!-- <div class='label-title mt-5'>出生日期</div> <div class='label-title mt-5'>出生日期</div>
<van-field <van-field
v-model='form.dataBirth' v-model='form.dataBirth'
is-link is-link
...@@ -47,7 +48,7 @@ ...@@ -47,7 +48,7 @@
placeholder='出生日期' placeholder='出生日期'
class='input-back mt-2 form-input' class='input-back mt-2 form-input'
:rules='rules.dataBirth' :rules='rules.dataBirth'
/>--> />
<div class='label-title mt-5'>本人电话</div> <div class='label-title mt-5'>本人电话</div>
<van-field <van-field
v-model='form.telephone' v-model='form.telephone'
...@@ -74,15 +75,14 @@ ...@@ -74,15 +75,14 @@
@cancel='showNational = false' @cancel='showNational = false'
/> />
</van-popup> </van-popup>
<!-- <div class='label-title mt-5'>年龄</div> <div class='label-title mt-5'>年龄</div>
<van-field <van-field
v-model='form.currentAge' v-model='form.currentAge'
readonly readonly
placeholder='年龄' placeholder='年龄'
class='input-back mt-2 form-input' class='input-back mt-2 form-input'
:rules='rules.currentAge' :rules='rules.currentAge'
/>--> />
<div class='label-title mt-5'>现住址</div> <div class='label-title mt-5'>现住址</div>
<van-field <van-field
...@@ -196,10 +196,10 @@ ...@@ -196,10 +196,10 @@
</template> </template>
<script> <script>
import { addToArr, fetchDataHandle } from '@/utils/common' import { addToArr } from '@/utils/common'
import { useStore } from '@/doctor/store' import { useStore } from '@/doctor/store'
import DocAddress from '@/components/docAddress/DocAddress' import DocAddress from '@/components/docAddress/DocAddress'
import dayjs from 'dayjs' import DocNavBar from '@/doctor/components/docNavBar/DocNavBar.vue'
import { getChronicResidentsId } from '@/api/doctor/generalFU' import { getChronicResidentsId } from '@/api/doctor/generalFU'
import { updateResident } from '@/api/doctor/resident' import { updateResident } from '@/api/doctor/resident'
...@@ -262,8 +262,27 @@ const defaultForm = (info = {}) => { ...@@ -262,8 +262,27 @@ const defaultForm = (info = {}) => {
// 与居民关系 // 与居民关系
relation: undefined, relation: undefined,
relationName: undefined, relationName: undefined,
relationOther: undefined relationOther: undefined,
// 人群 // 人群
chronicCrowd: undefined,
chronicTagsArray: undefined,
firstScreenDate: undefined,
firstScreenResult: undefined,
highTagsArray: undefined,
highTags: undefined,
latelyDiagnoseDate: undefined,
latelyScreenDate:undefined,
// 建档单位、科室、医生
createDoctorId: undefined,
createDoctorName: undefined,
createOfficeId: undefined,
createOfficeName: undefined,
createUnitId: undefined,
createUnitName: undefined,
// 当前人群-显示type=CP00181
groupsArrays: undefined,
// 当前人群-查询
groups: undefined,
} }
Reflect.ownKeys(form).forEach(key => { Reflect.ownKeys(form).forEach(key => {
if (info[key] != undefined) { if (info[key] != undefined) {
...@@ -274,7 +293,7 @@ const defaultForm = (info = {}) => { ...@@ -274,7 +293,7 @@ const defaultForm = (info = {}) => {
} }
export default { export default {
name: 'BaseInfo', name: 'BaseInfo',
components: { DocAddress }, components: { DocAddress, DocNavBar },
props: { props: {
info: { info: {
default: () => { default: () => {
...@@ -315,8 +334,8 @@ export default { ...@@ -315,8 +334,8 @@ export default {
authInfo() { authInfo() {
return this.store.$state.authInfo return this.store.$state.authInfo
}, },
routerDetail() { residentInfoId() {
return this.$route.query return this.$route.query.residentInfoId
} }
}, },
created() { created() {
...@@ -324,7 +343,7 @@ export default { ...@@ -324,7 +343,7 @@ export default {
}, },
methods: { methods: {
async load() { async load() {
const res = await getChronicResidentsId(this.routerDetail.residentInfoId) const res = await getChronicResidentsId(this.residentInfoId)
this.form = defaultForm(res.data) this.form = defaultForm(res.data)
if (this.form.presentCode) { if (this.form.presentCode) {
this.addressRecord.presentCode = addToArr(this.form.presentCode) this.addressRecord.presentCode = addToArr(this.form.presentCode)
...@@ -461,6 +480,7 @@ export default { ...@@ -461,6 +480,7 @@ export default {
:deep(.van-field__error-message) { :deep(.van-field__error-message) {
position: absolute; position: absolute;
margin-top: 3px;
} }
:deep(.van-cell:after) { :deep(.van-cell:after) {
......
...@@ -4,7 +4,9 @@ ...@@ -4,7 +4,9 @@
@click="onClick(item)" @click="onClick(item)"
:class="['py-2 px-3 shrink-0 check-btn-item', :class="['py-2 px-3 shrink-0 check-btn-item',
{ 'check-btn-item-active': isSelect(item) }, { 'check-btn-item-active': isSelect(item) },
{ 'check-btn-item-disabled': isDisabled(item) }]"> { 'check-btn-item-disabled': isDisabled(item) },
`text-align-${textAlign}`]"
>
{{ item[fieldNames.text] }} {{ item[fieldNames.text] }}
</div> </div>
</div> </div>
...@@ -20,11 +22,16 @@ export default { ...@@ -20,11 +22,16 @@ export default {
fieldNames: { fieldNames: {
type: Object, type: Object,
default: () => { default: () => {
return {text: 'name', value: 'code'} return {text: 'name', value: 'value'}
} }
}, },
// 点击取消选中 单选
clearable: { default: true },
// 是否多选 // 是否多选
multiple: Boolean multiple: Boolean,
textAlign: { default: 'center' },
// 关闭选中样式
activeStyleNone: Boolean
}, },
emits: ['update:value', 'change'], emits: ['update:value', 'change'],
data() { data() {
...@@ -49,20 +56,28 @@ export default { ...@@ -49,20 +56,28 @@ export default {
if (this.isDisabled(item)) { if (this.isDisabled(item)) {
return return
} }
const val = item[this.fieldNames.value]
if (this.multiple) { if (this.multiple) {
if (this.innerValue.includes(item[this.fieldNames.value])) { if (this.innerValue.includes(val)) {
this.innerValue = this.innerValue.filter(e => e !== item[this.fieldNames.value]) this.innerValue = this.innerValue.filter(e => e !== val)
} else { } else {
this.innerValue.push(item[this.fieldNames.value]) this.innerValue.push(val)
} }
} else { } else {
this.innerValue = item[this.fieldNames.value] if (this.clearable && this.innerValue === val) {
this.innerValue = undefined
} else {
this.innerValue = val
}
} }
this.$emit('update:value', this.innerValue) this.$emit('update:value', this.innerValue)
this.$emit('change', this.innerValue, item) this.$emit('change', this.innerValue, item)
}, },
// 是否选中 // 是否选中
isSelect(item){ isSelect(item){
if (this.activeStyleNone) {
return false
}
if (this.multiple) { if (this.multiple) {
return this.innerValue.includes(item[this.fieldNames.value]) return this.innerValue.includes(item[this.fieldNames.value])
} else { } else {
...@@ -86,25 +101,64 @@ export default { ...@@ -86,25 +101,64 @@ export default {
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.check-btn { .check-btn {
row-gap: 10px; row-gap: 10px;
column-gap: 10px; column-gap: 10px;
.check-btn-item {
border: 1px solid transparent;
background-color: #FAFAFA;
border-radius: 8px;
text-align: center;
transition: all .2s;
}
.check-btn-item-active {
border: 1px solid var(--van-primary-color);
background-color: #F0F6FF;
color: var(--van-primary-color);
}
.check-btn-item-disabled {
background-color: #F0F6FF;
color: var(--van-primary-color);
// opacity: 0.5;
filter: grayscale(1);
}
.text-align-left {
text-align: left;
}
.text-align-center {
text-align: center;
}
.text-align-right {
text-align: right;
}
} }
.check-btn-item {
border: 1px solid transparent; .check-btn.check-btn-workbench {
background-color: #FAFAFA; .check-btn-item {
border-radius: 8px; border-radius: 30px;
transition: all .2s; padding-top: 4px;
padding-bottom: 4px;
color: #595959;
}
.check-btn-item-active {
color: var(--van-primary-color);
}
} }
.check-btn-item-active {
border: 1px solid var(--van-primary-color); .check-btn[column-3] {
background-color: #F0F6FF; .check-btn-item {
color: var(--van-primary-color); width: calc(33.3% - 6.6px);
}
}
.check-btn[column-2] {
.check-btn-item {
width: calc(50% - 5px);
}
} }
.check-btn-item-disabled { .check-btn[column-1] {
background-color: #F0F6FF; .check-btn-item {
color: var(--van-primary-color); width: 100%;
// opacity: 0.5; }
filter: grayscale(1);
} }
</style> </style>
This diff is collapsed.
<template>
<div>
<van-field
v-model='innerValueName'
readonly
is-link
label='药品名称:'
placeholder='请选择'
class='input-back mt-2 form-input w-full'
:rules="[{required: true, message:'请选择'}]"
@click='showDrug= true'
/>
<van-popup v-model:show='showDrug' position='bottom'>
<div class='pb-4 pr-4 pl-4'>
<van-picker
:columns='array'
:columns-field-names='fieldNames'
@confirm='drugConfirm'
@cancel='showDrug = false'
>
<template #columns-top>
<van-search v-model="searchStr" :placeholder='placeholder' @search='onSearch' clearable/>
</template>
</van-picker>
</div>
</van-popup>
</div>
</template>
<script>
import { getDrug } from '@/api/doctor/generalFU'
import { debounce } from '@/utils/common'
export default {
name: 'DocDrug',
props: {
value: [String, Number],
valueName: String,
placeholder: String,
fieldNames: {
type: Object,
default: () => {
return { text: 'chemicalName', value: 'id' }
}
}
},
emits: ['update:value', 'change'],
data() {
return {
innerValue: null,
innerValueName: undefined,
array: [],
loading: false,
showDrug: false,
searchStr: ''
}
},
created() {
this.onSearch = debounce(this.onSearch, 500)
this.onSearch('')
},
methods: {
onSearch(value) {
if (this.loading) return
this.array = []
if (!value) {
return
}
if (!value.trim()) return
this.loading = true
getDrug(value).then(res => {
this.array = res.data || []
if (this.array.length && this.innerValue) {
let list = this.array.filter(item => item.id == this.innerValue)
if (list && list.length) {
this.innerValueName = list[0].chemicalName
}
}
}).finally(() => {
this.loading = false
})
},
drugConfirm({ selectedOptions }) {
this.innerValueName = selectedOptions[0].chemicalName
this.$emit('update:value', selectedOptions[0].id)
this.$emit('change', selectedOptions[0])
this.searchStr = ''
this.showDrug = false
}
},
watch: {
value: {
handler(value) {
this.innerValue = value
},
immediate: true
},
valueName: {
handler(value) {
if (!value) {
return
}
this.onSearch(value)
},
immediate: true
},
searchStr: {
handler(val) {
if (!val) return
this.onSearch(val)
}
}
}
}
</script>
<style lang='less' scoped>
.form-input {
padding: 8px 12px;
border-radius: 8px;
}
.input-back {
background: #FAFAFA;
}
//灰色
.greyColor {
color: var(--van-text-color-2);
}
//确认按钮颜色
.blueColor {
color: var(--van-primary-color)
}
</style>
<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;
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>
<template> <template>
<div class="doc-image-upload"> <div class='doc-image-upload'>
<div class="text-12 description">{{ description }}</div> <div class='text-12 description'>{{ description }}</div>
<div class="mt-2 py-3 text-center upload-btn" @click="fileSelect"> <div class='mt-2 py-3 text-center upload-btn' @click='fileSelect'>
<doc-icon type="doc-upload" class="mr-2 text-16"/> <doc-icon type='doc-upload' class='mr-2 text-16' />
<span>{{ btText }}</span> <span>{{ btText }}</span>
</div> </div>
<div class="flex flex-wrap justify-between mt-4 image-box"> <div class='flex flex-wrap mt-4 image-box'>
<div v-for="item in innerImage" :key="item.id"> <div v-for="item in innerImage.filter(e => e.fileType != 'pdf')" :key='item.id'
<div v-if="item.fileType === 'pdf'" class=""> class='item-img' @click.stop='toPreview(item)'>
<doc-icon type="doc-PDF" /> <DocImage :src='item.trueDownloadUrl' remove @onRemove='removeImage(item)' />
</div> </div>
<div v-else> <div v-for="item in innerImage.filter(e => e.fileType == 'pdf')" :key='item.id'
<img src="@/assets/image/doctor/empty.png" style="width: 100%"/> class='item-pdf'>
</div> <DocImage isPdf :src='item.trueDownloadUrl' name='pdf文件名称' remove @onRemove='removeImage(item)' />
<span class="close-btn" @click="removeImage(item)">
<doc-icon type="close-circle" />
</span>
</div> </div>
</div> </div>
<input type="file" <!-- accept='.jpg,.jpeg,.png,.pdf' -->
accept=".jpg,.jpeg,.png,.pdf" <input type='file'
ref="fileElem" accept="image/*"
style="display: none;" ref='fileElem'
@change="handleFiles" style='display: none;'
:key="inputKey"> @change='handleFiles'
:key='inputKey'>
<van-overlay :show='imgShow' @click='imgShow = false'>
<div class='wrapper'>
<van-swipe class='block' :initial-swipe='initSwipe'>
<van-swipe-item v-for="image in innerImage.filter(e => e.fileType != 'pdf')" :key='image'>
<img :src='image.trueDownloadUrl' style='width: 100%;height: 100%' />
</van-swipe-item>
</van-swipe>
</div>
</van-overlay>
</div> </div>
</template> </template>
<script> <script>
import DocImage from './DocImage.vue'
import { showToast } from 'vant' import { showToast } from 'vant'
import { fileUpload } from '@/api/base'
export default { export default {
name: 'DocImageUpload', name: 'DocImageUpload',
components: {
DocImage
},
props: { props: {
// 上传描述 // 上传描述
description: { default: '温馨提示:请上传JPG、PNG格式图片,文件大小不超过5M' }, description: { default: '温馨提示:请上传JPG、PNG格式图片,文件大小不超过10M' },
// 传入的img数据 { id, trueDownloadUrl } // 传入的img数据 { id, trueDownloadUrl }
imageData: { default: () => [] }, imageData: { default: () => [] },
// 上传按键的文字 // 上传按键的文字
...@@ -53,7 +66,10 @@ export default { ...@@ -53,7 +66,10 @@ export default {
spinning: false, spinning: false,
inputKey: '1', inputKey: '1',
// viewer显示 // viewer显示
visible: false visible: false,
//显示图片所在位置
initSwipe: 0,
imgShow: false
} }
}, },
computed: { computed: {
...@@ -64,15 +80,16 @@ export default { ...@@ -64,15 +80,16 @@ export default {
return this.innerImage.map(e => e.id).join(',') return this.innerImage.map(e => e.id).join(',')
} }
}, },
methods:{ methods: {
init() { init() {
if (this.imageData?.length) { if (this.imageData?.length) {
this.innerImage = [...this.imageData] this.innerImage = [...this.imageData]
} else { } else {
this.innerImage = [ this.innerImage = [
{ fileType: 'pdf', id: 1 }, // { fileType: 'pdf', id: 1, trueDownloadUrl: testUrl },
{ fileType: 'png', id: 2 }, // { fileType: 'png', id: 2, trueDownloadUrl: testUrl },
{ fileType: 'png', id: 3 } // { fileType: 'png', id: 3, trueDownloadUrl: testUrl },
// { fileType: 'png', id: 4, trueDownloadUrl: testUrl }
] ]
} }
}, },
...@@ -98,7 +115,6 @@ export default { ...@@ -98,7 +115,6 @@ export default {
this.addImage(result) this.addImage(result)
this.inputKey = Math.random().toString(16).substring(2, 6) this.inputKey = Math.random().toString(16).substring(2, 6)
this.$emit('change', this.ids, this.innerImage) this.$emit('change', this.ids, this.innerImage)
this.formItemContext.onFieldChange()
}).finally(() => { }).finally(() => {
this.spinning = false this.spinning = false
}) })
...@@ -109,8 +125,8 @@ export default { ...@@ -109,8 +125,8 @@ export default {
showToast('未选中文件,请尝试重新选择') showToast('未选中文件,请尝试重新选择')
return return
} }
if (files[0].size / 1024 / 1024 > 5) { if (files[0].size / 1024 / 1024 > 10) {
showToast('图片大小不能超过5M') showToast('图片大小不能超过10M')
return return
} }
this.file = files[0] this.file = files[0]
...@@ -129,6 +145,13 @@ export default { ...@@ -129,6 +145,13 @@ export default {
if (!item) return if (!item) return
this.innerImage = this.innerImage.filter(e => e.id != item.id) this.innerImage = this.innerImage.filter(e => e.id != item.id)
this.$emit('change', this.ids, this.innerImage) this.$emit('change', this.ids, this.innerImage)
},
//图片预览
toPreview(val) {
let res = this.innerImage.filter(e => e.fileType != 'pdf')
let index = res.findIndex(e => val.id == e.id)
this.initSwipe = index
this.imgShow = true
} }
}, },
watch: { watch: {
...@@ -142,31 +165,49 @@ export default { ...@@ -142,31 +165,49 @@ export default {
} }
</script> </script>
<style lang="less" scoped> <style lang='less' scoped>
.description { .description {
color: #A5AEBE; color: #A5AEBE;
} }
.upload-btn { .upload-btn {
color: var(--van-primary-color); color: var(--van-primary-color);
border: 1px solid #eee; border: 1px solid #eee;
background-color: #FAFAFA; background-color: #FAFAFA;
border-radius: 8px; border-radius: 8px;
} }
.image-box { .image-box {
>div { row-gap: 8px;
width: calc(33.3vw - 8px); column-gap: 12px;
.item-img {
width: calc(33.3% - 8px);
}
.item-pdf {
width: 100%;
}
> div {
width: calc(33.3% - 8px);
position: relative; position: relative;
border: 1px solid #999;
border-radius: 2px; border-radius: 2px;
img { img {
object-fit: contain; object-fit: contain;
} }
} }
.close-btn { }
position: absolute;
font-size: 16px; .wrapper {
top: -8px; display: flex;
right: -8px; align-items: center;
justify-content: center;
height: 100%;
.block {
width: 100%;
} }
} }
</style> </style>
<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">
<doc-icon type="doc-left-1" 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
},
methods: {
goBack() {
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>
<template> <template>
<van-popup :show="innerShow" position="bottom" <van-popup :show="innerShow" position="bottom"
:teleport="teleport"
class="doc-unit"> class="doc-unit">
<van-picker :loading="loading" <van-picker :loading="loading"
title="机构选择" title="机构选择"
...@@ -32,7 +33,8 @@ export default { ...@@ -32,7 +33,8 @@ export default {
default: () => { default: () => {
return {text: 'unitName', value: 'id'} return {text: 'unitName', value: 'id'}
} }
} },
teleport: [String, Element]
}, },
emits: ['update:show', 'update:value', 'change'], emits: ['update:show', 'update:value', 'change'],
data() { data() {
......
<template>
<van-uploader :max-size="5 * 1024 * 1024" :after-read="afterRead" max-count="1"
class="id-card-scan">
<slot>
<doc-icon type="doc-scan" class="shrink-0 mr-3 text-primary"/>
</slot>
</van-uploader>
</template>
<script>
import { showNotify } from 'vant'
export default {
name: 'IdCardScan',
emits: ['change'],
methods: {
// 证件上传后
afterRead(file) {
console.log(file)
showNotify({ type: 'primary', message: '文件上传' })
this.$emit('change', file)
}
}
}
</script>
<style lang="less" scoped>
</style>
<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
<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.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 '@/doctor/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>
<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.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" 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 '@/doctor/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/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;
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>
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)
}
}
}
<template>
<van-popup v-if='innerShow' v-model:show='innerShow' position='right' :style="{ height: '100%', width: '100%' }">
<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='grow overflow-y-auto pl-4 pr-4 pt-3 pb-3'>
<!-- {{fileType}}-->
<div>
<div class='flex flex-col '>
<!-- 文本 -->
<div class='card' v-if='contentList?.length' @click.stop='selectFiletype(1)'>
<div class='flex justify-between items-center'>
<div class='font-semibold mb-1'>文本</div>
<van-checkbox-group v-model="fileType" shape="square" icon-size="16px" >
<van-checkbox :name="1" @click.stop='()=> {}'></van-checkbox>
</van-checkbox-group>
</div>
<div class='conten-bg'>
<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>
</div>
<div class='card mt-4' v-if='mp4List?.length' @click='selectFiletype(3)'>
<div class='flex justify-between items-center'>
<div class='font-semibold mb-1'>视频</div>
<van-checkbox-group v-model="fileType" shape="square" icon-size="16px">
<van-checkbox :name="3" @click.stop='()=> {}'></van-checkbox>
</van-checkbox-group>
</div>
<div class='conten-bg'>
<Mp4 :files='mp4List' :activeMediaUrl='activeMediaUrl'
@play='e => activeMediaUrl = e.annexUrl' />
</div>
</div>
<div class='card flex flex-col mt-4' style='row-gap: .06rem;' v-if='mp3List?.length' @click='selectFiletype(2)'>
<div class='flex justify-between items-center'>
<div class='font-semibold mb-1'>音频</div>
<van-checkbox-group v-model="fileType" shape="square" icon-size="16px">
<van-checkbox :name="2" @click.stop='()=> {}'></van-checkbox>
</van-checkbox-group>
</div>
<div class='conten-bg'>
<Mp3 :file='item' v-for='item in mp3List' :key='item.annexId'
:activeMediaUrl='activeMediaUrl'
@play='e => activeMediaUrl = e.annexUrl' />
</div>
</div>
</div>
</div>
<div class='bbtn'>
<van-button type='primary' @click='toUse'>引用</van-button>
</div>
</div>
</van-popup>
</template>
<script>
import { showToast } from 'vant'
import { getTemplateDetail } from '@/api/doctor/workbench'
import Mp3 from '@/doctor/components/mediaPlay/Mp3.vue'
import Mp4 from '@/doctor/components/mediaPlay/Mp4.vue'
export default {
name: 'temDetail',
components: { Mp4, Mp3 },
props: {
show: { default: false },
id: String
},
data() {
return {
info: {},
activeMediaUrl: '',
fileType: [1, 2, 3],
}
},
computed: {
innerShow() {
return this.show
},
contentList() {
return this.info.contentList
},
// 文件内容
annexList() {
return this.info?.annexList || []
},
mp3List() {
return this.annexList.filter(e => e.type == 2)
},
mp4List() {
return this.annexList.filter(e => e.type == 3)
}
},
created() {
this.load()
},
methods: {
async load() {
if (!this.id) {
showToast('未获取到信息')
return
}
let par = {
id: this.id
}
getTemplateDetail(par).then(res => {
let result = res.data || {}
this.info = result
}).finally(() => {
})
},
selectFiletype(val) {
let index = this.fileType.findIndex(item => item == val)
if (index >= 0) {
this.fileType = this.fileType.filter(item => item != val)
} else {
this.fileType.push(val)
}
},
toUse() {
this.$emit('selectedInfo', this.id, this.fileType)
this.onBack()
},
onBack() {
this.$emit('closeDetail', false)
}
}
}
</script>
<style scoped lang='less'>
@import url('../../utils/common.less');
.bbtn {
padding: 8px 12px;
border-top: 1px solid #D7D8DA;
button {
width: 100%;
border-radius: 100px
}
}
.card {
border: 1px solid #CFD5DE;
padding: 8px;
border-radius: 8px;
color: #262626;
}
.conten-bg {
background: #F8FAFC;
padding: 6px 10px;
border-radius: 4px;
}
</style>
\ No newline at end of file
<template>
<van-popup v-model:show='innerShow' position='right' :style="{ height: '100%', width: '100%' }" :overlay='false' >
<div class='bg flex flex-col'>
<div class='p-3 flex items-center shrink-0 justify-between title bg-white'>
<div @click='onBack' class='text-12 back-bt'>
<doc-icon type='doc-left2' />
</div>
<div>选择内容</div>
<div class='text-primary left-btn' @click='openSearch'>筛查</div>
</div>
<div class='grow p-10 overflow-y-auto' ref='list'>
<van-pull-refresh v-model='loadingRefresh' @refresh='onRefresh'
:disabled='isRefreshDisable' style='min-height: 100%'>
<van-list
v-model:loading='loading'
:finished='finished'
:finished-text="list.length ? '没有更多了' : ''"
:immediate-check='false'
@load='onMore'
>
<div class='flex flex-col gap-y-2.5'>
<div class='py-3 px-4 doc-list-card' v-for='item in list' :key='item.id'>
<div class='flex flex-col gap-y-2.5'>
<div>
<span class='label'>模板分类</span>
<span>{{ item.templateClassifyTrans }}</span>
</div>
<div>
<span class='label'>模板名称</span>
<span>{{ item.templateName }}</span>
</div>
</div>
<div class='divider my-3'></div>
<div class='bt-group'>
<van-button round size='small' class='doc-btn-primary mr-3'
@click='toDetail(item)'>查看
</van-button>
<van-button round size='small' class='doc-btn-primary' @click='toUse(item)'>
引用
</van-button>
</div>
</div>
</div>
</van-list>
<div class='text-center shrink-0 empty' v-if='!list.length'>
<img src='@/assets/image/doctor/empty.png' alt='' style='width: 1.2rem;'>
<p>暂无数据</p>
</div>
</van-pull-refresh>
<van-popup v-model:show='searchVisible' position='top' :style="{ height: '60%' }"
style='position: absolute;transition: none'
:overlay-style="{ position: 'absolute' }"
transition='viewer-fade'
:teleport='listDom'>
<div class='h-full flex flex-col workbench-search-box'>
<div class='px-4 py-3 grow overflow-y-auto' style=''>
<van-field v-model='form.templateName' placeholder='请输入要查询的模板名称' maxlength='100'
class='doc-input' />
<div class='my-3'>模板分类(仅单选)</div>
<CheckBtn :options="store.getDict('DC00082')" v-model:value='form.templateClassify' column-3
class='check-btn-workbench' />
<div class='my-3'>文件类型(可多选)</div>
<CheckBtn multiple :options="store.getDict('DC00093')" v-model:value='form.fileType' column-3
class='check-btn-workbench' />
<div class='my-3'>共享类型(仅单选)</div>
<CheckBtn :options="store.getDict('DC00053')" v-model:value='form.templateType' column-3
class='check-btn-workbench' />
</div>
<div class='text-16 flex shrink-0 text-center bt-group'>
<div class='grow py-3' @click='reset'>重置</div>
<div class='grow py-3 submit-btn' @click='search'>确定</div>
</div>
</div>
</van-popup>
<!-- 查看详情组件-->
<temDetail v-if='detailShow && innerShow'
:show='detailShow'
:id='selectRecord.id'
@closeDetail='detailClosed'
@selectedInfo='detailToUse'
:overlay='false'
></temDetail>
</div>
</div>
</van-popup>
</template>
<script>
import { showToast } from 'vant'
import CheckBtn from '@/doctor/components/checkBtn/CheckBtn'
import { getTemplateByPage } from '@/api/doctor/workbench'
import { useStore } from '@/doctor/store'
import TemDetail from '@/doctor/components/template/temDetail'
const DefaultForm = () => {
return {
templateName: undefined,
templateClassify: undefined,
//慢病
businessType: 1,
//文件类型
fileType: [],
//共享类型
templateType: 1
}
}
export default {
name: 'temList',
components: { TemDetail, CheckBtn },
props: {
show: { default: false },
templateClassify: Number,
},
data() {
return {
store: useStore(),
list: [],
pagination: {
total: 0,
pageIndex: 1,
pageSize: 8
},
loading: false,
finished: false,
loadingRefresh: false,
isRefreshDisable: false,
// 搜索弹出框
searchVisible: false,
form: DefaultForm(),
//是否展示详情弹窗
detailShow: false,
//选中项
selectRecord: {}
}
},
computed: {
innerShow() {
return this.show
},
listDom() {
return this.$refs.list
}
},
created() {
this.form.templateClassify = this.templateClassify
this.load()
},
mounted() {
const list = this.$refs.list
if (list) {
list.addEventListener('scroll', () => {
if (list.scrollTop > 0) {
this.isRefreshDisable = true
} else {
this.isRefreshDisable = false
}
})
}
},
methods: {
load(loading = true) {
const {fileType = [], ...others} = this.form
const query = {
pageIndex: this.pagination.pageIndex,
pageSize: this.pagination.pageSize,
fileType: fileType&&fileType.length ? fileType.join(): '',
...others
}
getTemplateByPage(query, loading).then(res => {
if (this.pagination.pageIndex === 1) {
this.list = []
}
this.list = this.list.concat(res.data.dataList || [])
this.pagination.total = res.data.total || 0
this.finished = this.list.length >= this.pagination.total
}).finally(() => {
this.loading = false
this.loadingRefresh = false
})
},
search() {
this.pagination.pageIndex = 1
this.load()
this.searchVisible = false
},
reset() {
this.form = DefaultForm()
this.form.templateClassify = this.templateClassify
this.search()
},
onMore() {
this.pagination.pageIndex++
this.load(false)
},
onRefresh() {
this.pagination.pageIndex = 1
this.load()
},
openSearch() {
this.searchVisible = true
},
toDetail(record) {
this.selectRecord = record
this.detailShow = true
},
detailClosed(val) {
this.detailShow = val
},
//列表引用
toUse(record, typeList = [1, 2, 3]) {
this.$emit('selectRecord', record.id, typeList)
this.onBack()
},
//详情选中引用
detailToUse(val, typeList = []) {
this.$emit('selectRecord', val, typeList)
this.onBack()
},
onBack() {
this.$emit('closed', false)
}
}
}
</script>
<style scoped lang='less'>
.title {
font-size: 18px;
font-weight: 600;
}
.bg-white {
background: #FFFFFF;
}
.left-btn {
font-size: 14px;
font-weight: 400;
}
.bg {
background: rgb(245, 245, 245);
height: 100vh;
}
.p-10 {
padding: 10px;
}
:deep(.workbench-search-box) {
color: #595959;
.bt-group {
border-top: 1px solid #EBEBEC;
color: #262626;
.submit-btn {
color: #fff;
background-color: var(--van-primary-color);
}
}
}
</style>
\ No newline at end of file
<template>
<div class='all-back'>
<van-nav-bar title='慢病管理' left-text='' left-arrow
@click-right="toSearch" @click-left='toBack'>
<template #right>
<doc-icon type="doc-search" style="color: #262626"/>
</template>
</van-nav-bar>
<van-pull-refresh v-model="loading" @refresh="onRefresh"
:disabled='isRefreshDisable'>
<div class='top-title'>
我的待随访({{ total }})
</div>
<van-tabs v-model:active='active'>
<van-tab :name='item.name' v-for='item in tabList' :key="item.name">
<template #title>
<span>{{ item.title }}({{ item.num }})</span>
</template>
</van-tab>
</van-tabs>
<div class='list-data' ref='list'>
<div class='mt-10 white-back p-16' v-for='item in activeData' :key="item.id">
<div class='flex items-center'>
<div class='base-title'>{{ item.residentName }}</div>
<div class='second-title plr-8'>{{ getInfoByIdCard(item.idCard).age }}岁</div>
<div class='second-title plr-6'>{{ item.genderName }}</div>
</div>
<div class='mt-3 flex items-center'>
<div class='detail-left'>
身份证号
</div>
<div class='detail-right'>
{{ $idCardHide(item.idCard) }}
</div>
</div>
<div class='mt-3 flex items-center'>
<div class='detail-left'>
是否逾期
</div>
<div class='detail-right'>
{{ item.isOverdueName }}
</div>
</div>
<div class='mt-3 flex items-center'>
<div class='detail-left'>
逾期天数
</div>
<div class='detail-right'>
{{ item.overdueDay }} 天
</div>
</div>
<div class='flex mt-3' style='align-items: baseline'>
<div class='detail-left'>
慢病标签
</div>
<div class='detail-right' style='flex: 1'>
<ChronicTag :list="item.chronicTagsArray"/>
</div>
</div>
<van-divider class='mt-3' />
<div class='mt-3 flex word-right'>
<div></div>
<div>
<van-button round size='small' class='btn' @click='toGeneralDetail(item)'>详情</van-button>
<van-button round size='small' class='btn' style='margin-left: 16px' @click='toAddGeneral(item)'>通用随访
</van-button>
</div>
</div>
</div>
<div class="text-center empty" v-if="!activeData.length">
<img src="@/assets/image/doctor/empty.png" alt="" style="width: 1.2rem;">
<p>暂无数据</p>
</div>
</div>
</van-pull-refresh>
</div>
</template>
<script>
import dayjs from 'dayjs'
import { getVisitAll } from '@/api/doctor/generalFU.js'
import ChronicTag from '@/doctor/components/chronicTag/ChronicTag.vue'
import { backHome, getInfoByIdCard } from '@/utils/common'
export default {
name: 'List',
components: {
ChronicTag
},
data() {
return {
active: 1,
tabList: [
{ title: '高血压', name: 1, num: 0 },
{ title: '糖尿病', name: 2, num: 0 },
{ title: '冠心病', name: 3, num: 0 },
{ title: '脑卒中', name: 4, num: 0 },
{ title: '慢阻肺', name: 5, num: 0 },
{ title: '慢性肾病', name: 6, num: 0 },
{ title: '血脂异常', name: 7, num: 0 }
],
detailInfo: [],
total: 0,
// 下拉刷新
loading: false,
isRefreshDisable: false
}
},
computed: {
activeData() {
return this.detailInfo.filter(e => e.diseaseType === this.active)
}
},
created() {
this.init()
},
mounted() {
const list = this.$refs.list
list.addEventListener('scroll', () => {
if (list.scrollTop > 0) {
this.isRefreshDisable = true
} else {
this.isRefreshDisable = false
}
})
},
methods: {
getInfoByIdCard,
init() {
this.load()
},
load(loading = true) {
// const nextVisitDateStart = dayjs().format('YYYY-MM-DD')
// const nextVisitDateEnd = dayjs().add(6, 'day').format('YYYY-MM-DD')
const query = {
// nextVisitDateStart,
// nextVisitDateEnd
}
getVisitAll(query, loading).then(res => {
console.log('getVisitAll', res)
this.detailInfo = res.data || []
this.total = this.detailInfo.length
this.tabList.forEach(e => {
e.num = this.detailInfo.filter(i => i.diseaseType === e.name).length
})
}).finally(() => {
this.loading = false
})
},
scrollHandle(dom) {
if (!dom) return
if (dom.scrollTop > 0) {
this.isRefreshDisable = true
} else {
this.isRefreshDisable = false
}
},
onRefresh() {
this.load(false)
},
toGeneralDetail(item) {
this.$router.push({
path: `/doctor/resident/base`,
query: {
residentId: item.residentInfoId
}
})
},
toAddGeneral(val) {
const {id, ...others} = val
this.$router.push({
path: `/doctor/followUp/generalFU/add`,
query: {...others}
})
},
toSearch() {
this.$router.push({
path: `/doctor/followUp/search`
})
},
toBack() {
backHome()
}
}
}
</script>
<style scoped lang='less'>
.all-back {
background: #F5F5F5;
.top-title {
padding: 10px 12px;
}
.white-back {
background: #FFFFFF;
}
.mt-10 {
margin-top: 10px;
}
.p-16 {
padding: 16px;
}
.plr-8 {
padding: 0px 8px;
}
.plr-6 {
padding: 0px 6px;
}
.base-title {
font-weight: bold;
font-size: 16px;
}
.second-title {
background: #F0F3FF;
line-height: 24px;
margin-left: 10px;
}
.detail-left {
width: 104px;
font-size: 14px;
color: #8C8C8C;
}
.detail-right {
font-size: 14px;
}
.word-right {
justify-content: space-between;
align-items: center;
}
.btn {
background: #F0F3FF;
color: #607FF0;
border: 0px;
line-height: 26px;
height: 26px;
//padding: 4px 8px 4px 8px;
padding: 0px 8px;
}
.list-data {
height: calc(100vh - 140px);
overflow-y: auto;
}
}
</style>
\ No newline at end of file
<template>
<div class='all-back'>
<van-nav-bar title='慢病管理' left-text='' left-arrow
@click-right='toSearch' @click-left='toBack'>
<template #right>
<doc-icon type='doc-search' style='color: #262626' />
</template>
</van-nav-bar>
<div class='top-title'>
我的待随访({{ total }})
</div>
<van-tabs v-model:active='active' @change='changeTab'>
<van-tab :name='item.name' v-for='item in tabList' :key='item.name'>
<template #title>
<span>{{ item.title }}({{ item.num }})</span>
</template>
</van-tab>
</van-tabs>
<van-pull-refresh v-model='loading' @refresh='onRefresh'
:disabled='isRefreshDisable'>
<div class='list-data' ref='list'>
<van-list
v-model:loading='loadingTable'
:finished='finished'
:finished-text="detailInfo.length ? '没有更多了' : ''"
@load='onMore'
>
<div class='mt-10 white-back p-16' v-for='item in detailInfo' :key='item.id'>
<div class='flex items-center'>
<div class='base-title'>{{ item.residentName }}</div>
<div class='second-title plr-8'>{{ getInfoByIdCard(item.idCard).age }}岁</div>
<div class='second-title plr-6'>{{ item.genderName }}</div>
</div>
<div class='mt-3 flex items-center'>
<div class='detail-left'>
身份证号
</div>
<div class='detail-right'>
{{ $idCardHide(item.idCard) }}
</div>
</div>
<div class='mt-3 flex items-center'>
<div class='detail-left'>
是否逾期
</div>
<div class='detail-right'>
{{ item.isOverdueName }}
</div>
</div>
<div class='mt-3 flex items-center'>
<div class='detail-left'>
逾期天数
</div>
<div class='detail-right'>
{{ item.overdueDay }} 天
</div>
</div>
<div class='flex mt-3' style='align-items: baseline'>
<div class='detail-left'>
慢病标签
</div>
<div class='detail-right' style='flex: 1'>
<ChronicTag :list='item.chronicTagsArray' />
</div>
</div>
<van-divider class='mt-3' />
<div class='mt-3 flex word-right'>
<div></div>
<div>
<van-button round size='small' class='btn' @click='toGeneralDetail(item)'>详情
</van-button>
<van-button round size='small' class='btn' style='margin-left: 16px'
@click='toAddGeneral(item)'>通用随访
</van-button>
</div>
</div>
</div>
</van-list>
<div class='text-center empty' v-if='!detailInfo.length'>
<img src='@/assets/image/doctor/empty.png' alt='' style='width: 1.2rem;'>
<p>暂无数据</p>
</div>
</div>
</van-pull-refresh>
</div>
</template>
<script>
import dayjs from 'dayjs'
import { getVisitAll, queryVisitByPage } from '@/api/doctor/generalFU.js'
import ChronicTag from '@/doctor/components/chronicTag/ChronicTag.vue'
import { backHome, getInfoByIdCard } from '@/utils/common'
export default {
name: 'List',
components: {
ChronicTag
},
data() {
return {
active: 1,
tabList: [
{ title: '高血压', name: 1, num: 0 },
{ title: '糖尿病', name: 2, num: 0 },
{ title: '冠心病', name: 3, num: 0 },
{ title: '脑卒中', name: 4, num: 0 },
{ title: '慢阻肺', name: 5, num: 0 },
{ title: '慢性肾病', name: 6, num: 0 },
{ title: '血脂异常', name: 7, num: 0 }
],
detailInfo: [],
total: 0,
// 下拉刷新
loading: false,
isRefreshDisable: false,
//列表刷新
loadingTable: false,
pagination: {
total: 0,
pageIndex: 1,
pageSize: 5
},
finished: false
}
},
mounted() {
const list = this.$refs.list
list.addEventListener('scroll', () => {
if (list.scrollTop > 0) {
this.isRefreshDisable = true
} else {
this.isRefreshDisable = false
}
})
},
methods: {
getInfoByIdCard,
changeTab() {
this.detailInfo = []
this.pagination.pageIndex = 1
this.load()
},
onMore() {
this.pagination.pageIndex++
this.load()
},
load(loading = true) {
const query = {
diseaseType: this.active,
pageIndex: this.pagination.pageIndex,
pageSize: this.pagination.pageSize
}
getVisitAll(query, loading).then(res => {
console.log('getVisitAll', res)
this.detailInfo = this.detailInfo.concat(res.data || [])
this.total = this.detailInfo.length
this.finished = this.detailInfo.length >= this.pagination.total
}).finally(() => {
this.loading = false
this.loadingTable = false
})
},
scrollHandle(dom) {
if (!dom) return
if (dom.scrollTop > 0) {
this.isRefreshDisable = true
} else {
this.isRefreshDisable = false
}
},
onRefresh() {
this.detailInfo = []
this.pagination.pageIndex = 1
this.load(false)
},
toGeneralDetail(item) {
this.$router.push({
path: `/doctor/resident/base`,
query: {
residentId: item.residentInfoId
}
})
},
toAddGeneral(val) {
const { id, ...others } = val
this.$router.push({
path: `/doctor/followUp/generalFU/add`,
query: { ...others }
})
},
toSearch() {
this.$router.push({
path: `/doctor/followUp/search`
})
},
toBack() {
backHome()
}
}
}
</script>
<style scoped lang='less'>
.all-back {
background: #F5F5F5;
.top-title {
padding: 10px 12px;
}
.white-back {
background: #FFFFFF;
}
.mt-10 {
margin-top: 10px;
}
.p-16 {
padding: 16px;
}
.plr-8 {
padding: 0px 8px;
}
.plr-6 {
padding: 0px 6px;
}
.base-title {
font-weight: bold;
font-size: 16px;
}
.second-title {
background: #F0F3FF;
line-height: 24px;
margin-left: 10px;
}
.detail-left {
width: 104px;
font-size: 14px;
color: #8C8C8C;
}
.detail-right {
font-size: 14px;
}
.word-right {
justify-content: space-between;
align-items: center;
}
.btn {
background: #F0F3FF;
color: #607FF0;
border: 0px;
line-height: 26px;
height: 26px;
//padding: 4px 8px 4px 8px;
padding: 0px 8px;
}
.list-data {
height: calc(100vh - 140px);
overflow-y: auto;
}
}
</style>
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
<template>
<div class="h-full flex flex-col disease-index">
<van-tabs shrink type="card" class="shrink-0 doc-tab-round"
v-model:active="activeTab">
<van-tab :title="`${diseaseName}信息`"></van-tab>
<van-tab :title="`${diseaseName}管理`"></van-tab>
</van-tabs>
<div class="pt-3"></div>
<div class="grow pb-3 overflow-y-auto">
<DiseaseList :diseaseType="diseaseType" v-if="activeTab == 0"/>
<DiseaseVisit :diseaseType="diseaseType" v-if="activeTab == 1"/>
</div>
</div>
</template>
<script>
import DiseaseList from './List.vue'
import DiseaseVisit from './Visit.vue'
export default {
components: {
DiseaseList,
DiseaseVisit
},
inject: ['residentInfo'],
props: {
diseaseName: String,
diseaseType: Number
},
data() {
return {
activeTab: 0
}
}
}
</script>
<style lang="less" scoped>
:deep(.card-back-1) {
border-radius: 12px;
background: linear-gradient(to bottom, #FFC9D3, #FFE9E9);
.title {
color: #8E2A4A;
}
}
:deep(.card-back-2) {
border-radius: 12px;
background: linear-gradient(to bottom, #FFD8BC, #FFF0E9);
.title {
color: #8E562A;
}
}
:deep(.card-back-3) {
border-radius: 12px;
background: linear-gradient(to bottom, #B3F5F7, #FFFFE9);
.title {
color: #2A8E75;
}
}
</style>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -6,7 +6,11 @@ export const useStore = defineStore('chronic', { ...@@ -6,7 +6,11 @@ export const useStore = defineStore('chronic', {
// 字典 // 字典
dict: [], dict: [],
//登录医生相关基本信息 //登录医生相关基本信息
authInfo: {} authInfo: {},
// 刷新标记
refreshMark: 1,
// 页面是否处于隐藏状态
documentHidden: false
} }
}, },
getters: {}, getters: {},
...@@ -27,6 +31,12 @@ export const useStore = defineStore('chronic', { ...@@ -27,6 +31,12 @@ export const useStore = defineStore('chronic', {
} }
let temp = array.find(e => e.value == value) || {} let temp = array.find(e => e.value == value) || {}
return temp.name || '' return temp.name || ''
},
onRefreshMark() {
this.refreshMark++
},
onDocumentHidden(value) {
this.documentHidden = value
} }
} }
}) })
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -125,7 +125,7 @@ export default { ...@@ -125,7 +125,7 @@ export default {
}, },
created() { created() {
if (!this.id) { if (!this.id) {
showNotify({ type: 'warning', message: '未获取到查询信息', duration: 0 }) showNotify({ type: 'warning', message: '未获取到查询信息'})
return return
} }
this.init() this.init()
......
...@@ -53,7 +53,7 @@ export default { ...@@ -53,7 +53,7 @@ export default {
}, },
created() { created() {
if (!this.idCard) { if (!this.idCard) {
showNotify({ type: 'warning', message: '未获取到用户信息', duration: 0 }) showNotify({ type: 'warning', message: '未获取到用户信息'})
return return
} }
this.init() this.init()
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment