Files
his/openhis-ui-vue3/src/components/PendingPatientList/index.vue
chenqi 1c07108e58 refactor(PatientList): 重构患者列表卡片布局结构
- 将原有的 header-top 和 header-bottom 结构替换为 info-row 统一布局
- 新增姓名、性别年龄、房间床号、住院号、保险类型等独立信息行
- 使用 el-text 组件优化姓名显示效果
- 为性别标签添加女性样式标识
- 调整床位信息展示方式,支持溢出省略
- 修改溢出属性从 hidden 为 visible 确保内容正常显示
- 优化标签样式和间距布局
- 隐藏已废弃的旧布局元素
- 调整 pending 患者列表的换行和对齐方式
2026-01-21 17:50:51 +08:00

321 lines
7.5 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="pending-patient-list">
<div class="patient-cards" v-loading="loading">
<template v-if="list && list.length > 0">
<el-scrollbar class="patient-cards-scrollbar">
<div
class="patient-card"
v-for="(item, index) in list"
:key="item[idKey] ?? index"
:class="{ actived: !!item.active || activeId === item[idKey] }"
draggable="true"
@click="emit('item-click', item, index)"
@dblclick="emit('item-dblclick', item)"
@dragstart="(e) => emit('dragstart', e, item)"
@dragend="(e) => emit('dragend', e)"
>
<div class="patient-card-header">
<div class="header-top">
<div class="bed-container">
<div class="bed">
<el-text truncated tclass="bed-font" width="auto">
{{ item.bedName || '-' }}
</el-text>
</div>
</div>
<div class="header-tags">
<el-tag v-if="item.contractName" size="small" class="payer-tag" effect="light">
{{ item.contractName }}
</el-tag>
<el-tag
v-if="item.encounterStatus_enumText"
size="small"
class="status-tag"
effect="light"
:class="getStatusClass(item)"
>
{{ item.encounterStatus_enumText }}
</el-tag>
</div>
</div>
<div class="header-bottom">
<span class="bus-no">住院号{{ item.busNo || '-' }}</span>
</div>
<div class="meta">
<div class="meta-row">
<span class="meta-label">入院时间</span>
<span class="meta-value">{{
item.startTime ? formatDate(item.startTime) : '-'
}}</span>
</div>
<div class="meta-row">
<span class="meta-label">入科时间</span>
<span class="meta-value">{{
item.admissionTime ? formatDate(item.admissionTime) : '-'
}}</span>
</div>
</div>
</div>
<div class="doctor-parent-line" />
<div class="patient-card-body">
<div class="personal-info-container">
<div class="name-container">
<div class="name">
<el-text :text="item.patientName" tclass="name" width="auto">
{{ item.patientName || '-' }}
</el-text>
</div>
<div class="age">
<el-tag
size="small"
class="age-tag"
effect="plain"
:class="{
'age-tag-female': item.genderEnum_enumText === '女性',
'age-tag-male': item.genderEnum_enumText === '男性',
}"
>
{{ item.genderEnum_enumText || '-' }}
<span v-if="item.age"> · {{ item.age }}</span>
<span v-if="item.priorityEnum_enumText">
· {{ item.priorityEnum_enumText }}</span
>
</el-tag>
</div>
</div>
</div>
<div class="meta"></div>
</div>
</div>
</el-scrollbar>
</template>
<el-empty v-else description="暂无数据" />
</div>
</div>
</template>
<script setup lang="ts">
import {formatDate} from '@/utils/index';
withDefaults(
defineProps<{
list: any[];
activeId?: string | number;
idKey?: string;
loading?: boolean;
}>(),
{
list: () => [],
activeId: '',
idKey: 'id',
loading: false,
}
);
const emit = defineEmits<{
(e: 'item-click', item: any, index: number): void;
(e: 'item-dblclick', item: any): void;
(e: 'dragstart', event: DragEvent, item: any): void;
(e: 'dragend', event: DragEvent): void;
}>();
const getStatusClass = (item: any) => {
if (item?.encounterStatus == 2) return 'status-tag--blue';
if (item?.encounterStatus == 5) return 'status-tag--green';
return '';
};
</script>
<style scoped lang="scss" name="PendingPatientList">
.pending-patient-list {
height: 100%;
display: flex;
flex-direction: column;
min-height: 0;
min-width: 240px;
width: 240px;
}
.patient-cards {
flex: 1 1 auto;
min-height: 0;
overflow: hidden;
:deep(.patient-cards-scrollbar) {
width: 100%;
height: 100%;
.el-scrollbar__bar {
width: 0;
}
}
}
.patient-card {
width: 100%;
overflow: hidden;
background-color: #fff;
border-radius: 6px;
border: 1px solid rgba(0, 0, 0, 0.04);
box-shadow: 0 2px 6px 0 rgba(15, 35, 52, 0.12);
cursor: pointer;
transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
&:hover {
box-shadow: 0 4px 12px rgba(15, 35, 52, 0.18);
transform: translateY(-1px);
}
&.actived {
background-color: rgba(7, 155, 140, 0.06);
border-color: var(--el-color-primary);
box-shadow: 0 0 0 1px rgba(7, 155, 140, 0.3), 0 4px 14px rgba(7, 155, 140, 0.25);
}
}
.patient-card-header {
display: flex;
flex-direction: column;
padding: 10px 12px 4px;
.header-top {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
flex-wrap: nowrap; /* 防止换行 */
.bed-container {
display: flex;
flex: 1;
align-items: center;
min-width: 0;
.bed {
flex-grow: 0;
flex-shrink: 1;
min-width: 0;
:deep(.bed-font) {
color: #1f2933;
font-weight: 600;
font-size: 16px;
}
}
}
.payer-tag {
max-width: 120px;
font-size: 12px;
border-radius: 999px;
}
.header-tags {
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: flex-end;
gap: 6px;
flex-wrap: nowrap; /* 防止换行 */
}
}
.header-bottom {
margin-top: 4px;
width: 100%;
display: flex;
justify-content: flex-start;
color: #6b7280;
font-size: 12px;
.bus-no {
white-space: nowrap;
}
}
}
.doctor-parent-line {
margin: 6px 12px 0;
border-bottom: 1px dashed #e5e7eb;
}
.patient-card-body {
padding: 8px 12px 10px;
}
.personal-info-container {
display: block;
.name-container {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
width: 100%;
.name {
color: #111827;
font-weight: 600;
font-size: 14px;
}
.age {
flex-shrink: 0;
}
}
}
.age-tag {
border-radius: 999px;
padding: 0 8px;
}
.age-tag-female {
border-color: rgb(255, 55, 158);
color: rgb(255, 126, 184);
}
.age-tag-male {
border-color: #91d5ff;
color: #1677ff;
}
.status-tag {
border-radius: 999px;
padding: 0 8px;
flex-shrink: 0;
font-weight: 600;
}
.status-tag--blue {
border-color: #91d5ff;
background-color: #1677ff;
color: white;
}
.status-tag--green {
border-color: #b7eb8f;
background-color: #389e0d;
color: white;
}
.meta {
margin-top: 6px;
color: #6b7280;
font-size: 12px;
line-height: 18px;
}
.meta-row {
display: flex;
}
.meta-label {
flex-shrink: 0;
}
</style>