373 lines
10 KiB
Vue
Raw Normal View History

2026-03-02 18:01:54 +08:00
<template>
<div class="labpat_box">
2026-05-13 17:50:49 +08:00
<el-form :model="labPat" label-width="5rem" label-position="right" ref="formRef" class="left-form">
<div :class="['sh_box', getColor(newStatus)]" v-if="visbileMask">
<div class="text">{{ getLableType(newStatus) }}</div>
</div>
2026-03-02 18:01:54 +08:00
<el-form-item label="病人来源">
2026-05-13 17:50:49 +08:00
<SelectTable v-model:data="labPat.patType" :fields="brlyFields" :table-data="dictData.PT" placeholder=""
@getDataValue="handleFieldChange" @enter-press="selectEnter(1)" />
2026-03-02 18:01:54 +08:00
</el-form-item>
2026-05-13 17:50:49 +08:00
<el-form-item label="病人代号" required>
<el-input v-model="labPat.patId" @change="brdhHandle" @keydown.enter="nextFocus" />
2026-03-02 18:01:54 +08:00
</el-form-item>
2026-05-13 17:50:49 +08:00
<el-form-item label="姓 名" required>
<el-input v-model="labPat.patName" @change="handleFieldChange" @keydown.enter="nextFocus" />
2026-03-02 18:01:54 +08:00
</el-form-item>
2026-05-13 17:50:49 +08:00
<el-form-item label="性 别" required>
<SelectTable v-model:data="labPat.patSex" :table-data="dictData.SX" placeholder=""
@getDataValue="handleFieldChange" @enter-press="selectEnter(4)" />
2026-03-02 18:01:54 +08:00
</el-form-item>
2026-05-13 17:50:49 +08:00
<el-form-item label="年龄" required>
2026-03-05 18:03:05 +08:00
<el-col :span="14">
2026-05-13 17:50:49 +08:00
<el-input v-model="labPat.patAge" @change="handleFieldChange" @keydown.enter="nextFocus" />
2026-03-05 18:03:05 +08:00
</el-col>
<el-col :span="10">
2026-05-13 17:50:49 +08:00
<SelectTable v-model:data="labPat.ageUnit" :table-data="dictData.AU" placeholder="" :clearable="false"
@getDataValue="handleFieldChange" @enter-press="selectEnter(6)" />
2026-03-05 18:03:05 +08:00
</el-col>
2026-03-02 18:01:54 +08:00
</el-form-item>
2026-05-13 17:50:49 +08:00
<el-form-item label="生理周期" v-if="labPat.patSex == '2'">
<SelectTable v-model:data="labPat.slzq" :table-data="dictData.SLZQ" placeholder=""
@getDataValue="handleFieldChange" @enter-press="selectEnter(labPat.patSex == '2' ? 7 : -1)" />
2026-03-02 18:01:54 +08:00
</el-form-item>
2026-03-05 18:03:05 +08:00
<el-form-item label="送检医生">
2026-05-13 17:50:49 +08:00
<SelectTable v-model:data="labPat.doctorCode" :tableData="dictData.DOCTOR" placeholder=""
@getDataValue="doctorHandle" @enter-press="selectEnter(labPat.patSex == '2' ? 8 : 7)" />
2026-03-02 18:01:54 +08:00
</el-form-item>
2026-03-05 18:03:05 +08:00
<el-form-item label="送检科室">
2026-05-13 17:50:49 +08:00
<SelectTable v-model:data="labPat.departCode" :table-data="dictData.DEPT" placeholder=""
@getDataValue="deptHandle" @enter-press="selectEnter(labPat.patSex == '2' ? 9 : 8)" />
2026-03-02 18:01:54 +08:00
</el-form-item>
2026-03-05 18:03:05 +08:00
<el-form-item label="床 号">
2026-05-13 17:50:49 +08:00
<el-input v-model="labPat.patBed" @change="handleFieldChange" @keydown.enter="nextFocus" />
2026-03-02 18:01:54 +08:00
</el-form-item>
2026-03-05 18:03:05 +08:00
2026-03-02 18:01:54 +08:00
<el-form-item label="临床诊断">
2026-05-13 17:50:49 +08:00
<el-input v-model="labPat.diagnosisName" @change="handleFieldChange" @keydown.enter="nextFocus" />
2026-03-02 18:01:54 +08:00
</el-form-item>
<el-form-item label="备 注">
2026-05-13 17:50:49 +08:00
<el-input v-model="labPat.bz" @change="handleFieldChange" @keydown.enter="nextFocus" />
2026-03-02 18:01:54 +08:00
</el-form-item>
2026-03-05 18:03:05 +08:00
<el-form-item label="登记人员">
2026-05-13 17:50:49 +08:00
<el-input v-model="labPat.userName" disabled />
2026-03-02 18:01:54 +08:00
</el-form-item>
2026-03-05 18:03:05 +08:00
<el-form-item label="登记时间">
2026-05-13 17:50:49 +08:00
<el-date-picker v-model="labPat.orderTime" type="datetime" format="YYYY-MM-DD HH:mm:ss" disabled
value-format="YYYY-MM-DD HH:mm:ss" style="width: 100%;" />
2026-03-05 18:03:05 +08:00
</el-form-item>
2026-05-13 17:50:49 +08:00
<el-form-item label="医疗机构">
<el-input v-model="labPat.srcHospName" disabled />
2026-03-05 18:03:05 +08:00
</el-form-item>
<el-form-item label="证件类型">
2026-05-13 17:50:49 +08:00
<SelectTable v-model:data="labPat.zjlx" :table-data="dictData.ZJLX" placeholder=""
@getDataValue="handleFieldChange" @enter-press="selectEnter(labPat.patSex == '2' ? 13 : 12)" />
2026-03-05 18:03:05 +08:00
</el-form-item>
<el-form-item label="证件号码">
2026-05-13 17:50:49 +08:00
<el-input v-model="labPat.patIdentity" @keydown.enter="nextFocus" />
2026-03-05 18:03:05 +08:00
</el-form-item>
<el-form-item label="联系电话">
2026-05-13 17:50:49 +08:00
<el-input v-model="labPat.phone" @keydown.enter="nextFocus" />
2026-03-05 18:03:05 +08:00
</el-form-item>
2026-03-02 18:01:54 +08:00
</el-form>
</div>
</template>
<script setup lang="ts">
import SelectTable from '@/components/SelectTable/index.vue';
2026-03-05 18:03:05 +08:00
import { getDictData, formatDict, dictData } from '@/hooks'
2026-05-13 17:50:49 +08:00
2026-03-02 18:01:54 +08:00
const props = defineProps({
labPat: {
type: Object,
required: true
},
2026-05-13 17:50:49 +08:00
//展示水印
visbileMask: {
type: Boolean,
default: false
2026-03-02 18:01:54 +08:00
},
});
2026-05-13 17:50:49 +08:00
const newStatus = ref('');
watch(() => props.labPat.status, (newVal: any) => {
newStatus.value = newVal;
2026-03-02 18:01:54 +08:00
})
2026-03-05 18:03:05 +08:00
2026-05-13 17:50:49 +08:00
const emit = defineEmits(['update:labPat', 'getBrdh']);
2026-03-02 18:01:54 +08:00
const brlyFields = ref([
{ prop: 'value', label: '代号', width: 80, enablePinyinSearch: true },
{ prop: 'label', label: '名称', width: 120, enablePinyinSearch: true },
])
const ysFields = ref([
{ prop: 'userName', label: '用户代号', width: 80, enablePinyinSearch: true },
{ prop: 'nickName', label: '用户姓名', width: 150, enablePinyinSearch: true },
])
2026-05-13 17:50:49 +08:00
const doctorHandle = (data) => {
props.labPat.doctorName = data.label
}
const deptHandle = (data) => {
props.labPat.departName = data.label
}
2026-03-02 18:01:54 +08:00
const handleFieldChange = async () => {
2026-05-13 17:50:49 +08:00
2026-03-02 18:01:54 +08:00
};
2026-05-13 17:50:49 +08:00
const getLableType = (type: string) => {
const item = dictData.value.SQDS.find((p: any) => p.value === type);
return item && props.visbileMask ? item.label : '';
}
const getColor = (type: string) => {
switch (type) {
case '10':
return 'cs_color';
case '20':
return 'sh_color';
case '30':
return 'cb_color';
case '40':
return 'eb_color';
case '50':
return 'sd_color';
default:
return 'default';
}
}
2026-03-02 18:01:54 +08:00
2026-03-05 18:03:05 +08:00
// 病人代号查询病人信息的逻辑
const brdhHandle = () => {
2026-05-13 17:50:49 +08:00
emit('getBrdh', props.labPat.patId)
2026-03-05 18:03:05 +08:00
}
2026-03-02 18:01:54 +08:00
2026-05-13 17:50:49 +08:00
const formRef = useTemplateRef('formRef')
const currentTarget = ref(null);
// 回车跳转到下一个表单元素
const nextFocus = (e?: Event, idx?: number) => {
if (e) e.preventDefault() // 禁止回车提交表单
// 找到所有可聚焦的表单项:
const els = formRef.value.$el.querySelectorAll(
'input:not([type="hidden"]):not([disabled]), select:not([disabled]), textarea:not([disabled]), ' +
'.select-table__wrapper .el-select__input:not([disabled]), ' + '.el-date-editor input:not([disabled])'
);
const arr = Array.from(els).filter((el: any) => {
// 额外过滤:排除隐藏元素、禁用状态的父级封装组件(如 SelectTable 被 disabled 时)
const isHidden = el.offsetParent === null;
const isDisabled = el.hasAttribute('disabled') || el.parentElement?.closest('.is-disabled') !== null;
return !isHidden && !isDisabled;
});
let index: number;
if (!idx) {
// 找到当前触发元素在列表中的位置
currentTarget.value = e?.target as HTMLElement;
// 兼容 SelectTable:如果点击的是组件外层,定位到内部输入框
if (currentTarget.value.closest('.select-table-container')) {
currentTarget.value = currentTarget.value.closest('.select-table-container').querySelector('.el-select__input');
}
index = arr.findIndex((item: any) => item === currentTarget.value || item.contains(currentTarget.value));
} else {
index = idx - 1;
}
// 跳转到下一个可聚焦元素(循环到第一个 if 最后一个)
if (index > -1) {
const nextIndex = (index + 1) % arr.length;
// 确保下一个元素存在且可聚焦
if (arr[nextIndex]) {
nextTick(() => {
(arr[nextIndex] as HTMLElement)?.focus();
});
// 针对 SelectTable 额外处理:聚焦后激活下拉框
if ((arr[nextIndex] as HTMLElement).closest('.select-table-container')) {
(arr[nextIndex] as HTMLElement).dispatchEvent(new Event('click'));
}
}
}
}
2026-03-02 18:01:54 +08:00
2026-05-13 17:50:49 +08:00
const selectEnter = (index: number) => {
const emptyEvent = new Event('keydown', { cancelable: true });
nextFocus(emptyEvent, index)
}
2026-03-02 18:01:54 +08:00
onMounted(() => {
2026-03-05 18:03:05 +08:00
2026-03-02 18:01:54 +08:00
})
</script>
<style scoped lang="scss">
.labpat_box {
2026-03-05 18:03:05 +08:00
height: calc(90vh - 40px);
2026-03-02 18:01:54 +08:00
display: flex;
flex-direction: column;
overflow: hidden;
2026-03-05 18:03:05 +08:00
border-right: 1px solid #E6E9ED;
padding-right: 5px;
2026-03-02 18:01:54 +08:00
.check_box {
:deep(.el-checkbox__input.is-checked+.el-checkbox__label) {
color: #f00 !important;
2026-03-05 18:03:05 +08:00
font-size: .875rem;
}
:deep(.el-checkbox__label) {
font-size: .875rem;
2026-03-02 18:01:54 +08:00
}
}
:deep(.el-input__wrapper) {
box-shadow: 0 0 0 1px #96B8D9 inset;
background-color: rgba(236, 244, 251, 0.5);
color: #08355E;
.is-focus {
box-shadow: 0 0 0 1px #1f6dd3 inset !important;
}
&:hover {
box-shadow: 0 0 0 1px #1f6dd3 inset !important;
}
// .el-input__placeholder {
// color: none !important;
// }
}
:deep(.el-select__wrapper) {
box-shadow: 0 0 0 1px #96B8D9 inset;
background-color: rgba(236, 244, 251, 0.5);
color: #08355E;
.is-focus {
box-shadow: 0 0 0 1px #1f6dd3 inset !important;
}
&:hover {
box-shadow: 0 0 0 1px #1f6dd3 inset !important;
}
.el-select__placeholder {
color: #08355E !important;
}
}
:deep(.el-input__inner) {
color: #08355E !important;
-webkit-text-fill-color: #08355E;
}
:deep(.el-select__input) {
color: #08355E !important;
}
2026-05-13 17:50:49 +08:00
.left-form {
2026-03-02 18:01:54 +08:00
flex: 1;
position: relative;
height: 100%;
overflow-y: auto;
overflow-x: hidden;
2026-05-13 17:50:49 +08:00
padding-top: 5px;
2026-03-02 18:01:54 +08:00
.el-form-item {
2026-05-13 17:50:49 +08:00
margin-bottom: 8px;
2026-03-02 18:01:54 +08:00
}
2026-05-13 17:50:49 +08:00
:deep(.el-form-item__label) {
2026-03-02 18:01:54 +08:00
padding-bottom: 0px;
color: #08355E;
2026-05-13 17:50:49 +08:00
font-size: .875rem !important;
2026-03-02 18:01:54 +08:00
}
2026-05-13 17:50:49 +08:00
:deep(.el-form-item__label:before) {
margin-right: 0 !important;
}
2026-03-02 18:01:54 +08:00
:deep(.el-form-item--default .el-form-item__label) {
height: 27px !important;
line-height: 27px !important;
}
:deep(.el-form-item--default .el-form-item__content) {
line-height: 27px !important;
}
// pointer-events: none;
:deep(.el-radio__label) {
color: #08355E;
}
}
:deep(.el-switch__label) {
color: #08355E;
}
}
2026-05-13 17:50:49 +08:00
.sh_box {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0);
z-index: 9;
display: flex;
justify-content: center;
align-items: center;
writing-mode: vertical-rl;
font-weight: 500;
font-size: 100px;
.text {
font-style: italic;
}
// pointer-events: none;
}
.cs_color {
color: rgba(40, 189, 187, 0.25);
}
.sh_color {
color: rgba(238, 8, 8, 0.25);
}
.cb_color {
color: rgba(0, 128, 0, 0.25);
}
.eb_color {
color: rgba(255, 165, 0, 0.25);
}
.sd_color {
color: rgb(233, 126, 32, .25);
}
.default {
color: rgba(40, 189, 187, 0.25);
}
2026-03-02 18:01:54 +08:00
</style>