|
|
@@ -0,0 +1,255 @@
|
|
|
+<script setup lang="ts">
|
|
|
+import AnalysisReportPreview from '@/components/AnalysisReportPreview.vue';
|
|
|
+import { useDictionaries } from '@/libs/dictionary';
|
|
|
+import type { PatientModel, PatientReportModel } from '@/model';
|
|
|
+import { patientMethod } from '@/request/api/patient.api';
|
|
|
+import { patientIndicatorMethod, reportMethod, schemeMethod } from '@/request/api/report.api';
|
|
|
+import { ArrowDownOutlined, ArrowUpOutlined } from '@ant-design/icons-vue';
|
|
|
+import { useRequest, useWatcher } from 'alova/client';
|
|
|
+import { VxeUI } from 'vxe-pc-ui';
|
|
|
+
|
|
|
+
|
|
|
+const props = defineProps<{ report?: PatientReportModel['report'], patient: PatientModel }>();
|
|
|
+const { data: patient, loading: petientLoading } = useRequest(
|
|
|
+ () => patientMethod(props.patient.id),
|
|
|
+ { initialData: props.patient },
|
|
|
+);
|
|
|
+const { data: indicator, loading: indicatorLoading } = useRequest(
|
|
|
+ () => patientIndicatorMethod(props.patient.id),
|
|
|
+ { initialData: [] },
|
|
|
+);
|
|
|
+const reportId = ref<string>();
|
|
|
+const { data: report, loading: reportLoading } = useWatcher(
|
|
|
+ () => reportMethod(reportId.value!),
|
|
|
+ [ reportId ],
|
|
|
+ { initialData: props.report },
|
|
|
+);
|
|
|
+const { data: scheme, loading: schemeLoading } = useWatcher(
|
|
|
+ () => schemeMethod(reportId.value!),
|
|
|
+ [ reportId ],
|
|
|
+ { initialData: props.report },
|
|
|
+);
|
|
|
+
|
|
|
+onBeforeMount(() => {
|
|
|
+ if ( props.report?.id ) reportId.value = props.report.id;
|
|
|
+});
|
|
|
+
|
|
|
+const gender = useDictionaries('sys_user_sex', computed(() => patient.value.gender));
|
|
|
+const job = useDictionaries('job', computed(() => patient.value.job));
|
|
|
+const drinkState = useDictionaries('sys_yes_no', computed(() => patient.value.drinkState));
|
|
|
+const smokeState = useDictionaries('sys_yes_no', computed(() => patient.value.smokeState));
|
|
|
+const hobbyFlavor = useDictionaries('hobby_flavor', computed(() => patient.value.hobbyFlavor));
|
|
|
+const foodAllergy = useDictionaries('food_allergy', computed(() => patient.value.foodAllergy));
|
|
|
+const womenSpecialPeriod = useDictionaries('women_special_period', computed(() => patient.value.womenSpecialPeriod));
|
|
|
+
|
|
|
+function previewAnalysisRecord(show: 'report' | 'scheme') {
|
|
|
+ const titleRef = { report: `健康分析报告`, scheme: `调理方案` };
|
|
|
+ VxeUI.drawer.open({
|
|
|
+ title: titleRef[ show ],
|
|
|
+ maskClosable: true,
|
|
|
+ escClosable: true,
|
|
|
+ width: window.innerWidth * 0.85,
|
|
|
+ slots: {
|
|
|
+ default() {
|
|
|
+ return h(AnalysisReportPreview, <any> {
|
|
|
+ show,
|
|
|
+ report: report.value,
|
|
|
+ patient: patient.value,
|
|
|
+ });
|
|
|
+ },
|
|
|
+ title() {
|
|
|
+ return h('div', { class: 'analysis-record-title' });
|
|
|
+ },
|
|
|
+ corner() {
|
|
|
+ return h('div', { class: 'analysis-record-corner' });
|
|
|
+ },
|
|
|
+ },
|
|
|
+ });
|
|
|
+}
|
|
|
+</script>
|
|
|
+<template>
|
|
|
+ <div class="page-container flex flex-col">
|
|
|
+ <div class="card patient-card">
|
|
|
+ <div class="card__title">
|
|
|
+ <span>基础信息</span>
|
|
|
+ <a-button type="primary" size="small">更新记录</a-button>
|
|
|
+ </div>
|
|
|
+ <div class="card__content">
|
|
|
+ <div class="row">
|
|
|
+ <span>{{ patient.name }}</span>
|
|
|
+ <span>{{ gender.join() }}</span>
|
|
|
+ <span>{{ patient.age }}岁</span>
|
|
|
+ <span v-if="womenSpecialPeriod?.length">饮酒:{{ womenSpecialPeriod.join() }}</span>
|
|
|
+ <template v-for="d in job">
|
|
|
+ <span v-if="d">{{ d }}</span>
|
|
|
+ </template>
|
|
|
+ <span v-if="patient.phone">手机号:{{ patient.phone }}</span>
|
|
|
+ <span>身份证号:{{ patient.cardno }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="row">
|
|
|
+ <span>{{ patient.height }}cm</span>
|
|
|
+ <span>{{ patient.weight }}kg</span>
|
|
|
+ <span v-if="drinkState?.length">饮酒:{{ drinkState.join() }}</span>
|
|
|
+ <span v-if="smokeState?.length ">抽烟:{{ smokeState.join() }}</span>
|
|
|
+ <span v-if="hobbyFlavor?.length">喜好口味:<a-tag v-for="d in hobbyFlavor" :key="d">{{ d }}</a-tag></span>
|
|
|
+ <span v-if="foodAllergy?.length">食物过敏:<a-tag v-for="d in foodAllergy" :key="d">{{ d }}</a-tag></span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="card report-card">
|
|
|
+ <div class="card__title">
|
|
|
+ <span>健康状况</span>
|
|
|
+ <a-button type="primary" size="small">更新记录</a-button>
|
|
|
+ </div>
|
|
|
+ <div class="card__content">
|
|
|
+ <a-descriptions :column="3">
|
|
|
+ <a-descriptions-item v-if="report.pickedSymptom" label="症状信息" :span="3">{{ report.pickedSymptom }}
|
|
|
+ </a-descriptions-item>
|
|
|
+ <a-descriptions-item>
|
|
|
+ <a-image :width="200" :src="report.upImg" :preview="false" />
|
|
|
+ </a-descriptions-item>
|
|
|
+ <a-descriptions-item>
|
|
|
+ <a-image :width="200" :src="report.downImg" :preview="false" />
|
|
|
+ </a-descriptions-item>
|
|
|
+ <a-descriptions-item>
|
|
|
+ <a-image :width="200" :src="report.faceImg" :preview="false" />
|
|
|
+ </a-descriptions-item>
|
|
|
+ </a-descriptions>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="card report-card">
|
|
|
+ <div class="card__title">
|
|
|
+ <span>健康分析报告</span>
|
|
|
+ <a-button type="primary" size="small" :loading="reportLoading" @click="previewAnalysisRecord('report')">
|
|
|
+ 报告详情
|
|
|
+ </a-button>
|
|
|
+ </div>
|
|
|
+ <div class="card__content">
|
|
|
+ <a-descriptions :column="3">
|
|
|
+ <a-descriptions-item v-if="report.time" label="报告日期" :span="3">{{ report.time }}
|
|
|
+ </a-descriptions-item>
|
|
|
+ <a-descriptions-item v-if="report.willillStateName" label="健康状态">{{ report.willillStateName }}
|
|
|
+ </a-descriptions-item>
|
|
|
+ <a-descriptions-item v-if="report.willillDegreeName" label="程度" :span="2">{{ report.willillDegreeName }}
|
|
|
+ </a-descriptions-item>
|
|
|
+ <a-descriptions-item v-if="report.willillFunctionName" label="表现">{{ report.willillFunctionName }}
|
|
|
+ </a-descriptions-item>
|
|
|
+ <a-descriptions-item v-if="report.constitutionGroupName" label="体质" :span="2">
|
|
|
+ {{ report.constitutionGroupName }}
|
|
|
+ </a-descriptions-item>
|
|
|
+ </a-descriptions>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="card report-card">
|
|
|
+ <div class="card__title">
|
|
|
+ <span>调理方案</span>
|
|
|
+ <a-button type="primary" size="small" :loading="schemeLoading" @click="previewAnalysisRecord('scheme')">
|
|
|
+ 方案详情
|
|
|
+ </a-button>
|
|
|
+ </div>
|
|
|
+ <div class="card__content">
|
|
|
+ <a-descriptions :column="1">
|
|
|
+ <a-descriptions-item v-if="scheme.process" label="调理进程">{{ scheme.process }}</a-descriptions-item>
|
|
|
+ <a-descriptions-item v-if="scheme.types?.length" label="方案内容">
|
|
|
+ <div style="margin-top: -8px">
|
|
|
+ <a-tag style="margin-top: 8px;" v-for="item in scheme.types" :key="item.type">{{ item.type }}</a-tag>
|
|
|
+ </div>
|
|
|
+ </a-descriptions-item>
|
|
|
+ </a-descriptions>
|
|
|
+ <!--{{ scheme }}-->
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="card report-card">
|
|
|
+ <div class="card__title">
|
|
|
+ <span>指标信息</span>
|
|
|
+ <a-button type="primary" size="small">更新记录</a-button>
|
|
|
+ </div>
|
|
|
+ <div class="card__content">
|
|
|
+ <a-descriptions :column="3">
|
|
|
+ <a-descriptions-item v-for="item in indicator" :label="item?.name" :key="item?.quotaId">
|
|
|
+ {{ item.quotaVal }}
|
|
|
+ {{ item.unit }}
|
|
|
+ <ArrowUpOutlined class="icon" v-if="item.abnormal === 1" />
|
|
|
+ <ArrowDownOutlined class="icon" v-else-if="item.abnormal === -1" />
|
|
|
+ </a-descriptions-item>
|
|
|
+ </a-descriptions>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+<style scoped lang="scss">
|
|
|
+.card {
|
|
|
+ color: #333;
|
|
|
+
|
|
|
+ &__title {
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: 700;
|
|
|
+
|
|
|
+ .ant-btn {
|
|
|
+ margin-left: 8px;
|
|
|
+ }
|
|
|
+
|
|
|
+ &::before {
|
|
|
+ content: "";
|
|
|
+ display: inline-block;
|
|
|
+ margin-right: 8px;
|
|
|
+ height: 1em;
|
|
|
+ width: 2px;
|
|
|
+ background: linear-gradient(0deg, #4c6fd7 0%, #435cc8 100%);
|
|
|
+ transform: translateY(2px);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ &__content {
|
|
|
+ padding: 16px 24px 0;
|
|
|
+ font-size: 14px;
|
|
|
+
|
|
|
+ .row {
|
|
|
+ padding-bottom: 16px;
|
|
|
+
|
|
|
+ &:first-of-type {
|
|
|
+ margin-top: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ &:last-of-type {
|
|
|
+ margin-bottom: 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep(.ant-descriptions-item-container) {
|
|
|
+ .ant-descriptions-item-label {
|
|
|
+ flex: none;
|
|
|
+ }
|
|
|
+
|
|
|
+ .ant-descriptions-item-content {
|
|
|
+ flex-wrap: wrap;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.patient-card {
|
|
|
+ .card__content {
|
|
|
+ > div {
|
|
|
+ &:nth-of-type(1) {
|
|
|
+ > span::after {
|
|
|
+ content: ",";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ &:nth-of-type(2) {
|
|
|
+ > span::after {
|
|
|
+ content: ";";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.icon {
|
|
|
+ margin-left: 4px;
|
|
|
+ font-size: 18px;
|
|
|
+ color: #b22222ff;
|
|
|
+ transform: translateY(2px);
|
|
|
+}
|
|
|
+</style>
|