| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592 |
- <template>
- <el-form ref="formRef" :model="dataForm" label-width="100px" :toggleType="2">
- <div class="elder-detail-wrap">
- <div class="left" :style="infoStyle">
- <ContentWrap class="elderInfo">
- <div class="header">
- <h4 class="title">长者信息</h4>
- </div>
- <div style="margin-top: 10px">
- <el-button @click="showCardBad" type="warning" size="small">床头卡</el-button>
- <el-button @click="showCardDoor" type="danger" size="small">门头卡</el-button>
- <el-button @click="showCardShare" type="success" size="small">分享卡</el-button>
- </div>
- <div class="info-wrap">
- <el-image :src="dataForm.elderCover" style="width: 80px; height: 80px">
- <template #placeholder>
- <div>
- <img src="@/assets/imgs/old_man.png" style="width: 80px; height: 80px" alt="" />
- </div>
- </template>
- <template #error>
- <div>
- <img src="@/assets/imgs/old_man.png" style="width: 80px; height: 80px" alt="" />
- </div>
- </template>
- </el-image>
- <div class="info">
- <div class="top">
- <span class="f600">{{ dataForm.elderName }}</span>
- <span class="grey">{{
- getDictLabel(DICT_TYPE.SYSTEM_USER_SEX, dataForm.elderSex)
- }}</span>
- <span class="grey">{{ dataForm.elderAge }}</span>
- </div>
- <div>
- <el-tag type="warning">中度失能</el-tag>
- <el-tag type="primary" class="ml3">{{ dataForm.nurseLevelName }}</el-tag>
- </div>
- </div>
- </div>
- <div class="detail">
- <div class="bed">
- <span class="room">床号/房号:</span>
- <span>{{ dataForm.bedName }}</span>
- </div>
- <div class="box">
- <div class="colomn">
- <span class="f500">{{
- dataForm.checkInTime ? formatTime(dataForm.checkInTime, 'yyyy-MM-dd') : ''
- }}</span>
- <span class="f12">入住日期</span>
- </div>
- <div class="colomn">
- <span class="f500">{{ dataForm.stayDay }}天</span>
- <span class="f12">在院天数</span>
- </div>
- <div class="colomn">
- <span class="f500">{{ dataForm.stayNumber }}次</span>
- <span class="f12">入住次数</span>
- </div>
- </div>
- <el-progress :percentage="dataForm.infoPercentage">
- <template> </template>
- </el-progress>
- <div class="desc">
- <span class="grey">信息完善程度</span>
- <div>
- {{ dataForm.infoPercentage }}%
- <!-- <span class="num">{{ dataForm.infoFieldCount }}</span>/{{ dataForm.totalInfoFieldCount }} -->
- </div>
- </div>
- <div class="contract"> 档案号:{{ dataForm.fileNumber }} </div>
- </div>
- <div class="scene">
- <div class="title">业务场景</div>
- <div v-for="(item, index) in arr" :key="item.name" class="scene-item">
- <span class="line" v-if="index == 0 || index == arr.length - 1"></span>
- <div class="timeline-item__tail" v-if="index > 0"></div>
- {{ item.name }}
- </div>
- </div>
- <div class="btns">
- <el-button
- class="btn"
- type="primary"
- v-for="(item, index) in routeArr"
- :key="index"
- :disabled="item.show"
- plain
- @click="handleTo(item)"
- >{{ item.label }}</el-button
- >
- </div>
- </ContentWrap>
- </div>
- <div class="right" :style="contentStyle">
- <ContentWrap>
- <el-tabs class="demo-tabs" v-model="activeName" @tab-change="handleTabChange">
- <ElScrollbar :height="!smallerThanLg ? '78.5vh' : ''" class="tab-content">
- <el-tab-pane
- v-for="(item, index) in tabs"
- :key="index"
- :label="item.label"
- :name="item.value"
- style="padding-top: 14px"
- >
- <component
- :is="item.comp"
- :dataForm="dataForm"
- :ref="(el) => setFormRef(el, index)"
- />
- </el-tab-pane>
- </ElScrollbar>
- </el-tabs>
- </ContentWrap>
- </div>
- </div>
- </el-form>
- <!-- 使用通用床头卡弹窗组件 -->
- <BedCardModal
- ref="bedCardModalRef"
- v-model="dialogVisible"
- :patientData="dataForm"
- @import-card="importCardFun"
- :title="'床头卡预览'"
- :width="'1080px'"
- @edit="handleEdit"
- @close="handleDialogClose"
- />
- <!-- 分享卡弹窗组件 -->
- <ShareCardModal
- ref="shareCardModalRef"
- v-model="dialogVisibleShare"
- :patientData="dataForm"
- @import-card="importCardFun"
- :title="'分享卡预览'"
- :width="'900px'"
- @close="handleDialogClose"
- />
- <!-- 门头卡弹窗组件 -->
- <DoorCardModal
- ref="doorCardModalRef"
- v-model="dialogVisibleDoor"
- :patientData="dataForm"
- @import-card="importCardDoorFun"
- :title="'门头卡预览'"
- :width="'600px'"
- @close="handleDialogClose"
- />
- <Form ref="formRefE" @success="getElderInfoById(idE)" />
- </template>
- <script setup lang="ts">
- import { breakpointsTailwind, useBreakpoints } from '@vueuse/core'
- import { ElScrollbar } from 'element-plus'
- import BedCardModal from '@/components/BedCardModal/index.vue'
- import ShareCardModal from '@/components/ShareCardModal/index.vue'
- import DoorCardModal from '@/components/DoorCardModal/index.vue'
- import { getElderInfoById } from '@/api/elderly/elder/elderly-Info'
- import { useAppStore } from '@/store/modules/app'
- import { usePermissionStore } from '@/store/modules/permission'
- import { findTreeNode } from '@/utils/tree'
- import { getPatientData, importCard, getDoorCardPatientData } from '@/utils/outBedCard'
- import First from './First.vue'
- import Second from './Second.vue'
- import Third from './Third.vue'
- import Four from './Four.vue'
- import Five from './Five.vue'
- import Six from './Six.vue'
- import Seven from './Seven.vue'
- import Eight from './Eight.vue'
- import Nine from './Nine.vue'
- import adaptationTab from './adaptationTab.vue'
- import floorActivityTab from './floorActivityTab.vue'
- import carePlanTab from './carePlanTab.vue'
- import healthRecordTab from './healthRecordTab.vue'
- import { formatTime } from '@/utils'
- import { getElderHealthRecordById } from '@/api/elderly/elder/health-record'
- import { getDictLabel, DICT_TYPE } from '@/utils/dict'
- import Form from '@/views/elderly/elder/health-record/Form.vue'
- defineOptions({ name: 'ElderFileDetail' })
- const formRef = ref() // 表单 Ref
- const formRefE = ref() // 表单 Ref
- const bed = ref() // 表单 Ref
- const dataForm = ref<{
- elderName?: string
- elderSex?: string
- elderAge?: string
- nurseLevelName?: string
- bedName?: string
- checkInTime?: Date
- stayDay?: string
- stayNumber?: string
- infoPercentage?: number
- fileNumber?: string
- }>({})
- const router = useRouter()
- const permissionStore = usePermissionStore()
- const appStore = useAppStore()
- const layout = computed(() => appStore.getLayout)
- const tabs = [
- { label: '长者信息', value: 1, comp: First },
- { label: '家属信息', value: 2, comp: Second },
- { label: '合同信息', value: 3, comp: Third },
- { label: '费用信息', value: 4, comp: Four },
- { label: '能力评估', value: 5, comp: Five },
- { label: '护理计划', value: 6, comp: Six },
- { label: '活动相册', value: 7, comp: Seven },
- { label: '附件', value: 8, comp: Eight },
- { label: '操作记录', value: 9, comp: Nine },
- { label: '健康档案', value: 10, comp: healthRecordTab },
- { label: '入住适应服务', value: 11, comp: adaptationTab },
- { label: '楼层活动记录', value: 12, comp: floorActivityTab },
- { label: '长者照顾计划', value: 13, comp: carePlanTab }
- ]
- const arr = [
- { name: '入住' },
- { name: '入住申请' },
- { name: '能力评估' },
- { name: '入住审批通过' },
- { name: '入住办理' },
- { name: '在院' }
- ]
- const routers = computed(() =>
- unref(layout) === 'cutMenu' ? permissionStore.getMenuTabRouters : permissionStore.getRouters
- )
- const routeArr = [
- {
- label: '床位变更',
- value: '/elderly/bed-change',
- show: findTreeNode(routers.value, 'bed-change', 'path') ? false : true
- },
- {
- label: '餐饮变更',
- value: '/elderly/changes/ChangeFood/index',
- show: findTreeNode(routers.value, 'changes/ChangeFood/index', 'path') ? false : true
- },
- {
- label: '护理变更',
- value: '/elderly/nurse-change',
- show: findTreeNode(routers.value, 'nurse-change', 'path') ? false : true
- },
- {
- label: '价格变更',
- value: '/elderly/price-change',
- show: findTreeNode(routers.value, 'price-change', 'path') ? false : true
- },
- {
- label: '日常费用',
- value: '/fee/daily-fee',
- show: findTreeNode(routers.value, 'daily-fee', 'path') ? false : true
- },
- {
- label: '能力评估',
- value: '/apply/synthetic-ability',
- show: findTreeNode(routers.value, 'synthetic-ability', 'path') ? false : true
- },
- {
- label: '长者押金',
- value: '/fee/deposit',
- show: findTreeNode(routers.value, 'deposit', 'path') ? false : true
- },
- {
- label: '缴费管理',
- value: '/fee/bill-pay',
- show: findTreeNode(routers.value, 'bill-pay', 'path') ? false : true
- },
- {
- label: '生活护理计划',
- value: '/nursing/life-care-plan',
- show: findTreeNode(routers.value, 'life-care-plan', 'path') ? false : true
- },
- {
- label: '医疗护理计划',
- value: '/nursing/medical-care-plan',
- show: findTreeNode(routers.value, 'medical-care-plan', 'path') ? false : true
- }
- ]
- const route = useRoute()
- const healthRecord = ref({})
- let idE = undefined
- onMounted(async () => {
- const { id } = route.params
- idE = id
- activeName.value = 1
- // 获取长者详情
- try {
- const res = await getElderInfoById(id)
- console.log('长者详情:', res)
- dataForm.value = res
- } catch (e) {}
- try {
- const res = await getElderHealthRecordById(id)
- console.log('长者健康档案:', res)
- healthRecord.value = res
- } catch (e) {}
- })
- const activeName = ref(1)
- const handleTabChange = (tab) => {
- activeName.value = tab
- if (tab != 1 || tab != 2) {
- fcFormRefs.value[tab - 1].init()
- }
- }
- // 床头卡弹窗控制
- const dialogVisible = ref(false)
- const dialogVisibleShare = ref(false)
- const dialogVisibleDoor = ref(false)
- const bedCardModalRef = ref()
- const shareCardModalRef = ref()
- const doorCardModalRef = ref()
- // 显示床头卡弹窗
- const showCardBad = () => {
- dialogVisible.value = true
- nextTick(() => {
- bedCardModalRef.value.updatePatientData(getPatientData(healthRecord.value, dataForm.value))
- })
- }
- // 显示分享卡弹窗
- const showCardShare = () => {
- dialogVisibleShare.value = true
- nextTick(() => {
- shareCardModalRef.value.updatePatientData(getPatientData(healthRecord.value, dataForm.value))
- })
- }
- // 显示门头卡弹窗
- const showCardDoor = () => {
- dialogVisibleDoor.value = true
- nextTick(() => {
- doorCardModalRef.value.updatePatientData(getDoorCardPatientData(dataForm.value))
- })
- }
- // 处理弹窗关闭事件
- const handleDialogClose = () => {
- console.log('床头卡弹窗已关闭')
- }
- const handleEdit = () => {
- // 先显式关闭床头卡弹窗,再等关闭动画结束(约 300ms)后再跳转。
- // 否则 el-dialog 的关闭动画会被 <keep-alive> 的路由切换打断,
- // 弹窗内部动画状态会卡住,导致返回后再点关闭预览关不掉(log 仍会打)。
- dialogVisible.value = false
- setTimeout(() => {
- router.push({
- path: '/trend-charts/health-record'
- })
- }, 350)
- }
- const importCardFun = () => {
- importCard(healthRecord.value, dataForm.value)
- }
- const importCardDoorFun = () => {
- // cardType = 3 表示门头卡
- importCard(undefined, dataForm.value, 1, 3)
- }
- const fcFormRefs = ref<HTMLElement[]>([])
- const setFormRef = (el, index) => {
- if (el) {
- fcFormRefs.value[index] = el
- }
- }
- const handleTo = (item) => {
- router.push({
- path: item.value,
- query: { elderName: dataForm.value.elderName }
- })
- }
- const breakpoints = useBreakpoints(breakpointsTailwind)
- const smallerThanLg = breakpoints.smaller('lg')
- const infoStyle = computed(() => {
- if (!smallerThanLg.value) {
- return { width: '300px' }
- } else {
- return { width: '100%' }
- }
- })
- const contentStyle = computed(() => {
- if (!smallerThanLg.value) {
- return { width: 'calc(100% - 320px)', marginLeft: '20px' }
- } else {
- return { width: '100%' }
- }
- })
- </script>
- <style lang="scss" scoped>
- .elder-detail-wrap {
- display: flex;
- .left {
- display: inline-block;
- .elderInfo {
- .header {
- display: flex;
- justify-content: space-between;
- align-items: baseline;
- }
- .title {
- font-weight: 600;
- font-size: 16px;
- }
- .info-wrap {
- display: flex;
- img {
- width: 70px;
- height: 67px;
- }
- .info {
- flex: 3;
- display: flex;
- flex-direction: column;
- justify-content: space-between;
- padding: 0 10px;
- .top {
- display: flex;
- justify-content: space-between;
- align-items: center;
- .f600 {
- font-weight: 600;
- font-size: 18px;
- }
- .grey {
- font-weight: 400;
- font-size: 14px;
- color: #636363;
- }
- }
- }
- }
- .detail {
- .bed {
- padding: 10px;
- background-color: var(--el-color-primary-light-3);
- color: #fff;
- border-radius: 4px;
- font-size: 17px;
- .room {
- display: block;
- font-size: 12px;
- margin-bottom: 4px;
- }
- }
- .box {
- margin: 16px 0 22px 0;
- display: flex;
- justify-content: space-between;
- .colomn {
- display: flex;
- flex-direction: column;
- text-align: center;
- .f500 {
- font-size: 14px;
- font-weight: 500;
- margin-bottom: 6px;
- }
- .f12 {
- font-weight: 400;
- font-size: 12px;
- color: #7c7c7c;
- }
- }
- }
- .el-progress--line {
- display: block;
- }
- .desc {
- display: flex;
- justify-content: space-between;
- margin-top: 10px;
- font-size: 12px;
- .grey {
- font-weight: 400;
- color: #7c7c7c;
- }
- .num {
- color: var(--el-color-primary);
- }
- }
- .contract {
- margin-top: 11px;
- padding: 11px 12px;
- background-color: var(--el-color-primary-light-9);
- color: var(--el-color-primary);
- font-size: 13px;
- border-radius: 8px;
- }
- }
- .scene {
- margin: 24px 0;
- .title {
- margin-bottom: 16px;
- }
- .scene-item {
- position: relative;
- padding-left: 20px;
- font-weight: 400;
- font-size: 14px;
- color: #7c7c7c;
- padding-bottom: 12px;
- &:last-child {
- padding-bottom: 0px;
- }
- }
- .timeline-item__tail {
- position: absolute;
- top: -14px;
- left: 6px;
- height: 100%;
- border-left: 1px dotted var(--el-color-primary);
- }
- .line::before {
- content: '';
- position: absolute;
- top: 3px;
- left: 2px;
- width: 10px;
- height: 10px;
- border-radius: 50%;
- background: var(--el-color-primary);
- }
- }
- .btns {
- display: grid;
- grid-template-columns: repeat(2, 1fr);
- gap: 8px;
- .el-button {
- margin-left: 4px;
- margin-bottom: 6px;
- padding: 10px 15px !important;
- // padding: 0px;
- // width: 93px;
- }
- }
- }
- }
- .right {
- display: inline-block;
- font-size: 16px;
- }
- }
- </style>
- <style lang="scss">
- .tab-content {
- .el-scrollbar__wrap {
- .el-scrollbar__view {
- width: 96%;
- }
- }
- }
- </style>
|