患者列表优化

This commit is contained in:
2026-05-09 11:30:04 +08:00
parent dc1c5d5b17
commit fd9053a290
4 changed files with 163 additions and 21 deletions
@@ -1,6 +1,6 @@
<template>
<div class="call-record-panel">
<div class="call-record-toolbar">
<div v-if="!readOnly" class="call-record-toolbar">
<upload
ref="toolbarUploadRef"
type="video"
@@ -19,7 +19,11 @@
<div class="call-record-empty">
<div class="call-record-empty__title">暂无通话记录</div>
<div class="call-record-empty__desc">
现在可以直接点击上方上传视频系统会自动生成一条默认通话记录来承载回放
{{
readOnly
? '暂无录制回放数据。'
: '现在可以直接点击上方“上传视频”。系统会自动生成一条默认通话记录来承载回放。'
}}
</div>
</div>
</template>
@@ -47,7 +51,7 @@
{{ row.recording_status_text || '—' }}
</template>
</el-table-column>
<el-table-column label="上传回放" width="180">
<el-table-column v-if="!readOnly" label="上传回放" width="180">
<template #default="{ row }">
<upload
type="video"
@@ -92,7 +96,7 @@
import Upload from '@/components/upload/index.vue'
import feedback from '@/utils/feedback'
import { attachLocalCallRecording, createManualCallRecord, getCallRecords } from '@/api/tcm'
import { ref, useTemplateRef, watch } from 'vue'
import { ref, useTemplateRef, watch, withDefaults } from 'vue'
type CallRecordRow = {
id: number
@@ -106,9 +110,14 @@ type CallRecordRow = {
duration_text?: string
}
const props = defineProps<{
diagnosisId: number
}>()
const props = withDefaults(
defineProps<{
diagnosisId: number
/** 只读场景(如诊单只读详情):不展示任何上传入口 */
readOnly?: boolean
}>(),
{ readOnly: false }
)
const loading = ref(false)
const rows = ref<CallRecordRow[]>([])
@@ -3,7 +3,7 @@
<div class="toolbar">
<el-button
type="primary"
:disabled="!props.diagnosisId || !!props.readOnly || !hasDailyRecordPermission"
:disabled="!props.diagnosisId || !hasDailyRecordPermission"
@click="handleAdd"
v-perms="DAILY_RECORD_PERMS"
>
@@ -226,7 +226,7 @@ const disablePastDate = (date: Date) => {
}
const handleAdd = () => {
if (!props.diagnosisId || props.readOnly || !hasDailyRecordPermission.value) {
if (!props.diagnosisId || !hasDailyRecordPermission.value) {
feedback.msgWarning('诊单未保存,无法添加待办')
return
}
+144 -12
View File
@@ -40,23 +40,110 @@
<PatientCaseCard :apt="apt" :diag="diag" />
<!-- 日常记录只读 -->
<div class="card tracking-card">
<div v-if="hasDailyRecordPermission" class="card tracking-card">
<div class="card-title">日常记录</div>
<DailyMatrix
:diagnosis-id="Number(diagnosisIdNum)"
:patient-id="Number(diag?.patient_id ?? 0)"
:age="diag?.age ?? null"
:patient-name="diag?.patient_name || ''"
:read-only="true"
/>
<div class="card-body">
<DailyMatrix
:diagnosis-id="diagnosisNumericId"
:patient-id="patientNumericId"
:age="diag?.age ?? null"
:patient-name="diag?.patient_name || ''"
:read-only="true"
/>
</div>
</div>
<!-- 医生备注复用 reception NoteTimeline只读 -->
<div v-if="doctorNotes.length" class="card note-card">
<!-- 医生备注舌苔照片检查报告只读与编辑页医生备注同源 -->
<div class="card note-card">
<div class="card-title">医生备注 & 舌苔照片 & 检查报告</div>
<NoteTimeline :notes="doctorNotes" :diagnosis-id="diag?.id" />
<div class="card-body card-body--matrix-align">
<el-empty v-if="diagnosisNumericId <= 0" description="诊单数据不完整" />
<el-empty
v-else-if="!doctorNotesLocal.length"
description="暂无医生备注"
/>
<NoteTimeline
v-else
:notes="doctorNotesLocal"
:diagnosis-id="diagnosisNumericId"
:readonly="true"
/>
</div>
</div>
<!-- 业务订单 -->
<div
v-if="hasPermission(['tcm.diagnosis/patientOrders'])"
class="card section-card"
>
<div class="card-title">业务订单</div>
<div class="card-body card-body--matrix-align">
<patient-order-list
v-if="diagnosisNumericId > 0"
:diagnosis-id="diagnosisNumericId"
:patient-id="patientNumericId || 0"
/>
<el-empty v-else description="诊单数据不完整" />
</div>
</div>
<!-- 视频录制回放记录 -->
<div v-if="hasPermission(['tcm.diagnosis/huifang'])" class="card section-card">
<div class="card-title">视频录制回放记录</div>
<div class="card-body card-body--matrix-align">
<call-record-panel
v-if="diagnosisNumericId > 0"
:diagnosis-id="diagnosisNumericId"
:read-only="true"
/>
<el-empty v-else description="诊单数据不完整" />
</div>
</div>
<!-- 聊天记录 -->
<div v-if="hasPermission(['tcm.diagnosis/chat'])" class="card section-card">
<div class="card-title">聊天记录</div>
<div class="card-body card-body--matrix-align">
<im-chat-record-panel
v-if="diagnosisNumericId > 0"
:diagnosis-id="diagnosisNumericId"
/>
<el-empty v-else description="诊单数据不完整" />
</div>
</div>
<!-- 指派医助记录 -->
<div
v-if="
hasPermission(['tcm.diagnosis/assign']) ||
hasPermission(['tcm.diagnosis/detail'])
"
class="card section-card"
>
<div class="card-title">指派医助记录</div>
<div class="card-body card-body--matrix-align">
<assign-log-panel
v-if="diagnosisNumericId > 0"
:diagnosis-id="diagnosisNumericId"
/>
<el-empty v-else description="诊单数据不完整" />
</div>
</div>
<!-- 挂号记录 -->
<div
v-if="hasPermission(['doctor.appointment/lists'])"
class="card section-card"
>
<div class="card-title">挂号记录</div>
<div class="card-body card-body--matrix-align">
<appointment-record-panel
v-if="diagnosisNumericId > 0"
:diagnosis-id="diagnosisNumericId"
/>
<el-empty v-else description="诊单数据不完整" />
</div>
</div>
</template>
</div>
</template>
@@ -66,10 +153,17 @@ import { computed, onMounted, ref } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { ArrowLeft } from '@element-plus/icons-vue'
import { diagnosisReadonlyDetail } from '@/api/tcm'
import { getDoctorNotes } from '@/api/patient'
import { formatGender } from '@/utils/diag-display'
import { hasPermission } from '@/utils/perm'
import PatientInfoCard from './components/PatientInfoCard.vue'
import PatientCaseCard from './components/PatientCaseCard.vue'
import DailyMatrix from './components/DailyMatrix.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 PatientOrderList from './components/PatientOrderList.vue'
import NoteTimeline from '@/views/patient/reception/components/NoteTimeline.vue'
const route = useRoute()
@@ -80,10 +174,19 @@ const diagnosisIdNum = computed(() => Number(route.query.id || 0))
const loading = ref(false)
const errorMsg = ref('')
const detail = ref<any>(null)
/** 医生备注:readonlyDetail 返回 + getDoctorNotes 对齐接诊台结构 */
const doctorNotesLocal = ref<any[]>([])
const apt = computed<any>(() => detail.value?.appointment || {})
const diag = computed<any>(() => detail.value?.diagnosis || {})
const doctorNotes = computed<any[]>(() => detail.value?.doctor_notes || [])
const hasDailyRecordPermission = computed(() => hasPermission(['tcm.diagnosis/dailyRecord']))
const diagnosisNumericId = computed(() =>
Number(diag.value?.id ?? diagnosisIdNum.value ?? 0)
)
const patientNumericId = computed(() => Number(diag.value?.patient_id ?? 0))
const unservedDays = computed<number | null>(() => {
const v = detail.value?.unserved_days
return v === null || v === undefined ? null : Number(v)
@@ -103,11 +206,23 @@ const unservedDaysClass = (n: unknown) => {
return 'unserved-green'
}
const fetchDoctorNotes = async () => {
const id = diagnosisNumericId.value
if (!id) return
try {
const data = (await getDoctorNotes({ diagnosis_id: id })) || []
doctorNotesLocal.value = data
} catch {
/* 失败时保留 readonlyDetail 已下发的 doctor_notes,避免整块备注空白 */
}
}
const fetchDetail = async () => {
const id = diagnosisIdNum.value
if (!id || id <= 0) {
errorMsg.value = '诊单 id 缺失'
detail.value = null
doctorNotesLocal.value = []
return
}
loading.value = true
@@ -115,9 +230,12 @@ const fetchDetail = async () => {
try {
const res: any = await diagnosisReadonlyDetail({ id })
detail.value = res || null
doctorNotesLocal.value = Array.isArray(res?.doctor_notes) ? res.doctor_notes : []
await fetchDoctorNotes()
} catch (e: any) {
errorMsg.value = e?.message || ''
detail.value = null
doctorNotesLocal.value = []
} finally {
loading.value = false
}
@@ -276,4 +394,18 @@ onMounted(fetchDetail)
background: linear-gradient(180deg, #4f8cff 0%, #2563eb 100%);
}
}
.card-body {
min-width: 0;
}
/* 与 DailyMatrix 根节点 .daily-matrix { padding: 16px } 对齐,使下方区块与「日常记录 / 待办」主内容区左右留白一致 */
.card-body--matrix-align {
padding: 16px;
box-sizing: border-box;
}
.section-card .card-title {
margin-bottom: 0;
}
</style>