版本更新

This commit is contained in:
Zhang.WH
2025-09-03 15:54:41 +08:00
parent 0b93d16b64
commit 8f82322d10
3290 changed files with 154339 additions and 23829 deletions

View File

@@ -0,0 +1,87 @@
import request from '@/utils/request'
/**
* 获取初始化
*/
export function getInit(queryParams) {
return request({
url: '/nurse-station/atd-manage/init',
method: 'get',
params: queryParams
})
}
/**
* 获取患者列表
*/
export function getPendingInfo(queryParams) {
return request({
url: '/nurse-station/atd-manage/admission-patient',
method: 'get',
params: queryParams
})
}
/**
* 获取床位列表
*/
export function getBedInfo(queryParams) {
return request({
url: '/nurse-station/atd-manage/admission-bed',
method: 'get',
params: queryParams
})
}
/**
* 获取患者详细信息
*/
export function getPatientInfo(queryParams) {
return request({
url: '/nurse-station/atd-manage/admission-patient-info',
method: 'get',
params: queryParams
})
}
/**
* 获取医生列表
*/
export function getDoctorInfo(queryParams) {
return request({
url: '/charge-manage/register/practitioner-metadata?orgId=' + queryParams.organizationId,
method: 'get'
})
}
/**
* 获取护士列表
*/
export function getNurseInfo(queryParams) {
return request({
url: '/app-common/nurse-list?orgId=' + queryParams.organizationId,
method: 'get'
})
}
/**
* 入科床位分配
*/
export function bedAssignment(data) {
return request({
url: '/nurse-station/atd-manage/bed-assignment',
method: 'post',
data: data
})
}
/**
* 获取病区
*/
export function childLocationList(queryParams) {
return request({
url: '/app-common/child-location-list',
method: 'get',
params: queryParams
})
}

View File

@@ -0,0 +1,738 @@
<template>
<div class="bedAllocation-container">
<div>
<el-form :model="queryParams" ref="queryRef" :inline="true">
<el-row style="margin-top: 8px;">
<el-form-item label="入院病区" prop="wardId" style="width: 240px">
<el-select v-model="queryParams.wardId" @change="changeWardLocationId">
<el-option
v-for="item in initInfoOptions.wardListOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="入院病房" prop="houseId">
<el-select v-model="queryParams.houseId" style="width: 240px">
<el-option
v-for="item in wardLocationList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="住院状态" prop="encounterStatus">
<el-select v-model="queryParams.encounterStatus" style="width: 240px">
<el-option label="全部" value="" />
<el-option
v-for="item in initInfoOptions.encounterStatusOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="床位状态" prop="bedStatus" style="width: 240px">
<el-select v-model="bedStatusFilter">
<el-option label="全部" value="" />
<el-option
v-for="item in initInfoOptions.bedStatusOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<div style="margin-bottom: 10px">
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</div>
</el-form-item>
</el-row>
</el-form>
</div>
<div style="display: flex; justify-content: space-between; height: 86vh">
<div style="width: 15%; height: 100%; border: 1px solid #eee; border-right: 0">
<div style="padding: 10px; border: 1px solid #eee; height: 50px; border-right: 0">
<span>新入院患者</span>
</div>
<div style="width: 100%; padding: 10px">
<el-input
v-model="queryParams.searchKey"
placeholder="请输入住院号"
clearable
style="width: 100%; margin-bottom: 10px"
@keyup.enter="handleQuery"
>
<template #append>
<el-button icon="Search" @click="handleQuery" />
</template>
</el-input>
<el-scrollbar height="700px">
<div
v-for="(item, index) in patientList"
:class="item.active ? 'patient-card actived' : 'patient-card'"
:key="item.id"
@click="handleCardClick(item, index)"
@dblclick="handleCardDblClick(item)"
draggable="true"
@dragstart="handleDragStart($event, item)"
@dragend="handleDragEnd"
>
<div class="main-info-container">
<div class="name-container">
<!-- 患者姓名 -->
<div class="name" style="max-width: 90px">
<el-text class="name" width="auto">{{ item.patientName || '未知' }}</el-text>
</div>
</div>
<div class="name-container">
<!-- 患者性别/年龄 -->
<div class="age">
<el-text class="name" width="auto">
{{ item.genderEnum_enumText }}/{{ item.age }}/{{ item.priorityEnum_enumText }}
</el-text>
</div>
</div>
<div class="patient-tag" :class="getPatientTagClass(item)">
{{ item.encounterStatus_enumText }}
</div>
</div>
<div class="doctor-parent-line" />
<div class="personal-info-container">
<div class="name-container">
<div class="name">
<el-text class="name" width="auto">入院时间</el-text>
<el-text class="name" width="auto">
{{ item.startTime ? formatDate(item.startTime) : '-' }}
</el-text>
</div>
</div>
</div>
<div class="personal-info-container">
<div class="name-container">
<el-text class="name" width="auto">入院科室</el-text>
<el-text class="name" width="auto">
{{ item.organizationName ? item.organizationName : '-' }}
</el-text>
</div>
</div>
<div class="personal-info-container">
<div class="name-container">
<el-text class="name" width="auto">住院号</el-text>
<el-text class="name" width="auto">
{{ item.busNo ? item.busNo : '-' }}
</el-text>
</div>
</div>
</div>
</el-scrollbar>
</div>
</div>
<div
class="disabled-wrapper"
style="width: 85%; border: 1px solid #eee; position: relative"
@dragover="handleDragOver"
@drop="handleDrop"
>
<div class="bedAllocation-search">
<div
v-for="item in filteredBadList"
:key="item.id"
class="search-item"
:class="{ 'drag-over': draggedOverBedId === item.bedId }"
style="padding: 10px; border: 1px solid #eee; margin: 5px; border-radius: 4px;"
@dragover="handleBedDragOver($event, item)"
@dragenter="handleBedDragEnter(item)"
@dragleave="handleBedDragLeave"
@drop="handleBedDrop($event, item)"
>
<div class="bed-tag" :class="getBedTagClass(item)">
{{ item.bedStatus_enumText }}
</div>
<div>
<div>
{{ item.houseName + '-' + item.bedName }}
</div>
<div style="margin-top: 6px;">
{{ item.patientName }}
<el-text class="name" width="auto" v-if="item.encounterId">
{{ item.genderEnum_enumText }}/{{ item.age }}
</el-text>
</div>
</div>
</div>
</div>
</div>
</div>
<TransferInDialog
v-model:visible="transferInDialogVisible"
:pendingInfo="pendingInfo"
:priorityOptions="priorityOptions"
@okAct="handleTransferInOk" />
<SignEntryDialog v-model:visible="signEntryDialogVisible" />
</div>
</template>
<script setup lang="ts">
import { getCurrentInstance, onBeforeMount, onMounted, reactive, ref, computed } from 'vue'
import { TransferInDialog, SignEntryDialog } from './index'
import { getPendingInfo, getBedInfo, getInit, childLocationList } from './api'
import { formatDate } from '@/utils/index';
import { init } from '../../../basicmanage/consumablesBinding/components/api';
import { ElMessage, ElMessageBox } from 'element-plus'
// 定义相关类型
interface OptionItem {
id: string | number;
name: string;
}
interface OptionItemTwo {
value: string | number;
label: string;
}
interface InitInfoOptions {
encounterStatusOptions: OptionItemTwo[];
bedStatusOptions: OptionItemTwo[];
priorityOptions: OptionItem[];
wardListOptions: OptionItemTwo[]
}
const transferInDialogVisible = ref(false)
const signEntryDialogVisible = ref(false)
const state = reactive({})
const loading = ref(false)
const total = ref();
const badList = ref<any[]>([])
const patientList = ref<any[]>([]);
const pendingInfo = ref({})
const draggedPatient = ref<any>(null);
const wardLocationList = ref<OptionItem[]>([])
const draggedOverBedId = ref<number | null>(null)
const priorityOptions = ref<OptionItem[]>([])
const wardListOptions = ref<OptionItem[]>([])
const houseListOptions = ref<OptionItem[]>([])
const initInfoOptions = ref<InitInfoOptions>({
encounterStatusOptions: [],
bedStatusOptions: [],
priorityOptions: [],
wardListOptions: []
})
// 新增床状态筛选字段
const bedStatusFilter = ref('')
onBeforeMount(() => {})
const queryParams = ref({
pageNo: 1,
pageSize: 50,
searchKey: '',
wardId: '',
houseId: '',
encounterStatus: '',
bedStatus: '' // 这个字段现在只用于床位查询,不再用于患者列表查询
})
onMounted(() => {
getInit().then(res => {
initInfoOptions.value = res.data
priorityOptions.value = res.data.priorityOptions || []
queryParams.value.wardId = res.data.wardListOptions[0].value
changeWardLocationId(res.data.wardListOptions[0].value)
getList()
})
})
defineExpose({ state })
// 计算属性:根据床状态筛选条件过滤床位列表
const filteredBadList = computed(() => {
if (!bedStatusFilter.value) {
return badList.value
}
return badList.value.filter(item => item.bedStatus == bedStatusFilter.value)
})
const getList = () => {
getPatientList()
// 床位查询不使用encounterStatus参数只使用基本的查询参数
const bedQueryParams = {
...queryParams.value,
encounterStatus: undefined // 移除encounterStatus确保不影响床位列表查询
}
getBedInfo(bedQueryParams).then(res => {
badList.value = res.data.records
})
}
// 重置查询条件
function resetQuery() {
queryParams.value = {
pageNo: 1,
pageSize: 50,
searchKey: '',
wardId: '',
houseId: '',
encounterStatus: '',
bedStatus: ''
}
bedStatusFilter.value = ''
getList()
}
function changeWardLocationId(id) {
let params = {
locationId: id,
locationForm: 10
}
queryParams.value.houseId = ''
childLocationList(params).then(res => {
wardLocationList.value = res
})
}
// 获新入院患者列表
function getPatientList() {
// 为患者列表查询创建一个新的参数对象不包含bedStatus
const patientQueryParams = {
...queryParams.value,
bedStatus: undefined // 移除bedStatus确保不影响患者列表查询
}
getPendingInfo(patientQueryParams).then(res => {
loading.value = false
patientList.value = res.data.records
total.value = res.data.total;
})
}
const handleTransferInOk = () => {
transferInDialogVisible.value = false
getList()
}
function handleCardClick(item: any, index: number) {
}
// 双击患者卡片事件
function handleCardDblClick(item: any) {
if(item.encounterStatus == 2) {
ElMessage({
message: '请分配病床!',
type: 'warning',
grouping: true,
showClose: true,
})
}else {
pendingInfo.value = {
...item,
entranceType: 1
};
transferInDialogVisible.value = true;
}
}
// 拖拽开始事件
function handleDragStart(event: DragEvent, item: any) {
if (event.dataTransfer) {
event.dataTransfer.setData('text/plain', JSON.stringify(item));
draggedPatient.value = item;
// 设置拖拽样式
if (event.target instanceof HTMLElement) {
event.target.classList.add('dragging');
}
}
}
function handleQuery() {
getList()
}
// 拖拽结束事件
function handleDragEnd(event: DragEvent) {
// 清除拖拽样式
if (event.target instanceof HTMLElement) {
event.target.classList.remove('dragging');
}
// 清除高亮
draggedOverBedId.value = null;
}
// 拖拽过程中阻止默认行为
function handleDragOver(event: DragEvent) {
event.preventDefault();
}
// 拖拽放置事件
function handleDrop(event: DragEvent) {
event.preventDefault();
// 清除高亮
draggedOverBedId.value = null;
}
// 床位拖拽事件
function handleBedDragOver(event: DragEvent, bed: any) {
event.preventDefault();
}
// 床位拖拽进入事件
function handleBedDragEnter(bed: any) {
draggedOverBedId.value = bed.bedId;
}
// 床位拖拽离开事件
function handleBedDragLeave(event: DragEvent) {
// 避免子元素触发的dragleave事件清除高亮
if (event.target === event.currentTarget) {
draggedOverBedId.value = null;
}
}
// 床位放置事件
function handleBedDrop(event: DragEvent, bed: any) {
if(draggedPatient.value.encounterStatus == 2 && bed.bedStatus == 5) {
ElMessage({
message: '该床位已被占用!',
type: 'error',
grouping: true,
showClose: true,
})
}else {
if(draggedPatient.value.encounterStatus == 5) {
ElMessageBox.confirm('是否确认换床?')
.then(() => {
event.preventDefault();
// 清除高亮
draggedOverBedId.value = null;
if (draggedPatient.value) {
// 合并患者信息和床位信息
pendingInfo.value = {
...draggedPatient.value,
bedName: bed.bedName,
bedId: bed.bedId,
targetHouseId: bed.houseId,
entranceType: 2,
targetEncounterId: bed.encounterId,
houseName: bed.houseName
};
// 显示TransferInDialog对话框
transferInDialogVisible.value = true;
// 清空拖拽的患者信息
draggedPatient.value = null;
}
})
.catch(() => {
// catch error
})
}else {
event.preventDefault();
// 清除高亮
draggedOverBedId.value = null;
if (draggedPatient.value) {
// 合并患者信息和床位信息
pendingInfo.value = {
...draggedPatient.value,
bedName: bed.bedName,
bedId: bed.bedId,
targetHouseId: bed.houseId,
entranceType: 2,
targetEncounterId: bed.encounterId
};
// 显示TransferInDialog对话框
transferInDialogVisible.value = true;
// 清空拖拽的患者信息
draggedPatient.value = null;
}
}
}
}
// 根据bedStatus获取床位标签类
function getBedTagClass(item: any) {
if (item.bedStatus == 6) {
return 'blue-tag';
} else if (item.bedStatus == 5) {
return 'green-tag';
}
return '';
}
function getPatientTagClass(item: any) {
if (item.encounterStatus == 2) {
return 'blue-tag';
} else if (item.encounterStatus == 5) {
return 'green-tag';
}
return '';
}
const addSigns = (row: any) => {
// TODO 新增入院体征
signEntryDialogVisible.value = true
}
const selectBed = (row: any) => {
pendingInfo.value = row
// TODO 选床 入科
transferInDialogVisible.value = true
}
</script>
<style lang="scss" scoped>
.bedAllocation-container {
height: 100%;
display: flex;
flex-direction: column;
.bedAllocation-search {
height: 100px;
width: 100%;
display: flex;
flex-wrap: wrap;
align-items: center;
.search-item {
width: 200px;
height: 100px;
display: flex;
margin: 10px;
border-radius: 4px;
box-shadow: 0 2px 2px 0 rgba(57.55, 69.04, 86.28, 20%);
position: relative;
transition: all 0.2s ease;
&.drag-over {
background-color: #e6f7ff;
border-color: #1890ff;
box-shadow: 0 0 8px rgba(24, 144, 255, 0.6);
transform: scale(1.03);
}
&.blue-bed {
background-color: #e6f7ff; // 蓝色背景
border-color: #91d5ff;
}
&.green-bed {
background-color: #f6ffed; // 绿色背景
border-color: #b7eb8f;
}
.bed-tag {
position: absolute;
top: 0;
right: 0;
font-size: 14px;
padding: 2px 8px;
border-radius: 4px;
&.blue-tag {
background-color: #1890ff; // 蓝色标签
color: white;
}
&.green-tag {
background-color: #52c41a; // 绿色标签
color: white;
}
}
}
}
.bedAllocation-table {
flex: auto;
}
}
.patient-card {
width: 100%;
overflow: hidden;
background-color: #fff;
border: 1px solid;
border-color: #eee;
border-radius: 4px;
box-shadow: 0 2px 2px 0 rgba(57.55, 69.04, 86.28, 20%);
margin-bottom: 10px;
cursor: pointer;
transition: all 0.2s ease;
&.actived {
background-color: rgb(7, 155, 140, 5%);
border-color: var(--el-color-primary);
}
&.dragging {
opacity: 0.5;
transform: rotate(5deg);
}
.cross-dept {
height: 24px;
padding: 0 16px;
color: #fff;
font-size: 14px;
line-height: 24px;
background-color: #256d95;
}
.doctor-parent-line {
margin: 0 16px;
border-bottom: 1px dashed #ddd;
}
.personal-info-container {
display: flex;
align-items: center;
justify-content: space-between;
margin: 8px 0;
padding: 0 16px;
.name-container {
display: flex;
align-items: center;
height: 18px;
.name {
color: #333;
font-size: 14px;
}
.age {
margin-left: 10px;
color: #666;
font-size: 14px;
}
}
.change-department {
width: 58px;
height: 24px;
color: #5585e3;
font-size: 14px;
line-height: 24px;
text-align: center;
background: #e6edfb;
border-radius: 4px;
}
}
.dept {
margin-bottom: 4px;
padding: 0 16px;
display: flex;
justify-content: space-between;
align-items: center;
.doctor {
display: flex;
align-items: center;
height: 32px;
line-height: 32px;
.doctor_name {
display: flex;
align-items: center;
margin-left: 4px;
color: #333;
}
}
.deptNurseName {
display: flex;
align-items: center;
height: 32px;
color: #256d95;
line-height: 32px;
}
}
}
// 拖拽时的全局样式
.patient-card.dragging {
opacity: 0.6;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
transform: rotate(3deg);
z-index: 100;
}
.main-info-container {
display: flex;
align-items: center;
justify-content: space-between;
height: 32px;
margin: 7px 0;
padding: 0 16px;
margin-right: 48px;
position: relative;
.patient-tag {
position: absolute;
top: -7px;
right: -48px;
font-size: 14px;
padding: 2px 8px;
border-radius: 4px;
&.blue-tag {
background-color: #1890ff; // 蓝色标签
color: white;
}
&.green-tag {
background-color: #52c41a; // 绿色标签
color: white;
}
}
.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: #333;
font-weight: 600;
font-size: 16px;
}
}
.bed_new {
flex-shrink: 0;
width: 10px;
height: 10px;
margin-left: 4px;
background: #29af6f;
border-radius: 50%;
}
}
.indepatient-code-container {
display: flex;
flex-shrink: 0;
align-items: center;
padding-left: 6px;
color: #666;
font-size: 14px;
.sign {
width: 24px;
height: 24px;
color: white;
line-height: 24px;
text-align: center;
border-radius: 50%;
user-select: none;
}
}
}
.pagination-container {
padding: 0px 20px !important;
}
::v-deep .el-form-item--default .el-form-item__label {
line-height: 44px;
}
</style>

View File

@@ -0,0 +1,111 @@
<!--
* @Author: sjjh
* @Date: 2025-04-10 13:02:22
* @Description:
-->
<template>
<div class="bedCardsInfo-container">
<div class="bedCardsInfo" v-for="item in 20" :key="item">
<div class="">
<span>{{ bed.roomNo }}-{{ bed.bedName }}</span>
<el-icon><Male /></el-icon>
<!-- 男女的标识 -->
</div>
<div>
<el-icon size="40px"><HomeFilled /></el-icon>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { getCurrentInstance, onBeforeMount, onMounted, reactive, ref } from 'vue'
// const { proxy } = getCurrentInstance();
const emits = defineEmits(['drop_handler', 'click_handler'])
const props = defineProps({
// bed: {
// type: Object as PropType<Array<Partial<IBedInfo>>>,
// require: true,
// default: () => {
// return {}
// },
// },
})
const state = reactive({})
const bed = ref({
roomNo: 1,
bedName: 2,
})
// onBeforeMount(() => {
// })
// onMounted(() => {
// })
defineExpose({ state })
</script>
<style lang="scss" scoped>
.bedCardsInfo-container {
display: flex;
flex-wrap: wrap;
.bedCardsInfo {
width: 163px;
height: 104px;
margin: 8px;
padding: 0 16px;
background: #fff;
border: 1px solid #ddd;
border-radius: 4px;
.selectbed {
cursor: pointer;
fill: #999;
}
&::backdrop {
outline: 2px solid #13c0b3;
.selectbed {
fill: #13c0b3;
}
}
&:hover {
outline: 2px solid;
.selectbed {
fill: #13c0b3;
}
}
> div:first-child {
display: flex;
align-items: center;
justify-content: space-between;
height: 40px;
line-height: 40px;
border-bottom: 1px dashed #ddd;
// > :last-child {
// // text-align: right;
// margin-left: auto;
// }
}
> div:nth-child(2) {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: calc(100% - 41px);
}
}
.bedCardInfo-active {
outline: 2px solid #13c0b3;
.selectbed {
fill: #13c0b3;
}
}
}
</style>

View File

@@ -0,0 +1,11 @@
/*
* @Author: sjjh
* @Date: 2025-04-09 20:32:21
* @Description:
*/
import BedAllocation from './bedAllocation.vue'
import TransferInDialog from './transferInDialog.vue'
import SignEntryDialog from './signEntryDialog.vue'
import BedCards from './bedcards.vue'
export { BedAllocation, TransferInDialog, SignEntryDialog, BedCards }

View File

@@ -0,0 +1,175 @@
<template>
<el-dialog v-model="visible" top="6vh" :width="width" title="体征录入" @open="openAct" @closed="closedAct" :z-index="20" destroy-on-close>
<div class="transferIn-container">
<div class="beds"></div>
<el-form :model="signForm" :rules="rules" ref="signFormRef">
<div class="admission-signs">
<el-row>
<el-col :span="8">
<el-form-item label="身高" label-width="50px">
<el-input-number style="width: 160px" clearable v-model="signForm.height" placeholder="请输入" :min="0"
:max="999"></el-input-number><span class="unit">cm</span>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="体重" label-width="50px">
<el-input-number style="width: 160px" v-model="signForm.weight" clearable placeholder="请输入" :min="0"
:max="999"></el-input-number>
<span class="unit">kg</span>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="体温" label-width="50px">
<el-input-number style="width: 160px" v-model="signForm.temperature" clearable placeholder="请输入"
:min="0" :max="99"></el-input-number>
<span class="unit"></span>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="心率" label-width="50px">
<el-input-number style="width: 160px" v-model="signForm.hertRate" clearable placeholder="请输入" :min="0"
:max="999"></el-input-number>
<span class="unit">BPM</span>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="脉搏" label-width="50px">
<el-input-number style="width: 160px" v-model="signForm.pulse" clearable placeholder="请输入" :min="0"
:max="999"></el-input-number><span class="unit">P</span>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="血压" label-width="50px">
<el-input-number style="width: 72px" v-model="signForm.endBloodPressure" clearable placeholder="请输入"
:min="0" :max="999"></el-input-number>
<span style="display: inline-block; width: 8px; margin: 0 4px"> ~ </span>
<el-input-number style="width: 72px" v-model="signForm.highBloodPressure" clearable placeholder="请输入"
:min="0" :max="999"></el-input-number>
<span class="unit">mmHg</span>
</el-form-item>
</el-col>
</el-row>
</div>
</el-form>
</div>
<template #footer>
<el-button class="margin-left-auto" @click="cancelAct">取消 </el-button>
<el-button type="primary" @click="handleSubmit(signFormRef)">保存</el-button>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { reactive, ref, onMounted, inject } from 'vue'
import type { FormInstance, FormRules } from 'element-plus'
import { dayjs, ElMessage } from 'element-plus'
import type { IInPatient } from '@/model/IInPatient'
const currentInPatient = ref<Partial<IInPatient>>({})
const initCurrentInPatient = () => {
currentInPatient.value = {
feeType: '08',
sexName: '男',
age: '0',
}
}
/* 初始化数据 */
const init = () => {
initCurrentInPatient()
}
/* 入科 */
const signForm = ref({
visitCode: '', // 就诊流水号
height: 0, // 身高
weight: 0, // 体重
temperature: 0, // 体温
hertRate: 0, // 心率
pulse: 0, // 脉搏
highBloodPressure: 0, // 收缩压
endBloodPressure: 0, // 舒张压
loginDeptCode: '', // 当前登录科室
bingqing: '', //患者病情
inDeptDate: dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss'), //入院时间
signsId: '',
})
const rules = reactive<FormRules>({
admittedDoctor: [{ required: true, message: '请选择住院医生', trigger: ['blur', 'change'] }],
masterNurse: [{ required: true, message: '请选择责任护士', trigger: ['blur', 'change'] }],
})
const printWristband = ref(false)
const emits = defineEmits(['okAct'])
const visible = defineModel('visible')
const width = '920px'
/* 取消 */
const cancelAct = () => {
visible.value = false
}
/* 录入患者体征*/
const signFormRef = ref()
const handleSubmit = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate((valid, fields) => {
if (valid) {
console.log('submit!')
try {
// 录入患者体征方法(signForm.value).then((res: any) => {
// ElMessage({
// message: '登记成功!',
// type: 'success',
// grouping: true,
// showClose: true,
// })
// emits('okAct')
// })
} catch (error) {
console.log(error)
}
}
})
}
const openAct = () => {
init()
}
const closedAct = () => {
visible.value = false
}
onMounted(() => { })
</script>
<style lang="scss" scoped>
.transferIn-container {
width: 100%;
.admission-signs,
.admission-information {
width: 888px;
.unit {
display: inline-block;
margin-left: 10px;
color: #bbb;
font-weight: 400;
font-size: 14px;
font-family: '思源黑体 CN';
}
}
}
.print-wriBtn {
margin-left: 565px;
}
.w-p100 {
width: 100%;
}
.w-80 {
width: 80px;
}
.mb-90 {
margin-bottom: 90px !important;
}
</style>

View File

@@ -0,0 +1,534 @@
<template>
<el-dialog
v-model="visible"
top="6vh"
:width="width"
title="入科选床"
@open="openAct"
@closed="closedAct"
:z-index="20"
destroy-on-close
>
<div class="transferIn-container">
<el-form :model="interventionForm" :rules="rules" ref="interventionFormRef">
<div class="admission-information">
<el-row>
<el-col :span="24">
<div class="patient-info">
<div style="display: flex;align-items: center;margin-bottom: 16px;">
<div style="margin-right: 36px;font-size: 18px;font-weight: 700;">{{ props.pendingInfo.houseName + '-' + props.pendingInfo.bedName }}</div>
<div style="border-radius: 50px;border: 2px solid slategray;padding: 4px 12px;">{{ props.pendingInfo.contractName }}</div>
</div>
<div>
<el-row>
<el-col :span="12">
<div style="margin-bottom: 12px;">
{{ props.pendingInfo.patientName}}
<span style="color: #9f9f9f;">{{ props.pendingInfo.genderEnum_enumText}}/</span>
<span style="color: #9f9f9f;">{{ props.pendingInfo.age}}</span>
</div>
</el-col>
<el-col :span="12">
<div>
电话{{ pendingInfo.phone }}
</div>
</el-col>
<el-col :span="12">
<div>
住院诊断{{ pendingInfo.conditionNames }}
</div>
</el-col>
<el-col :span="12">{{ props.pendingInfo.patientId }}</el-col>
</el-row>
</div>
</div>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<div class="info-title">
入院体征
</div>
</el-col>
<el-col :span="8">
<el-form-item label="身高" label-width="50px">
<el-input-number :controls="false" style="width: 160px" clearable v-model="interventionForm.height" placeholder="请输入" :min="0"
:max="999"></el-input-number><span class="unit">cm</span>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="体重" label-width="50px">
<el-input-number :controls="false" style="width: 160px" v-model="interventionForm.weight" clearable placeholder="请输入" :min="0"
:max="999"></el-input-number>
<span class="unit">kg</span>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="体温" label-width="50px">
<el-input-number :controls="false" style="width: 160px" v-model="interventionForm.temperature" clearable placeholder="请输入"
:min="0" :max="99"></el-input-number>
<span class="unit"></span>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="心率" label-width="50px">
<el-input-number :controls="false" style="width: 160px" v-model="interventionForm.hertRate" clearable placeholder="请输入" :min="0"
:max="999"></el-input-number>
<span class="unit">BPM</span>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="脉搏" label-width="50px">
<el-input-number :controls="false" style="width: 160px" v-model="interventionForm.pulse" clearable placeholder="请输入" :min="0"
:max="999"></el-input-number><span class="unit">P</span>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="血压" label-width="50px">
<el-input-number :controls="false" style="width: 72px" v-model="interventionForm.endBloodPressure" clearable placeholder="请输入"
:min="0" :max="999"></el-input-number>
<span style="display: inline-block; width: 8px; margin: 0 4px"> ~ </span>
<el-input-number :controls="false" style="width: 72px" v-model="interventionForm.highBloodPressure" clearable placeholder="请输入"
:min="0" :max="999"></el-input-number>
<span class="unit">mmHg</span>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<div class="info-title">
入院信息
</div>
</el-col>
<el-col :span="8">
<el-form-item label="入院科室" label-width="100px">
<el-input
class="w-p100"
clearable
disabled
v-model="interventionForm.organizationName"
placeholder="请输入"
></el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="入院病区" label-width="100px">
<el-input
class="w-p100"
v-model="interventionForm.wardName"
disabled
clearable
placeholder="请输入"
></el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="入住床位" label-width="100px">
<el-input
class="w-p100"
v-model="interventionForm.bedName"
disabled
clearable
placeholder="请输入"
></el-input>
<!-- <el-select v-model="interventionForm.bedLocationId" placeholder="请选择入住床位" style="width: 100%">
<el-option
v-for="item in bedInfoOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select> -->
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="住院医生" label-width="100px" prop="admittingDoctorId">
<el-select
v-model="interventionForm.admittingDoctorId"
placeholder="请选择住院医生"
style="width: 240px"
:disabled="props.pendingInfo.encounterStatus == 5 && props.pendingInfo.entranceType == 2"
>
<el-option
v-for="item in doctorInfoOptions"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="主治医生" label-width="100px">
<el-select
v-model="interventionForm.attendingDoctorId"
placeholder="请选择主治医生"
style="width: 240px"
:disabled="props.pendingInfo.encounterStatus == 5 && props.pendingInfo.entranceType == 2"
>
<el-option
v-for="item in doctorInfoOptions"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="主任医生" label-width="100px">
<el-select
v-model="interventionForm.chiefDoctorId"
placeholder="请选择主任医生"
style="width: 240px"
:disabled="props.pendingInfo.encounterStatus == 5 && props.pendingInfo.entranceType == 2"
>
<el-option
v-for="item in doctorInfoOptions"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="入科时间" label-width="100px">
<el-date-picker
class="w-p100"
v-model="interventionForm.startTime"
type="datetime"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="请输入"
:disabled="props.pendingInfo.encounterStatus == 5"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="责任护士" label-width="100px" prop="primaryNurseId">
<el-select
v-model="interventionForm.primaryNurseId"
placeholder="请选择责任护士"
style="width: 240px"
:disabled="props.pendingInfo.encounterStatus == 5 && props.pendingInfo.entranceType == 2"
>
<el-option
v-for="item in nurseInfoOptions"
:key="item.practitionerId"
:label="item.name"
:value="item.practitionerId"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="患者病情" label-width="100px">
<el-select
v-model="interventionForm.priorityEnum"
placeholder="请选择患者病情"
style="width: 240px"
:disabled="props.pendingInfo.encounterStatus == 5 && props.pendingInfo.entranceType == 2"
>
<el-option
v-for="item in props.priorityOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
</div>
</el-form>
</div>
<template #footer>
<!-- <div class="transferInDialog-footer"> -->
<div class="isPrintWristband">
<el-checkbox v-model="printWristband">打印腕带</el-checkbox>
</div>
<el-button class="margin-left-auto" @click="cancelAct">取消 </el-button>
<el-button type="primary" @click="handleSubmit">入科</el-button>
<!-- </div> -->
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { reactive, ref, onMounted, inject, type Ref, watch } from 'vue'
import type { FormInstance, FormRules } from 'element-plus'
import { dayjs, ElMessage } from 'element-plus'
// import type { IInPatient } from '@/model/IInPatient'
import { getBedInfo, getDoctorInfo, getNurseInfo, getInit, bedAssignment, getPatientInfo } from './api'
const props = defineProps({
pendingInfo: {
type: Object,
require: true,
default: () => ({})
},
priorityOptions: {
type: Object,
require: true,
default: () => ({})
},
})
const currentInPatient = ref<Partial<IInPatient>>({})
const bedInfoOptions = ref<{ label: string; value: string }[]>([])
const doctorInfoOptions = ref<{ name: string; id: string }[]>([])
const nurseInfoOptions = ref<{ name: string; practitionerId: string }[]>([])
const InitInfoOptions = ref<any>({})
const priorityListOptions = ref<{ info: string; value: string }[]>([])
const pendingInfo = ref<any>({})
const initCurrentInPatient = () => {
currentInPatient.value = {
feeType: '08',
sexName: '男',
age: '0',
}
}
/* 入科 */
const interventionForm = ref({
height: undefined,
weight: undefined,
temperature: undefined,
hertRate: undefined,
pulse: undefined,
endBloodPressure: undefined,
highBloodPressure: undefined,
bedLocationId: '', // 床号
admittingDoctorId: '', // 住院医师
attendingDoctorId: '', // 主治医师
chiefDoctorId: '', // 主任医师
primaryNurseId: '', // 责任护士
priorityEnum: '', //患者病情
organizationName: '',
wardName: '',
bedName: '',
attendingDocUpdateId: '',
startTime: '', //入院时间
})
watch(() => props.pendingInfo, (newVal, oldVal) => {
console.log(newVal)
if(newVal) {
getPatientInfo({encounterId: newVal.encounterId}).then(res => {
pendingInfo.value = res.data
interventionForm.value.admittingDoctorId = res.data.admittingDoctorId
interventionForm.value.attendingDoctorId = res.data.attendingDoctorId
interventionForm.value.chiefDoctorId = res.data.chiefDoctorId
interventionForm.value.primaryNurseId = res.data.primaryNurseId
if(res.data.startTime) {
interventionForm.value.startTime = dayjs(res.data.startTime).format('YYYY-MM-DD HH:mm:ss')
}else {
interventionForm.value.startTime = dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss')
}
})
interventionForm.value.priorityEnum = newVal.priorityEnum
interventionForm.value.organizationName = newVal.organizationName
interventionForm.value.wardName = newVal.wardName
interventionForm.value.bedName = newVal.bedName
}
},{ deep: true })
/* 初始化数据 */
const init = () => {
initCurrentInPatient()
getInit().then(res => {
InitInfoOptions.value = res.data
// 安全地设置priorityListOptions
if (res.data && res.data.priorityListOptions) {
priorityListOptions.value = res.data.priorityListOptions
}
}).catch(error => {
console.error('获取初始化数据失败:', error)
})
if (props.pendingInfo.wardLocationId) {
getBedInfo({wardLocationId: props.pendingInfo.wardLocationId}).then(res => {
bedInfoOptions.value = res.data || []
}).catch(error => {
console.error('获取床位信息失败:', error)
bedInfoOptions.value = []
})
}
if (props.pendingInfo.organizationId) {
getDoctorInfo({organizationId: props.pendingInfo.organizationId}).then(res => {
doctorInfoOptions.value = res.data.records || []
}).catch(error => {
console.error('获取医生信息失败:', error)
doctorInfoOptions.value = []
})
getNurseInfo({organizationId: props.pendingInfo.organizationId}).then(res => {
nurseInfoOptions.value = res.data || []
}).catch(error => {
console.error('获取护士信息失败:', error)
nurseInfoOptions.value = []
})
}
}
const rules = reactive<FormRules>({
admittingDoctorId: [{ required: true, message: '请选择住院医生', trigger: ['blur', 'change'] }],
primaryNurseId: [{ required: true, message: '请选择责任护士', trigger: ['blur', 'change'] }],
bedLocationId: [{ required: true, message: '请选择入住床位', trigger: ['blur', 'change'] }],
})
const printWristband = ref(false)
const emits = defineEmits(['okAct'])
const visible = defineModel('visible')
const width = '950px'
/* 取消 */
const cancelAct = () => {
resetForm()
visible.value = false
}
const resetForm = () => {
// interventionForm.value = {
// height: undefined,
// weight: undefined,
// temperature: undefined,
// hertRate: undefined,
// pulse: undefined,
// endBloodPressure: undefined,
// highBloodPressure: undefined,
// bedLocationId: '', // 床号
// admittingDoctorId: '', // 住院医师
// attendingDoctorId: '', // 主治医师
// chiefDoctorId: '', // 主任医师
// primaryNurseId: '', // 责任护士
// priorityEnum: '', //患者病情
// organizationName: '',
// wardName: '',
// attendingDocUpdateId: '',
// startTime: '', //入院时间
// }
// 可选:清空校验状态
if (interventionFormRef.value) {
interventionFormRef.value.resetFields()
}
}
/* 入科 */
const interventionFormRef = ref<FormInstance | null>(null)
const handleSubmit = async () => {
// TODO 登记入科
if (!interventionFormRef.value) {
console.error('表单引用不存在')
return
}
try {
const valid = await interventionFormRef.value.validate()
if (valid) {
const params = {
...pendingInfo.value,
...interventionForm.value,
targetBedId: props.pendingInfo.bedId,
busNo: props.pendingInfo.busNo,
inHosTime: props.pendingInfo.inHosTime,
targetHouseId : props.pendingInfo.targetHouseId,
targetEncounterId: props.pendingInfo.targetEncounterId,
editFlag: props.pendingInfo.entranceType == 1 ? 1 : 0
}
bedAssignment(params).then((res: any) => {
ElMessage({
message: '登记成功!',
type: 'success',
grouping: true,
showClose: true,
})
resetForm()
emits('okAct')
visible.value = false // 关闭对话框
}).catch((error: any) => {
console.error('登记失败:', error)
ElMessage({
message: '登记失败!',
type: 'error',
grouping: true,
showClose: true,
})
})
}
} catch (error) {
console.log('表单验证失败:', error)
}
}
const openAct = () => {
init()
if (props.pendingInfo) {
interventionForm.value.priorityEnum = props.pendingInfo.priorityEnum || ''
interventionForm.value.admittingDoctorId = props.pendingInfo.practitionerId || ''
interventionForm.value.organizationName = props.pendingInfo.organizationName || ''
interventionForm.value.wardName = props.pendingInfo.wardName || ''
interventionForm.value.attendingDocUpdateId = props.pendingInfo.admittingDoctorId || ''
}
}
const closedAct = () => {
resetForm()
visible.value = false
}
onMounted(() => {})
</script>
<style lang="scss" scoped>
.transferIn-container {
width: 100%;
.admission-information {
width: 896px;
.unit {
display: inline-block;
margin-left: 10px;
color: #bbb;
font-weight: 400;
font-size: 14px;
font-family: '思源黑体 CN';
}
}
.beds {
margin-bottom: 8px;
}
}
.patient-info {
padding: 16px;
margin: 10px;
border-radius: 4px;
box-shadow: 0 2px 2px 0 rgba(58, 69, 86, 0.2);
position: relative;
transition: all 0.2s ease;
}
.isPrintWristband {
float: left;
display: inline-block;
}
.w-p100 {
width: 100%;
}
.w-80 {
width: 80px;
}
.info-title {
background: #f6f7f9;
color: #4f6877;
padding: 5px 10px;
margin-bottom: 16px;
}
</style>

View File

@@ -0,0 +1,54 @@
<!--
* @Author: sjjh
* @Date: 2025-04-09 14:50:04
* @Description:
-->
<template>
<div class="inpatientNurseHome-inOut-container">
<el-tabs v-model="activeTabName" type="card" class="inOut-tabs">
<el-tab-pane label="入科" name="first">
<BedAllocation />
</el-tab-pane>
<el-tab-pane label="转出" name="second">Config</el-tab-pane>
<el-tab-pane label="出院" name="second">Config</el-tab-pane>
<el-tab-pane label="出院患者" name="second">Config</el-tab-pane>
</el-tabs>
</div>
</template>
<script setup lang="ts">
import { getCurrentInstance, onBeforeMount, onMounted, reactive, ref } from 'vue'
import { BedAllocation, TransferInDialog, SignEntryDialog } from './components/index'
// const { proxy } = getCurrentInstance()
// const emits = defineEmits([])
// const props = defineProps({})
const state = reactive({})
onBeforeMount(() => {})
onMounted(() => {
})
defineExpose({ state })
const activeTabName = ref('first')
</script>
<style lang="scss" scoped>
.inpatientNurseHome-inOut-container {
width: 100%;
height: 100%;
display: flex;
padding: 0 8px 8px;
:deep(.inOut-tabs) {
height: 100%;
width: 100%;
.el-tabs__header {
margin: 0;
}
.el-tab-pane {
height: 100%;
}
.el-tabs__content {
height: calc(100% - 40px);
}
}
}
</style>