Files
zyt/admin/src/views/tcm/diagnosis/edit.vue
T
long 320d3783ac 日常记录
归总 血糖、饮食、运动、备注、代办
2026-05-07 14:46:12 +08:00

1819 lines
65 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="edit-drawer">
<el-drawer
v-model="visible"
size="60%"
:before-close="handleClose"
:z-index="viewOnly ? 4000 : 1500"
:modal="true"
class="diagnosis-drawer tcm-diagnosis-drawer"
>
<template #header>
<div class="tcm-dd-header">
<div class="tcm-dd-header__row">
<h2 class="tcm-dd-header__title">{{ drawerTitle }}</h2>
<el-tag
v-if="viewOnly"
type="info"
effect="plain"
round
size="small"
class="tcm-dd-header__badge"
>
只读
</el-tag>
<el-tag
v-else-if="mode === 'add'"
type="success"
effect="plain"
round
size="small"
class="tcm-dd-header__badge"
>
新建
</el-tag>
<el-tag
v-else
type="warning"
effect="plain"
round
size="small"
class="tcm-dd-header__badge"
>
编辑
</el-tag>
</div>
<p v-if="formData.patient_name || formData.id" class="tcm-dd-header__sub">
<span v-if="formData.patient_name" class="tcm-dd-header__name">{{ formData.patient_name }}</span>
<span v-if="formData.id" class="tcm-dd-header__id">
<span v-if="formData.patient_name" class="tcm-dd-header__sep">·</span>
诊单 {{ formData.patient_id || formData.id }}
</span>
</p>
</div>
</template>
<el-tabs v-model="activeTab" class="diagnosis-tabs tcm-diagnosis-tabs">
<!-- 基本信息标签页 -->
<el-tab-pane label="病历" name="basic">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="160px"
>
<fieldset
:disabled="viewOnly"
class="diagnosis-view-fieldset border-0 min-w-0 p-0 m-0"
>
<!-- 基本信息 -->
<el-divider content-position="left">基本信息</el-divider>
<el-form-item label="诊单ID">
<el-input v-model="formData.patient_id" disabled placeholder="系统自动生成" />
</el-form-item>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="姓名" prop="patient_name">
<el-input
v-model="formData.patient_name"
placeholder="请输入姓名"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="身份证号" prop="id_card">
<el-input
v-model="formData.id_card"
placeholder="请输入身份证号"
maxlength="18"
@focus="handleIdCardFocus"
@blur="handleIdCardBlur"
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="手机号" prop="phone">
<template v-if="showPhoneMaskedEdit">
<el-input
:model-value="
phoneRevealUnlocked ? originalPhone || '' : maskPhone(originalPhone || '')
"
readonly
placeholder="点击可查看完整手机号"
maxlength="11"
class="cursor-pointer phone-mask-toggle"
@click="togglePhoneReveal"
/>
<p
v-if="originalPhone && !phoneRevealUnlocked"
class="text-xs text-gray-400 mt-1"
>
当前为脱敏显示点击输入框可查看完整号码
</p>
</template>
<el-input
v-else
v-model="formData.phone"
placeholder="请输入手机号"
maxlength="11"
@focus="handlePhoneFocus"
@blur="handlePhoneBlur"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="性别" prop="gender">
<el-radio-group v-model="formData.gender">
<el-radio :label="1"></el-radio>
<el-radio :label="0"></el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="年龄" prop="age">
<el-input-number
v-model="formData.age"
:min="0"
:max="150"
placeholder="请输入年龄"
class="w-full"
/>
</el-form-item>
</el-col>
</el-row>
<!-- 生命体征 -->
<el-divider content-position="left">生命体征</el-divider>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="婚姻状态" prop="marital_status">
<el-select
v-model="formData.marital_status"
placeholder="请选择婚姻状态"
class="w-full"
:popper-options="{ strategy: 'fixed' }"
popper-class="high-z-index"
>
<el-option label="未婚" :value="0" />
<el-option label="已婚" :value="1" />
<el-option label="离异" :value="2" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="就诊人身高(cm)" prop="height">
<el-input-number
v-model="formData.height"
:min="0"
:max="300"
placeholder="请输入身高"
class="w-full"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="体重(kg)" prop="weight">
<el-input-number
v-model="formData.weight"
:min="0"
:max="500"
:step="0.1"
placeholder="请输入体重"
class="w-full"
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="地区" prop="region">
<el-input
v-model="formData.region"
placeholder="请输入地区"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="就诊人血压(高压mmHg)" prop="systolic_pressure">
<el-input-number
v-model="formData.systolic_pressure"
:min="0"
:max="250"
placeholder="请输入高压"
class="w-full"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="就诊人血压(低压mmHg)" prop="diastolic_pressure">
<el-input-number
v-model="formData.diastolic_pressure"
:min="0"
:max="150"
placeholder="请输入低压"
class="w-full"
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="空腹血糖(mmol/L)" prop="fasting_blood_sugar">
<el-input
v-model="formData.fasting_blood_sugar"
placeholder="请输入空腹血糖,如:8.5 或 8-9"
maxlength="20"
class="w-full"
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="诊断类型" prop="diagnosis_type">
<el-select
v-model="formData.diagnosis_type"
placeholder="请选择诊断类型"
class="w-full"
:popper-options="{ strategy: 'fixed' }"
popper-class="high-z-index"
>
<el-option
v-for="item in diagnosisTypeOptions"
:key="item.value"
:label="item.name"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="状态" prop="status">
<el-radio-group v-model="formData.status">
<el-radio :label="1">启用</el-radio>
<el-radio :label="0">禁用</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="在用药物" prop="current_medications">
<el-input
v-model="formData.current_medications"
type="textarea"
:rows="3"
placeholder="请填写患者当前正在使用的药物(如降压药、降糖药等),多种请换行或顿号分隔"
maxlength="2000"
show-word-limit
/>
</el-form-item>
</el-col>
</el-row>
<el-divider content-position="left">主诉</el-divider>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="当地医院诊断日期" prop="diagnosis_date">
<el-date-picker
v-model="formData.diagnosis_date"
type="date"
placeholder="请选择诊断日期"
value-format="YYYY-MM-DD"
class="w-full"
:popper-options="{ strategy: 'fixed' }"
popper-class="high-z-index"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="发现糖尿病患病史" prop="diabetes_discovery_year">
<el-input
v-model="formData.diabetes_discovery_year"
clearable
maxlength="50"
show-word-limit
placeholder="可填数字或文字,如:5、1年、半年"
class="w-full"
/>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="当地医院诊断结果" prop="local_hospital_diagnosis" class="checkbox-form-item">
<el-checkbox-group v-model="formData.local_hospital_diagnosis">
<el-checkbox-button label="糖尿病">糖尿病</el-checkbox-button>
<el-checkbox-button label="消渴病">消渴病</el-checkbox-button>
<el-checkbox-button label="糖尿病前期">糖尿病前期</el-checkbox-button>
</el-checkbox-group>
</el-form-item>
<el-form-item label="当地就诊医院名称" prop="local_hospital_name">
<el-input
v-model="formData.local_hospital_name"
placeholder="请输入当地就诊医院名称(不能填写当地、本地、互联网等关键词)"
/>
</el-form-item>
<el-divider content-position="left">现病史</el-divider>
<el-row :gutter="20">
<el-form-item label="口腔感觉" class="checkbox-form-item">
<el-checkbox-group v-model="formData.appetite">
<el-checkbox-button v-for="item in appetiteOptions" :key="item.value" :label="item.value">
{{ item.name }}
</el-checkbox-button>
</el-checkbox-group>
</el-form-item>
</el-row>
<el-row :gutter="20">
<el-col :span="20">
<el-form-item label="每日饮水量" class="compact-form-item">
<el-radio-group v-model="formData.water_intake">
<el-radio-button label=""></el-radio-button>
<el-radio-button v-for="item in waterIntakeOptions" :key="item.value" :label="item.value">
{{ item.name }}
</el-radio-button>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="近一个月体重变化" class="compact-form-item">
<el-radio-group v-model="formData.weight_change">
<el-radio-button label=""></el-radio-button>
<el-radio-button v-for="item in weightChangeOptions" :key="item.value" :label="item.value">
{{ item.name }}
</el-radio-button>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="脂肪肝程度" class="compact-form-item">
<el-radio-group v-model="formData.fatty_liver_degree">
<el-radio-button label=""></el-radio-button>
<el-radio-button v-for="item in fattyLiverDegreeOptions" :key="item.value" :label="item.value">
{{ item.name }}
</el-radio-button>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="饮食情况" class="checkbox-form-item">
<el-checkbox-group v-model="formData.diet_condition">
<el-checkbox-button v-for="item in dietConditionOptions" :key="item.value" :label="item.value">
{{ item.name }}
</el-checkbox-button>
</el-checkbox-group>
</el-form-item>
<el-form-item label="肢体感觉" class="checkbox-form-item">
<el-checkbox-group v-model="formData.body_feeling">
<el-checkbox-button v-for="item in bodyFeelingOptions" :key="item.value" :label="item.value">
{{ item.name }}
</el-checkbox-button>
</el-checkbox-group>
</el-form-item>
<el-form-item label="睡眠情况" class="checkbox-form-item">
<el-checkbox-group v-model="formData.sleep_condition">
<el-checkbox-button v-for="item in sleepConditionOptions" :key="item.value" :label="item.value">
{{ item.name }}
</el-checkbox-button>
</el-checkbox-group>
</el-form-item>
<el-form-item label="眼睛情况" class="checkbox-form-item">
<el-checkbox-group v-model="formData.eye_condition">
<el-checkbox-button v-for="item in eyeConditionOptions" :key="item.value" :label="item.value">
{{ item.name }}
</el-checkbox-button>
</el-checkbox-group>
</el-form-item>
<el-form-item label="头部感觉" class="checkbox-form-item">
<el-checkbox-group v-model="formData.head_feeling">
<el-checkbox-button v-for="item in headFeelingOptions" :key="item.value" :label="item.value">
{{ item.name }}
</el-checkbox-button>
</el-checkbox-group>
</el-form-item>
<el-form-item label="出汗情况" class="checkbox-form-item">
<el-checkbox-group v-model="formData.sweat_condition">
<el-checkbox-button v-for="item in sweatConditionOptions" :key="item.value" :label="item.value">
{{ item.name }}
</el-checkbox-button>
</el-checkbox-group>
</el-form-item>
<el-form-item label="皮肤情况" class="checkbox-form-item">
<el-checkbox-group v-model="formData.skin_condition">
<el-checkbox-button v-for="item in skinConditionOptions" :key="item.value" :label="item.value">
{{ item.name }}
</el-checkbox-button>
</el-checkbox-group>
</el-form-item>
<el-form-item label="小便情况" class="checkbox-form-item">
<el-checkbox-group v-model="formData.urine_condition">
<el-checkbox-button v-for="item in urineConditionOptions" :key="item.value" :label="item.value">
{{ item.name }}
</el-checkbox-button>
</el-checkbox-group>
</el-form-item>
<el-form-item label="大便情况" class="checkbox-form-item">
<el-checkbox-group v-model="formData.stool_condition">
<el-checkbox-button v-for="item in stoolConditionOptions" :key="item.value" :label="item.value">
{{ item.name }}
</el-checkbox-button>
</el-checkbox-group>
</el-form-item>
<el-form-item label="腰肾情况" class="checkbox-form-item">
<el-checkbox-group v-model="formData.kidney_condition">
<el-checkbox-button v-for="item in kidneyConditionOptions" :key="item.value" :label="item.value">
{{ item.name }}
</el-checkbox-button>
</el-checkbox-group>
</el-form-item>
<el-form-item label="其他补充" prop="symptoms">
<el-input
v-model="formData.symptoms"
type="textarea"
:rows="3"
placeholder="请输入症状"
/>
</el-form-item>
<!-- 既往史 -->
<el-divider content-position="left">既往史</el-divider>
<el-form-item label="" prop="past_history" class="checkbox-form-item">
<el-checkbox-group v-model="formData.past_history">
<el-checkbox-button
v-for="item in pastHistoryOptions"
:key="item.value"
:label="item.value"
>
{{ item.name }}
</el-checkbox-button>
</el-checkbox-group>
</el-form-item>
<!-- 其他病史 -->
<el-divider content-position="left">其他病史</el-divider>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="外伤史">
<el-radio-group v-model="formData.trauma_history">
<el-radio-button :label="1"></el-radio-button>
<el-radio-button :label="0"></el-radio-button>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="手术史">
<el-radio-group v-model="formData.surgery_history">
<el-radio-button :label="1"></el-radio-button>
<el-radio-button :label="0"></el-radio-button>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="过敏史">
<el-radio-group v-model="formData.allergy_history">
<el-radio-button :label="1"></el-radio-button>
<el-radio-button :label="0"></el-radio-button>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="家族病史">
<el-radio-group v-model="formData.family_history">
<el-radio-button :label="1"></el-radio-button>
<el-radio-button :label="0"></el-radio-button>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="妊娠哺乳史">
<el-radio-group v-model="formData.pregnancy_history">
<el-radio-button :label="1"></el-radio-button>
<el-radio-button :label="0"></el-radio-button>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<!-- 诊断信息 -->
<el-divider content-position="left">诊断信息</el-divider>
<el-form-item label="病史补充" prop="remark">
<el-input
v-model="formData.remark"
type="textarea"
:rows="2"
placeholder="请输入病史补充"
/>
</el-form-item>
</fieldset>
</el-form>
</el-tab-pane>
<el-tab-pane label="医生备注" name="doctorNote" :disabled="!formData.id" lazy>
<div v-if="formData.id" class="p-4">
<NoteTimeline
:notes="diagNotes"
:diagnosis-id="Number(formData.id)"
:readonly="viewOnly"
@refresh="fetchDiagNotes"
/>
</div>
<el-empty v-else description="请先保存诊单后查看" />
</el-tab-pane>
<el-tab-pane label="跟踪备注" name="trackingNote" :disabled="!formData.id" lazy>
<div v-if="formData.id" class="p-4">
<TrackingNoteTimeline
:notes="trackingNotes"
:diagnosis-id="Number(formData.id)"
:readonly="viewOnly"
@refresh="fetchTrackingNotes"
/>
</div>
<el-empty v-else description="请先保存诊单后查看" />
</el-tab-pane>
<el-tab-pane label="日常记录" name="daily" :disabled="!formData.id" lazy>
<daily-matrix
v-if="formData.id"
:diagnosis-id="Number(formData.id)"
:patient-id="Number(formData.patient_id)"
:age="formData.age"
:patient-name="formData.patient_name"
:read-only="viewOnly"
/>
<el-empty v-else description="请先保存诊单后查看" />
</el-tab-pane>
<!-- 病历记录标签页开方后自动显示 -->
<el-tab-pane label="处方" name="bingli" :disabled="!formData.id" v-if="hasPermission(['tcm.diagnosis/chufang'])">
<div v-if="formData.id" class="bingli-tab-content">
<!-- 病历记录列表 -->
<case-record-list
ref="caseRecordListRef"
:diagnosis-id="Number(formData.id)"
:read-only="viewOnly"
@view="handleViewCase"
@openPrescription="handleOpenPrescription"
/>
</div>
<el-empty v-else description="请先保存诊单,开方后病历将在此显示" />
</el-tab-pane>
<!-- 业务订单复用处方业务订单接口按患者ID聚合 / 按当前诊单过滤 -->
<el-tab-pane
label="业务订单"
name="patientOrders"
:disabled="!formData.id"
lazy
v-if="hasPermission(['tcm.diagnosis/patientOrders'])"
>
<patient-order-list
v-if="formData.id"
:diagnosis-id="Number(formData.id)"
:patient-id="Number(formData.patient_id) || 0"
/>
<el-empty v-else description="请先保存诊单后查看业务订单" />
</el-tab-pane>
<el-tab-pane
v-if="hasPermission(['tcm.diagnosis/huifang'])"
label="视频录制回放记录"
name="visit"
:disabled="!formData.id"
lazy
>
<call-record-panel
v-if="formData.id"
ref="callRecordPanelRef"
:diagnosis-id="Number(formData.id)"
/>
<el-empty v-else description="请先保存诊单后再查看视频录制回放记录" />
</el-tab-pane>
<el-tab-pane
v-if="hasPermission(['tcm.diagnosis/chat'])"
label="聊天记录"
name="chat"
:disabled="!formData.id"
lazy
>
<im-chat-record-panel
v-if="activeTab === 'chat' && formData.id"
:diagnosis-id="Number(formData.id)"
/>
<el-empty v-else-if="!formData.id" description="请先保存诊单后再查看聊天记录" />
</el-tab-pane>
<el-tab-pane
v-if="
hasPermission(['tcm.diagnosis/assign']) ||
hasPermission(['tcm.diagnosis/detail'])
"
label="指派医助记录"
name="assignLog"
:disabled="!formData.id"
lazy
>
<assign-log-panel
v-if="formData.id"
:diagnosis-id="Number(formData.id)"
/>
<el-empty v-else description="请先保存诊单后再查看指派记录" />
</el-tab-pane>
<el-tab-pane
v-if="hasPermission(['doctor.appointment/lists'])"
label="挂号记录"
name="appointmentRecords"
:disabled="!formData.id"
lazy
>
<appointment-record-panel
v-if="formData.id"
:diagnosis-id="Number(formData.id)"
/>
<el-empty v-else description="请先保存诊单后再查看挂号记录" />
</el-tab-pane>
</el-tabs>
<!-- 处方详情(查看病历) -->
<tcm-prescription ref="prescriptionRef" @success="caseRecordListRef?.refresh?.()" />
<template #footer>
<div class="tcm-dd-footer">
<el-button class="tcm-dd-footer__btn" @click="handleClose">
{{ viewOnly ? '关闭' : '取消' }}
</el-button>
<el-button
v-if="!viewOnly && activeTab === 'basic'"
class="tcm-dd-footer__btn"
type="primary"
@click="handleSubmit"
:loading="submitting"
>
保存病历
</el-button>
</div>
</template>
</el-drawer>
</div>
</template>
<script setup lang="ts">
import { tcmDiagnosisAdd, tcmDiagnosisEdit, tcmDiagnosisDetail, checkPhone, checkIdCard, diagnosisTrackingNotes } from '@/api/tcm'
import { getDictData } from '@/api/app'
import feedback from '@/utils/feedback'
import { hasPermission } from '@/utils/perm'
import useUserStore from '@/stores/modules/user'
import useAppStore from '@/stores/modules/app'
import { ElMessage } from 'element-plus'
import { QuestionFilled } from '@element-plus/icons-vue'
import DailyMatrix from './components/DailyMatrix.vue'
import CaseRecordList from './components/CaseRecordList.vue'
import CallRecordPanel from './components/CallRecordPanel.vue'
import ImChatRecordPanel from './components/ImChatRecordPanel.vue'
import AssignLogPanel from './components/AssignLogPanel.vue'
import AppointmentRecordPanel from './components/AppointmentRecordPanel.vue'
import NoteTimeline from '@/views/patient/reception/components/NoteTimeline.vue'
import TrackingNoteTimeline from './components/TrackingNoteTimeline.vue'
import PatientOrderList from './components/PatientOrderList.vue'
import TcmPrescription from '@/components/tcm-prescription/index.vue'
import { getDoctorNotes } from '@/api/patient'
const emit = defineEmits(['success'])
const appStore = useAppStore()
const getImageUrl = (url: string) => (url?.indexOf?.('http') === 0 ? url : appStore.getImageUrl(url || ''))
const caseRecordListRef = ref()
const callRecordPanelRef = ref<{ refresh?: () => void } | null>(null)
const prescriptionRef = ref()
const visible = ref(false)
/** 只读查看:与 consumers 处方等处「查看诊单」一致,全部 Tab 仅展示不可保存 */
const viewOnly = ref(false)
const formRef = ref()
const mode = ref('add')
const submitting = ref(false)
/** 拥有后手机号可正常编辑,失焦不再强制脱敏 */
const hasPhonePlainPermission = computed(() => hasPermission(['tcm.diagnosis/phonePlain']))
/** 编辑且无明文权限:只读脱敏,点击切换查看完整号 */
const showPhoneMaskedEdit = computed(() => mode.value === 'edit' && !hasPhonePlainPermission.value)
const phoneRevealUnlocked = ref(false)
const activeTab = ref('basic')
const drawerTitle = computed(() => {
if (viewOnly.value) return '诊单详情'
return mode.value === 'add' ? '新增诊单' : '编辑诊单'
})
const diagNotes = ref<any[]>([])
const fetchDiagNotes = async () => {
if (!formData.value.id) return
try {
diagNotes.value = await getDoctorNotes({ diagnosis_id: Number(formData.value.id) }) || []
} catch { diagNotes.value = [] }
}
const trackingNotes = ref<any[]>([])
const fetchTrackingNotes = async () => {
if (!formData.value.id) return
try {
trackingNotes.value = await diagnosisTrackingNotes({ diagnosis_id: Number(formData.value.id) }) || []
} catch { trackingNotes.value = [] }
}
watch(() => activeTab.value, async (tab) => {
if (tab === 'doctorNote' && formData.value.id) {
await fetchDiagNotes()
}
if (tab === 'trackingNote' && formData.value.id) {
await fetchTrackingNotes()
}
})
watch([visible, activeTab], () => {
if (!visible.value) return
if (activeTab.value === 'chat' && !hasPermission(['tcm.diagnosis/chat'])) {
activeTab.value = 'basic'
}
if (activeTab.value === 'visit' && !hasPermission(['tcm.diagnosis/huifang'])) {
activeTab.value = 'basic'
}
if (
activeTab.value === 'assignLog' &&
!hasPermission(['tcm.diagnosis/assign']) &&
!hasPermission(['tcm.diagnosis/detail'])
) {
activeTab.value = 'basic'
}
if (activeTab.value === 'appointmentRecords' && !hasPermission(['doctor.appointment/lists'])) {
activeTab.value = 'basic'
}
})
const formData = ref({
id: '',
patient_id: '',
patient_name: '',
id_card: '',
phone: '',
gender: 1,
age: undefined as number | undefined,
diagnosis_date: '',
diagnosis_type: '',
syndrome_type: '',
diabetes_type: '',
diabetes_discovery_year: '',
local_hospital_diagnosis: [],
local_hospital_name: '',
marital_status: undefined as number | undefined,
height: undefined as number | undefined,
weight: undefined as number | undefined,
region: '',
systolic_pressure: undefined as number | undefined,
diastolic_pressure: undefined as number | undefined,
fasting_blood_sugar: '',
appetite: [] as string[],
water_intake: '',
diet_condition: [],
weight_change: '',
body_feeling: [],
sleep_condition: [],
eye_condition: [],
head_feeling: [],
sweat_condition: [],
skin_condition: [],
urine_condition: [],
stool_condition: [],
kidney_condition: [],
fatty_liver_degree: '',
past_history: [],
trauma_history: 0,
surgery_history: 0,
allergy_history: 0,
family_history: 0,
pregnancy_history: 0,
assistant_id: undefined as number | undefined,
symptoms: '',
tongue_coating: '',
pulse: '',
treatment_principle: '',
prescription: '',
doctor_advice: '',
remark: '',
current_medications: '',
status: 1,
external_userid: ''
})
// 保存原始完整数据
const originalPhone = ref('')
const originalIdCard = ref('')
const isPhoneFocused = ref(false)
const isIdCardFocused = ref(false)
// 脱敏函数
const maskPhone = (phone: string) => {
if (!phone || phone.length < 11) return phone
return phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
}
const togglePhoneReveal = () => {
if (!originalPhone.value) return
phoneRevealUnlocked.value = !phoneRevealUnlocked.value
}
const maskIdCard = (idCard: string) => {
if (!idCard) return idCard
if (idCard.length === 15) {
return idCard.replace(/(\d{6})\d{5}(\d{4})/, '$1*****$2')
} else if (idCard.length === 18) {
return idCard.replace(/(\d{6})\d{8}(\d{4})/, '$1********$2')
}
return idCard
}
// 手机号聚焦 - 显示完整数据(无「明文」权限时仅新增模式在失焦后可再次展开编辑)
const handlePhoneFocus = () => {
isPhoneFocused.value = true
if (!originalPhone.value) return
if (hasPhonePlainPermission.value) {
formData.value.phone = originalPhone.value
return
}
if (mode.value === 'add') {
formData.value.phone = originalPhone.value
}
}
// 手机号失焦:有明文权限则保持明文并校验;新增且无明文权限时仍脱敏展示
const handlePhoneBlur = async () => {
isPhoneFocused.value = false
if (hasPhonePlainPermission.value) {
if (formData.value.phone && formData.value.phone.length === 11) {
originalPhone.value = formData.value.phone
if (/^1[3-9]\d{9}$/.test(formData.value.phone)) {
try {
const result = await checkPhone({
phone: formData.value.phone,
id: formData.value.id || ''
})
if (result.exists) {
ElMessage.warning(result.message)
}
} catch (error) {
console.error('检查手机号失败:', error)
}
}
}
return
}
if (mode.value !== 'add') {
return
}
if (formData.value.phone && formData.value.phone.length === 11) {
originalPhone.value = formData.value.phone
if (/^1[3-9]\d{9}$/.test(formData.value.phone)) {
try {
const result = await checkPhone({
phone: formData.value.phone,
id: formData.value.id || ''
})
if (result.exists) {
ElMessage.warning(result.message)
}
} catch (error) {
console.error('检查手机号失败:', error)
}
}
formData.value.phone = maskPhone(formData.value.phone)
}
}
// 身份证聚焦 - 显示完整数据
const handleIdCardFocus = () => {
isIdCardFocused.value = true
if (originalIdCard.value) {
formData.value.id_card = originalIdCard.value
}
}
// 身份证失焦 - 恢复脱敏并验证
const handleIdCardBlur = async () => {
isIdCardFocused.value = false
// 保存原始数据并脱敏显示
if (formData.value.id_card && (formData.value.id_card.length === 15 || formData.value.id_card.length === 18)) {
originalIdCard.value = formData.value.id_card
// 验证身份证格式并计算年龄
if (/^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/.test(formData.value.id_card)) {
// 从身份证提取出生日期计算年龄
const id = formData.value.id_card
const birthYear = parseInt(id.substring(6, 10))
const birthMonth = parseInt(id.substring(10, 12))
const birthDay = parseInt(id.substring(12, 14))
const today = new Date()
let age = today.getFullYear() - birthYear
if (today.getMonth() + 1 < birthMonth || (today.getMonth() + 1 === birthMonth && today.getDate() < birthDay)) {
age--
}
formData.value.age = age
// 验证身份证唯一性
try {
const result = await checkIdCard({
id_card: formData.value.id_card,
id: formData.value.id || ''
})
if (result.exists) {
ElMessage.warning(result.message)
}
} catch (error) {
console.error('检查身份证号失败:', error)
}
}
// 脱敏显示
formData.value.id_card = maskIdCard(formData.value.id_card)
}
}
// 自定义验证规则
const validatePhone = (rule: any, value: any, callback: any) => {
// 使用原始数据进行验证
const phoneToValidate = originalPhone.value || value
if (!phoneToValidate) {
callback(new Error('请输入手机号'))
return
}
if (!/^1[3-9]\d{9}$/.test(phoneToValidate)) {
callback(new Error('手机号格式不正确'))
return
}
callback()
}
const validateIdCard = (rule: any, value: any, callback: any) => {
// 使用原始数据进行验证
const idCardToValidate = originalIdCard.value || value
if (idCardToValidate && !/^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/.test(idCardToValidate)) {
callback(new Error('身份证号格式不正确'))
return
}
callback()
}
const formRules = {
patient_name: [{ required: true, message: '请输入患者姓名', trigger: 'blur' }],
id_card: [{ validator: validateIdCard, trigger: 'blur' }],
phone: [{ required: true, validator: validatePhone, trigger: 'blur' }],
gender: [{ required: true, message: '请选择性别', trigger: 'change' }],
age: [{ required: true, message: '请输入年龄', trigger: 'blur' }],
fasting_blood_sugar: [{ required: true, message: '请输入空腹血糖', trigger: 'blur' }],
diagnosis_type: [{ required: true, message: '请选择诊断类型', trigger: 'change' }],
diabetes_discovery_year: [{ max: 50, message: '最多50个字符', trigger: 'blur' }],
}
// 获取字典选项
const diagnosisTypeOptions = ref<any[]>([])
const syndromeTypeOptions = ref<any[]>([])
const diabetesTypeOptions = ref<any[]>([])
const pastHistoryOptions = ref<any[]>([])
// 现病史字典选项
const appetiteOptions = ref<any[]>([])
const waterIntakeOptions = ref<any[]>([])
const dietConditionOptions = ref<any[]>([])
const weightChangeOptions = ref<any[]>([])
const bodyFeelingOptions = ref<any[]>([])
const sleepConditionOptions = ref<any[]>([])
const eyeConditionOptions = ref<any[]>([])
const headFeelingOptions = ref<any[]>([])
const sweatConditionOptions = ref<any[]>([])
const skinConditionOptions = ref<any[]>([])
const urineConditionOptions = ref<any[]>([])
const stoolConditionOptions = ref<any[]>([])
const kidneyConditionOptions = ref<any[]>([])
const fattyLiverDegreeOptions = ref<any[]>([])
const getDictOptions = async () => {
try {
const [
diagnosisType,
syndromeType,
diabetesType,
pastHistory,
appetite,
waterIntake,
dietCondition,
weightChange,
bodyFeeling,
sleepCondition,
eyeCondition,
headFeeling,
sweatCondition,
skinCondition,
urineCondition,
stoolCondition,
kidneyCondition,
fattyLiverDegree
] = await Promise.all([
getDictData({ type: 'diagnosis_type' }),
getDictData({ type: 'syndrome_type' }),
getDictData({ type: 'diabetes_type' }),
getDictData({ type: 'past_history' }),
getDictData({ type: 'appetite' }),
getDictData({ type: 'water_intake' }),
getDictData({ type: 'diet_condition' }),
getDictData({ type: 'weight_change' }),
getDictData({ type: 'body_feeling' }),
getDictData({ type: 'sleep_condition' }),
getDictData({ type: 'eye_condition' }),
getDictData({ type: 'head_feeling' }),
getDictData({ type: 'sweat_condition' }),
getDictData({ type: 'skin_condition' }),
getDictData({ type: 'urine_condition' }),
getDictData({ type: 'stool_condition' }),
getDictData({ type: 'kidney_condition' }),
getDictData({ type: 'fatty_liver_degree' })
])
diagnosisTypeOptions.value = diagnosisType?.diagnosis_type || []
syndromeTypeOptions.value = syndromeType?.syndrome_type || []
diabetesTypeOptions.value = diabetesType?.diabetes_type || []
pastHistoryOptions.value = pastHistory?.past_history || []
appetiteOptions.value = appetite?.appetite || []
waterIntakeOptions.value = waterIntake?.water_intake || []
dietConditionOptions.value = dietCondition?.diet_condition || []
weightChangeOptions.value = weightChange?.weight_change || []
bodyFeelingOptions.value = bodyFeeling?.body_feeling || []
sleepConditionOptions.value = sleepCondition?.sleep_condition || []
eyeConditionOptions.value = eyeCondition?.eye_condition || []
headFeelingOptions.value = headFeeling?.head_feeling || []
sweatConditionOptions.value = sweatCondition?.sweat_condition || []
skinConditionOptions.value = skinCondition?.skin_condition || []
urineConditionOptions.value = urineCondition?.urine_condition || []
stoolConditionOptions.value = stoolCondition?.stool_condition || []
kidneyConditionOptions.value = kidneyCondition?.kidney_condition || []
fattyLiverDegreeOptions.value = fattyLiverDegree?.fatty_liver_degree || []
} catch (error) {
console.error('获取字典数据失败:', error)
}
}
async function loadDiagnosisDetailIntoForm(id: number): Promise<void> {
const data = await tcmDiagnosisDetail({ id })
originalPhone.value = data.phone || ''
originalIdCard.value = data.id_card || ''
data.phone = hasPhonePlainPermission.value ? data.phone || '' : maskPhone(data.phone || '')
data.id_card = maskIdCard(data.id_card || '')
formData.value = data
const y = data.diabetes_discovery_year
formData.value.diabetes_discovery_year = y == null || y === '' ? '' : String(y)
}
const open = async (type: string, id?: number) => {
viewOnly.value = false
mode.value = type
visible.value = true
activeTab.value = 'basic' // 重置到基本信息标签页
phoneRevealUnlocked.value = false
// 加载字典数据
await getDictOptions()
if (type === 'edit' && id) {
await loadDiagnosisDetailIntoForm(id)
} else if (type === 'add') {
const userStore = useUserStore()
formData.value.assistant_id = userStore.userInfo?.id || ''
// 字典 diagnosis_type:复诊 → follow_up(见 server/sql/tcm_diagnosis.sql
formData.value.diagnosis_type = 'follow_up'
}
}
/** 只读打开:与编辑同一套界面与全部 Tab,不可保存 */
const openViewOnly = async (id: number) => {
if (!id) return
viewOnly.value = true
mode.value = 'edit'
visible.value = true
activeTab.value = 'basic'
phoneRevealUnlocked.value = false
await getDictOptions()
await loadDiagnosisDetailIntoForm(id)
}
const handleSubmit = async () => {
if (viewOnly.value) return
await formRef.value?.validate()
submitting.value = true
try {
// 准备提交数据,使用原始完整数据
const submitData = {
...formData.value,
phone: originalPhone.value || formData.value.phone,
id_card: originalIdCard.value || formData.value.id_card
}
if (mode.value === 'add') {
const result = await tcmDiagnosisAdd(submitData)
// 如果是新增,保存成功后切换到编辑模式,这样可以添加血糖血压记录
if (result && result.id) {
mode.value = 'edit'
phoneRevealUnlocked.value = false
formData.value.id = result.id
// 重新获取详情,确保patient_id等字段正确
try {
const detail = await tcmDiagnosisDetail({ id: result.id })
formData.value.patient_id = detail.patient_id
// 更新原始数据
originalPhone.value = detail.phone || ''
originalIdCard.value = detail.id_card || ''
formData.value.phone = hasPhonePlainPermission.value
? detail.phone || ''
: maskPhone(detail.phone || '')
formData.value.id_card = maskIdCard(detail.id_card || '')
} catch (error) {
console.error('获取详情失败:', error)
}
}
} else {
await tcmDiagnosisEdit(submitData)
}
emit('success')
} catch (error) {
console.error('提交失败:', error)
} finally {
submitting.value = false
}
}
const handleViewCase = (row: any) => {
prescriptionRef.value?.openById(row.id)
}
// 开方:传入当前诊单数据,包含详细病历(深拷贝避免响应式引用)
const handleOpenPrescription = () => {
if (viewOnly.value) return
const data = {
id: formData.value.id,
diagnosis_id: formData.value.id,
appointment_id: 0,
patient_name: formData.value.patient_name,
patient_phone: originalPhone.value || formData.value.phone,
patient_gender: formData.value.gender,
patient_age: formData.value.age,
case_record: JSON.parse(JSON.stringify(formData.value))
}
prescriptionRef.value?.open(data)
}
const handleClose = () => {
formRef.value?.resetFields()
formData.value = {
id: '',
patient_id: '',
patient_name: '',
id_card: '',
phone: '',
gender: 1,
age: undefined as number | undefined,
diagnosis_date: '',
diagnosis_type: '',
syndrome_type: '',
diabetes_type: '',
diabetes_discovery_year: '',
local_hospital_diagnosis: [],
local_hospital_name: '',
marital_status: undefined as number | undefined,
height: undefined as number | undefined,
weight: undefined as number | undefined,
region: '',
systolic_pressure: undefined as number | undefined,
diastolic_pressure: undefined as number | undefined,
fasting_blood_sugar: '',
appetite: [] as string[],
water_intake: '',
diet_condition: [],
weight_change: '',
body_feeling: [],
sleep_condition: [],
eye_condition: [],
head_feeling: [],
sweat_condition: [],
skin_condition: [],
urine_condition: [],
stool_condition: [],
kidney_condition: [],
fatty_liver_degree: '',
past_history: [],
trauma_history: 0,
surgery_history: 0,
allergy_history: 0,
family_history: 0,
pregnancy_history: 0,
assistant_id: undefined as number | undefined,
symptoms: '',
tongue_coating: '',
pulse: '',
treatment_principle: '',
prescription: '',
doctor_advice: '',
remark: '',
current_medications: '',
status: 1,
external_userid: ''
}
// 重置原始数据
originalPhone.value = ''
originalIdCard.value = ''
isPhoneFocused.value = false
isIdCardFocused.value = false
phoneRevealUnlocked.value = false
viewOnly.value = false
visible.value = false
}
defineExpose({
open,
openViewOnly,
refreshCaseList: () => caseRecordListRef.value?.refresh?.()
})
</script>
<style lang="scss" scoped>
.edit-drawer {
font-size: 12px;
.diagnosis-view-fieldset:disabled {
opacity: 1;
:deep(.el-input__wrapper),
:deep(.el-textarea__inner) {
box-shadow: none;
}
}
:deep(.el-form) {
padding-bottom: 20px;
font-size: 12px;
}
:deep(.el-divider) {
margin: 28px 0 22px;
border-color: transparent;
&::before,
&::after {
border-top-color: #e2e8f0;
}
.el-divider__text {
font-size: 14px;
font-weight: 600;
color: #0f172a;
letter-spacing: -0.01em;
background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
padding: 7px 16px;
border-radius: 999px;
border: 1px solid #e2e8f0;
box-shadow: 0 1px 2px rgb(15 23 42 / 6%);
}
}
:deep(.el-form-item) {
margin-bottom: 18px;
}
:deep(.el-form-item__label) {
font-size: 12px;
font-weight: 500;
color: #606266;
}
:deep(.el-input__inner) {
font-size: 12px;
}
:deep(.el-textarea__inner) {
font-size: 12px;
}
:deep(.el-radio-button__inner) {
font-size: 12px;
}
:deep(.el-checkbox-button__inner) {
font-size: 12px;
}
:deep(.el-button) {
font-size: 12px;
}
// 紧凑型表单项(单选框)
.compact-form-item {
:deep(.el-radio-group) {
display: flex;
flex-wrap: wrap;
gap: 12px;
.el-radio {
margin-right: 0;
margin-bottom: 0;
}
}
}
// 复选框表单项
.checkbox-form-item {
:deep(.el-checkbox-group) {
display: flex;
flex-wrap: wrap;
gap: 12px 16px;
.el-checkbox {
margin-right: 0;
margin-bottom: 0;
}
}
}
// 通用单选框样式
:deep(.el-radio-group) {
.el-radio {
margin-right: 16px;
margin-bottom: 8px;
&:last-child {
margin-right: 0;
}
}
}
// 通用复选框样式
:deep(.el-checkbox-group) {
.el-checkbox {
margin-right: 16px;
margin-bottom: 8px;
}
}
.form-tips {
font-size: 12px;
color: #909399;
margin-top: 4px;
line-height: 1.5;
}
/* 病历 tab 诊断信息 */
.bingli-tab-content {
padding: 0 4px;
}
.bingli-diagnosis-section {
margin-bottom: 24px;
padding: 16px;
background: #f5f7fa;
border-radius: 6px;
}
.bingli-label {
font-size: 13px;
font-weight: 500;
color: #606266;
margin-bottom: 10px;
}
.bingli-images {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.bingli-img {
width: 80px;
height: 80px;
border-radius: 4px;
cursor: pointer;
}
.bingli-empty {
font-size: 13px;
color: #909399;
}
// 输入圆角:医疗表单更易扫读
:deep(.el-input__wrapper) {
border-radius: 10px;
transition:
box-shadow 0.2s ease,
border-color 0.2s ease;
}
:deep(.el-textarea__inner) {
border-radius: 10px;
}
:deep(.el-select .el-input__wrapper) {
border-radius: 10px;
}
:deep(.el-date-editor .el-input__wrapper) {
border-radius: 10px;
}
:deep(.el-input-number .el-input__wrapper) {
border-radius: 10px;
}
}
.tcm-dd-header {
min-width: 0;
flex: 1;
padding-right: 8px;
}
.tcm-dd-header__row {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 8px 10px;
}
.tcm-dd-header__title {
margin: 0;
font-size: 18px;
font-weight: 600;
color: #0f172a;
line-height: 1.3;
letter-spacing: -0.02em;
}
.tcm-dd-header__badge {
flex-shrink: 0;
font-weight: 500;
}
.tcm-dd-header__sub {
margin: 6px 0 0;
font-size: 13px;
line-height: 1.45;
color: #475569;
}
.tcm-dd-header__name {
font-weight: 600;
color: #334155;
}
.tcm-dd-header__id {
font-weight: 500;
color: #64748b;
}
.tcm-dd-header__sep {
margin: 0 4px;
color: #94a3b8;
}
.tcm-dd-footer {
display: flex;
flex-wrap: wrap;
justify-content: flex-end;
align-items: center;
gap: 12px;
width: 100%;
padding: 14px 20px 18px;
box-sizing: border-box;
border-top: 1px solid rgb(226 232 240 / 90%);
background: linear-gradient(180deg, rgb(248 250 252 / 95%) 0%, #fff 40%);
}
.tcm-dd-footer__btn {
min-height: 40px;
padding: 10px 20px;
font-weight: 600;
border-radius: 10px;
transition:
transform 0.15s ease,
box-shadow 0.2s ease;
}
.tcm-dd-footer__btn:focus-visible {
outline: 2px solid var(--el-color-primary);
outline-offset: 2px;
}
@media (prefers-reduced-motion: reduce) {
.tcm-dd-footer__btn {
transition: none;
}
}
</style>
<style lang="scss" scoped>
/* 全局样式,用于提高弹出层的z-index */
.high-z-index {
z-index: 3000 !important;
}
/* 勿对全局 .el-drawer / .el-overlay 写 z-index,会覆盖子组件的 :z-index(例如从消费处方里嵌套打开只读诊单时会被压在下面) */
/* 确保日期选择器和下拉选择器的弹出层在最上层 */
.el-picker__popper,
.el-select__popper,
.el-popper {
z-index: 3000 !important;
}
/* 确保Element Plus的弹出层容器在最上层 */
.el-picker-panel,
.el-select-dropdown {
z-index: 3000 !important;
}
</style>
<style lang="scss">
/**
* 诊单抽屉壳层挂到 body 时通过 .diagnosis-drawer 限定作用域
*/
.diagnosis-drawer.tcm-diagnosis-drawer {
.el-drawer__header {
align-items: flex-start !important;
border-bottom: 1px solid #e2e8f0;
background: linear-gradient(180deg, #fff 0%, #f8fafc 100%);
}
.el-drawer__body {
background: #f8fafc;
min-width: 0;
}
.el-drawer__footer {
padding: 0 !important;
background: #fff;
box-shadow: 0 -4px 24px rgb(15 23 42 / 7%);
}
/* Tab 标签保证在窄抽屉内可横向滚动 flex 子项 min-width EP 内层 overflow */
.tcm-diagnosis-tabs.el-tabs {
width: 100%;
max-width: 100%;
min-width: 0;
box-sizing: border-box;
}
.tcm-diagnosis-tabs .el-tabs__header {
min-width: 0;
width: 100%;
}
.tcm-diagnosis-tabs .el-tabs__nav-wrap {
flex: 1;
min-width: 0;
overflow-x: auto;
overflow-y: hidden;
-webkit-overflow-scrolling: touch;
scrollbar-width: thin;
scrollbar-color: rgb(148 163 184 / 55%) transparent;
}
.tcm-diagnosis-tabs .el-tabs__nav-wrap::-webkit-scrollbar {
height: 4px;
}
.tcm-diagnosis-tabs .el-tabs__nav-wrap::-webkit-scrollbar-thumb {
background-color: rgb(148 163 184 / 55%);
border-radius: 4px;
}
.tcm-diagnosis-tabs .el-tabs__nav-scroll {
overflow: visible !important;
}
.tcm-diagnosis-tabs .el-tabs__nav {
display: flex;
flex-wrap: nowrap;
float: none !important;
width: max-content;
min-width: 100%;
}
.tcm-diagnosis-tabs .el-tabs__item {
flex: 0 0 auto;
padding: 0 14px;
font-weight: 500;
color: #64748b;
transition: color 0.2s ease;
}
.tcm-diagnosis-tabs .el-tabs__item.is-active {
color: var(--el-color-primary);
font-weight: 600;
}
.tcm-diagnosis-tabs .el-tabs__active-bar {
height: 3px;
border-radius: 3px 3px 0 0;
}
.tcm-dd-footer {
box-shadow: none;
border-top: 1px solid #e2e8f0;
background: #fff;
}
}
@media (prefers-reduced-motion: reduce) {
.diagnosis-drawer.tcm-diagnosis-drawer .tcm-diagnosis-tabs .el-tabs__item {
transition: none;
}
}
/**
* 窄屏诊单抽屉drawer 通过 teleport 挂到 bodyscoped 无法作用到内部此处用抽屉 class H5 适配
*/
@media screen and (max-width: 768px) {
.diagnosis-drawer.el-drawer {
width: 100% !important;
max-width: 100vw;
}
.diagnosis-drawer .el-drawer__header {
padding: 12px 14px !important;
margin-bottom: 0 !important;
}
.diagnosis-drawer .el-drawer__body {
padding: 10px 12px 12px !important;
}
.diagnosis-drawer .el-drawer__footer {
padding: 0 !important;
}
.diagnosis-drawer .tcm-dd-footer {
flex-direction: column;
align-items: stretch;
gap: 10px;
padding: 12px 14px calc(12px + env(safe-area-inset-bottom, 0px)) !important;
}
.diagnosis-drawer .tcm-dd-footer__btn {
width: 100%;
min-height: 44px;
}
.diagnosis-drawer .tcm-dd-header__title {
font-size: 17px;
}
.diagnosis-drawer .diagnosis-tabs .el-tabs__header {
margin: 0 0 10px;
}
.diagnosis-drawer .el-tabs__item {
padding: 0 12px;
font-size: 13px;
min-height: 44px;
line-height: 44px;
}
.diagnosis-drawer .el-tabs__nav-wrap::after {
height: 1px;
}
/* 表单标签在上控件全宽避免 160px 标签 + 三列栅格把内容挤没 */
.diagnosis-drawer .el-form-item {
display: flex !important;
flex-direction: column !important;
align-items: stretch !important;
margin-bottom: 14px !important;
}
.diagnosis-drawer .el-form-item__label {
width: 100% !important;
max-width: 100% !important;
height: auto !important;
line-height: 1.4 !important;
text-align: left !important;
justify-content: flex-start !important;
margin: 0 0 6px !important;
padding: 0 !important;
box-sizing: border-box;
}
.diagnosis-drawer .el-form-item__content {
margin-left: 0 !important;
max-width: 100% !important;
flex: 1 1 auto;
}
.diagnosis-drawer .el-row {
margin-left: 0 !important;
margin-right: 0 !important;
row-gap: 0;
}
.diagnosis-drawer .el-col,
.diagnosis-drawer .el-col-12,
.diagnosis-drawer .el-col-8,
.diagnosis-drawer .el-col-20,
.diagnosis-drawer [class*='el-col-'] {
flex: 0 0 100% !important;
max-width: 100% !important;
width: 100% !important;
padding-left: 0 !important;
padding-right: 0 !important;
}
.diagnosis-drawer .el-input-number {
width: 100% !important;
}
.diagnosis-drawer .el-radio-group {
display: flex !important;
flex-wrap: wrap !important;
gap: 8px 16px;
align-items: center;
}
.diagnosis-drawer .el-radio {
margin-right: 0 !important;
margin-bottom: 0 !important;
}
.diagnosis-drawer .el-radio-button:last-child {
margin-right: 0;
}
.diagnosis-drawer .el-checkbox-group {
display: flex !important;
flex-wrap: wrap !important;
gap: 8px 10px;
}
.diagnosis-drawer .el-divider {
margin: 18px 0 14px;
}
.diagnosis-drawer .el-divider__text {
font-size: 13px;
padding: 0 10px;
}
}
</style>