版本更新

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,26 @@
<template>
<div class="waitForDischarge-container">
<patientList />
<Review />
</div>
</template>
<script setup >
import patientList from './patientList.vue'
import Review from './review.vue'
</script>
<style lang="scss" scoped>
.waitForDischarge-container {
display: flex;
height: 100%;
width: 100%;
.patientList-container {
flex: none;
width: 240px;
}
.medicalOrderList-container {
flex: 1;
}
}
</style>

View File

@@ -0,0 +1,73 @@
<template>
<div class="patientList-container">
<div class="search-container">
<el-button>查询</el-button>
</div>
<div class="patientList-table">
<el-table :data="patientListData" row-key="id" style="width: 100%; height: 100%" highlight-current-row
@selection-change="handleSelectionChange" :show-header="false" show-overflow-tooltip>
<el-table-column label="姓名" prop="name" min-width="100">
<template #default="{ row }">
<div class="patient-name">
<span class="name">{{ row.name }}</span>
</div>
</template>
</el-table-column>
<el-table-column type="expand">
患者详细信息状态是否审核开始时间住院号姓名性别年龄费别责任医生责任护士入院诊断出院诊断在院科室
操作审核撤销审核
</el-table-column>
</el-table>
</div>
</div>
</template>
<script setup >
import { ref } from 'vue';
const patientListData = ref([
{
id: 1,
name: '张三1111111',
age: 30,
gender: '男',
status: '在科',
attention: '医生A',
department: '儿科',
},
{
id: 2,
name: '李四',
age: 25,
gender: '女',
status: '转科',
attention: '医生B'
}
])
const handleSelectionChange = (selection) => {
console.log('handleSelectionChange', selection)
}
</script>
<style lang="scss" scoped>
.patientList-container {
display: flex;
flex-direction: column;
height: 100%;
width: 100%;
overflow: hidden;
width: 240px;
border-right: 1px solid #e4e7ed;
.search-container {
flex: none;
padding: 8px 8px;
text-align: right;
}
.patientList-table {
flex: 1;
}
}
</style>

View File

@@ -0,0 +1,91 @@
<template>
<div class="review-container">
<div class="search-container">
<el-button>出院召回</el-button>
<el-button>费用审核</el-button>
</div>
<div class="review-table">
<el-tabs v-model="activeTabName" type="card" class="inOut-tabs">
<el-tab-pane label="待处理执行单" name="first">
<el-table :data="tableData" style="width: 100%">
<el-table-column prop="date" label="类型" width="180" />
<el-table-column prop="name" label="医嘱内容" width="180" />
<el-table-column prop="address" label="开始/终止" />
<el-table-column prop="address" label="预计执行" />
</el-table>
</el-tab-pane>
<el-tab-pane label="退费申请" name="second">
<el-table :data="tableData" style="width: 100%">
<el-table-column prop="date" label="退费申请科室" width="180" />
<el-table-column prop="name" label="申请时间" width="180" />
<el-table-column prop="address" label="项目名称【规格】" />
<el-table-column prop="date" label="申请数量" width="180" />
<el-table-column prop="date" label="单价" width="180" />
<el-table-column prop="date" label="总金额" width="180" />
<el-table-column prop="date" label="申请人" width="180" />
<el-table-column prop="date" label="备注" width="180" />
</el-table>
</el-tab-pane>
<el-tab-pane label="待取药/待退药" name="third">
<el-table :data="tableData" style="width: 100%">
<el-table-column prop="date" label="类型(取/退)" width="180" />
<el-table-column prop="name" label="发送科室" width="180" />
<el-table-column prop="address" label="发送时间" />
<el-table-column prop="address" label="药房" />
<el-table-column prop="address" label="项目名称【规格】" />
<el-table-column prop="address" label="单价" />
<el-table-column prop="address" label="数量" />
<el-table-column prop="address" label="金额" />
<el-table-column prop="address" label="发送人" />
<el-table-column prop="address" label="预计执行时间" />
</el-table>
</el-tab-pane>
</el-tabs>
</div>
</div>
</template>
<script setup >
import { ref } from 'vue';
const activeTabName = ref('first');
const tableData = [
{
date: '2016-05-03',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-02',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-04',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-01',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
]
</script>
<style lang="scss" scoped>
.review-container {
display: flex;
flex-direction: column;
height: 100%;
width: 100%;
overflow: hidden;
.search-container {
flex: none;
padding: 8px 8px;
text-align: right;
}
.medicalOrderList-table {
flex: 1;
}
}
</style>

View File

@@ -0,0 +1,4 @@
import WaitForDischarge from './waitForDischarge/index.vue'
import Discharged from './discharged/index.vue'
export { WaitForDischarge, Discharged }

View File

@@ -0,0 +1,26 @@
<template>
<div class="waitForDischarge-container">
<patientList />
<medicalOrderList />
</div>
</template>
<script setup >
import patientList from './patientList.vue'
import medicalOrderList from './medicalOrderList.vue'
</script>
<style lang="scss" scoped>
.waitForDischarge-container {
display: flex;
height: 100%;
width: 100%;
.patientList-container {
flex: none;
width: 240px;
}
.medicalOrderList-container {
flex: 1;
}
}
</style>

View File

@@ -0,0 +1,187 @@
<template>
<div class="medicalOrderList-container">
<div class="search-container">
<el-button>出院</el-button>
</div>
<div class="medicalOrderList-table">
<el-table :data="medicalOrderListData" row-key="id" style="width: 100%; height: 100%" highlight-current-row
show-overflow-tooltip>
<el-table-column label="类型" prop="name" min-width="100">
<template #default="{ row }">
<span>长期/西药</span>
</template>
</el-table-column>
<el-table-column label="开始时间">
<template #default="{ row }">
<span>{{ row.dates[0].date }}</span>
</template>
</el-table-column>
<el-table-column label="医嘱内容" prop="name" min-width="100">
<template #default="{ row }">
<span>{{ row.content }}</span>
</template>
</el-table-column>
<el-table-column label="执行科室" prop="name" min-width="100">
<template #default="{ row }">
<span>{{ row.content }}</span>
</template>
</el-table-column>
<el-table-column label="医生" prop="name" min-width="100">
<template #default="{ row }">
<span>{{ row.content }}</span>
</template>
</el-table-column>
<el-table-column label="开立科室" prop="name" min-width="100">
<template #default="{ row }">
<span>{{ row.content }}</span>
</template>
</el-table-column>
<el-table-column label="停止作废" prop="name" min-width="100">
<template #default="{ row }">
<span>{{ row.content }}</span>
</template>
</el-table-column>
</el-table>
</div>
</div>
</template>
<script setup >
import { ref } from 'vue';
const medicalOrderListData = ref([
{
name: '',
age: 10,
gender: '男',
content: '维生素B12注射液【1ml0.5mg*1】 ',
dates: [{
date: '05/04',
times: [{
time: '08:00',
nurse: '刘护士',
checked: false
}, {
time: '12:00',
nurse: '刘护士',
checked: false
}]
}, {
date: '05/05',
times: [{
time: '08:00',
nurse: '刘护士',
checked: false
}, {
time: '12:00',
nurse: '刘护士',
checked: false
}]
}]
}, {
name: '',
age: 10,
gender: '男',
content: '维生素B12注射液【1ml0.5mg*1】 ',
dates: [{
date: '05/04',
times: [{
time: '08:00',
nurse: '刘护士',
checked: false
}, {
time: '12:00',
nurse: '刘护士',
checked: false
}]
}, {
date: '05/05',
times: [{
time: '08:00',
nurse: '刘护士',
checked: false
}, {
time: '12:00',
nurse: '刘护士',
checked: false
}]
}]
}
,
{
name: '',
age: 10,
gender: '男',
content: '维生素B12注射液【1ml0.5mg*1】 ',
dates: [{
date: '05/04',
times: [{
time: '08:00',
nurse: '刘护士',
checked: false
}, {
time: '12:00',
nurse: '刘护士',
checked: false
}]
}, {
date: '05/05',
times: [{
time: '08:00',
nurse: '刘护士',
checked: false
}, {
time: '12:00',
nurse: '刘护士',
checked: false
}]
}]
}, {
name: '',
age: 10,
gender: '男',
content: '维生素B12注射液【1ml0.5mg*1】 ',
dates: [{
date: '05/04',
times: [{
time: '08:00',
nurse: '刘护士',
checked: false
}, {
time: '12:00',
nurse: '刘护士',
checked: false
}]
}, {
date: '05/05',
times: [{
time: '08:00',
nurse: '刘护士',
checked: false
}, {
time: '12:00',
nurse: '刘护士',
checked: false
}]
}]
}
])
</script>
<style lang="scss" scoped>
.medicalOrderList-container {
display: flex;
flex-direction: column;
height: 100%;
width: 100%;
overflow: hidden;
.search-container {
flex: none;
padding: 8px 8px;
text-align: right;
}
.medicalOrderList-table {
flex: 1;
}
}
</style>

View File

@@ -0,0 +1,72 @@
<template>
<div class="patientList-container">
<div class="search-container">
<el-button>查询</el-button>
</div>
<div class="patientList-table">
<el-table :data="patientListData" row-key="id" style="width: 100%; height: 100%" highlight-current-row
@selection-change="handleSelectionChange" :show-header="false" show-overflow-tooltip>
<el-table-column label="姓名" prop="name" min-width="100">
<template #default="{ row }">
<div class="patient-name">
<span class="name">{{ row.name }}</span>
</div>
</template>
</el-table-column>
<el-table-column type="expand">
患者详细信息
</el-table-column>
</el-table>
</div>
</div>
</template>
<script setup >
import { ref } from 'vue';
const patientListData = ref([
{
id: 1,
name: '张三1111111',
age: 30,
gender: '男',
status: '在科',
attention: '医生A',
department: '儿科',
},
{
id: 2,
name: '李四',
age: 25,
gender: '女',
status: '转科',
attention: '医生B'
}
])
const handleSelectionChange = (selection) => {
console.log('handleSelectionChange', selection)
}
</script>
<style lang="scss" scoped>
.patientList-container {
display: flex;
flex-direction: column;
height: 100%;
width: 100%;
overflow: hidden;
width: 240px;
border-right: 1px solid #e4e7ed;
.search-container {
flex: none;
padding: 8px 8px;
text-align: right;
}
.patientList-table {
flex: 1;
}
}
</style>

View File

@@ -0,0 +1,56 @@
<!--
* @Author: sjjh
* @Date: 2025-04-21 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">
<WaitForDischarge />
</el-tab-pane>
<el-tab-pane label="已出院" name="second">
<Discharged />
</el-tab-pane>
</el-tabs>
</div>
</template>
<script setup >
import { getCurrentInstance, onBeforeMount, onMounted, reactive, ref } from 'vue'
import { WaitForDischarge, Discharged } from './components/index.ts'
// 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>

View File

@@ -0,0 +1,378 @@
<template>
<div class="medicalOrderList-container">
<div class="search-container">
<el-space :size="4" direction="vertical" class="search-content" alignment="left
">
<el-space :size="4">
<el-radio-group v-model="searchForm.drugType">
<el-radio-button label="西药" value="1" />
<el-radio-button label="中药" value="2" />
<el-radio-button label="整取药" value="3" />
</el-radio-group>
<el-radio-group v-model="searchForm.isDetails">
<el-radio-button label="明细" value="1" />
<el-radio-button label="汇总" value="2" />
</el-radio-group>
<el-select v-model="searchForm.orderClass" v-if="searchForm.drugType == '1'" placeholder="医嘱类型"
style="width: 100px">
<el-option label="全部" value="0" />
<el-option label="长期" value="1" />
<el-option label="临时" value="2" />
</el-select>
<el-select v-model="searchForm.department" placeholder="领药科室" style="width: 140px">
<el-option label="全部" value="0" />
<el-option label="儿科" value="1" />
<el-option label="神经内科" :value="2" />
</el-select>
<el-date-picker v-model="searchForm.endTime" v-if="searchForm.drugType == '1'" type="date" placeholder="截止时间"
style="width: 100px" />
<el-input v-model="searchForm.searchVal" v-if="searchForm.drugType == '1'" style="width: 140px"
placeholder="请输入名称" />
<el-button type="primary">查询</el-button>
</el-space>
<el-space :size="4" alignment="right" style="align-items: center; ">
<span>默认打印</span>
<el-checkbox v-model="searchForm.printDetails" label="明细" />
<el-checkbox v-model="searchForm.printSummary" label="汇总" />
<el-button type="primary">领药发送</el-button>
</el-space>
</el-space>
</div>
<div class="medicalOrderList-table">
<el-table :data="drugDistributionDetailData" v-if="searchForm.isDetails == '1'" row-key="id"
style="width: 100%; height: 100%" border :span-method="arraySpanMethod" show-overflow-tooltip>
<el-table-column type="selection" />
<el-table-column label="类型" prop="name" min-width=" 60px">
<template #default="{ row }">
<span v-if="!row.children">长期</span>
<template v-else>
{{ row.name }} 11 000000001 &nbsp; 林俊杰 /24 &nbsp;1级 自费 主诊断 医生医生甲&nbsp; 预交金1990.3
</template>
</template>
</el-table-column>
<el-table-column label="医嘱内容" prop="content" min-width="220px">
<template #default="{ row }">
<span v-if="row.children">{{ row.content }}</span>
</template>
</el-table-column>
<el-table-column label="用法/频次" prop="gender" min-width="120px"
v-if="searchForm.drugType == '1' || searchForm.drugType == '3'">
<template #default="{ row }">
<span>注射/qd</span>
</template>
</el-table-column>
<el-table-column label="领药数量" prop="gender" min-width="120px" v-if="searchForm.drugType == '3'">
<template #default="{ row }">
<el-input-number v-model="row.num" :min="1" width="80px" style="width: 100px;" />
</template>
</el-table-column>
<el-table-column label="领药总量" prop="gender" min-width="100px"
v-if="searchForm.drugType == '1' || searchForm.drugType == '2'">
<template #default="{ row }">
<span>2 </span>
</template>
</el-table-column>
<el-table-column label="参考金额" prop="gender" min-width="100px">
<template #default="{ row }">
<span>20.00</span>
</template>
</el-table-column>
<el-table-column label="取药科室" prop="gender" min-width="140px">
<template #default="{ row }">
<span>儿科</span>
</template>
</el-table-column>
<el-table-column label="领药次数" prop="gender" fixed="right" min-width="340px" v-if="searchForm.drugType == '1'">
<template #default="{ row }">
<template v-if="!row.children">
<div v-for="item in row.dates" :key="item.id">
<span>{{ item.date }}</span>
<span v-for="time in item.times" :key="time.id">
<el-checkbox v-model="time.checked" :label="`${time.time}`" border />
</span>
</div>
</template>
<template v-else>
</template>
</template>
</el-table-column>
</el-table>
<el-table :data="drugDistributionSummaryData" v-else row-key="id" style="width: 100%; height: 100%" border
:span-method="arraySpanMethod" show-overflow-tooltip>
<el-table-column type="selection" />
<el-table-column label="医嘱内容" prop="content" min-width="220px">
<template #default="{ row }">
<span v-if="!row.children">{{ row.content }}</span>
<template v-else>
**药房
</template>
</template>
</el-table-column>
<el-table-column label="领药数量" prop="gender" min-width="120px">
<template #default="{ row }">
<span>2 </span>
</template>
</el-table-column>
<el-table-column label="单价" prop="gender" min-width="100px">
<template #default="{ row }">
<span>20.00</span>
</template>
</el-table-column>
<el-table-column label="参考金额" prop="gender" min-width="140px">
<template #default="{ row }">
<span>40.00</span>
</template>
</el-table-column>
</el-table>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const searchForm = ref({
drugType: '1',
isDetails: '1',
orderClass: '0',
department: '0',
printDetails: false,
printSummary: false,
searchVal: '',
endTime: '',
})
const drugDistributionDetailData = ref([
{
id: 1,
name: '张三',
age: 20,
gender: '男',
children: [
{
name: '',
age: 10,
gender: '男',
content: '维生素B12注射液【1ml0.5mg*1】 ',
dates: [{
date: '05/04',
times: [{
time: '08:00',
nurse: '刘护士',
checked: false
}, {
time: '12:00',
nurse: '刘护士',
checked: false
}]
}, {
date: '05/05',
times: [{
time: '08:00',
nurse: '刘护士',
checked: false
}, {
time: '12:00',
nurse: '刘护士',
checked: false
}]
}]
}, {
name: '',
age: 10,
gender: '男',
content: '维生素B12注射液【1ml0.5mg*1】 ',
dates: [{
date: '05/04',
times: [{
time: '08:00',
nurse: '刘护士',
checked: false
}, {
time: '12:00',
nurse: '刘护士',
checked: false
}]
}, {
date: '05/05',
times: [{
time: '08:00',
nurse: '刘护士',
checked: false
}, {
time: '12:00',
nurse: '刘护士',
checked: false
}]
}]
}]
},
{
id: 2,
name: '李四',
age: 20,
gender: '男',
children: [
{
name: '',
age: 10,
gender: '男',
content: '维生素B12注射液【1ml0.5mg*1】 ',
dates: [{
date: '05/04',
times: [{
time: '08:00',
nurse: '刘护士',
checked: false
}, {
time: '12:00',
nurse: '刘护士',
checked: false
}]
}, {
date: '05/05',
times: [{
time: '08:00',
nurse: '刘护士',
checked: false
}, {
time: '12:00',
nurse: '刘护士',
checked: false
}]
}]
}, {
name: '',
age: 10,
gender: '男',
content: '维生素B12注射液【1ml0.5mg*1】 ',
dates: [{
date: '05/04',
times: [{
time: '08:00',
nurse: '刘护士',
checked: false
}, {
time: '12:00',
nurse: '刘护士',
checked: false
}]
}, {
date: '05/05',
times: [{
time: '08:00',
nurse: '刘护士',
checked: false
}, {
time: '12:00',
nurse: '刘护士',
checked: false
}]
}]
}]
}
])
const arraySpanMethod = ({
row,
column,
rowIndex,
columnIndex,
}: any) => {
// console.log(row, column, rowIndex, columnIndex);
// 如果是父级行
if (row.children && row.children.length > 0) {
if (columnIndex === 0) {
return [1, 1]
}
// 如果是患者列
if (columnIndex === 1) {
return [1, 16]
}
else {
return [1, 0]
}
}
// 如果是子级行,显示其他列
if (!row.children || row.children.length == 0) {
return [1, 1]
}
// 如果是父级行,隐藏其他列
return [1, 1]
}
const drugDistributionSummaryData = ref([
{
id: 1,
name: '张三',
age: 20,
gender: '男',
children: [
{
name: '',
age: 10,
gender: '男',
content: '维生素B12注射液【1ml0.5mg*1】 ',
}, {
name: '',
age: 10,
gender: '男',
content: '维生素B12注射液【1ml0.5mg*1】 ',
}]
},
{
id: 2,
name: '李四',
age: 20,
gender: '男',
children: [
{
name: '',
age: 10,
gender: '男',
content: '维生素B12注射液【1ml0.5mg*1】 ',
}, {
name: '',
age: 10,
gender: '男',
content: '维生素B12注射液【1ml0.5mg*1】 ',
}]
}
])
</script>
<style lang="scss" scoped>
.medicalOrderList-container {
display: flex;
flex-direction: column;
height: 100%;
width: 100%;
overflow: hidden;
.search-container {
flex: none;
padding: 8px 8px;
border-bottom: 1px solid #e4e7ed;
:deep(.search-content) {
width: 100%;
.el-space__item:nth-child(2) {
align-self: end;
}
}
}
.medicalOrderList-table {
flex: 1;
:deep(.el-table__indent) {
display: none !important;
}
:deep(.el-table__placeholder) {
display: none !important;
}
}
}
</style>

View File

@@ -0,0 +1,26 @@
<template>
<div class="drugDistribution-container">
<patientList />
<DrugDistributionList />
</div>
</template>
<script setup >
import patientList from './patientList.vue'
import DrugDistributionList from './drugDistributionList.vue'
</script>
<style lang="scss" scoped>
.drugDistribution-container {
display: flex;
height: 100%;
width: 100%;
.patientList-container {
flex: none;
width: 240px;
}
.medicalOrderList-container {
flex: 1;
}
}
</style>

View File

@@ -0,0 +1,112 @@
<template>
<div class="patientList-container">
<div class="search-container">
<el-space :size="4">
<el-input v-model="searchForm.searchVal" style="width: 100px" placeholder="请输入" />
<el-button>查询</el-button>
</el-space>
</div>
<div class="patientList-table">
<el-table :data="patientListData" row-key="id" style="width: 100%; height: 100%" highlight-current-row
@selection-change="handleSelectionChange" :show-header="false" show-overflow-tooltip>
<el-table-column label="姓名" prop="name" min-width="100">
<template #default="{ row }">
<span class="name" v-if="row.children"> {{ row.department }}({{ row.children?.length || 0 }})</span>
<div class="patient-name" v-else>
<span class="name">{{ row.name }}</span>
</div>
</template>
</el-table-column>
</el-table>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const searchForm = ref({
searchVal: '',
})
const patientListData = ref([
{
id: 1,
department: '儿科',
children: [
{
id: 11,
name: '张三',
bedName: '1201',
gender: '男',
status: '在科',
attention: '医生A'
},
{
id: 12,
name: '张三-2',
age: 3,
gender: '女',
status: '在科',
attention: '医生A'
}
]
},
{
id: 2,
department: '神经内科科',
children: [
{
id: 21,
name: '张三',
bedName: '1201',
gender: '男',
status: '在科',
attention: '医生A'
},
{
id: 22,
name: '张三-2',
age: 3,
gender: '女',
status: '在科',
attention: '医生A'
}
]
}
])
const handleSelectionChange = (selection: any[]) => {
console.log('handleSelectionChange', selection)
}
</script>
<style lang="scss" scoped>
.patientList-container {
display: flex;
flex-direction: column;
height: 100%;
width: 100%;
overflow: hidden;
width: 240px;
border-right: 1px solid #e4e7ed;
.search-container {
flex: none;
padding: 0px 8px;
border-bottom: 1px solid #e4e7ed;
height: 40px;
display: flex;
align-items: center;
}
.patientList-table {
flex: 1;
:deep(.el-table__indent) {
display: none !important;
}
:deep(.el-table__placeholder) {
display: none !important;
}
}
}
</style>

View File

@@ -0,0 +1,78 @@
import request from '@/utils/request'
/**
* 获取患者列表
*
* @param query 查询参数对象,可以包含多个查询条件
* @returns Promise<any> 返回一个Promise对象解析后得到患者列表数据
*/
export function listPatient(query) {
return request({
url: '/patient-home-manage/init',
method: 'get',
params: query
})
}
/**
* 获取空床列表
*
* @param organizationId 科室ID
* @returns Promise<any> 返回一个Promise对象解析后得到患者列表数据
*/
export function getEmptyBed(organizationId) {
return request({
url: '/patient-home-manage/empty-bed',
method: 'get',
params: { organizationId }
})
}
/**
* 保存换床信息
*
*/
export function saveBedTransfer(params) {
return request({
url: '/patient-home-manage/bed-transfer',
method: 'put',
params: params
})
}
/**
* 获取科室列表
*
* @returns Promise<any> 返回一个Promise对象解析后得到科室列表数据
*/
export function getCaty() {
return request({
url: '/patient-home-manage/caty',
method: 'get'
})
}
/**
* 保存转科信息
*
*/
export function saveDepartmentTransfer(params) {
return request({
url: '/patient-home-manage/department-transfer',
method: 'put',
params: params
})
}
/**
* 保存出院信息
*
*/
export function saveDischargeHospital(params) {
return request({
url: '/patient-home-manage/discharge-from-hospital',
method: 'put',
params: params
})
}

View File

@@ -0,0 +1,560 @@
<template>
<div style="width: 100%; padding: 0px 20px">
<el-row :gutter="20" v-if="cardList.length > 0" class="custom-row">
<el-col
v-for="o in cardList"
:key="o.patientID"
:span="4"
style="margin-bottom: 10px; margin-right: 0px"
class="custom-col"
>
<div class="pf_card" @click="clickAct">
<el-card class="box-card" :body-style="{ padding: '0px' }">
<div class="card-content" @dblclick="openPatientDetailDialog(o)">
<div
class="header"
style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis"
>
<span v-if="o.priorityEnum == 1" class="label1">{{
o.locationId_dictText ? o.locationId_dictText : '暂无床位'
}}</span>
<span v-else-if="o.priorityEnum == 2" class="label2">
{{ o.locationId_dictText ? o.locationId_dictText : '暂无床位' }}
</span>
<span v-else-if="o.priorityEnum == 3" class="label3">
{{ o.locationId_dictText ? o.locationId_dictText : '暂无床位' }}
</span>
<span v-else-if="o.priorityEnum == 4" class="label4">
{{ o.locationId_dictText ? o.locationId_dictText : '暂无床位' }}
</span>
<span v-else-if="o.priorityEnum == '' || o.priorityEnum === null" class="label5">
{{ o.locationId_dictText ? o.locationId_dictText : '暂无床位' }}
</span>
<span v-else class="label5" />
<!-- 左侧内容优先级标签 + 姓名 -->
<div style="flex: 1; overflow: hidden; text-overflow: ellipsis">
<span
class="header-label"
:title="o.patientName"
style="display: inline-block; max-width: 140px"
>{{ o.patientName }}</span
>
</div>
<span class="header-label" style="margin-right: 10px"
>{{ o.genderEnum_enumText }}/{{ o.ageString }}</span
>
</div>
<div class="row">
<div class="layui-inline">
<div>住院号</div>
<div>{{ o.hospitalNo }}</div>
</div>
</div>
<div class="row">
<div class="layui-inline">
<div>入院科室</div>
<div>{{ o.organizationId_dictText }}</div>
</div>
</div>
<div class="row2">
<div class="layui-inline">
<div>诊断</div>
<div class="patientDiagnosis" :title="o.mainDiagnosis">
{{ o.mainDiagnosis }}
</div>
</div>
</div>
<div class="row">
<div class="layui-inline">
<div>入院</div>
<div>{{ o.admissionDate }}</div>
</div>
</div>
<div class="row">
<div class="layui-inline">
<div>入院天数</div>
<div>{{ o.hospitalizationDays }}</div>
</div>
</div>
<!-- <div class="row">
<div class="layui-inline">
<div>手术时间</div>
<div>{{ o.surgeryStartTime }}</div>
</div>
</div>
<div class="row">
<div class="layui-inline">
<div>手术天数</div>
<div>{{ o.postoperativeDays }}</div>
</div>
</div> -->
<div class="row">
<div class="layui-inline">
<div>医生</div>
<div>{{ o.responsibleDoctor }}</div>
</div>
</div>
<div class="row">
<div style="margin-left: 10px">
<!-- <div>操作</div> -->
<el-button type="primary" link>腕带</el-button>
<el-button type="primary" link>床头卡</el-button>
<el-button type="primary" link @click="openTransferCyDialog(o)">出院</el-button>
<el-button type="primary" link @click="openTransferZkDialog(o)">转科</el-button>
<el-button type="primary" link @click="openTransferToBedDialog(o)"
>转床</el-button
>
</div>
</div>
</div>
<!-- </div> -->
</el-card>
</div>
</el-col>
</el-row>
<div v-else class="no-data">暂无患者数据</div>
<patient-detial-dialog
ref="patientDetialDialogRef"
:open="openPatientDetail"
@close="closePatientDetialDialog"
/>
<transfer-to-bed-dialog
ref="transferToBedRef"
:open="openTransferToBed"
@close="closeTransferToBedDialog"
/>
<transfer-dialog
ref="transferRef"
:open="openTransfer"
:title="title"
@close="closeTransferDialog"
/>
</div>
</template>
<script setup>
import patientDetialDialog from './patientDetialDialog.vue';
import transferToBedDialog from './transferToBedDialog.vue';
import transferDialog from './transferDialog.vue';
import { ref, nextTick } from 'vue';
const { proxy } = getCurrentInstance();
const radio = ref(1);
const props = defineProps({
openPrescription: {
type: Boolean,
default: false,
},
cardList: {
type: Object,
required: true,
},
});
const { method_code, unit_code, rate_code, distribution_category_code } = proxy.useDict(
'method_code',
'unit_code',
'rate_code',
'distribution_category_code'
);
const emit = defineEmits(
'close',
'openPatientDetail',
'closePatientDetail',
'submit',
'openTransferToBed',
'closeTransferToBed',
'openTransferZk',
'openTransferCy',
'closeTransfer'
);
const total = ref(0);
const queryParams = ref({
pageNum: 1,
pageSize: 10,
});
const form = reactive({
patientId: '', // 患者
encounterId: '', // 就诊id
prescriptionNo: '', // 处方号
rxTypeCode: 1, // 处方类型编码
validityDays: '', // 有效天数
extensionReason: '', // 延长原因
medicationInfoList: [],
});
// 患者详细对话框相关变量
const patientDetialDialogRef = ref();
const openPatientDetail = ref(false);
const dosageInputRefs = ref([]);
// 转床对话框相关变量
const transferToBedRef = ref();
const openTransferToBed = ref(false);
// 转科/出院对话框相关变量
const transferRef = ref();
const openTransfer = ref(false);
const title = ref('');
const rowRules = ref({
conditionDefinitionId: [{ required: true, message: '请选择诊断', trigger: 'change' }],
dose: [{ required: true, message: '请输入单次剂量', trigger: 'change' }],
doseQuantity: [{ required: true, message: '请输入单次剂量', trigger: 'change' }],
quantity: [{ required: true, message: '请输入数量', trigger: 'change' }],
dispensePerDuration: [{ required: true, message: '请输入用药天数', trigger: 'change' }],
});
const unitMap = ref({
dose: 'dose',
minUnit: 'minUnit',
unit: 'unit',
});
/**
* 打开患者信息详细对话框
*/
function openPatientDetailDialog(row) {
emit('openPatientDetail', row);
}
/**
* 关闭新增处方弹窗
*/
function closePatientDetialDialog(str) {
emit('closePatientDetail');
}
/**
* 打开转床对话框
*/
function openTransferToBedDialog(row) {
console.log(row, '卡片转床弹窗打开');
emit('openTransferToBed', row);
}
/**
* 关闭转床对话框
*/
function closeTransferToBedDialog(str) {
emit('closeTransferToBed');
}
/**
* 打开转科对话框
*/
function openTransferZkDialog(row) {
emit('openTransferZk', row);
}
/**
* 打开出院对话框
*/
function openTransferCyDialog(row) {
emit('openTransferCy', row);
}
/**
* 关闭转科/出院对话框
*/
function closeTransferDialog(str) {
emit('closeTransfer');
}
function close() {
reset();
emit('close');
}
function reset() {
form.medicationInfoList = [];
form.patientId = '';
form.encounterId = '';
form.prescriptionNo = '';
form.rxTypeCode = 1;
form.validityDays = '';
form.extensionReason = '';
}
function getBedBackColor(triageLevel) {
const Level = triageLevel?.display ?? '0级';
let backColor = '#808080';
switch (Level) {
case '1':
backColor = this.colors[0];
break;
case '2':
backColor = this.colors[1];
break;
case '3':
backColor = this.colors[2];
break;
case '4':
backColor = this.colors[3];
break;
default:
backColor = '#C4C4C4';
}
return backColor;
}
function getDisplay(triageLevel) {
return triageLevel?.display ?? '';
}
// defineExpose({
// getPrescriptionNoInit,
// });
</script>
<style scoped>
.pf_card {
outline-style: inherit;
position: relative;
border-radius: 5px;
background-color: #ffffff;
box-shadow: 1px 1px 4px #888888;
border: 1px solid #e2dfdf;
width: 100%;
user-select: none;
font-family: Microsoft YaHei;
/* margin-left: 5px; */
}
.pf_card:hover {
box-shadow: 4px 4px 16px #888888;
}
.layui-input-inline {
display: inline-block;
}
.layui-inline {
display: grid;
grid-template-columns: 30% 60%;
padding: 3% 0 3% 5%;
}
/* .box-card { */
.header {
/* display: grid;
grid-template-columns: 25% 75%;
position: relative;
height: 40px;
grid-template-columns: 25% 75%;
*/
border-bottom: 1px solid #d3d4d6;
/* 可选: 设置行分隔线 */
display: flex;
align-items: center;
white-space: nowrap; /* 禁止换行 */
overflow: hidden; /* 隐藏溢出内容 */
width: 100%; /* 根据需要设置宽度 */
height: 36px; /* 固定高度 */
}
.label1 {
background-color: #a61302;
text-align: center;
padding: 10px 5px;
color: white;
border-radius: 5px;
}
.label2 {
background-color: #ec1500;
text-align: center;
padding: 10px 5px;
color: white;
border-radius: 5px;
}
.label3 {
background-color: #10d45b;
text-align: center;
padding: 10px 5px;
color: white;
border-radius: 5px;
}
.label4 {
background-color: #848d88;
text-align: center;
padding: 10px 5px;
color: white;
border-radius: 5px;
}
.label5 {
text-align: center;
padding: 10px 5px;
border-radius: 5px;
}
.header-label {
/* padding-left: 10px;
padding-top: 8px;
font-size: large;
font-weight: bold; */
display: inline-block;
margin-left: 8px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 150px; /* 根据需要调整 */
font-size: large;
font-weight: bold;
}
/* } */
.card-content .row {
font-size: 15px;
display: grid;
padding: 3px 0;
/* 设置行间距 */
border-bottom: 1px solid #e4e7ed;
/* 可选: 设置行分隔线 */
}
.card-content .row2 {
font-size: 15px;
display: grid;
padding: 3px 0;
/* 设置行间距 */
/* border-bottom: 2px solid #c6c7c7; */
border-bottom: 1px solid #e4e7ed;
/* 可选: 设置行分隔线 */
}
.card-content .row:last-child {
font-size: 15px;
border-bottom: none;
/* 最后一行不显示分隔线 */
}
.exceptionalCare ::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 15px;
height: 15px;
border-radius: 50%;
/* 使其成为圆形 */
background-color: #a61302;
/* 背景颜色 */
}
.primaryCare ::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 15px;
height: 15px;
border-radius: 50%;
/* 使其成为圆形 */
background-color: #ec1500;
/* 背景颜色 */
}
.secondaryCare ::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 15px;
height: 15px;
border-radius: 50%;
/* 使其成为圆形 */
background-color: #10d45b;
/* 背景颜色 */
}
.tertiaryCare ::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 15px;
height: 15px;
border-radius: 50%;
/* 使其成为圆形 */
background-color: #848d88;
/* 背景颜色 */
}
.patientDiagnosis {
white-space: nowrap;
/* 不折行 */
overflow: hidden;
/* 隐藏溢出的内容 */
text-overflow: ellipsis;
/* 使用省略号表示溢出 */
width: 150px;
/* 设置宽度,控制显示效果 */
display: block;
/* 必须设置为块级元素或行内块元素 */
margin-left: -3px;
}
.dialog-row {
display: grid;
grid-template-columns: 85% 15%;
margin-left: 15px;
margin-bottom: 2px;
}
.dialog-inline {
display: flex;
}
.dialog-detaile-inline {
font-size: 20px;
display: grid;
grid-template-columns: 40% 75%;
}
.dialog-line1 {
text-align: right;
margin-top: 10px;
}
.dialog-line2 {
border-bottom: 1px solid black;
width: 60%;
text-align: center;
margin-top: 10px;
}
.header-container {
display: inline-flex;
align-items: center;
}
.no-data {
display: grid;
place-items: center; /* 水平和垂直居中 */
height: 100%; /* 确保父容器有高度 */
width: 100%; /* 确保父容器有宽度 */
margin-top: 20px;
}
::v-deep .el-dialog_header {
font-size: 20px;
/* 设置字体大小 */
color: #ff4500;
/* 设置字体颜色 */
}
::v-deep .el-card__body {
padding: 0px !important;
}
.custom-row {
display: flex;
flex-wrap: wrap;
margin-left: -10px !important; /* 抵消 gutter 的 margin */
margin-right: -10px !important;
}
.custom-col {
width: calc(20% - 20px) !important; /* 5列布局 */
margin-left: 10px;
margin-right: 10px;
}
</style>

View File

@@ -0,0 +1,568 @@
<template>
<el-dialog
title="患者详情"
v-model="props.open"
width="1200px"
append-to-body
destroy-on-close
@close="close"
>
<div>
<el-form :model="form" ref="formRef" label-width="110">
<el-row :gutter="24" class="mb8">
<el-col :span="6">
<el-form-item label="患者姓名:" prop="patientName">
<el-input
v-model="form.patientName"
placeholder=""
clearable
style="width: 260px"
disabled
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="性别:" prop="genderEnum_enumText">
<el-input
v-model="form.genderEnum_enumText"
placeholder=""
clearable
style="width: 260px"
disabled
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="住院号:" prop="hospitalNo">
<el-input v-model="form.hospitalNo" placeholder="" clearable disabled />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="床号:" prop="locationId_dictText">
<el-input v-model="form.locationId_dictText" placeholder="" clearable disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24" class="mb8">
<el-col :span="6">
<el-form-item label="年龄:" prop="ageString">
<el-input
v-model="form.ageString"
placeholder=""
clearable
style="width: 260px"
disabled
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="生日:" prop="birthDate">
<el-input
v-model="form.birthDate"
placeholder=""
clearable
style="width: 260px"
disabled
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="婚姻状态:" prop="maritalStatusEnum_enumText">
<el-input
v-model="form.maritalStatusEnum_enumText"
placeholder=""
clearable
style="width: 260px"
disabled
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="职业:" prop="prfsEnum_enumText">
<el-input
v-model="form.prfsEnum_enumText"
placeholder=""
clearable
style="width: 260px"
disabled
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24" class="mb8">
<el-col :span="6">
<el-form-item label="电话:" prop="phone">
<el-input v-model="form.phone" placeholder="" clearable disabled />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="地址:" prop="addressInfo">
<el-input
v-model="form.addressInfo"
placeholder=""
clearable
style="width: 260px"
disabled
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="民族:" prop="nationalityCode">
<el-input
v-model="form.nationalityCode"
placeholder=""
clearable
style="width: 260px"
disabled
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="身份证号:" prop="idCard">
<el-input
v-model="form.idCard"
placeholder=""
clearable
style="width: 260px"
disabled
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24" class="mb8">
<el-col :span="6">
<el-form-item label="籍贯:" prop="nativePlace">
<el-input
v-model="form.nativePlace"
placeholder=""
clearable
style="width: 260px"
disabled
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="国家:" prop="countryCode">
<el-input
v-model="form.countryCode"
placeholder=""
clearable
style="width: 260px"
disabled
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="联系人:" prop="linkName">
<el-input
v-model="form.linkName"
placeholder=""
clearable
style="width: 260px"
disabled
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="联系人关系:" prop="linkRelationCode_codeText">
<el-input
v-model="form.linkRelationCode_codeText"
placeholder=""
clearable
disabled
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24" class="mb8">
<el-col :span="6">
<el-form-item label="联系人电话:" prop="linkTelcom">
<el-input
v-model="form.linkTelcom"
placeholder=""
clearable
style="width: 260px"
disabled
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="其他联系人:" prop="linkJsons">
<el-input
v-model="form.linkJsons"
placeholder=""
clearable
style="width: 260px"
disabled
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="工作单位:" prop="workCompany">
<el-input v-model="form.workCompany" placeholder="" clearable disabled />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="护理级别:" prop="priorityEnum_enumText">
<el-input
v-model="form.priorityEnum_enumText"
placeholder=""
clearable
style="width: 260px"
disabled
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24" class="mb8">
<el-col :span="6">
<el-form-item label="患者状态:" prop="statusEnum_enumText">
<el-input
v-model="form.statusEnum_enumText"
placeholder=""
clearable
disabled
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="入院科室:" prop="organizationId_dictText">
<el-input
v-model="form.organizationId_dictText"
placeholder=""
clearable
style="width: 260px"
disabled
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="入院日期:" prop="admissionDate">
<el-input
v-model="form.admissionDate"
placeholder=""
clearable
style="width: 260px"
disabled
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="责任医生:" prop="responsibleDoctor">
<el-input
v-model="form.responsibleDoctor"
placeholder=""
clearable
style="width: 260px"
disabled
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24" class="mb8">
<el-col :span="6">
<el-form-item label="责任护士:" prop="responsibleNurse">
<el-input v-model="form.responsibleNurse" placeholder="" clearable disabled />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="主要诊断:" prop="mainDiagnosis">
<el-input
v-model="form.mainDiagnosis"
placeholder=""
clearable
style="width: 260px"
disabled
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="费别:" prop="typeCode_dictText">
<el-input
v-model="form.typeCode_dictText"
placeholder=""
clearable
style="width: 260px"
disabled
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="住院天数:" prop="hospitalizationDays">
<el-input
v-model="form.hospitalizationDays"
placeholder=""
clearable
style="width: 260px"
disabled
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24" class="mb8">
<el-col :span="6">
<el-form-item label="就诊类别:" prop="classEnum_enumText">
<el-input
v-model="form.classEnum_enumText"
placeholder=""
clearable
disabled
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="术后天数:" prop="postoperativeDays">
<el-input
v-model="form.postoperativeDays"
placeholder=""
clearable
style="width: 260px"
disabled
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="手术开始日期:" prop="surgeryStartTime">
<el-input
v-model="form.surgeryStartTime"
placeholder=""
clearable
style="width: 260px"
disabled
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="手术结束日期:" prop="surgeryEndTime">
<el-input
v-model="form.surgeryEndTime"
placeholder=""
clearable
style="width: 260px"
disabled
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24" class="mb8">
<el-col :span="6">
<el-form-item label="手术状态:" prop="surgeryStatusEnum_enumText">
<el-input
v-model="form.surgeryStatusEnum_enumText"
placeholder=""
clearable
disabled
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="过敏原类别:" prop="categoryCode_dictText">
<el-input
v-model="form.categoryCode_dictText"
placeholder=""
clearable
style="width: 260px"
disabled
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="入院科室名:" prop="caty">
<el-input
v-model="form.caty"
placeholder=""
clearable
style="width: 260px"
disabled
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="血型ABO" prop="bloodAbo_enumText">
<el-input
v-model="form.bloodAbo_enumText"
placeholder=""
clearable
style="width: 260px"
disabled
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="血型RH" prop="bloodRh_enumText">
<el-input
v-model="form.bloodRh_enumText"
placeholder=""
clearable
style="width: 260px"
disabled
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="close"> </el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { ref, nextTick } from 'vue';
import { listPatient } from './api';
const { proxy } = getCurrentInstance();
const props = defineProps({
open: {
type: Boolean,
default: false,
},
patientId: {
type: String,
default: '',
},
});
const { method_code, unit_code, rate_code, distribution_category_code } = proxy.useDict(
'method_code',
'unit_code',
'rate_code',
'distribution_category_code'
);
const emit = defineEmits(['close']);
const queryParams = ref({
pageNum: 1,
pageSize: 10,
patientId: undefined, // 患者id
});
const form = ref({});
const title = ref('');
const rowRules = ref({
conditionDefinitionId: [{ required: true, message: '请选择诊断', trigger: 'change' }],
dose: [{ required: true, message: '请输入单次剂量', trigger: 'change' }],
doseQuantity: [{ required: true, message: '请输入单次剂量', trigger: 'change' }],
quantity: [{ required: true, message: '请输入数量', trigger: 'change' }],
dispensePerDuration: [{ required: true, message: '请输入用药天数', trigger: 'change' }],
});
/**
* 取得患者信息详细
*/
function getPatientDetial() {
reset();
title.value = '';
title.value = props.title;
console.log(props, 'props', title.value);
console.log(queryParams.value, 'queryParams.value', props.patientId);
queryParams.value.patientId = props.patientId;
listPatient(queryParams.value).then((res) => {
if (res.data && res.data.records && res.data.records.length > 0) {
form.value = res.data.records[0];
}
form.value.addressInfo =
form.value.addressProvince +
'' +
form.value.addressCity +
'' +
form.value.addressDistrict +
'' +
form.value.addressStreet +
'' +
form.value.address;
// loading.value = false;
console.log(res, 'resqqqqqqqqqqqqqqqqqqqqqqq', form.value);
});
}
function close() {
reset();
emit('close');
}
/** 重置操作表单 */
function reset() {
form.value = {
id: undefined,
activeFlag: undefined, // 活动标记
tempFlag: undefined, // 临时标识
patientName: undefined, // 患者姓名
nameJson: undefined, // 患者其他名称
hospitalNo: undefined, // 病历号
genderEnum: undefined, // 性别
genderEnum_enumText: undefined, // 性别
birthDate: undefined, // 生日
deceasedDate: undefined, // 死亡时间
maritalStatusEnum: undefined, // 婚姻状态
maritalStatusEnum_enumText: undefined, // 婚姻状态
prfsEnum: undefined, // 职业编码
prfsEnum_enumText: undefined, // 职业编码
phone: undefined, // 电话
address: undefined, // 地址
addressProvince: undefined, // 地址省
addressCity: undefined, // 地址市
addressDistrict: undefined, // 地址区
addressStreet: undefined, // 地址街道
addressJson: undefined, // 患者其他地址
nationalityCode: undefined, // 民族
idCard: undefined, // 身份证号
pyStr: undefined, //拼音码
wbStr: undefined, // 五笔码
bloodAbo: undefined, // 血型ABO
bloodAbo_enumText: undefined, // 血型ABO
bloodRh: undefined, // 血型RH
bloodRh_enumText: undefined, // 血型RH
workCompany: undefined, // 工作单位
nativePlace: undefined, // 籍贯
countryCode: undefined, // 国家编码
linkName: undefined, // 联系人
linkRelationCode: undefined, // 联系人关系
linkRelationCode_codeText: undefined, // 联系人关系
linkTelcom: undefined, // 联系人电话
linkJsons: undefined, // 其他联系人
tenanid: undefined, // 租户ID
ageString: undefined, // 病人年龄
priorityEnum: undefined, // 护理级别
priorityEnum_enumText: undefined, // 护理级别
statusEnum: undefined, // 患者状态
statusEnum_enumText: undefined, // 患者状态
organizationId: undefined, // 入院科室
organizationId_dictText: undefined, // 入院科室
admissionDate: undefined, // 入院日期
dischargeDate: undefined, // 出院日期
responsibleDoctor: undefined, // 责任医生
responsibleNurse: undefined, // 责任护士
mainDiagnosis: undefined, // 主要诊断
typeCode: undefined, // 费别
typeCode_dictText: undefined, // 费别
hospitalizationDays: undefined, //住院天数
classEnum: undefined, // 就诊类别
classEnum_enumText: undefined, // 就诊类别
postoperativeDays: undefined, // 术后天数
surgeryStartTime: undefined, // 手术开始日期
surgeryEndTime: undefined, // 手术结束日期
surgeryStatusEnum: undefined, // 手术状态
surgeryStatusEnum_enumText: undefined, // 手术状态
categoryCode: undefined, // 过敏源类别
categoryCode_dictText: undefined, // 过敏源类别
caty: undefined, // 入院科室名称
locationId: undefined, // 床位号
locationId_dictText: undefined, // 床位号
encounterId: undefined, // 就诊流水号
encounterLocationId: undefined, // 就诊地点流水号
};
proxy.resetForm('formRef');
}
defineExpose({
getPatientDetial,
});
</script>
<style scoped>
:deep(.pagination-container .el-pagination) {
right: 20px !important;
}
</style>

View File

@@ -0,0 +1,235 @@
<template>
<el-dialog
:title="props.title"
v-model="props.open"
width="480px"
append-to-body
destroy-on-close
@close="close"
>
<div>
<el-form :model="form" ref="formRef">
<el-row :gutter="24" class="mb8">
<el-col>
<el-form-item label="病历号:" prop="patientNo" label-width="100">
<el-input
v-model="form.patientNo"
placeholder="病历号"
clearable
style="width: 260px"
disabled
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24" class="mb8">
<el-col>
<el-form-item label="患者姓名:" prop="patientName" label-width="100">
<el-input
v-model="form.patientName"
placeholder="患者姓名"
clearable
style="width: 260px"
disabled
/>
</el-form-item>
</el-col>
</el-row>
<!-- <el-row :gutter="24" class="mb8" v-if="props.title == '出院'">
<el-col>
<el-form-item label="出院原因:" prop="dscgTrtRslt" label-width="100">
<el-select v-model="form.dscgTrtRslt" clearable>
<el-option
v-for="dict in dscg_trt_rslt_code"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</el-col>
</el-row> -->
<el-row :gutter="24" class="mb8" v-if="props.title == '出院'">
<el-col>
<el-form-item label="出院时间:" prop="DischargeHospitalYmd" label-width="100">
<el-date-picker
v-model="form.DischargeHospitalYmd"
value-format="YYYY-MM-DD HH:mm:ss"
type="datetime"
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24" class="mb8" v-if="props.title == '转科'">
<el-col>
<el-form-item label="转科去向:" prop="organizationId" label-width="100">
<el-select v-model="form.organizationId" clearable>
<el-option
v-for="caty in catyList"
:key="caty.id"
:label="caty.name"
:value="caty.id"
:disabled="caty.id === form.organizationIdOld"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24" class="mb8" v-if="props.title == '转科'">
<el-col>
<el-form-item label="转科时间:" prop="DepartmentTransferYmd" label-width="100">
<el-date-picker
v-model="form.DepartmentTransferYmd"
value-format="YYYY-MM-DD HH:mm:ss"
type="datetime"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submit">保存</el-button>
<el-button @click="close"> </el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { ref, nextTick } from 'vue';
import { getCaty, saveDepartmentTransfer, saveDischargeHospital } from './api';
const { proxy } = getCurrentInstance();
const props = defineProps({
open: {
type: Boolean,
default: false,
},
title: {
type: String,
default: '',
},
transferInfo: {
type: Object,
},
});
const { dscg_trt_rslt_code, unit_code, rate_code, distribution_category_code } = proxy.useDict(
'dscg_trt_rslt_code',
'unit_code',
'rate_code',
'distribution_category_code'
);
const emit = defineEmits(['close']);
const selectRow = ref({});
const prescriptionTypeList = ref([]);
const catyList = ref([]);
const form = ref({});
const title = ref('');
const rowRules = ref({
conditionDefinitionId: [{ required: true, message: '请选择诊断', trigger: 'change' }],
dose: [{ required: true, message: '请输入单次剂量', trigger: 'change' }],
doseQuantity: [{ required: true, message: '请输入单次剂量', trigger: 'change' }],
quantity: [{ required: true, message: '请输入数量', trigger: 'change' }],
dispensePerDuration: [{ required: true, message: '请输入用药天数', trigger: 'change' }],
});
getCatyList();
/**
* 取得床位号
*/
function show() {
reset();
title.value = '';
title.value = props.title;
form.value = props.transferInfo;
console.log(props, 'props', title.value);
}
/**
* 查询科室信息
*
* @param row 要选择的床位信息对象
*/
function getCatyList() {
getCaty().then((res) => {
if (res.code == 200) {
catyList.value = res.data;
} else {
catyList.value = [];
}
console.log(res, ' catyList.value');
});
}
/**
* 选择科室信息
*
* @param row 要选择科室信息对象
*/
function selectOrganizationId(value) {
console.log(value, ' value');
form.value.organizationId = value;
}
/**
* 保存处方
*/
function submit() {
console.log(form.value, 'form, prescriptionList.value新增处方');
// console.log(row, ' 保存处方row 1234567890');
// 新增的药品信息调用新增接口
if (title.value == '转科') {
saveDepartmentTransfer(form.value).then((res) => {
if (res.code == 200) {
emit('close', 'success');
reset();
}
});
}
if (title.value == '出院') {
saveDischargeHospital(form.value).then((res) => {
if (res.code == 200) {
emit('close', 'success');
reset();
}
});
}
}
function close() {
reset();
emit('close');
}
/**
* 重置表单
*/
function reset() {
form.value = {
organizationId: '',
organizationIdOld: '',
patientName: '',
patientId: '', // 处方号
hospitalNo: '',
dscgTrtRslt: '',
encounterId: '',
encounterLocationId: '',
locationId: '',
DepartmentTransferYmd: undefined,
DischargeHospitalYmd: undefined,
};
proxy.resetForm('formRef');
}
defineExpose({
show,
});
</script>
<style scoped>
:deep(.pagination-container .el-pagination) {
right: 20px !important;
}
</style>

View File

@@ -0,0 +1,162 @@
<template>
<el-dialog
title="转床"
v-model="props.open"
width="600px"
append-to-body
destroy-on-close
@close="close"
>
<div>
<el-form :model="form" ref="formRef">
<el-row :gutter="24" class="mb8">
<el-col :span="12">
<el-form-item label="区域:" prop="organizationId_dictText" label-width="100">
<el-input
v-model="transferToBedInfo.organizationId_dictText"
placeholder="请输入区域名称"
clearable
disabled
/>
<!-- <el-select v-model="medRoute" clearable>
<el-option
v-for="dict in method_code"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select> -->
</el-form-item>
</el-col>
</el-row>
</el-form>
<el-table
ref="table"
:data="bedList"
row-key="locationId"
style="width: 100%; height: 100%"
highlight-current-row
show-overflow-tooltip
max-height="400px"
@row-click="selectBed"
>
<el-table-column label="床号" prop="locationId_dictText" min-width="80" align="center" />
</el-table>
</div>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submit">保存</el-button>
<el-button @click="close"> </el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { ref, nextTick } from 'vue';
import { getEmptyBed, saveBedTransfer } from './api';
const { proxy } = getCurrentInstance();
const props = defineProps({
open: {
type: Boolean,
default: false,
},
transferToBedInfo: {
type: Object,
default: () => {},
},
});
const { method_code, unit_code, rate_code, distribution_category_code } = proxy.useDict(
'method_code',
'unit_code',
'rate_code',
'distribution_category_code'
);
const emit = defineEmits(['close','openTransferToBed']);
const form = ref({});
const bedList = ref([]);
const title = ref('');
const rowRules = ref({
conditionDefinitionId: [{ required: true, message: '请选择诊断', trigger: 'change' }],
dose: [{ required: true, message: '请输入单次剂量', trigger: 'change' }],
doseQuantity: [{ required: true, message: '请输入单次剂量', trigger: 'change' }],
quantity: [{ required: true, message: '请输入数量', trigger: 'change' }],
dispensePerDuration: [{ required: true, message: '请输入用药天数', trigger: 'change' }],
});
/**
* 取得床位号
*/
function show() {
reset();
title.value = '';
title.value = props.title;
form.value = props.transferToBedInfo;
console.log(props, 'props', title.value, ' props.transferToBedInfo', props.transferToBedInfo);
if (form.value) {
getEmptyBed(form.value.organizationId).then((res) => {
bedList.value = res.data;
// loading.value = false;
console.log(res, 'resqqqqqqqqqqqqqqqqqqqqqqq', form.value);
});
} else {
bedList.value = [];
}
}
/**
* 选择床位
*
* @param row 要选择的床位信息对象
*/
function selectBed(row) {
console.log(row, 'row 选择床位信息对象');
form.value.newLocationId = row.locationId;
}
/**
* 保存换床信息
*/
function submit() {
console.log(form.value, 'form, prescriptionList.value新增处方');
// console.log(row, ' 保存处方row 1234567890');
// 新增的药品信息调用新增接口
saveBedTransfer(form.value).then((res) => {
if (res.code == 200) {
emit('close', 'success');
reset();
}
});
}
function close() {
reset();
emit('close');
}
/**
* 重置表单
*/
function reset() {
form.value = {
organizationId: '',
newLocationId: '',
organizationId_dictText: '',
patientId: '', // 处方号
oldLocationId: '',
busNo: '',
encounterLocationId: '',
};
proxy.resetForm('formRef');
}
defineExpose({
show,
});
</script>
<style scoped>
:deep(.pagination-container .el-pagination) {
right: 20px !important;
}
</style>

View File

@@ -0,0 +1,446 @@
<template>
<div class="inpatientNurse-container">
<div class="search-container">
<div class="view-container">
<el-radio-group v-model="isBed" @change="bedChange">
<el-radio-button label="card" border>床卡</el-radio-button>
<el-radio-button label="table" border>列表</el-radio-button>
</el-radio-group>
</div>
<el-space>
<el-form
:model="queryParams"
ref="queryRef"
:inline="true"
v-show="showSearch"
@submit.prevent
>
<el-form-item label="" prop="statusEnum">
<el-radio-group v-model="queryParams.statusEnum" size="default" @change="getList">
<el-radio-button
v-for="(item, index) in statusEnumList"
:key="index"
:label="item.value"
:disabled="item.disabled"
>{{ item.label }}</el-radio-button
>
</el-radio-group>
</el-form-item>
<el-form-item label="" prop="checkboxGroup2">
<el-checkbox-group v-model="queryParams.nursingLevelList" @change="getList">
<el-checkbox-button
v-for="item in levelList"
:key="item.value"
v-model="item.value"
style="display: inline-block"
:label="item.label"
>
{{ item.label }}
</el-checkbox-button>
</el-checkbox-group>
</el-form-item>
<el-form-item label="" prop="searchKey">
<el-input
placeholder="住院号/姓名/责任医生/责任护士"
v-model="queryParams.searchKey"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-button @click="getList">查询</el-button>
</el-form>
</el-space>
</div>
<div class="medicalOrderList-table">
<patientCard
v-if="isBed === 'card'"
ref="cardsRef"
:cardList="patientData"
:bed-config="bedManageConfig"
@openPatientDetail="openPatientDetailDialog"
@closePatientDetail="closePatientDetialDialog"
@openTransferToBed="openTransferToBedDialog"
@closeTransferToBed="closeTransferToBedDialog"
@openTransferZk="openTransferZkDialog"
@openTransferCy="openTransferCyDialog"
@closeTransfer="closeTransferDialog"
/>
<el-table
v-if="isBed === 'table'"
ref="table"
:data="patientData"
row-key="id"
style="width: 100%; height: 100%"
highlight-current-row
show-overflow-tooltip
@row-dblclick="openPatientDetailDialog"
max-height="800px"
>
<el-table-column label="床号" prop="locationId_dictText" min-width="80" align="center" />
<el-table-column label="患者姓名" prop="patientName" min-width="100" align="center" />
<el-table-column
label="就诊类别"
prop="classEnum_enumText"
min-width="100"
align="center"
/>
<el-table-column label="性别" prop="genderEnum_enumText" min-width="60" align="center" />
<el-table-column label="年龄" prop="ageString" min-width="60" align="center" />
<el-table-column label="手机号" prop="phone" min-width="120" align="center" />
<el-table-column label="费别" prop="typeCode_dictText" min-width="80" align="center" />
<el-table-column label="住院号" prop="hospitalNo" min-width="120" align="center" />
<el-table-column
label="患者状态"
prop="statusEnum_enumText"
min-width="100"
align="center"
/>
<el-table-column
label="入院科室"
prop="organizationId_dictText"
min-width="120"
align="center"
/>
<el-table-column label="入院日期" prop="admissionDate" min-width="120" align="center" />
<el-table-column
label="护理级别"
prop="priorityEnum_enumText"
min-width="100"
align="center"
/>
<el-table-column label="主要诊断" prop="mainDiagnosis" min-width="150" align="center" />
<el-table-column
label="过敏源"
prop="categoryCode_dictText"
min-width="100"
align="center"
/>
<el-table-column
label="住院天数"
prop="hospitalizationDays"
min-width="80"
align="center"
/>
<el-table-column label="责任医生" prop="responsibleDoctor" min-width="120" align="center" />
<el-table-column label="责任护士" prop="responsibleNurse" min-width="120" align="center" />
<el-table-column
label="操作"
prop="operations"
min-width="360"
fixed="right"
align="center"
>
<template #default="scope">
<el-button type="primary" link>打印腕带</el-button>
<el-button type="primary" link>打印床头卡</el-button>
<el-button type="primary" link @click="openTransferCyDialog(scope.row)">出院</el-button>
<el-button type="primary" link @click="openTransferZkDialog(scope.row)">转科</el-button>
<el-button type="primary" link @click="openTransferToBedDialog(scope.row)"
>转床</el-button
>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
style="margin-bottom: 20px"
/>
</div>
<patient-detial-dialog
ref="patientDetialDialogRef"
:open="openPatientDetail"
:patientId="patientId"
@close="closePatientDetialDialog"
/>
<transfer-to-bed-dialog
ref="transferToBedRef"
:transferToBedInfo="transferToBedInfo"
:open="openTransferToBed"
@close="closeTransferToBedDialog"
/>
<transfer-dialog
ref="transferRef"
:transferInfo="transferInfo"
:open="openTransfer"
:title="title"
@close="closeTransferDialog"
/>
</div>
</template>
<script setup>
import { ref } from 'vue';
import patientCard from './components/patientCard.vue';
import { listPatient } from './components/api';
import patientDetialDialog from './components/patientDetialDialog.vue';
import transferToBedDialog from './components/transferToBedDialog.vue';
import transferDialog from './components/transferDialog.vue';
const data = reactive({
form: {},
queryParams: {
pageNo: 1,
pageSize: 10,
searchKey: undefined, // 品名/商品名/英文品名/编码/拼音
checkboxGroup2: [], // 类型(包括 1中药2成药
statusEnum: 1, // 状态
},
rules: {},
});
const { proxy } = getCurrentInstance();
const { queryParams, form, rules } = toRefs(data);
const statusEnumList = ref([
{ label: '在科', value: 1 },
{ label: '待转科', value: 2 },
{ label: '待出院', value: 3 },
{ label: '危重', value: 4 },
{ label: '手术', value: 5 },
{ label: '欠费', value: 6 },
{ label: '已出院', value: 7 },
]);
const levelList = ref([
{ label: '特级', value: 1 },
{ label: '一级', value: 2 },
{ label: '二级', value: 3 },
{ label: '三级', value: 4 },
]);
const patientData = ref([]);
const bedStations = ref([]); // 床卡状态
const isBed = ref('card');
const bedManageConfig = ref({});
const showSearch = ref(true);
const total = ref(0);
const currentPatient = ref({}); // 当前患者
const nursingMeasuresVal = ref([]); // 护理措施
const specialArrangementVal = ref([]); // 特殊安排
const cardsRef = ref(null); // 卡片引用
const table = ref(null); // 表格引用
// 患者详细对话框相关变量
const patientDetialDialogRef = ref();
const openPatientDetail = ref(false);
const patientId = ref(''); // 患者ID
// 转床对话框相关变量
const transferToBedRef = ref();
const openTransferToBed = ref(false);
// 转科/出院对话框相关变量
const transferRef = ref();
const openTransfer = ref(false);
const title = ref('');
// 转床信息
const transferToBedInfo = ref({
organizationId: '',
organizationId_dictText: '',
oldLocationId: '',
patientId: '', // 处方号
busNo: '',
encounterLocationId: '',
encounterId: '',
});
// 转院/出院信息
const transferInfo = ref({
// organizationId: '',
organizationIdOld: '',
patientName: '',
patientId: '', // 处方号
busNo: '',
encounterId: '',
encounterLocationId: '',
patientNo: '',
});
getList();
function getList() {
// loading.value = true;
console.log(queryParams.value, 'queryParams.value');
listPatient(queryParams.value).then((res) => {
patientData.value = res.data.records;
total.value = res.data.total;
// loading.value = false;
console.log(res, 'resqqqqqqqqqqqqqqqqqqqqqqq');
});
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNo = 1;
getList();
}
/**
* 切换患者信息显示形式(卡片/列表)
*
* @param val 床号
*/
function bedChange(val) {
getBadFirstMes();
}
/**
* 切换患者信息显示形式实现
*
*/
function getBadFirstMes() {
if (patientData.value.length > 0 && patientData.value[0].bedOperationalStatus !== 'U') {
currentPatient.value = JSON.parse(JSON.stringify(patientData.value[0]));
nursingMeasuresVal.value = currentPatient.value.nursingMeasures || [];
specialArrangementVal.value = currentPatient.value.specialArrangement || [];
} else {
currentPatient.value = {};
nursingMeasuresVal.value = [];
specialArrangementVal.value = [];
}
if (
patientData.value.length > 0 &&
patientData.value[0].bedOperationalStatus !== bedStations.value[0]?.code
) {
nextTick(() => {
if (isBed.value === 'card' && cardsRef.value) {
cardsRef.value.activePatient.bedId = patientData.value[0].bedId;
}
if (isBed.value === 'table' && table.value) {
table.value.setCurrentRow(patientData.value[0]);
}
});
}
}
/**
* 打开患者信息详细对话框
*/
function openPatientDetailDialog(row) {
openPatientDetail.value = true;
patientId.value = row.id;
nextTick(() => {
proxy.$refs['patientDetialDialogRef'].getPatientDetial();
});
console.log(openPatientDetail.value, '打开患者信息详细对话框');
}
/**
* 关闭患者信息详细对话框
*/
function closePatientDetialDialog(str) {
if (str === 'success') {
getList();
proxy.$modal.msgSuccess('操作成功');
}
openPatientDetail.value = false;
}
/**
* 打开转床对话框
*/
function openTransferToBedDialog(row) {
transferToBedInfo.value.organizationId = row.organizationId;
transferToBedInfo.value.oldLocationId = row.locationId;
transferToBedInfo.value.organizationId_dictText = row.organizationId_dictText;
transferToBedInfo.value.patientId = row.id; // 病人ID
transferToBedInfo.value.busNo = row.busNo;
transferToBedInfo.value.encounterLocationId = row.encounterLocationId;
transferToBedInfo.value.encounterId = row.encounterId;
openTransferToBed.value = true;
// console.log(transferToBedInfo.value, '打开转床对话框==============');
nextTick(() => {
proxy.$refs['transferToBedRef'].show();
});
console.log(openTransferToBed.value, '打开转床对话框1', transferToBedInfo.value);
}
/**
* 关闭转床对话框
*/
function closeTransferToBedDialog(str) {
if (str === 'success') {
getList();
proxy.$modal.msgSuccess('操作成功');
}
openTransferToBed.value = false;
}
/**
* 打开转科对话框
*/
function openTransferZkDialog(row) {
transferInfo.value.organizationIdOld = row.organizationId;
transferInfo.value.patientName = row.patientName;
transferInfo.value.patientId = row.id; // 病人ID
transferInfo.value.busNo = row.busNo; // 病人ID
transferInfo.value.encounterId = row.encounterId;
transferInfo.value.encounterLocationId = row.encounterLocationId;
transferInfo.value.patientNo = row.patientNo;
title.value = '';
openTransfer.value = true;
title.value = '转科';
nextTick(() => {
proxy.$refs['transferRef'].show();
});
console.log(openTransfer.value, '打开转床对话框2');
}
/**
* 打开出院对话框
*/
function openTransferCyDialog(row) {
transferInfo.value.patientName = row.patientName;
transferInfo.value.patientId = row.id; // 病人ID
transferInfo.value.busNo = row.busNo; // 病人ID
transferInfo.value.encounterId = row.encounterId;
transferInfo.value.encounterLocationId = row.encounterLocationId;
transferInfo.value.locationId = row.locationId;
transferInfo.value.patientNo = row.patientNo;
title.value = '';
openTransfer.value = true;
title.value = '出院';
nextTick(() => {
proxy.$refs['transferRef'].show();
});
console.log(openTransfer.value, '打开转床对话框3');
}
/**
* 关闭转科/出院对话框
*/
function closeTransferDialog(str) {
if (str === 'success') {
getList();
proxy.$modal.msgSuccess('操作成功');
}
openTransfer.value = false;
}
</script>
<style lang="scss" scoped>
.inpatientNurse-container {
display: flex;
flex-direction: column;
height: 100%;
width: 100%;
overflow: hidden;
.search-container {
flex: none;
padding: 8px 8px;
text-align: right;
border-bottom: 1px solid #e4e7ed;
}
.view-container {
flex: none;
padding: 8px 8px;
text-align: left;
border-bottom: 1px solid #e4e7ed;
}
.medicalOrderList-table {
flex: 1;
}
}
</style>

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>

View File

@@ -0,0 +1,34 @@
import request from '@/utils/request'
/**
* 获取住院患者列表
*/
export function getPatientList(queryParams) {
return request({
url: '/nurse-station/advice-process/inpatient',
method: 'get',
params: queryParams
})
}
/**
* 获取当前登录人管理病区
*/
export function getWardList(queryParams) {
return request({
url: '/app-common/practitioner-ward',
method: 'get',
params: queryParams
})
}
/**
* 获取当前选中患者全部医嘱
*/
export function getPrescriptionList(queryParams) {
return request({
url: '/nurse-station/advice-process/inpatient-advice',
method: 'get',
params: queryParams
})
}

View File

@@ -0,0 +1,148 @@
<template>
<div>
<div>
<el-input placeholder="住院号/姓名">
<template #append>
<el-button icon="Search" @click="getPatientList" />
</template>
</el-input>
</div>
<el-tree
ref="treeRef"
:load="loadNode"
lazy
show-checkbox
node-key="id"
default-expand-all
:props="{ label: 'name', children: 'children' }"
@node-click="handleNodeClick"
@check="handleCheckChange"
@node-expand="onNodeExpand"
>
<template #default="{ node, data }">
<div class="custom-tree-node" v-if="node.level === 2">
<span>{{ data.bedName + ' / ' + node.label }}</span>
<span class="tree-node-actions">
{{ data.genderEnum_enumText + ' / ' + data.age }}
</span>
</div>
</template>
</el-tree>
</div>
</template>
<script setup>
import { getPatientList, getWardList } from './api';
import { updatePatientInfoList } from '../store/patient';
import { nextTick, onMounted } from 'vue';
const treeRef = ref(null);
const allNodesLoaded = ref(false);
// 树节点加载完成后的回调
function onTreeLoaded() {
if (!allNodesLoaded.value && treeRef.value) {
// 等待DOM更新后设置全选
nextTick(() => {
// 获取所有节点并设置为选中状态
const allNodes = getAllNodes(treeRef.value.store.root.childNodes);
const allKeys = allNodes.map((node) => node.key);
treeRef.value.setCheckedKeys(allKeys, true); // 第二个参数设为true表示级联选中
allNodesLoaded.value = true;
});
}
}
// 递归获取所有节点
function getAllNodes(nodes) {
let result = [];
if (nodes && nodes.length > 0) {
nodes.forEach((node) => {
result.push(node);
if (node.childNodes && node.childNodes.length > 0) {
result = result.concat(getAllNodes(node.childNodes));
}
});
}
return result;
}
function loadNode(node, resolve) {
// 初始加载:获取所有病区(父级节点)
if (node.level === 0) {
getWardList().then((res) => {
// 确保病区节点不是叶子节点
const wards = res.map((ward) => ({
...ward,
leaf: false,
}));
return resolve(wards);
});
}
// 展开病区节点时:获取该病区下的患者列表
else if (node.level === 1) {
const wardId = node.data.id;
getPatientList({ wardId: wardId }).then((res) => {
let children = res.data.records.map((item) => {
return {
leaf: true, // 患者节点为叶子节点
...item,
name: item.patientName,
};
});
return resolve(children);
});
}
// 更深层级直接返回空数组
else {
return resolve([]);
}
}
// 获取所有选中的子节点(叶子节点)
function getCheckedLeafNodes() {
if (!treeRef.value) return [];
// 获取所有选中的节点key
const checkedKeys = treeRef.value.getCheckedKeys();
// 获取所有半选中的节点key父节点
const halfCheckedKeys = treeRef.value.getHalfCheckedKeys();
// 获取所有选中的节点数据
const checkedNodes = treeRef.value.getCheckedNodes();
// 只返回叶子节点(患者节点)
return checkedNodes.filter((node) => node.leaf === true);
}
// 处理节点选中状态变化
function handleCheckChange(data, checked) {
// 可以在这里处理选中状态变化的逻辑
let list = getCheckedLeafNodes();
console.log(list, '2345678');
updatePatientInfoList(list);
handleGetPrescription()
}
const handleGetPrescription = inject('handleGetPrescription')
</script>
<style scoped lang="scss">
.custom-tree-node {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
}
.tree-node-actions {
display: flex;
align-items: center;
}
:deep(.el-tree-node__content) {
height: 35px;
}
</style>

View File

@@ -0,0 +1,298 @@
<template>
<div style="height: calc(100vh - 126px)">
<div
style="
height: 51px;
border-bottom: 2px solid #e4e7ed;
display: flex;
align-items: center;
justify-content: space-between;
"
>
<div>
<span class="descriptions-item-label">截止时间</span>
<el-date-picker
v-model="deadline"
type="datetime"
format="YYYY/MM/DD HH:mm:ss"
value-format="YYYY/MM/DD HH:mm:ss"
:clearable="false"
@change="handleGetPrescription"
/>
<el-radio-group v-model="therapyEnum" class="ml20" @change="handleRadioChange">
<el-radio :value="undefined">全部</el-radio>
<el-radio :value="1">长期</el-radio>
<el-radio :value="2">临时</el-radio>
</el-radio-group>
<el-button class="ml20" type="primary" plain @click="handleGetPrescription">
查询
</el-button>
</div>
<div>
<el-button class="ml20" type="danger" plain> 不执行 </el-button>
<el-button class="ml20" type="primary"> 皮试结果 </el-button>
<el-button class="ml20 mr20" type="primary"> 执行选中 </el-button>
</div>
</div>
<div
style="padding: 10px; background-color: #eef9fd; height: 100%; overflow-y: auto"
v-loading="loading"
>
<el-collapse
v-model="activeNames"
expand-icon-position="left"
v-if="prescriptionList.length > 0"
style="
border-bottom: 0px;
border-top: 0px;
border-radius: 0px;
overflow-y: auto;
max-height: calc(100vh - 200px);
"
>
<el-collapse-item
v-for="(item, index) in prescriptionList"
:key="index"
:name="item[0].encounterId"
style="
border: 2px solid #e4e7ed;
border-radius: 8px;
margin-bottom: 10px;
overflow: hidden;
"
>
<template #title>
<div style="display: flex; justify-content: space-between; align-items: center">
<div>
<span class="item-value">{{ item[0].badName }}</span>
<span class="item-value">{{ '【' + item[0].busNo + '】' }}</span>
<span class="item-value">{{ item[0].patientName + item[0].age }}</span>
<span>{{ item[0].contractName }}</span>
<span>{{ item[0].conditionNames }}</span>
</div>
<div
style="
display: flex;
justify-content: space-between;
gap: 20px;
align-items: center;
margin-right: 20px;
"
>
<div style="display: inline-block; margin-right: 10px">
<span class="descriptions-item-label">住院医生</span>
<span>{{ item[0].requesterId_dictText }}</span>
</div>
<div style="display: inline-block; margin-right: 10px">
<div
class="descriptions-item-label"
style="height: 20px; line-height: 20px; text-align: center; margin: 0"
>
预交金额
</div>
<div
style="
height: 20px;
line-height: 20px;
text-align: center;
font-size: 15px;
color: #ec8c43;
"
>
{{ item[0].balanceAmount?.toFixed(2) }}
</div>
</div>
</div>
</div>
</template>
<el-table :data="item" border :header-cell-style="{ background: '#eef9fd !important' }">
<el-table-column type="selection" align="center" width="50" />
<el-table-column label="类型" align="center" prop="therapyEnum_enumText" width="80">
<template #default="scope">
<span :style="scope.row.therapyEnum == '1' ? 'color: #a6745c' : 'color: #3787a5'">
{{ scope.row.therapyEnum_enumText }}
</span>
</template>
</el-table-column>
<el-table-column label="医嘱内容" prop="adviceName" />
<el-table-column label="开始/终止" prop="requestTime" width="230" />
<el-table-column label="预计执行" prop="times">
<template #default="scope">
<div
v-for="(item, timeIndex) in scope.row.times"
:key="timeIndex"
style="padding-bottom: 5px"
>
<span>{{ item }}</span>
<el-checkbox-group
v-model="scope.row.checkedRates[timeIndex]"
style="display: inline-block; margin-left: 15px"
>
<el-checkbox
v-for="(rateItem, rateIndex) in scope.row.rate"
:key="rateIndex"
:value="rateItem"
border
size="small"
style="margin-right: 15px"
>
{{ rateItem }}
</el-checkbox>
</el-checkbox-group>
</div>
</template>
</el-table-column>
</el-table>
</el-collapse-item>
</el-collapse>
<el-empty v-else description="点击查询获取患者医嘱信息"></el-empty>
</div>
</div>
</template>
<script setup>
import { getPrescriptionList } from './api';
import { patientInfoList } from '../store/patient.js';
import { formatDate, formatDateStr } from '@/utils/index';
const activeNames = ref([]);
const prescriptionList = ref([]);
const deadline = ref(formatDateStr(new Date(), 'YYYY-MM-DD') + ' 23:59:59');
const therapyEnum = ref(undefined);
const { proxy } = getCurrentInstance();
const loading = ref(false);
const props = defineProps({
exeStatus: {
type: Number,
default: 1,
},
});
function handleRadioChange() {
handleGetPrescription();
}
function handleGetPrescription() {
if (patientInfoList.value.length > 0) {
loading.value = true;
let encounterIds = patientInfoList.value.map((i) => i.encounterId).join(',');
getPrescriptionList({
encounterIds: encounterIds,
pageSize: 10000,
pageNo: 1,
therapyEnum: therapyEnum.value,
exeStatus: props.exeStatus,
}).then((res) => {
// try {
// 根据encounterId分组
const groupedPrescriptions = res.data.records.reduce((groups, prescription) => {
// 获取当前医嘱全部执行频次
let rate;
let times;
if (prescription.therapyEnum == 1) {
rate = prescription.dayTimes?.split(',');
times = getDateRange(prescription.requestTime, deadline.value);
} else {
rate = [formatDateStr(prescription.requestTime, 'HH:mm')];
times = [formatDateStr(prescription.requestTime, 'MM-DD')];
}
prescription.times = times;
prescription.rate = rate;
// 添加复选框状态管理
prescription.checkedRates = {};
if (rate) {
times.forEach((time, index) => {
// 默认选中所有执行频次
prescription.checkedRates[index] = [...rate];
});
}
// 把相同encounterId的医嘱放在同一个数组中
const encounterId = prescription.encounterId;
if (!groups[encounterId]) {
groups[encounterId] = [];
}
if (!activeNames.value.includes(encounterId)) {
activeNames.value.push(encounterId);
}
groups[encounterId].push(prescription);
return groups;
}, {});
// 将分组结果转换为数组形式
prescriptionList.value = Object.values(groupedPrescriptions);
console.log(prescriptionList.value, '1111');
loading.value = false;
// } catch {
// loading.value = false;
// }
});
} else {
prescriptionList.value = [];
// proxy.$message.warning('请选择患者');
}
}
/**
* 计算两个日期之间的所有日期(包含起始和结束日期)
* @param {string|Date} startDate - 开始日期
* @param {string|Date} endDate - 结束日期
* @returns {Array<string>} 格式为MM-DD的日期数组
*/
function getDateRange(startDate, endDate) {
const start = new Date(startDate);
const end = new Date(endDate);
// 重置时间部分,只保留日期
start.setHours(0, 0, 0, 0);
end.setHours(0, 0, 0, 0);
const dates = [];
const current = new Date(start);
// 循环添加日期直到结束日期
while (current <= end) {
// 格式化为MM-DD
const month = String(current.getMonth() + 1).padStart(2, '0');
const day = String(current.getDate()).padStart(2, '0');
dates.push(`${month}-${day}`);
// 移动到下一天
current.setDate(current.getDate() + 1);
}
return dates;
}
// 处理后端返回的时间集合
function handleTime() {}
defineExpose({
handleGetPrescription,
});
</script>
<style scoped>
.el-collapse-icon-position-left :deep(.el-collapse-item__header) {
padding: 10px;
}
:deep(.el-collapse-item__wrap) {
padding: 10px;
}
/* 表头背景色 */
:deep(.prescription-table .el-table__header th) {
background-color: #eef9fd !important;
}
:deep(.el-table__row:hover > td) {
background-color: #eef9fd !important;
}
.item-value {
color: #606266;
font-size: 15px;
font-weight: 500;
}
</style>

View File

@@ -0,0 +1,137 @@
<template>
<div style="display: flex; justify-content: space-between">
<div style="width: 20%; height: 90vh; border-right: solid 2px #e4e7ed">
<div
style="
height: 40px;
display: flex;
align-items: center;
justify-content: flex-end;
border-bottom: solid 2px #e4e7ed;
"
>
<el-icon
@click="refresh"
class="refresh-icon"
style="cursor: pointer; font-size: 20px; margin-right: 10px"
>
<Refresh />
</el-icon>
</div>
<el-tabs v-model="active" class="demo-tabs centered-tabs tab-header" @tab-click="handleClick">
<el-tab-pane label="在科" name="first" style="padding: 15px 10px">
<PatientList />
</el-tab-pane>
<el-tab-pane label="转科" name="second" style="padding: 0 10px">
<PatientList />
</el-tab-pane>
</el-tabs>
</div>
<div style="width: 100%">
<el-tabs
v-model="activeName"
class="demo-tabs centered-tabs"
@tab-change="handleClick"
>
<el-tab-pane
v-for="tab in prescriptionTabs"
:key="tab.name"
:lazy="true"
:label="tab.label"
:name="tab.name"
>
<!-- 使用模板引用 -->
<PrescriptionList
:exeStatus="exeStatus"
:ref="(el) => setPrescriptionRef(el, tab.name)"
/>
</el-tab-pane>
</el-tabs>
</div>
</div>
</template>
<script setup>
import { getCurrentInstance } from 'vue';
import PatientList from './components/patientList.vue';
import PrescriptionList from './components/prescriptionList.vue';
const activeName = ref('preparation');
const active = ref('first');
const exeStatus = ref(1);
const { proxy } = getCurrentInstance();
// 存储子组件引用的对象
const prescriptionRefs = ref({});
// 定义处方列表tabs配置
const prescriptionTabs = [
{ label: '待执行', name: 'preparation' },
{ label: '已执行', name: 'completed' },
{ label: '不执行', name: 'stopped' },
{ label: '取消执行', name: 'cancel' }
];
// 设置处方组件引用
function setPrescriptionRef(el, name) {
if (el) {
prescriptionRefs.value[name] = el;
}
}
function handleClick(tabName) {
// tabName是tab的name属性值
const activeTabName = tabName || activeName.value;
switch(activeTabName){
case 'preparation':
exeStatus.value = 1;
break;
case 'completed':
exeStatus.value = 6;
break;
case 'stopped':
exeStatus.value = 5;
break;
case 'cancel':
exeStatus.value = 9;
break;
}
// 调用子组件方法
nextTick(() => {
if (prescriptionRefs.value[activeTabName] &&
typeof prescriptionRefs.value[activeTabName].handleGetPrescription === 'function') {
prescriptionRefs.value[activeTabName].handleGetPrescription();
}
});
}
provide('handleGetPrescription', (value) => {
prescriptionRefs.value[activeName.value].handleGetPrescription();
});
</script>
<style scoped>
.centered-tabs :deep(.el-tabs__nav-wrap) {
display: flex;
justify-content: center;
}
.centered-tabs :deep(.el-tabs__nav-scroll) {
display: flex;
justify-content: center;
}
.tab-header :deep(.el-tabs__item) {
height: 50px !important;
}
.centered-tabs :deep(.el-tabs__nav) {
display: flex;
justify-content: center;
}
:deep(.el-tabs__header) {
margin: 0;
}
</style>

View File

@@ -0,0 +1,12 @@
// 选择患者信息
export const patientInfo = ref()
export function updatePatientInfo(info) {
patientInfo.value = info
}
// 多选患者
export const patientInfoList = ref([])
export function updatePatientInfoList(info) {
patientInfoList.value = info
}

View File

@@ -0,0 +1,300 @@
<!--
* @Author: sjjh
* @Date: 2025-04-16 20:54:48
* @Description:
-->
<template>
<div class="medicalOrderManagement-container">
<div class="medicalOrderManagement-operate">
<el-space :size="4">
<el-select v-model="searchForm.patientStatus" placeholder="执行状态" style="width: 100px">
<el-option v-for="item in statusOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<el-select v-model="searchForm.selectedType" placeholder="医嘱类型" style="width: 100px">
<el-option v-for="item in typeOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<el-select v-model="searchForm.executionType" placeholder="执行单类型" style="width: 100px">
<el-option v-for="item in executionTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<el-input v-model="searchForm.searchVal" style="width: 100px" placeholder="医嘱名称" />
<!-- 增加预计执行时间 时间范围筛选 -->
<el-date-picker v-model="searchForm.timeRange" type="daterange" range-separator="至" start-placeholder="开始日期"
end-placeholder="结束日期" style="width: 200px" />
<el-button type="primary">查询</el-button>
<el-button type="danger">退回</el-button>
<el-button type="primary">通过校对</el-button>
</el-space>
<el-space :size="4">
</el-space>
</div>
<div class="medicalOrderManagement-table">
<el-table :data="medicalOrderManagementData" row-key="id" style="width: 100%; height: 100%" border
:span-method="arraySpanMethod">
<el-table-column type="selection" />
<el-table-column label="类型" prop="name">
<template #default="{ row }">
<span v-if="!row.children">长期/西药</span>
<template v-else>
{{ row.name }} 11 000000001 &nbsp; 林俊杰 /24 &nbsp;1级 自费 主诊断 医生医生甲&nbsp; 预交金1990.3
</template>
</template>
</el-table-column>
<el-table-column label="医嘱内容" prop="content">
<template #default="{ row }">
<span v-if="row.children">{{ row.content }}</span>
</template>
</el-table-column>
<el-table-column label="开始终止" prop="gender">
<template #default="{ row }">
<div v-if="!row.children">
<div> 05/04 07:00 </div>
<div> 05/25 07:00 </div>
</div>
</template>
</el-table-column>
<el-table-column label="补费绑定" prop="gender">
<template #default="{ row }">
<el-select v-model="row.reimbursementBinding" placeholder="请选择" style="width: 100%">
<el-option v-for="item in reimbursementOptions" :key="item.value" :label="item.label"
:value="item.value" />
</el-select>
</template>
</el-table-column>
<el-table-column label="执行科室" prop="gender">
</el-table-column>
<el-table-column label="签发时间" prop="gender">
</el-table-column>
</el-table>
</div>
</div>
</template>
<script setup lang="ts">
import { onBeforeMount, onMounted, reactive, ref } from 'vue'
// const { proxy } = getCurrentInstance()
// const emits = defineEmits([])
// const props = defineProps({})
const state = reactive({})
onBeforeMount(() => { })
onMounted(() => { })
defineExpose({ state })
const medicalOrderManagementData = ref([
{
id: 1,
name: '张三',
age: 20,
gender: '男',
children: [
{
name: '',
age: 10,
gender: '男',
content: '维生素B12注射液【1ml0.5mg*1】 ',
dates: [{
date: '05/04',
times: [{
time: '08:00',
nurse: '刘护士',
checked: false
}, {
time: '12:00',
nurse: '刘护士',
checked: false
}]
}, {
date: '05/05',
times: [{
time: '08:00',
nurse: '刘护士',
checked: false
}, {
time: '12:00',
nurse: '刘护士',
checked: false
}]
}]
}, {
name: '',
age: 10,
gender: '男',
content: '维生素B12注射液【1ml0.5mg*1】 ',
dates: [{
date: '05/04',
times: [{
time: '08:00',
nurse: '刘护士',
checked: false
}, {
time: '12:00',
nurse: '刘护士',
checked: false
}]
}, {
date: '05/05',
times: [{
time: '08:00',
nurse: '刘护士',
checked: false
}, {
time: '12:00',
nurse: '刘护士',
checked: false
}]
}]
}]
},
{
id: 2,
name: '李四',
age: 20,
gender: '男',
children: [
{
name: '',
age: 10,
gender: '男',
content: '维生素B12注射液【1ml0.5mg*1】 ',
dates: [{
date: '05/04',
times: [{
time: '08:00',
nurse: '刘护士',
checked: false
}, {
time: '12:00',
nurse: '刘护士',
checked: false
}]
}, {
date: '05/05',
times: [{
time: '08:00',
nurse: '刘护士',
checked: false
}, {
time: '12:00',
nurse: '刘护士',
checked: false
}]
}]
}, {
name: '',
age: 10,
gender: '男',
content: '维生素B12注射液【1ml0.5mg*1】 ',
dates: [{
date: '05/04',
times: [{
time: '08:00',
nurse: '刘护士',
checked: false
}, {
time: '12:00',
nurse: '刘护士',
checked: false
}]
}, {
date: '05/05',
times: [{
time: '08:00',
nurse: '刘护士',
checked: false
}, {
time: '12:00',
nurse: '刘护士',
checked: false
}]
}]
}]
}
])
const reimbursementOptions = [
{ value: '首瓶8.5', label: '首瓶8.5' },
{ value: '未绑定', label: '未绑定' },
{ value: '待绑定', label: '待绑定' }
]
const arraySpanMethod = ({
row,
column,
rowIndex,
columnIndex
}: any) => {
console.log(row, column, rowIndex, columnIndex);
// 如果是父级行
if (row.children && row.children.length > 0) {
if (columnIndex === 0) {
return [1, 1]
}
// 如果是患者列
if (columnIndex === 1) {
return [1, 6]
} else {
return [1, 0]
}
}
// 如果是子级行,显示其他列
if (!row.children || row.children.length == 0) {
return [1, 1]
}
// 如果是父级行,隐藏其他列
return [1, 1]
}
const statusOptions = [
{ value: '全部', label: '全部' },
{ value: '药品', label: '药品' },
{ value: '本院区', label: '本院区' },
{ value: '他科', label: '他科' },
{ value: '床头卡', label: '床头卡' }
]
const typeOptions = [
{ value: '全部', label: '全部' },
{ value: '长期', label: '长期' },
{ value: '临时', label: '临时' }
]
const executionTypeOptions = [
{ value: '未交对', label: '未交对' },
{ value: '已校对', label: '已校对' },
{ value: '已停止', label: '已停止' },
{ value: '已作废', label: '已作废' }
]
const searchForm = reactive({
searchVal: '',
patientStatus: '全部',
selectedType: '全部',
timeRange: [],
executionType: '全部',
isPrintExecution: true,
isPrintLabel: true
})
</script>
<style lang="scss" scoped>
.medicalOrderManagement-container {
height: 100%;
width: 100%;
display: flex;
flex-direction: column;
.medicalOrderManagement-operate {
height: 49px;
width: 100%;
flex: none;
align-items: center;
border-bottom: 1px solid #e8e8e8;
padding: 8px;
}
.medicalOrderManagement-table {
height: 44px;
width: 100%;
flex: 1;
padding: 8px;
}
}
</style>

View File

@@ -0,0 +1,310 @@
<!--
* @Author: sjjh
* @Date: 2025-04-16 20:14:58
* @Description: 患者列表组件
-->
<template>
<div class="patientList-container">
<div class="patientList-wrapper" :class="{ 'collapsed': isCollapsed }">
<div class="patientList-header">
<el-space :size="4">
<el-input v-model="searchForm.searchVal" style="width: 100px" placeholder="住院号/姓名" v-if="!isCollapsed" />
<el-select v-model="searchForm.patientStatus" placeholder="" style="min-width: 70px" v-if="!isCollapsed">
<el-option key="1" label="在科" value="1" />
<el-option key="2" label="转科" value="2" />
</el-select>
<el-icon @click="refresh" class="refresh-icon">
<Refresh />
</el-icon>
<el-icon @click="toggleCollapse" class="collapse-icon">
<template v-if="isCollapsed">
<Expand />
</template>
<template v-else>
<Fold />
</template>
</el-icon>
</el-space>
</div>
<!-- 待入科列表 -->
<div class="patientList-table">
<el-table :data="patientListData" row-key="id" style="width: 100%; height: 100%" highlight-current-row
@selection-change="handleSelectionChange" :show-header="false" show-overflow-tooltip>
<!-- <el-table-column type="selection" :width="isCollapsed ? 14 : 20" /> -->
<el-table-column label="姓名" prop="name" min-width="100">
<template #default="{ row }">
<template v-if="row?.children?.length > 0">
<span>{{ row.department }}</span>
</template>
<div class="patient-name" v-else>
<span class="name">{{ row.name }}</span>
<span class="age" v-if="!isCollapsed">{{ row.age }}</span>
<span class="gender" v-if="!isCollapsed">{{ row.gender }}</span>
</div>
</template>
</el-table-column>
</el-table>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
import { Expand, Fold, Refresh } from '@element-plus/icons-vue'
const isCollapsed = ref(false)
const toggleCollapse = () => {
isCollapsed.value = !isCollapsed.value
}
const refresh = () => {
// 刷新逻辑
}
const searchForm = reactive({
searchVal: '',
patientStatus: '',
attention: ''
})
const patientListData = ref([
{
id: 1,
name: '张三1111111',
age: 30,
gender: '男',
status: '在科',
attention: '医生A',
department: '儿科',
children: [
{
id: 11,
name: '张三-11111111',
age: 5,
gender: '男',
status: '在科',
attention: '医生A'
},
{
id: 12,
name: '张三-2',
age: 3,
gender: '女',
status: '在科',
attention: '医生A'
}
]
},
{
id: 2,
name: '李四',
age: 25,
gender: '女',
status: '转科',
attention: '医生B'
}
])
const selectedRows = ref<any[]>([])
const handleSelectionChange = (selection) => {
selectedRows.value = selection
}
</script>
<style scoped lang="scss">
.patientList-container {
// width: 100%;
height: 100%;
overflow: hidden;
max-width: 240px;
position: relative;
display: flex;
flex-direction: column;
.patientList-wrapper {
height: 100%;
width: 240px;
background: #fff;
border-right: 1px solid #e8e8e8;
display: flex;
flex-direction: column;
transition: width 0.3s ease;
&.collapsed {
width: 70px;
.el-input,
.el-select {
display: none;
}
.patientList-table {
width: 100% !important;
overflow: hidden;
padding: 0 0px 8px 0px;
}
.el-table {
width: 100% !important;
overflow: hidden;
position: relative;
}
.el-table__header-wrapper,
.el-table__body-wrapper {
width: 100% !important;
overflow: hidden;
}
.el-table__header {
display: none;
}
.el-table__body {
display: block;
overflow: hidden;
}
.el-table__body tr {
display: block;
padding: 4px 8px;
text-align: center;
border-bottom: 1px solid #e8e8e8;
overflow: hidden;
}
.el-table__body td {
display: block;
padding: 0;
border: none;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.el-table__body .name {
font-size: 16px;
}
.el-table__body .status,
.el-table__body .attention {
display: none;
}
}
.patientList-header {
min-height: 88px;
padding: 8px 8px;
border-bottom: 1px solid #e8e8e8;
background: #fff;
display: flex;
flex-direction: column;
gap: 8px;
min-height: 40px;
.el-space {
flex: 1;
display: flex;
align-items: center;
width: 100%;
gap: 8px;
.el-input {
width: 120px;
}
.el-select {
flex: 1;
min-width: 70px;
}
.el-icon {
flex: none;
width: auto;
}
}
}
.patientList-table {
flex: 1;
overflow: hidden;
width: 100%;
position: relative;
display: flex;
flex-direction: column;
padding: 0 8px 8px 8px;
}
.el-table {
width: 100% !important;
height: 100%;
overflow: hidden;
position: relative;
}
.el-table__body {
overflow: hidden;
position: relative;
}
.el-table__body-wrapper {
overflow: hidden !important;
}
.el-table__body tr {
position: relative;
}
.collapse-icon,
.refresh-icon {
cursor: pointer;
font-size: 20px;
}
}
}
.patient-name {
display: inline-flex;
align-items: center;
gap: 8px;
font-size: 16px;
color: #666;
}
::v-deep .el-table__indent {
display: none !important;
}
::v-deep .el-table__placeholder {
display: none !important;
}
::v-deep .el-table__expanded-cell {
padding: 0 !important;
}
::v-deep .el-table__expanded-cell .el-table__cell {
padding: 0 !important;
}
::v-deep .el-table__expanded-cell .el-table__cell .patient-name {
margin-left: 4px;
}
::v-deep .cell {
padding-left: 0 !important;
padding-right: 0 !important;
}
::v-deep .el-table__expanded-cell {
padding: 0 !important;
}
::v-deep .el-table__expanded-cell .el-table__cell .patient-name {
margin-left: 4px;
}
</style>

View File

@@ -0,0 +1,360 @@
<!--
* @Author: sjjh
* @Date: 2025-04-16 20:54:48
* @Description:
-->
<template>
<div class="medicalOrderManagement-container">
<div class="medicalOrderManagement-operate">
<el-space :size="4">
<el-select v-model="searchForm.patientStatus" placeholder="执行状态" style="width: 100px">
<el-option
v-for="item in statusOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-select v-model="searchForm.selectedType" placeholder="医嘱类型" style="width: 100px">
<el-option
v-for="item in typeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-select v-model="searchForm.executionType" placeholder="执行单类型" style="width: 100px">
<el-option
v-for="item in executionTypeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-input v-model="searchForm.searchVal" style="width: 100px" placeholder="医嘱名称" />
<!-- 增加预计执行时间 时间范围筛选 -->
<el-date-picker
v-model="searchForm.timeRange"
type="daterange"
range-separator=""
start-placeholder="开始日期"
end-placeholder="结束日期"
style="width: 200px"
/>
<el-button type="primary">查询</el-button>
<el-button type="danger">不执行</el-button>
<el-checkbox v-model="searchForm.isPrintExecution">执行单打印</el-checkbox>
<el-checkbox v-model="searchForm.isPrintLabel">瓶贴打印</el-checkbox>
<el-button type="primary">执行</el-button>
<el-button type="">皮试结果</el-button>
</el-space>
<el-space :size="4"> </el-space>
</div>
<div class="medicalOrderManagement-table">
<el-table
:data="medicalOrderManagementData"
row-key="id"
style="width: 100%; height: 100%"
border
:span-method="arraySpanMethod"
>
<el-table-column type="selection" />
<el-table-column label="类型" prop="name">
<template #default="{ row }">
<span v-if="!row.children">长期/西药</span>
<template v-else>
{{ row.name }}
11 000000001 &nbsp; 林俊杰 /24 &nbsp;1级 自费 主诊断 医生医生甲&nbsp;
预交金1990.3
</template>
</template>
</el-table-column>
<el-table-column label="医嘱内容" prop="content">
<template #default="{ row }">
<span v-if="row.children">{{ row.content }}</span>
</template>
</el-table-column>
<el-table-column label="开始终止" prop="gender">
<template #default="{ row }">
<div v-if="!row.children">
<div>05/04 07:00</div>
<div>05/25 07:00</div>
</div>
</template>
</el-table-column>
<el-table-column label="执行时间" prop="gender" min-width="200px">
<template #default="{ row }">
<template v-if="!row.children">
<div v-for="item in row.dates" :key="item.id">
<span>{{ item.date }}</span>
<span v-for="time in item.times" :key="time.id">
<el-checkbox v-model="time.checked" :label="`${time.time + time.nurse}`" border />
</span>
</div>
</template>
<template v-else> </template>
</template>
</el-table-column>
</el-table>
</div>
</div>
</template>
<script setup >
import { onBeforeMount, onMounted, reactive, ref } from 'vue';
// const { proxy } = getCurrentInstance()
// const emits = defineEmits([])
// const props = defineProps({})
const state = reactive({});
onBeforeMount(() => {});
onMounted(() => {});
defineExpose({ state });
const medicalOrderManagementData = ref([
{
id: 1,
name: '张三',
age: 20,
gender: '男',
children: [
{
name: '',
age: 10,
gender: '男',
content: '维生素B12注射液【1ml0.5mg*1】 ',
dates: [
{
date: '05/04',
times: [
{
time: '08:00',
nurse: '刘护士',
checked: false,
},
{
time: '12:00',
nurse: '刘护士',
checked: false,
},
],
},
{
date: '05/05',
times: [
{
time: '08:00',
nurse: '刘护士',
checked: false,
},
{
time: '12:00',
nurse: '刘护士',
checked: false,
},
],
},
],
},
{
name: '',
age: 10,
gender: '男',
content: '维生素B12注射液【1ml0.5mg*1】 ',
dates: [
{
date: '05/04',
times: [
{
time: '08:00',
nurse: '刘护士',
checked: false,
},
{
time: '12:00',
nurse: '刘护士',
checked: false,
},
],
},
{
date: '05/05',
times: [
{
time: '08:00',
nurse: '刘护士',
checked: false,
},
{
time: '12:00',
nurse: '刘护士',
checked: false,
},
],
},
],
},
],
},
{
id: 2,
name: '李四',
age: 20,
gender: '男',
children: [
{
name: '',
age: 10,
gender: '男',
content: '维生素B12注射液【1ml0.5mg*1】 ',
dates: [
{
date: '05/04',
times: [
{
time: '08:00',
nurse: '刘护士',
checked: false,
},
{
time: '12:00',
nurse: '刘护士',
checked: false,
},
],
},
{
date: '05/05',
times: [
{
time: '08:00',
nurse: '刘护士',
checked: false,
},
{
time: '12:00',
nurse: '刘护士',
checked: false,
},
],
},
],
},
{
name: '',
age: 10,
gender: '男',
content: '维生素B12注射液【1ml0.5mg*1】 ',
dates: [
{
date: '05/04',
times: [
{
time: '08:00',
nurse: '刘护士',
checked: false,
},
{
time: '12:00',
nurse: '刘护士',
checked: false,
},
],
},
{
date: '05/05',
times: [
{
time: '08:00',
nurse: '刘护士',
checked: false,
},
{
time: '12:00',
nurse: '刘护士',
checked: false,
},
],
},
],
},
],
},
]);
const arraySpanMethod = ({ row, column, rowIndex, columnIndex }) => {
console.log(row, column, rowIndex, columnIndex);
// 如果是父级行
if (row.children && row.children.length > 0) {
if (columnIndex === 0) {
return [1, 1];
}
// 如果是患者列
if (columnIndex === 1) {
return [1, 6];
} else {
return [1, 0];
}
}
// 如果是子级行,显示其他列
if (!row.children || row.children.length == 0) {
return [1, 1];
}
// 如果是父级行,隐藏其他列
return [1, 1];
};
const statusOptions = [
{ value: '未执行', label: '未执行' },
{ value: '已执行', label: '已执行' },
{ value: '不执行', label: '不执行' },
{ value: '取消执行', label: '取消执行' },
];
const typeOptions = [
{ value: '全部', label: '全部' },
{ value: '长期', label: '长期' },
{ value: '临时', label: '临时' },
];
const executionTypeOptions = [
{ value: '全部', label: '全部' },
{ value: '口服单', label: '口服单' },
{ value: '输液单', label: '输液单' },
{ value: '针剂单', label: '针剂单' },
{ value: '雾化单', label: '雾化单' },
{ value: '治疗单', label: '治疗单' },
{ value: '其他', label: '其他' },
];
const searchForm = reactive({
searchVal: '',
patientStatus: '未执行',
selectedType: '全部',
timeRange: [],
executionType: '全部',
isPrintExecution: true,
isPrintLabel: true,
});
</script>
<style lang="scss" scoped>
.medicalOrderManagement-container {
height: 100%;
width: 100%;
display: flex;
flex-direction: column;
.medicalOrderManagement-operate {
height: 49px;
width: 100%;
flex: none;
align-items: center;
border-bottom: 1px solid #e8e8e8;
padding: 8px;
}
.medicalOrderManagement-table {
height: 44px;
width: 100%;
flex: 1;
padding: 8px;
}
}
</style>

View File

@@ -0,0 +1,310 @@
<!--
* @Author: sjjh
* @Date: 2025-04-16 20:14:58
* @Description: 患者列表组件
-->
<template>
<div class="patientList-container">
<div class="patientList-wrapper" :class="{ 'collapsed': isCollapsed }">
<div class="patientList-header">
<el-space :size="4">
<el-input v-model="searchForm.searchVal" style="width: 100px" placeholder="住院号/姓名" v-if="!isCollapsed" />
<el-select v-model="searchForm.patientStatus" placeholder="" style="min-width: 70px" v-if="!isCollapsed">
<el-option key="1" label="在科" value="1" />
<el-option key="2" label="转科" value="2" />
</el-select>
<el-icon @click="refresh" class="refresh-icon">
<Refresh />
</el-icon>
<el-icon @click="toggleCollapse" class="collapse-icon">
<template v-if="isCollapsed">
<Expand />
</template>
<template v-else>
<Fold />
</template>
</el-icon>
</el-space>
</div>
<!-- 待入科列表 -->
<div class="patientList-table">
<el-table :data="patientListData" row-key="id" style="width: 100%; height: 100%" highlight-current-row
@selection-change="handleSelectionChange" :show-header="false" show-overflow-tooltip>
<!-- <el-table-column type="selection" :width="isCollapsed ? 14 : 20" /> -->
<el-table-column label="姓名" prop="name" min-width="100">
<template #default="{ row }">
<template v-if="row?.children?.length > 0">
<span>{{ row.department }}</span>
</template>
<div class="patient-name" v-else>
<span class="name">{{ row.name }}</span>
<span class="age" v-if="!isCollapsed">{{ row.age }}</span>
<span class="gender" v-if="!isCollapsed">{{ row.gender }}</span>
</div>
</template>
</el-table-column>
</el-table>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
import { Expand, Fold, Refresh } from '@element-plus/icons-vue'
const isCollapsed = ref(false)
const toggleCollapse = () => {
isCollapsed.value = !isCollapsed.value
}
const refresh = () => {
// 刷新逻辑
}
const searchForm = reactive({
searchVal: '',
patientStatus: '',
attention: ''
})
const patientListData = ref([
{
id: 1,
name: '张三1111111',
age: 30,
gender: '男',
status: '在科',
attention: '医生A',
department: '儿科',
children: [
{
id: 11,
name: '张三-11111111',
age: 5,
gender: '男',
status: '在科',
attention: '医生A'
},
{
id: 12,
name: '张三-2',
age: 3,
gender: '女',
status: '在科',
attention: '医生A'
}
]
},
{
id: 2,
name: '李四',
age: 25,
gender: '女',
status: '转科',
attention: '医生B'
}
])
const selectedRows = ref<any[]>([])
const handleSelectionChange = (selection) => {
selectedRows.value = selection
}
</script>
<style scoped lang="scss">
.patientList-container {
// width: 100%;
height: 100%;
overflow: hidden;
max-width: 240px;
position: relative;
display: flex;
flex-direction: column;
.patientList-wrapper {
height: 100%;
width: 240px;
background: #fff;
border-right: 1px solid #e8e8e8;
display: flex;
flex-direction: column;
transition: width 0.3s ease;
&.collapsed {
width: 70px;
.el-input,
.el-select {
display: none;
}
.patientList-table {
width: 100% !important;
overflow: hidden;
padding: 0 0px 8px 0px;
}
.el-table {
width: 100% !important;
overflow: hidden;
position: relative;
}
.el-table__header-wrapper,
.el-table__body-wrapper {
width: 100% !important;
overflow: hidden;
}
.el-table__header {
display: none;
}
.el-table__body {
display: block;
overflow: hidden;
}
.el-table__body tr {
display: block;
padding: 4px 8px;
text-align: center;
border-bottom: 1px solid #e8e8e8;
overflow: hidden;
}
.el-table__body td {
display: block;
padding: 0;
border: none;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.el-table__body .name {
font-size: 16px;
}
.el-table__body .status,
.el-table__body .attention {
display: none;
}
}
.patientList-header {
min-height: 88px;
padding: 8px 8px;
border-bottom: 1px solid #e8e8e8;
background: #fff;
display: flex;
flex-direction: column;
gap: 8px;
min-height: 40px;
.el-space {
flex: 1;
display: flex;
align-items: center;
width: 100%;
gap: 8px;
.el-input {
width: 120px;
}
.el-select {
flex: 1;
min-width: 70px;
}
.el-icon {
flex: none;
width: auto;
}
}
}
.patientList-table {
flex: 1;
overflow: hidden;
width: 100%;
position: relative;
display: flex;
flex-direction: column;
padding: 0 8px 8px 8px;
}
.el-table {
width: 100% !important;
height: 100%;
overflow: hidden;
position: relative;
}
.el-table__body {
overflow: hidden;
position: relative;
}
.el-table__body-wrapper {
overflow: hidden !important;
}
.el-table__body tr {
position: relative;
}
.collapse-icon,
.refresh-icon {
cursor: pointer;
font-size: 20px;
}
}
}
.patient-name {
display: inline-flex;
align-items: center;
gap: 8px;
font-size: 16px;
color: #666;
}
::v-deep .el-table__indent {
display: none !important;
}
::v-deep .el-table__placeholder {
display: none !important;
}
::v-deep .el-table__expanded-cell {
padding: 0 !important;
}
::v-deep .el-table__expanded-cell .el-table__cell {
padding: 0 !important;
}
::v-deep .el-table__expanded-cell .el-table__cell .patient-name {
margin-left: 4px;
}
::v-deep .cell {
padding-left: 0 !important;
padding-right: 0 !important;
}
::v-deep .el-table__expanded-cell {
padding: 0 !important;
}
::v-deep .el-table__expanded-cell .el-table__cell .patient-name {
margin-left: 4px;
}
</style>

View File

@@ -0,0 +1,88 @@
<!--
* @Author: sjjh
* @Date: 2025-04-09 17:14:59
* @Description:
-->
<template>
<el-tabs type="border-card" class="medicalOrderManagement-container">
<el-tab-pane label="医嘱校对">
<div class="check-wrapper">
<!-- 患者列表 -->
<CheckPatientList />
<!-- main -->
<CheckMedicalOrderManagement />
</div>
</el-tab-pane>
<el-tab-pane label="医嘱执行">
<div class="execute-wrapper">
<!-- 患者列表 -->
<ExecutePatientList />
<!-- main -->
<ExecuteMedicalOrderManagement />
</div>
</el-tab-pane>
<el-tab-pane label="查询与打印">查询与打印</el-tab-pane>
</el-tabs>
</template>
<script setup lang="ts">
import { onBeforeMount, onMounted, reactive, ref } from 'vue'
import CheckPatientList from './components/check/patientList.vue'
import CheckMedicalOrderManagement from './components/check/MedicalOrderManagement.vue'
import ExecutePatientList from './components/execute/patientList.vue'
import ExecuteMedicalOrderManagement from './components/execute/MedicalOrderManagement.vue'
const transferInDialogVisible = ref(false)
const signEntryDialogVisible = ref(false)
const state = reactive({})
onBeforeMount(() => { })
onMounted(() => {
query()
})
defineExpose({ state })
const allocationData = ref([{}, {}])
const query = () => {
// 查询列表
}
const addSigns = (row: any) => {
// TODO 新增入院体征
signEntryDialogVisible.value = true
}
const selectBed = (row: any) => {
// TODO 选床 入科
transferInDialogVisible.value = true
}
</script>
<style lang="scss" scoped>
.medicalOrderManagement-container {
height: 100%;
width: 100%;
:deep(.el-tabs__content) {
padding: 0;
}
:deep(.el-tab-pane) {
height: 100%;
width: 100%;
}
.check-wrapper {
height: 100%;
width: 100%;
display: flex;
}
.execute-wrapper {
height: 100%;
width: 100%;
display: flex;
}
.patientList-container {
flex: none;
}
}
</style>

View File

@@ -0,0 +1,34 @@
import request from '@/utils/request'
/**
* 获取住院患者列表
*/
export function getPatientList(queryParams) {
return request({
url: '/nurse-station/advice-process/inpatient',
method: 'get',
params: queryParams
})
}
/**
* 获取当前登录人管理病区
*/
export function getWardList(queryParams) {
return request({
url: '/app-common/practitioner-ward',
method: 'get',
params: queryParams
})
}
/**
* 获取当前选中患者全部医嘱
*/
export function getPrescriptionList(queryParams) {
return request({
url: '/nurse-station/advice-process/inpatient-advice',
method: 'get',
params: queryParams
})
}

View File

@@ -0,0 +1,144 @@
<template>
<div>
<div>
<el-input placeholder="住院号/姓名">
<template #append>
<el-button icon="Search" @click="getPatientList" />
</template>
</el-input>
</div>
<el-tree
ref="treeRef"
:load="loadNode"
lazy
show-checkbox
node-key="id"
default-expand-all
:props="{ label: 'name', children: 'children' }"
@node-click="handleNodeClick"
@check="handleCheckChange"
@node-expand="onNodeExpand"
>
<template #default="{ node, data }">
<div class="custom-tree-node" v-if="node.level === 2">
<span>{{ data.bedName + ' / ' + node.label }}</span>
<span class="tree-node-actions">
{{ data.genderEnum_enumText + ' / ' + data.age }}
</span>
</div>
</template>
</el-tree>
</div>
</template>
<script setup>
import { getPatientList, getWardList } from './api';
import { updatePatientInfoList } from '../store/patient';
import { nextTick, onMounted } from 'vue';
const treeRef = ref(null);
const allNodesLoaded = ref(false);
// 树节点加载完成后的回调
function onTreeLoaded() {
if (!allNodesLoaded.value && treeRef.value) {
// 等待DOM更新后设置全选
nextTick(() => {
// 获取所有节点并设置为选中状态
const allNodes = getAllNodes(treeRef.value.store.root.childNodes);
const allKeys = allNodes.map((node) => node.key);
treeRef.value.setCheckedKeys(allKeys, true); // 第二个参数设为true表示级联选中
allNodesLoaded.value = true;
});
}
}
// 递归获取所有节点
function getAllNodes(nodes) {
let result = [];
if (nodes && nodes.length > 0) {
nodes.forEach((node) => {
result.push(node);
if (node.childNodes && node.childNodes.length > 0) {
result = result.concat(getAllNodes(node.childNodes));
}
});
}
return result;
}
function loadNode(node, resolve) {
// 初始加载:获取所有病区(父级节点)
if (node.level === 0) {
getWardList().then((res) => {
// 确保病区节点不是叶子节点
const wards = res.map((ward) => ({
...ward,
leaf: false,
}));
return resolve(wards);
});
}
// 展开病区节点时:获取该病区下的患者列表
else if (node.level === 1) {
const wardId = node.data.id;
getPatientList({ wardId: wardId }).then((res) => {
let children = res.data.records.map((item) => {
return {
leaf: true, // 患者节点为叶子节点
...item,
name: item.patientName,
};
});
return resolve(children);
});
}
// 更深层级直接返回空数组
else {
return resolve([]);
}
}
// 获取所有选中的子节点(叶子节点)
function getCheckedLeafNodes() {
if (!treeRef.value) return [];
// 获取所有选中的节点key
const checkedKeys = treeRef.value.getCheckedKeys();
// 获取所有半选中的节点key父节点
const halfCheckedKeys = treeRef.value.getHalfCheckedKeys();
// 获取所有选中的节点数据
const checkedNodes = treeRef.value.getCheckedNodes();
// 只返回叶子节点(患者节点)
return checkedNodes.filter((node) => node.leaf === true);
}
// 处理节点选中状态变化
function handleCheckChange(data, checked) {
// 可以在这里处理选中状态变化的逻辑
let list = getCheckedLeafNodes();
console.log(list, '2345678');
updatePatientInfoList(list);
}
</script>
<style scoped lang="scss">
.custom-tree-node {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
}
.tree-node-actions {
display: flex;
align-items: center;
}
:deep(.el-tree-node__content) {
height: 35px;
}
</style>

View File

@@ -0,0 +1,216 @@
<template>
<div style="height: calc(100vh - 126px)">
<div
style="
height: 51px;
border-bottom: 2px solid #e4e7ed;
display: flex;
align-items: center;
justify-content: space-between;
"
>
<div>
<el-radio-group v-model="type" class="ml20" @change="handleRadioChange">
<el-radio :label="1">全部</el-radio>
<el-radio :label="2">长期</el-radio>
<el-radio :label="3">临时</el-radio>
</el-radio-group>
<el-button class="ml20" type="primary" plain @click="handleGetPrescription">
查询
</el-button>
</div>
<div>
<span class="descriptions-item-label">全选</span>
<el-switch/>
<el-button class="ml20" type="primary"> 核对通过 </el-button>
<el-button class="ml20 mr20" type="danger"> 退回 </el-button>
</div>
</div>
<div
style="padding: 10px; background-color: #eef9fd; height: 100%; overflow-y: auto"
v-loading="loading"
>
<el-collapse
v-model="activeNames"
expand-icon-position="left"
v-if="prescriptionList.length > 0"
style="
border-bottom: 0px;
border-top: 0px;
border-radius: 0px;
overflow-y: auto;
max-height: calc(100vh - 200px);
"
>
<el-collapse-item
v-for="(item, index) in prescriptionList"
:key="index"
:name="item[0].encounterId"
style="
border: 2px solid #e4e7ed;
border-radius: 8px;
margin-bottom: 10px;
overflow: hidden;
"
>
<template #title>
<span>11202501010101</span>
<span>张先生//20</span>
<span>自费</span>
</template>
<el-table :data="item" border :header-cell-style="{ background: '#eef9fd !important' }">
<el-table-column type="selection" align="center" width="50" />
<el-table-column label="类型" align="center" prop="therapyEnum_enumText" width="80">
<template #default="scope">
<span :style="scope.row.therapyEnum == '1' ? 'color: #a6745c' : 'color: #3787a5'">
{{ scope.row.therapyEnum_enumText }}
</span>
</template>
</el-table-column>
<el-table-column label="医嘱内容" prop="adviceName" />
<el-table-column label="开始/终止" prop="requestTime" width="230" />
<el-table-column label="预计执行" prop="times">
<template #default="scope">
<div
v-for="(item, timeIndex) in scope.row.times"
:key="timeIndex"
style="padding-bottom: 5px"
>
<span>{{ item }}</span>
<el-checkbox-group
v-model="scope.row.checkedRates[timeIndex]"
style="display: inline-block; margin-left: 15px"
>
<el-checkbox
v-for="(rateItem, rateIndex) in scope.row.rate"
:key="rateIndex"
:value="rateItem"
border
size="small"
style="margin-right: 15px"
>
{{ rateItem }}
</el-checkbox>
</el-checkbox-group>
</div>
</template>
</el-table-column>
</el-table>
</el-collapse-item>
</el-collapse>
<el-empty v-else description="点击查询获取患者医嘱信息"></el-empty>
</div>
</div>
</template>
<script setup>
import { getPrescriptionList } from './api';
import { patientInfoList } from '../store/patient.js';
import { formatDate, formatDateStr } from '@/utils/index';
const activeNames = ref([]);
const prescriptionList = ref([]);
const deadline = ref(formatDateStr(new Date(), 'YYYY-MM-DD') + ' 23:59:59');
const type = ref(1);
const { proxy } = getCurrentInstance();
const loading = ref(false);
function handleGetPrescription() {
if (patientInfoList.value.length > 0) {
loading.value = true;
let encounterIds = patientInfoList.value.map((i) => i.encounterId).join(',');
getPrescriptionList({ encounterIds: encounterIds, pageSize: 10000, pageNo: 1 }).then((res) => {
// try {
// 根据encounterId分组
const groupedPrescriptions = res.data.records.reduce((groups, prescription) => {
// 获取当前医嘱全部执行频次
let rate = prescription.dayTimes?.split(',');
let times = getDateRange(prescription.requestTime, deadline.value);
prescription.times = times;
prescription.rate = rate;
// 添加复选框状态管理
prescription.checkedRates = {};
if (rate) {
times.forEach((time, index) => {
// 默认选中所有执行频次
prescription.checkedRates[index] = [...rate];
});
}
const encounterId = prescription.encounterId;
if (!groups[encounterId]) {
groups[encounterId] = [];
}
if (!activeNames.value.includes(encounterId)) {
activeNames.value.push(encounterId);
}
groups[encounterId].push(prescription);
return groups;
}, {});
// 将分组结果转换为数组形式
prescriptionList.value = Object.values(groupedPrescriptions);
console.log(prescriptionList.value, '1111');
loading.value = false;
// } catch {
// loading.value = false;
// }
});
} else {
proxy.$message.warning('请选择患者');
}
}
/**
* 计算两个日期之间的所有日期(包含起始和结束日期)
* @param {string|Date} startDate - 开始日期
* @param {string|Date} endDate - 结束日期
* @returns {Array<string>} 格式为MM-DD的日期数组
*/
function getDateRange(startDate, endDate) {
const start = new Date(startDate);
const end = new Date(endDate);
// 重置时间部分,只保留日期
start.setHours(0, 0, 0, 0);
end.setHours(0, 0, 0, 0);
const dates = [];
const current = new Date(start);
// 循环添加日期直到结束日期
while (current <= end) {
// 格式化为MM-DD
const month = String(current.getMonth() + 1).padStart(2, '0');
const day = String(current.getDate()).padStart(2, '0');
dates.push(`${month}-${day}`);
// 移动到下一天
current.setDate(current.getDate() + 1);
}
return dates;
}
// 处理后端返回的时间集合
function handleTime() {}
</script>
<style scoped>
.el-collapse-icon-position-left :deep(.el-collapse-item__header) {
padding: 10px;
}
:deep(.el-collapse-item__wrap) {
padding: 10px;
}
/* 表头背景色 */
:deep(.prescription-table .el-table__header th) {
background-color: #eef9fd !important;
}
:deep(.el-table__row:hover > td) {
background-color: #eef9fd !important;
}
</style>

View File

@@ -0,0 +1,74 @@
<template>
<div style="display: flex; justify-content: space-between">
<div style="width: 20%; height: 90vh; border-right: solid 2px #e4e7ed">
<div
style="
height: 40px;
display: flex;
align-items: center;
justify-content: flex-end;
border-bottom: solid 2px #e4e7ed;
"
>
<el-icon
@click="refresh"
class="refresh-icon"
style="cursor: pointer; font-size: 20px; margin-right: 10px"
>
<Refresh />
</el-icon>
</div>
<el-tabs v-model="active" class="demo-tabs centered-tabs tab-header" @tab-click="handleClick">
<el-tab-pane label="在科" name="first" style="padding: 15px 10px">
<PatientList />
</el-tab-pane>
<el-tab-pane label="转科" name="second" style="padding: 0 10px">
<PatientList />
</el-tab-pane>
</el-tabs>
</div>
<div style="width: 100%">
<el-tabs v-model="activeName" class="demo-tabs centered-tabs" @tab-click="handleClick">
<el-tab-pane label="未校对" name="first">
<PrescriptionList />
</el-tab-pane>
<el-tab-pane label="已校对" name="second">Config</el-tab-pane>
<el-tab-pane label="已停止" name="third">Role</el-tab-pane>
<el-tab-pane label="已作废" name="fourth">Task</el-tab-pane>
</el-tabs>
</div>
</div>
</template>
<script setup>
import PatientList from './components/patientList.vue';
import PrescriptionList from './components/prescriptionList.vue';
const activeName = ref('first');
const active = ref('first');
</script>
<style scoped>
.centered-tabs :deep(.el-tabs__nav-wrap) {
display: flex;
justify-content: center;
}
.centered-tabs :deep(.el-tabs__nav-scroll) {
display: flex;
justify-content: center;
}
.tab-header :deep(.el-tabs__item){
height: 50px !important
}
.centered-tabs :deep(.el-tabs__nav) {
display: flex;
justify-content: center;
}
:deep(.el-tabs__header){
margin: 0;
}
</style>

View File

@@ -0,0 +1,12 @@
// 选择患者信息
export const patientInfo = ref()
export function updatePatientInfo(info) {
patientInfo.value = info
}
// 多选患者
export const patientInfoList = ref([])
export function updatePatientInfoList(info) {
patientInfoList.value = info
}

View File

@@ -0,0 +1,419 @@
<template>
<div>
<el-dialog
:title="title"
v-model="props.open"
width="1400px"
append-to-body
destroy-on-close
@close="close"
>
<div style="display: flex; justify-content: space-between; width: 100%">
<div style="width: 40%">
<el-row :gutter="24">
<el-col :span="24" :xs="24">
<el-input
v-model="searchKey"
placeholder="模板名称"
clearable
style="width: 100%; margin-bottom: 10px"
@keyup.enter="getTemplateListInfo"
>
<template #append>
<el-button icon="Search" @click="getTemplateListInfo" />
</template>
</el-input>
<el-button size="default" type="primary" @click="openTemplateDialog"
>新增模板</el-button
>
<el-button type="danger" plain @click="deleteTemplate()" :disabled="false">
删除
</el-button>
<el-table
ref="patientListRef"
height="680"
:data="templateList"
row-key="id"
highlight-current-row
@row-click="setTemplate"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" />
<el-table-column prop="templateName" label="模板名称" width="180" />
<el-table-column prop="contextJson" label="模板内容" width="80" />
<el-table-column prop="useScopeCodeText" label="使用范围" width="80" />
<el-table-column label="操作" min-width="150" fixed="right">
<template #default="scope">
<el-button
link
type="primary"
icon="Edit"
@click="handleEditTemplate(scope.row)"
>编辑</el-button
>
</template>
</el-table-column>
</el-table>
<pagination
v-show="templateTotal > 0"
:total="templateTotal"
v-model:page="templateQueryParams.pageNo"
v-model:limit="templateQueryParams.pageSize"
@pagination="getTemplateListInfo"
style="margin-bottom: 20px"
/>
</el-col>
</el-row>
</div>
<div
style="display: flex; justify-content: space-between; width: 69%"
class="app-container"
>
<el-form ref="formRef" :model="form" label-width="100px">
<el-form-item class="changeMajorFromItem" label-width="100px" label="记录时间:">
<el-date-picker
v-model="form.recordingTime"
type="datetime"
placeholder="选择日期"
style="width: 30%"
value-format="YYYY-MM-DD HH:mm:ss"
/>
</el-form-item>
<el-form-item label="生命体征:" class="changeMajorFromItem" />
<el-form-item class="changeMajorFromItem" label-width="10px">
<el-row :span="24">
<!-- 第一个表单项 -->
<el-col :span="5">
<el-form-item label="体温:" prop="tw" label-width="80px">
<el-input v-model="form.tw" style="width: 80%" />
</el-form-item>
</el-col>
<!-- 第二个表单项 -->
<el-col :span="5">
<el-form-item label="脉搏:" prop="mb" label-width="80px">
<el-input v-model="form.mb" style="width: 80%" />
</el-form-item>
</el-col>
<!-- 第三个表单项 -->
<el-col :span="5">
<el-form-item label="呼吸:" prop="hx" label-width="80px">
<el-input v-model="form.hx" style="width: 80%" />
</el-form-item>
</el-col>
<!-- 第四个表单项 -->
<el-col :span="9">
<el-form-item label="血压:" prop="bloodPressure" label-width="80px">
<div class="xy-container" style="display: flex; align-items: center">
<el-input v-model="form.systolicBloodPressure" style="width: 25%" />
<span>/</span>
<el-input v-model="form.diastolicBloodPressure" style="width: 25%" />
(/)mmHg
</div>
</el-form-item>
</el-col>
<!-- 第一个表单项 -->
<el-col :span="5" style="margin-top: 10px">
<el-form-item label="心率:" prop="xl" label-width="80px">
<el-input v-model="form.xl" style="width: 80%" />
</el-form-item>
</el-col>
<!-- 第二个表单项 -->
<el-col :span="5" style="margin-top: 10px">
<el-form-item label="血氧:" prop="xy" label-width="80px">
<el-input v-model="form.xy" style="width: 80%" />
</el-form-item>
</el-col>
<!-- 第五个表单项 -->
<el-col :span="4" style="margin-top: 10px">
<el-form-item style="margin-left: 20px">
<el-checkbox
v-model="form.vitalSignsSyncFlag"
label="同步到体征表"
name="SYP"
/>
<!-- @change="checkTimeValidity" -->
</el-form-item>
</el-col>
</el-row>
</el-form-item>
<el-form-item
label="病情观察与护理记录:"
label-width="90px"
class="changeMajorFromItem"
prop="column081"
>
<el-input
v-model="form.bqgcOther"
type="textarea"
:rows="8"
:autosize="{ minRows: 3, maxRows: 8 }"
class="el-textarea"
style="width: 95%"
/>
</el-form-item>
</el-form>
</div>
</div>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submit">保存</el-button>
<el-button @click="close"> </el-button>
</div>
</template>
</el-dialog>
<record-template
ref="recordRemplateDialogRef"
:open="openRecordTemplate"
:patientId="patientId"
:editData="editData"
:recordTitle="recordTitle"
@close="closeRecordTemplateDialog"
/>
</div>
</template>
<script setup>
import recordTemplate from './recordTemplate.vue';
import { ref, nextTick } from 'vue';
import { saveRecord, updateRecord, getRecordTemplateList, deleteRecordTemplate } from './api';
const { proxy } = getCurrentInstance();
const props = defineProps({
open: {
type: Boolean,
default: false,
},
title: {
type: String,
default: '',
},
patientId: {
type: String,
default: '',
},
patientInfo: {
type: Object,
default: () => {},
},
editData: {
type: Object,
default: () => {},
},
});
const searchKey = ref('');
const emit = defineEmits(['close']);
const templateQueryParams = ref({
pageNum: 1,
pageSize: 10,
searchKey: undefined, // 患者id
});
const templateTotal = ref(0);
const templateList = ref([]);
const patientInfo = ref({});
const form = ref({});
const templateIds = ref([]);
const single = ref(true);
const multiple = ref(true);
const editData = ref({});
const title = ref('');
const recordTitle = ref('');
const openRecordTemplate = ref(false);
/**
* 取得患者信息详细
*/
function show() {
patientInfo.value = props.patientInfo;
console.log(props, 'props', props.patientInfo);
reset();
title.value = '';
title.value = props.title;
if (title.value === '编辑') {
form.value = props.editData.content;
}
console.log(props, 'props', title.value);
getTemplateListInfo();
}
/** 选择删除模板条数 */
function handleSelectionChange(selection) {
console.log(selection, '选择条数');
templateIds.value = selection.map((item) => item.id);
console.log(templateIds.value, '选择条数');
single.value = selection.length != 1;
multiple.value = !selection.length;
}
/**
* 模板列表
*/
function getTemplateListInfo() {
console.log(searchKey.value, '搜索关键字');
templateQueryParams.value.searchKey = searchKey.value;
getRecordTemplateList(templateQueryParams.value).then((res) => {
console.log('模板列表', res);
templateList.value = res.data.records;
templateTotal.value = res.data.total;
});
}
/**
* 删除模板
*
* @param index - 要删除的处方在列表中的索引
*/
function deleteTemplate(index) {
console.log(templateIds.value, '删除记录单模板');
if (templateIds.value.length == 0) {
proxy.$modal.msgWarning('请选择要删除的数据信息!');
return;
}
proxy.$modal
.confirm('是否确认删除以上数据!')
.then(function () {
return deleteRecordTemplate(templateIds.value);
})
.then(() => {
getTemplateListInfo();
proxy.$modal.msgSuccess('删除成功');
})
.catch(() => {});
}
function close() {
reset();
emit('close');
}
/** 重置操作表单 */
function reset() {
form.value = {
tw: undefined,
mb: undefined,
hx: undefined,
systolicBloodPressure: undefined,
diastolicBloodPressure: undefined,
xl: undefined,
xy: undefined,
vitalSignsSyncFlag: false,
bqgc: undefined,
bqgcOther: undefined,
};
proxy.resetForm('formRef');
}
/**
* 保存记录单
*/
function submit() {
if (title.value === '新增') {
const insertParam = {
encounterId: props.patientInfo.encounterId,
patientId: props.patientInfo.patientId,
orgId: props.patientInfo.orgId,
recordingTime: form.value.recordingTime,
vitalSignsSyncFlag: form.value.vitalSignsSyncFlag ? form.value.vitalSignsSyncFlag : false,
contextJson: JSON.stringify(form.value),
};
console.log(insertParam, 'insertParam');
saveRecord(insertParam).then((res) => {
if (res.code == 200) {
emit('close', 'success');
reset();
}
});
} else {
const updateParamParam = {
recordId: props.editData.recordId,
encounterId: props.patientInfo.encounterId,
patientId: props.patientInfo.patientId,
orgId: props.patientInfo.orgId,
recordingTime: form.value.recordingTime,
vitalSignsSyncFlag: form.value.vitalSignsSyncFlag ? form.value.vitalSignsSyncFlag : false,
contextJson: JSON.stringify(form.value),
};
console.log(updateParamParam, 'updateParamParam');
updateRecord(updateParamParam).then((res) => {
if (res.code == 200) {
emit('close', 'success');
reset();
}
});
}
}
/**
* 设定病情观测
*/
function setTemplate(row) {
console.log(row, '设定病情观测');
form.value.bqgcOther = row.contextJson;
}
/**
* 新增护理模板
*/
function openTemplateDialog() {
recordTitle.value = '新增模板';
openRecordTemplate.value = true;
nextTick(() => {
proxy.$refs['recordRemplateDialogRef'].show();
});
}
/**
* 编辑护理模板
*/
function handleEditTemplate(row) {
recordTitle.value = '编辑模板';
openRecordTemplate.value = true;
editData.value = row;
nextTick(() => {
proxy.$refs['recordRemplateDialogRef'].show();
});
}
/**
* 关闭记录模板对话框
*
* 该函数用于关闭记录模板对话框。
*/
function closeRecordTemplateDialog(str) {
openRecordTemplate.value = false;
getTemplateListInfo();
if (str === 'success') {
proxy.$modal.msgSuccess('操作成功!');
}
}
defineExpose({
show,
});
</script>
<style scoped>
:deep(.pagination-container .el-pagination) {
right: 20px !important;
}
.input-select-container {
display: flex;
justify-content: space-between;
align-items: center;
}
.input-select-container .el-input__inner,
.input-select-container .el-select {
width: 100%;
}
.flex-container {
display: flex;
align-items: center; /* 垂直居中对齐 */
justify-content: flex-start; /* 水平起始对齐 */
gap: 8px; /* 两个输入框之间的间距 */
}
.flex-container label {
margin: 0 8px; /* 标签的间距 */
}
</style>

View File

@@ -0,0 +1,113 @@
import request from '@/utils/request'
/**
* 获取患者列表
*
* @param query 查询参数对象,可以包含多个查询条件
* @returns Promise<any> 返回一个Promise对象解析后得到患者列表数据
*/
export function listPatient(query) {
return request({
url: '/nursing-record/patient-page',
method: 'get',
params: query
})
}
/**
* 获取患者记录单
*
* @param query 查询参数对象,可以包含多个查询条件
* @returns Promise<any> 返回一个Promise对象解析后得到患者列表数据
*/
export function getNursingPatientPage(query) {
return request({
url: '/nursing-record/nursing-patient-page',
method: 'get',
params: query
})
}
/**
* 新增记录单信息
*
*/
export function saveRecord(data) {
return request({
url: '/nursing-record/save-nursing',
method: 'post',
data: data
})
}
/**
* 保存记录单信息
*
*/
export function updateRecord(data) {
return request({
url: '/nursing-record/update-nursing',
method: 'post',
data: data
})
}
/**
* 删除记录单
*/
export function delRecord(data) {
return request({
url: '/nursing-record/delete-nursing',
method: 'post',
data: data
})
}
/**
*获取记录单模板列表
*
* @param query 查询参数对象,可以包含多个查询条件
* @returns Promise<any> 返回一个Promise对象解析后得到患者列表数据
*/
export function getRecordTemplateList(query) {
return request({
url: '/nursing-record/emr-template-page',
method: 'get',
params: query
})
}
/**
* 新增记录单模板
*
*/
export function saveRecordTemplate(data) {
return request({
url: '/nursing-record/emr-template-save',
method: 'post',
data: data
})
}
/**
* 保存记录单模板
*
*/
export function updateRecordTemplate(data) {
return request({
url: '/nursing-record/emr-template-update',
method: 'post',
data: data
})
}
/**
* 删除记录单模板
*/
export function deleteRecordTemplate(data) {
return request({
url: '/nursing-record/emr-template-del',
method: 'post',
data: data
})
}

View File

@@ -0,0 +1,146 @@
<template>
<el-dialog
:title="props.recordTitle"
v-model="props.open"
width="800px"
append-to-body
destroy-on-close
@close="close"
>
<div>
<span> 模板名称 </span>
<el-input v-model="templateName" style="width: 260px; margin-top: 10px; margin-right: 20px" />
<el-radio-group v-model="radio">
<el-radio-button :label="1">个人</el-radio-button>
<el-radio-button :label="2">科室</el-radio-button>
<el-radio-button :label="3">全院</el-radio-button>
</el-radio-group>
</div>
<div style="display: flex">
<span> 模板内容 </span>
<el-input
v-model="contextJson"
type="textarea"
:rows="8"
:autosize="{ minRows: 3, maxRows: 8 }"
class="el-textarea"
style="width: 80%; margin-top: 10px; margin-right: 20px"
/>
</div>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submit"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { parse } from 'vue/compiler-sfc';
import { saveRecordTemplate, updateRecordTemplate } from './api';
import useUserStore from '@/store/modules/user';
const title = ref('');
const templateName = ref('');
const radio = ref(1);
const contextJson = ref('');
const userStore = useUserStore();
const emits = defineEmits(['close']);
const props = defineProps({
open: {
type: Boolean,
required: true,
},
recordTitle: {
type: String,
default: '',
},
editData: {
type: Object,
default: () => {},
},
});
/**
* 取得患者信息详细
*/
function show() {
console.log(props.recordTitle, 'props.recordTitle', props.editData, 'props.editData');
title.value = '';
title.value = props.recordTitle;
reset();
if (title.value === '编辑模板') {
console.log(typeof props.editData.useScopeCode, 'props.editData',props.editData.useScopeCode);
templateName.value = props.editData.templateName;
contextJson.value = props.editData.contextJson;
radio.value = +props.editData.useScopeCode;
}
}
/**
* 弹窗确认操作,保存模板
*/
function submit() {
console.log(title.value, 'title');
if (title.value === '新增模板') {
const insertParam = {
templateName: templateName.value,
templateTypeCode: '1',
useScopeCode: radio.value,
contextJson: contextJson.value,
};
if (radio.value == 1) {
insertParam.userId = userStore.id;
} else if (radio.value == 2) {
insertParam.userId = userStore.orgId;
} else {
insertParam.userId = '';
}
console.log(insertParam, 'insertParam');
saveRecordTemplate(insertParam).then((res) => {
if (res.code == 200) {
emits('close', 'success');
reset();
}
});
} else {
const updateParamParam = {
id: props.editData.id,
templateName: templateName.value,
templateTypeCode: '1',
useScopeCode: radio.value,
contextJson: contextJson.value,
};
if (radio.value == 1) {
updateParamParam.userId = userStore.id;
} else if (radio.value == 2) {
updateParamParam.userId = userStore.orgId;
} else {
updateParamParam.userId = '';
}
console.log(updateParamParam, 'updateParamParam');
updateRecordTemplate(updateParamParam).then((res) => {
if (res.code == 200) {
emits('close', 'success');
reset();
}
});
}
}
function close() {
emits('close');
}
function reset() {
templateName.value = '';
contextJson.value = '';
radio.value = 1;
}
defineExpose({
show,
});
</script>

View File

@@ -0,0 +1,343 @@
<template>
<div class="business-temperature" style="display: flex; justify-content: space-evenly">
<el-card style="width: 35%">
<template #header>
<span style="vertical-align: middle">患者列表</span>
</template>
<div style="width: 100%">
<el-input
v-model="queryParams.searchKey"
placeholder="请输入患者名/病历号"
clearable
style="width: 48%; margin-bottom: 10px; margin-right: 10px"
@keyup.enter="getPatientListInfo"
>
</el-input>
<el-button type="primary" style="margin-bottom: 10px" @click="getPatientListInfo">
搜索
</el-button>
<el-table
ref="patientListRef"
height="672"
:data="patientList"
row-key="encounterId"
@row-click="viewPatient"
highlight-current-row
>
<el-table-column prop="bedLocationId_dictText" label="床号" min-width="50" />
<el-table-column label="病历号" align="center" prop="patientBusNo" />
<el-table-column label="姓名" align="center" prop="patientName" />
<el-table-column label="性别" align="center" prop="genderEnum_enumText" />
<el-table-column label="年龄" align="center" prop="ageString" />
</el-table>
<pagination
v-show="total > 0"
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getPatientListInfo"
style="margin-bottom: 20px"
/>
</div>
</el-card>
<el-card style="width: 60%">
<template #header>
<span style="vertical-align: middle">护理记录</span>
</template>
<div style="width: 100%">
<div style="width: 100%">
<el-date-picker
v-model="recordingTime"
type="daterange"
range-separator="~"
start-placeholder="开始时间"
end-placeholder="结束时间"
placement="bottom"
value-format="YYYY-MM-DD"
style="width: 64%; margin-bottom: 10px; margin-right: 10px"
/>
<el-button type="primary" style="margin-bottom: 10px" @click="viewPatient(patientData)">
搜索
</el-button>
</div>
<div style="margin-bottom: 10px">
<el-button size="default" type="primary" @click="openAddTprDialog">新增</el-button>
<el-button type="danger" plain @click="deletePrescription()" :disabled="false">
删除
</el-button>
</div>
<el-table
ref="patientListRef"
height="680"
:data="recordList"
row-key="recordId"
highlight-current-row
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" />
<el-table-column prop="content.recordingTime" label="记录时间" width="180" />
<el-table-column prop="content.tw" label="体温" width="80" />
<el-table-column prop="content.systolicBloodPressure" label="收缩压" min-width="80" />
<el-table-column prop="content.diastolicBloodPressure" label="舒张压" width="80" />
<el-table-column prop="content.xl" label="心率" min-width="120" />
<el-table-column prop="content.mb" label="脉搏" width="80" />
<el-table-column prop="content.hx" label="呼吸" min-width="120" />
<el-table-column prop="content.xy" label="血氧" width="80" />
<el-table-column prop="content.bqgcOther" label="病情观察与护理记录" min-width="80" />
<el-table-column label="操作" min-width="150" fixed="right">
<template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleEdit(scope.row)"
>编辑</el-button
>
</template>
</el-table-column>
</el-table>
<pagination
v-show="recordsTotal > 0"
:total="recordsTotal"
v-model:page="recordQueryParams.pageNo"
v-model:limit="recordQueryParams.pageSize"
@pagination="viewPatient(patientData)"
style="margin-bottom: 20px"
/>
</div>
</el-card>
<add-nursing-record-dialog
ref="addNursingRecordDialogRef"
:open="openAddTpr"
:patientId="patientId"
:patientInfo="patientData"
:editData="editData"
:title="title"
@close="closePatientDetialDialog"
/>
<!-- </div> -->
</div>
</template>
<script setup>
import addNursingRecordDialog from './components/addNursingRecordDialog.vue';
import { listPatient, getNursingPatientPage, delRecord } from './components/api';
import useUserStore from '@/store/modules/user';
const userStore = useUserStore();
// 响应式数据
const patientId = ref('');
const data = ref(undefined);
const openAddTpr = ref(false);
const total = ref(0);
const recordsTotal = ref(0);
const recordList = ref([]);
const contextJson = ref(undefined);
const editData = ref({});
const { proxy } = getCurrentInstance();
const print = ref(null);
const queryParams = ref({
pageNo: 1,
pageSize: 10,
searchKey: undefined,
orgId: userStore.orgId,
});
const recordQueryParams = ref({
pageNo: 1,
pageSize: 10,
});
const patientData = ref({});
const recordingTime = ref([
// formatDateStr(new Date(), 'YYYY-MM-DD'),
// formatDateStr(new Date(), 'YYYY-MM-DD'),
]);
const title = ref('');
const patientList = ref([]);
const addNursingRecordDialogRef = ref(null);
const selectedData = ref([]);
const ids = ref([]); // 存储选择的药品信息行数据
const single = ref(true);
const multiple = ref(true);
getPatientListInfo();
/**
* 患者列表
*/
function getPatientListInfo() {
listPatient(queryParams.value).then((res) => {
console.log(userStore, 'userStore', res);
patientList.value = res.data.records;
total.value = res.data.total;
});
}
/**
* 查看患者护理记录单
*
* @param row 患者数据对象
*/
function viewPatient(row) {
patientData.value = row;
patientData.value.orgId = userStore.orgId;
// recordQueryParams
recordQueryParams.value.encounterId = row.encounterId;
if (recordingTime.value.length > 0) {
recordQueryParams.value.recordingTimeSTime = recordingTime.value[0] + ' 00:00:00';
recordQueryParams.value.recordingTimeETime = recordingTime.value[1] + ' 23:59:59';
} else {
recordQueryParams.value.recordingTimeSTime = undefined;
recordQueryParams.value.recordingTimeETime = undefined;
}
recordList.value = [];
getNursingPatientPage(recordQueryParams.value).then((response) => {
recordList.value = [];
// recordList.value = res.data.records;
if (response.data && response.data.records.length > 0) {
for (let i = 0; i < response.data.records.length; i++) {
console.log(
typeof response.data.records[i].contextJson,
'typeofcontextJson',
response.data.records[i]
);
if (typeof response.data.records[i].contextJson === 'string') {
console.log('Parsing string...');
try {
contextJson.value = JSON.parse(response.data.records[i].contextJson);
} catch (error) {
console.error('Parsing error:', error);
}
} else {
contextJson.value = response.data.records[i].contextJson; // 如果已经是对象
}
contextJson.value.recordTime = contextJson.value.recordTime
? moment(contextJson.value.recordTime).format('YYYY-MM-DD HH:mm:ss')
: '';
const tableItems = {
content: contextJson.value,
recordId: response.data.records[i].recordId,
patientId: response.data.records[i].patientId,
encounterId: response.data.records[i].encounterId,
recordingTime: response.data.records[i].recordingTime,
};
recordList.value.push(tableItems);
}
} else {
recordList.value = [];
}
console.log(recordList.value, 'recordList');
recordsTotal.value = response.data.total;
});
console.log('查看患者体温单', row);
proxy.$refs.addNursingRecordDialogRef.show(row);
}
/**
* 打开体征录入
*/
function openAddTprDialog() {
if (!patientData.value.patientId) {
proxy.$modal.msgError('请先选择患者!');
return;
}
title.value = '新增';
openAddTpr.value = true;
nextTick(() => {
proxy.$refs['addNursingRecordDialogRef'].show();
});
console.log(openAddTpr.value, '打开体征录入对话框');
}
/**
* 关闭新增体征弹窗
*/
function closePatientDetialDialog(str) {
openAddTpr.value = false;
viewPatient(patientData.value);
if (str === 'success') {
proxy.$modal.msgSuccess('操作成功!');
}
}
/** 选择条数 */
function handleSelectionChange(selection) {
console.log(selection, '选择条数');
selectedData.value = selection.map((item) => ({ ...item })); // 存储选择的行数据
ids.value = selection.map((item) => item.recordId);
console.log(ids.value, '选择条数');
single.value = selection.length != 1;
multiple.value = !selection.length;
}
/**
* 编辑护理记录
*/
function handleEdit(row) {
title.value = '编辑';
openAddTpr.value = true;
editData.value = row;
nextTick(() => {
proxy.$refs['addNursingRecordDialogRef'].show();
});
console.log(openAddTpr.value, '打开体征录入对话框');
}
/**
* 删除记录单
*
* @param index - 要删除的处方在列表中的索引
*/
function deletePrescription(index) {
console.log(selectedData.value, '删除记录单');
if (selectedData.value.length == 0) {
proxy.$modal.msgWarning('请选择要删除的数据信息!');
return;
}
console.log('deletePrescription删除', data);
proxy.$modal
.confirm('是否确认删除以上数据!')
.then(function () {
return delRecord(selectedData.value);
})
.then(() => {
viewPatient(patientData.value);
proxy.$modal.msgSuccess('删除成功');
})
.catch(() => {});
}
</script>
<style lang="scss" scoped>
.business-temperature {
grid-template-columns: 100%;
background-color: white;
}
::v-deep .business-temperature .el-icon-arrow-down {
font-size: 12px;
}
.business1 {
background: white;
padding: 10px 16px;
border-radius: 6px;
height: 40%;
justify-content: center;
}
.layui-form-label {
line-height: 35px;
text-align: right;
padding-right: 10px;
}
.layui-input-inline {
display: inline-block;
}
.business-temperature-sheet {
display: grid;
grid-template-columns: 59px 1px 780px;
}
::v-deep .business-temperature-sheet .el-icon-arrow-down {
font-size: 12px;
}
</style>

View File

@@ -0,0 +1,948 @@
<template>
<el-dialog
title="患者详情"
v-model="props.open"
width="1700px"
append-to-body
destroy-on-close
@close="close"
>
<div style="display: flex; justify-content: space-between" class="app-container">
<div style="width: 50%">
<el-card style="margin-bottom: 20px">
<template #header>
<span style="vertical-align: middle">基本信息</span>
</template>
<el-row :gutter="24">
<el-col :span="8">
<span>姓名:{{ patientInfo.patientName }}</span>
</el-col>
<el-col :span="8">
<span>性别:{{ patientInfo.genderEnum_enumText }}</span>
</el-col>
<el-col :span="8">
<span>年龄:{{ patientInfo.ageString }}</span>
</el-col>
</el-row>
</el-card>
<el-card>
<template #header>
<span style="vertical-align: middle">体征信息</span>
</template>
<div style="width: 100%">
<div style="width: 100%">
<el-date-picker
v-model="receptionTime"
type="daterange"
range-separator="~"
start-placeholder="开始时间"
end-placeholder="结束时间"
placement="bottom"
value-format="YYYY-MM-DD"
style="width: 84%; margin-bottom: 10px; margin-right: 10px"
/>
<el-button type="primary" style="margin-bottom: 10px" @click="getPatientList">
搜索
</el-button>
</div>
<div style="margin-bottom: 10px">
<el-button type="primary" @click="confirmCharge()" :disabled="buttonDisabled">
保存
</el-button>
<el-button type="primary" plain @click="handleReadCard('01')" style="width: 65px">
修改
</el-button>
<el-button
type="primary"
plain
@click="handleReadCard('02')"
style="width: 65px"
:disabled="true"
>
删除
</el-button>
</div>
<el-table
ref="patientListRef"
max-height="650"
:data="patientList"
row-key="encounterId"
@cell-click="clickRow"
highlight-current-row
>
<el-table-column type="selection" :selectable="checkSelectable" width="55" />
<el-table-column prop="busNo" label="体温" width="80" />
<el-table-column prop="statusEnum_enumText" label="收缩压" min-width="120" />
<el-table-column prop="busNo" label="舒张压" width="80" />
<el-table-column prop="statusEnum_enumText" label="心率" min-width="120" />
<el-table-column prop="busNo" label="脉搏" width="80" />
<el-table-column prop="statusEnum_enumText" label="呼吸" min-width="120" />
<el-table-column prop="busNo" label="血氧" width="80" />
<el-table-column prop="statusEnum_enumText" label="动脉压" min-width="120" />
<el-table-column prop="busNo" label="血糖" width="80" />
<el-table-column prop="statusEnum_enumText" label="物理降温" min-width="120" />
<el-table-column prop="busNo" label="左瞳孔(光)" width="80" />
<el-table-column prop="statusEnum_enumText" label="右瞳孔(光)" min-width="120" />
<el-table-column prop="busNo" label="CCU心率" width="280" />
<el-table-column prop="statusEnum_enumText" label="左瞳孔(大小)" min-width="120" />
<el-table-column prop="busNo" label="右瞳孔(大小)" width="280" />
<el-table-column prop="statusEnum_enumText" label="意识" min-width="120" />
<el-table-column prop="busNo" label="新生儿箱温" width="280" />
<el-table-column prop="statusEnum_enumText" label="血酮" min-width="120" />
<el-table-column prop="busNo" label="体重" width="280" />
<el-table-column prop="statusEnum_enumText" label="身高" min-width="120" />
<el-table-column prop="busNo" label="腹围" width="280" />
<el-table-column prop="statusEnum_enumText" label="大便次数" min-width="120" />
<el-table-column prop="busNo" label="灌肠次数" width="280" />
<el-table-column prop="statusEnum_enumText" label="灌肠后大便次数" min-width="120" />
<el-table-column prop="busNo" label="出量" width="280" />
<el-table-column prop="statusEnum_enumText" label="入量" min-width="120" />
<el-table-column prop="statusEnum_enumText" label="尿量" min-width="120" />
<el-table-column prop="busNo" label="大便量" width="280" />
<el-table-column label="操作" min-width="150" fixed="right">
<!-- <template #default="scope"> -->
<template>
<el-button link type="primary" size="small">保存</el-button>
</template>
</el-table-column>
</el-table>
</div>
</el-card>
</div>
<div style="width: 49%">
<el-card>
<template #header>
<span style="vertical-align: middle">体征录入</span>
</template>
<div style="margin-bottom: 10px">
<el-button type="primary" @click="confirmCharge()" :disabled="buttonDisabled">
保存
</el-button>
</div>
<el-form ref="dynamicForm" :model="formData" label-width="100px" :rules="formRules">
<div class="page-bottom">
<el-row :gutter="24">
<el-col :span="8">
<el-form-item style="margin-top: 15px" label="录入时间">
<div class="input-time-inline">
<el-select
v-model="formData.timePoint"
clearable
size="small"
placeholder=""
>
<el-option
v-for="item in InputOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
</el-form-item>
</el-col>
<!-- <el-col :span="3">
<el-form-item style="margin-top: 15px">
<div v-if="formData.id === '' || formData.id === undefined">
<el-button
size="small"
type="primary"
style="margin-left: 20px"
@click="handleAdd"
:disabled="buttonDisabled"
>新增</el-button
>
</div>
<div v-else>
<el-button
size="small"
type="primary"
style="margin-left: 20px"
@click="handleUpdate"
:disabled="buttonDisabled"
>保存</el-button
>
</div>
</el-form-item>
</el-col> -->
</el-row>
<el-row :gutter="24">
<el-col :span="8">
<el-form-item prop="temperature" label="体温">
<div class="input-select-container">
<el-input
v-model="formData.temperature"
size="small"
@keydown="onKeyDown('0', '0', $event)"
:ref="`input-0-0`"
style="width: 80%"
/>
<el-select
v-model="formData.column133"
clearable
size="small"
placeholder=""
@change="
handlechangedict(bodyTemperatureList, formData.column133, 'column009')
"
>
<el-option
v-for="item in bodyTemperatureList"
:key="item.code"
:label="item.display"
:value="item.code"
/>
</el-select>
</div>
</el-form-item>
</el-col>
<el-col :span="14">
<div class="flex-container">
<el-form-item prop="bloodPressure" label="血压">
<div class="flex-container">
<el-input
prop="lowBloodPressure"
v-model="formData.date"
style="width: 90px"
size="small"
@keydown="onKeyDown('1', '1', $event)"
:ref="`input-1-1`"
/>
<label>/</label>
<el-input
prop="HighBloodPressure"
v-model="formData.times"
style="width: 90px"
size="small"
@keydown="onKeyDown('1', '2', $event)"
:ref="`input-1-2`"
/>
</div>
<el-select
v-model="formData.column134"
size="small"
style="width: 100px"
clearable
placeholder=""
@change="
handlechangedict(
bloodPressureList,
formData.column134,
'column012',
'column013'
)
"
>
<el-option
v-for="item in bloodPressureList"
:key="item.code"
:label="item.display"
:value="item.code"
/>
</el-select>
</el-form-item>
</div>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="8">
<el-form-item prop="heartRate" label="心率">
<el-input
v-model="formData.heartRate"
size="small"
@keydown="onKeyDown('1', '0', $event)"
:ref="`input-1-0`"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item prop="pulseRate" label="脉搏">
<el-input
v-model="formData.pulseRate"
size="small"
@keydown="onKeyDown('0', '1', $event)"
:ref="`input-0-1`"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item prop="respirationRate" label="呼吸">
<el-input
v-model="formData.respirationRate"
size="small"
@keydown="onKeyDown('0', '2', $event)"
:ref="`input-0-2`"
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="8">
<div class="layui-form-item">
<el-form-item prop="bloodOxygen" label="血氧">
<el-input
v-model="formData.bloodOxygen"
size="small"
@keydown="onKeyDown('1', '3', $event)"
:ref="`input-1-3`"
/>
</el-form-item>
</div>
</el-col>
<!-- <el-col :span="8">
<el-form-item prop="column089" label="动脉压">
<el-input
v-model="formData.column089"
size="small"
@keydown="onKeyDown('2', '0', $event)"
:ref="`input-2-0`"
/>
</el-form-item>
</el-col> -->
<el-col :span="8">
<el-form-item prop="bloodGlucose" label="血糖">
<div class="input-select-container">
<el-input
v-model="formData.bloodGlucose"
size="small"
@keydown="onKeyDown('2', '1', $event)"
:ref="`input-2-1`"
/>
<el-select
v-model="formData.column135"
clearable
placeholder=""
size="small"
@change="handlechangedict(bloodSugarList, formData.column135, 'column091')"
>
<el-option
v-for="item in bloodSugarList"
:key="item.code"
:label="item.display"
:value="item.code"
/>
</el-select>
</div>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item prop="physicalCooling" label="物理降温">
<el-input
v-model="formData.physicalCooling"
size="small"
@keydown="onKeyDown('2', '2', $event)"
:ref="`input-2-2`"
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<!-- <el-col :span="8">
<el-form-item label="左瞳孔(光)">
<el-select v-model="formData.column092" clearable placeholder="" size="small">
<el-option
v-for="item in pupilList"
:key="item.code"
:label="item.display"
:value="item.code"
/>
</el-select>
</el-form-item>
</el-col> -->
<!-- <el-col :span="8">
<el-form-item label="右瞳孔(光)">
<el-select v-model="formData.column093" clearable placeholder="" size="small">
<el-option
v-for="item in pupilList"
:key="item.code"
:label="item.display"
:value="item.code"
/>
</el-select>
</el-form-item>
</el-col> -->
</el-row>
<el-row :gutter="24">
<!-- <el-col :span="8">
<el-form-item label="左瞳孔(大小)">
<el-input
v-model="formData.column051"
size="small"
@keydown="onKeyDown('3', '0', $event)"
:ref="`input-3-0`"
/> </el-form-item
></el-col> -->
<!-- <el-col :span="8">
<el-form-item label="右瞳孔(大小)">
<el-input
v-model="formData.column052"
size="small"
@keydown="onKeyDown('3', '1', $event)"
:ref="`input-3-1`"
/>
</el-form-item>
</el-col> -->
</el-row>
<el-row :gutter="24">
<!-- <el-col :span="8">
<el-form-item label="意识">
<el-select v-model="formData.column138" clearable placeholder="" size="small">
<el-option
v-for="item in sanityList"
:key="item.code"
:label="item.display"
:value="item.code"
/>
</el-select>
</el-form-item>
</el-col> -->
<el-col :span="8">
<el-form-item label="CCU心率">
<el-select v-model="formData.ccuHeartRate" clearable placeholder="" size="small">
<el-option
v-for="item in CCUHeartRateList"
:key="item.code"
:label="item.display"
:value="item.code"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="新生儿箱温">
<el-input
v-model="formData.newbornsIncubator"
size="small"
@keydown="onKeyDown('4', '0', $event)"
:ref="`input-4-0`"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="血酮">
<div class="flex-container">
<el-input
v-model="formData.bloodKetone"
size="small"
@keydown="onKeyDown('4', '1', $event)"
:ref="`input-4-1`"
/>
<template>
<el-select
v-model="formData.column141"
clearable
placeholder=""
size="small"
@change="
handlechangedict(bloodKetoneList, formData.column141, 'column140')
"
>
<el-option
v-for="item in bloodKetoneList"
:key="item.code"
:label="item.display"
:value="item.code"
/>
</el-select>
</template>
</div> </el-form-item
></el-col>
</el-row>
<el-row :gutter="24">
<!-- <el-col :span="8">
<el-form-item prop="column009" label="体重(kg)">
<div class="input-select-container">
<el-input
v-model="formData.column009"
size="small"
@keydown="onKeyDown('0', '0', $event)"
:ref="`input-0-0`"
/>
<el-select
v-model="formData.column133"
clearable
size="small"
placeholder=""
@change="
handlechangedict(bodyTemperatureList, formData.column133, 'column009')
"
>
<el-option
v-for="item in bodyTemperatureList"
:key="item.code"
:label="item.display"
:value="item.code"
/>
</el-select>
</div>
</el-form-item>
</el-col> -->
<el-col :span="8">
<el-form-item prop="height" label="身高(cm)">
<div class="input-select-container">
<el-input
v-model="formData.height"
size="small"
@keydown="onKeyDown('0', '0', $event)"
:ref="`input-0-0`"
/>
<el-select
v-model="formData.column133"
clearable
size="small"
placeholder=""
@change="
handlechangedict(bodyTemperatureList, formData.column133, 'column009')
"
>
<el-option
v-for="item in bodyTemperatureList"
:key="item.code"
:label="item.display"
:value="item.code"
/>
</el-select>
</div>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item prop="waistCircumference" label="腹围(cm)">
<div class="input-select-container">
<el-input
v-model="formData.waistCircumference"
size="small"
@keydown="onKeyDown('0', '0', $event)"
:ref="`input-0-0`"
/>
<el-select
v-model="formData.column133"
clearable
size="small"
placeholder=""
@change="
handlechangedict(bodyTemperatureList, formData.column133, 'column009')
"
>
<el-option
v-for="item in bodyTemperatureList"
:key="item.code"
:label="item.display"
:value="item.code"
/>
</el-select>
</div>
</el-form-item>
</el-col>
</el-row>
<!-- </el-form-item> -->
<el-row :gutter="24">
<el-col :span="8">
<div class="flex-container">
<el-form-item prop="stoolFrequency" label="大便次数(次)">
<div class="input-select-container">
<el-input
v-model="formData.stoolFrequency"
size="small"
@keydown="onKeyDown('0', '0', $event)"
:ref="`input-0-0`"
/>
<el-select
v-model="formData.column133"
clearable
size="small"
placeholder=""
@change="
handlechangedict(bodyTemperatureList, formData.column133, 'column009')
"
>
<el-option
v-for="item in bodyTemperatureList"
:key="item.code"
:label="item.display"
:value="item.code"
/>
</el-select>
</div>
</el-form-item>
</div>
</el-col>
<el-col :span="8">
<div class="flex-container">
<el-form-item prop="enemaFrequency" label="灌肠次数(次)">
<el-input
v-model="formData.enemaFrequency"
size="small"
@keydown="onKeyDown('0', '0', $event)"
:ref="`input-0-0`"
/>
</el-form-item>
</div>
</el-col>
<el-col :span="8">
<div class="flex-container">
<el-form-item prop="sfAfterEnema" label="灌肠后大便次数(次)">
<el-input
v-model="formData.sfAfterEnema"
size="small"
@keydown="onKeyDown('0', '0', $event)"
:ref="`input-0-0`"
/>
</el-form-item>
</div>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="8">
<div class="flex-container">
<el-form-item prop="output" label="出量ml">
<el-input
v-model="formData.output"
size="small"
@keydown="onKeyDown('0', '0', $event)"
:ref="`input-0-0`"
/>
</el-form-item>
</div>
</el-col>
<el-col :span="8">
<div class="flex-container">
<el-form-item prop="input" label="入量ml">
<el-input
v-model="formData.input"
size="small"
@keydown="onKeyDown('0', '0', $event)"
:ref="`input-0-0`"
/>
</el-form-item>
</div>
</el-col>
<el-col :span="8">
<div class="flex-container">
<el-form-item prop="urineVolume" label="尿量ml">
<el-input
v-model="formData.urineVolume"
size="small"
@keydown="onKeyDown('0', '0', $event)"
:ref="`input-0-0`"
/>
</el-form-item>
</div>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="8">
<div class="flex-container">
<el-form-item prop="stoolVolume" label="大便量ml">
<el-input
v-model="formData.stoolVolume"
size="small"
@keydown="onKeyDown('0', '0', $event)"
:ref="`input-0-0`"
/>
</el-form-item>
</div>
</el-col>
</el-row>
</div>
</el-form>
</el-card>
</div>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="close"> </el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { ref, nextTick } from 'vue';
import { listPatient, addVitalSigns } from './api';
import moment from "moment";
const { proxy } = getCurrentInstance();
const props = defineProps({
open: {
type: Boolean,
default: false,
},
patientId: {
type: String,
default: '',
},
patientInfo: {
type: Object,
default: () => {},
},
});
const { method_code, unit_code, rate_code, distribution_category_code } = proxy.useDict(
'method_code',
'unit_code',
'rate_code',
'distribution_category_code'
);
const emit = defineEmits(['close']);
const queryParams = ref({
pageNum: 1,
pageSize: 10,
patientId: undefined, // 患者id
});
// const patientInfo = ref({
// patientName: '张三',
// });
const patientInfo = ref({});
const form = ref({});
const title = ref('');
const rowRules = ref({
conditionDefinitionId: [{ required: true, message: '请选择诊断', trigger: 'change' }],
dose: [{ required: true, message: '请输入单次剂量', trigger: 'change' }],
doseQuantity: [{ required: true, message: '请输入单次剂量', trigger: 'change' }],
quantity: [{ required: true, message: '请输入数量', trigger: 'change' }],
dispensePerDuration: [{ required: true, message: '请输入用药天数', trigger: 'change' }],
});
// 表单配置数据
const formConfig = ref([
{
type: 'input', // 表单项类型
label: '用户名', // 标签文本
prop: 'username', // 表单字段名
rules: [{ required: true, message: '请输入用户名', trigger: 'blur' }], // 验证规则
attrs: {
// el-input 的属性
placeholder: '请输入用户名',
clearable: true,
},
},
{
type: 'select',
label: '性别',
prop: 'gender',
options: [
// select 的选项
{ value: 'male', label: '男' },
{ value: 'female', label: '女' },
],
attrs: {
placeholder: '请选择性别',
},
},
// 更多表单项配置...
]);
const InputOptions = ref([
{
value: '0200', label: '2点',
},
{
value: '0600', label: '6点',
},
{
value: '1000', label: '10点',
},
{
value: '1400', label: '14点',
},
{
value: '1800', label: '18点',
},
{
value: '2200', label: '22点',
},
])
// 表单数据
const formData = ref({
username: '',
gender: '',
});
// 表格列配置数据
const tableColumns = ref([
{
type: 'selection', // 特殊列类型
width: '55',
// selectable: checkSelectable, // 可选函数
},
{
prop: 'encounterBusNo', // 字段名
label: '病历号', // 列标题
align: 'center',
width: '120',
},
{
prop: 'patientName',
label: '姓名',
align: 'center',
},
{
prop: 'statusEnum_enumText',
label: '收费状态',
align: 'center',
formatter: (row) => formatStatus(row.statusEnum_enumText), // 格式化函数
},
// 更多列配置...
]);
function getPatientList() {}
/**
* 取得患者信息详细
*/
function getPatientDetial() {
patientInfo.value = props.patientInfo;
console.log(props, 'props', props.patientInfo);
reset();
title.value = '';
title.value = props.title;
console.log(props, 'props', title.value);
console.log(queryParams.value, 'queryParams.value', props.patientId);
queryParams.value.patientId = props.patientId;
listPatient(queryParams.value).then((res) => {
if (res.data && res.data.records && res.data.records.length > 0) {
form.value = res.data.records[0];
}
form.value.addressInfo =
form.value.addressProvince +
'' +
form.value.addressCity +
'' +
form.value.addressDistrict +
'' +
form.value.addressStreet +
'' +
form.value.address;
// loading.value = false;
console.log(res, 'resqqqqqqqqqqqqqqqqqqqqqqq', form.value);
});
}
function close() {
reset();
emit('close');
}
function confirmCharge() {
let params = {}
params = formData.value
params.patientId = props.patientInfo.patientId
params.encounterId = props.patientInfo.encounterId
params.recordingDate = moment(new Date()).format('YYYY-MM-DD');
params.timePoint = formData.value.timePoint
params.vitalSignsCode = ['003']
params.vitalSignsValues = ['38']
addVitalSigns(formData.value).then(res => {
console.log(res)
})
}
/** 重置操作表单 */
function reset() {
form.value = {
id: undefined,
activeFlag: undefined, // 活动标记
tempFlag: undefined, // 临时标识
name: undefined, // 患者姓名
nameJson: undefined, // 患者其他名称
busNo: undefined, // 病历号
genderEnum: undefined, // 性别
genderEnum_enumText: undefined, // 性别
birthDate: undefined, // 生日
deceasedDate: undefined, // 死亡时间
maritalStatusEnum: undefined, // 婚姻状态
maritalStatusEnum_enumText: undefined, // 婚姻状态
prfsEnum: undefined, // 职业编码
prfsEnum_enumText: undefined, // 职业编码
phone: undefined, // 电话
address: undefined, // 地址
addressProvince: undefined, // 地址省
addressCity: undefined, // 地址市
addressDistrict: undefined, // 地址区
addressStreet: undefined, // 地址街道
addressJson: undefined, // 患者其他地址
nationalityCode: undefined, // 民族
idCard: undefined, // 身份证号
pyStr: undefined, //拼音码
wbStr: undefined, // 五笔码
bloodAbo: undefined, // 血型ABO
bloodAbo_enumText: undefined, // 血型ABO
bloodRh: undefined, // 血型RH
bloodRh_enumText: undefined, // 血型RH
workCompany: undefined, // 工作单位
nativePlace: undefined, // 籍贯
countryCode: undefined, // 国家编码
linkName: undefined, // 联系人
linkRelationCode: undefined, // 联系人关系
linkRelationCode_codeText: undefined, // 联系人关系
linkTelcom: undefined, // 联系人电话
linkJsons: undefined, // 其他联系人
tenanid: undefined, // 租户ID
ageString: undefined, // 病人年龄
priorityEnum: undefined, // 护理级别
priorityEnum_enumText: undefined, // 护理级别
statusEnum: undefined, // 患者状态
statusEnum_enumText: undefined, // 患者状态
organizationId: undefined, // 入院科室
organizationId_dictText: undefined, // 入院科室
startTime: undefined, // 入院日期
endTime: undefined, // 出院日期
responsibleDoctor: undefined, // 责任医生
responsibleNurse: undefined, // 责任护士
iptDiseTypeCode: undefined, // 主要诊断
typeCode: undefined, // 费别
typeCode_dictText: undefined, // 费别
hospitalizationDays: undefined, //住院天数
classEnum: undefined, // 就诊类别
classEnum_enumText: undefined, // 就诊类别
postoperativeDays: undefined, // 术后天数
surgeryStartTime: undefined, // 手术开始日期
surgeryEndTime: undefined, // 手术结束日期
surgeryStatusEnum: undefined, // 手术状态
surgeryStatusEnum_enumText: undefined, // 手术状态
categoryCode: undefined, // 过敏源类别
categoryCode_dictText: undefined, // 过敏源类别
caty: undefined, // 入院科室名称
locationId: undefined, // 床位号
locationId_dictText: undefined, // 床位号
encounterId: undefined, // 就诊流水号
encounterLocationId: undefined, // 就诊地点流水号
};
proxy.resetForm('formRef');
}
defineExpose({
getPatientDetial,
});
</script>
<style scoped>
:deep(.pagination-container .el-pagination) {
right: 20px !important;
}
.input-select-container {
display: flex;
justify-content: space-between;
align-items: center;
}
.input-select-container .el-input__inner,
.input-select-container .el-select {
width: 100%;
}
.flex-container {
display: flex;
align-items: center; /* 垂直居中对齐 */
justify-content: flex-start; /* 水平起始对齐 */
gap: 8px; /* 两个输入框之间的间距 */
}
.flex-container label {
margin: 0 8px; /* 标签的间距 */
}
</style>

View File

@@ -0,0 +1,124 @@
import request from '@/utils/request'
/**
* 获取患者列表
*
* @param query 查询参数对象,可以包含多个查询条件
* @returns Promise<any> 返回一个Promise对象解析后得到患者列表数据
*/
export function listPatient(query) {
return request({
url: '/nursing-record/patient-page',
method: 'get',
params: query
})
}
/**
* 查询患者体征数据
*
* @param query 查询参数对象,可以包含多个查询条件
* @returns Promise<any> 返回一个Promise对象解析后得到患者列表数据
*/
export function getVitalSignsInfo(query) {
return request({
url: '/vital-signs/patient-message',
method: 'get',
params: query
})
}
/**
* 获取空床列表
*
* @param organizationId 科室ID
* @returns Promise<any> 返回一个Promise对象解析后得到患者列表数据
*/
export function getEmptyBed(organizationId) {
return request({
url: '/patient-home-manage/empty-bed',
method: 'get',
params: { organizationId }
})
}
/**
* 保存换床信息
*
*/
export function saveBedTransfer(params) {
return request({
url: '/patient-home-manage/bed-transfer',
method: 'put',
params: params
})
}
/**
* 获取科室列表
*
* @returns Promise<any> 返回一个Promise对象解析后得到科室列表数据
*/
export function getCaty() {
return request({
url: '/patient-home-manage/caty',
method: 'get'
})
}
/**
* 保存转科信息
*
*/
export function saveDepartmentTransfer(params) {
return request({
url: '/patient-home-manage/department-transfer',
method: 'put',
params: params
})
}
/**
* 保存出院信息
*
*/
export function saveDischargeHospital(params) {
return request({
url: '/patient-home-manage/discharge-from-hospital',
method: 'put',
params: params
})
}
/**
* 收费患者列表
*/
export function getList(queryParams) {
return request({
url: '/charge-manage/charge/encounter-patient-page',
method: 'get',
params: queryParams
})
}
/**
* 新增体征录入
*/
export function addVitalSigns(data) {
return request({
url: '/vital-signs/record-saving',
method: 'put',
data: data
})
}
/**
* 删除体征录入
*/
export function delVitalSigns(data) {
return request({
url: '/vital-signs/record-delete',
method: 'delete'
})
}

View File

@@ -0,0 +1,636 @@
<template>
<div class="business-temperature" style="display: flex; justify-content: space-evenly">
<!--<div class="business1">
<PatientInfo @send-data="handleData">
<el-button size="small" type="primary" style="margin-left: 10px" @click="seleteData"
>查询</el-button
>
<el-button size="small" type="primary" style="margin-left: 10px" @click="printJS"
>打印</el-button
>
<label class="layui-form-label" style="margin-left: 10px">日期</label>
<div class="layui-input-inline" style="width: 180px">
<el-date-picker
v-model="recordingDate"
style="width: 180px"
type="date"
value-format="yyyy-MM-dd"
placeholder="选择日期"
size="small"
/>
</div>
</PatientInfo>
</div>-->
<el-card style="width: 35%">
<template #header>
<span style="vertical-align: middle">患者列表</span>
</template>
<div style="width: 100%">
<el-input
v-model="queryParams.searchKey"
placeholder="请输入患者名/病历号"
clearable
style="width: 48%; margin-bottom: 10px; margin-right: 10px"
@keyup.enter="getPatientListInfo"
/>
<el-button type="primary" style="margin-bottom: 10px" @click="getPatientListInfo">
搜索
</el-button>
<el-table
ref="patientListRef"
height="620"
:data="patientList"
row-key="encounterId"
@row-click="viewPatient"
highlight-current-row
>
<el-table-column prop="bedLocationId_dictText" label="床号" min-width="50" />
<el-table-column label="病历号" align="center" prop="encounterId" />
<el-table-column label="姓名" align="center" prop="patientName" />
<el-table-column label="性别" align="center" prop="genderEnum_enumText" />
<el-table-column label="年龄" align="center" prop="ageString" />
<!-- <el-table-column label="时间" align="center" prop="receptionTime" width="160">
<template #default="scope">
{{ formatDate(scope.row.receptionTime) }}
</template>
</el-table-column> -->
</el-table>
<pagination
v-show="total > 0"
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getPatientListInfo"
style="margin-bottom: 20px"
/>
</div>
</el-card>
<el-card style="width: 60%">
<div>
<el-button size="default" type="primary" @click="openAddTprDialog"
>新增</el-button
>
</div>
<div class="business-temperature-sheet" style="width: 60%">
<div>
<el-tooltip content="首页" placement="right-end">
<el-button
style="margin-left: 12px; margin-top: 400px"
icon="Upload"
size="default"
type="primary"
@click="toFirst"
/>
</el-tooltip>
<el-tooltip content="上一页" placement="right-end">
<el-button
style="margin-left: 12px; margin-top: 15px"
icon="ArrowUpBold"
size="default"
type="primary"
@click="lastWeek"
/>
</el-tooltip>
<el-tooltip content="下一页" placement="right-end">
<el-button
style="margin-left: 12px; margin-top: 15px"
icon="ArrowDown"
size="default"
type="primary"
@click="nextWeek"
/>
</el-tooltip>
<el-tooltip content="尾页" placement="right-end">
<el-button
style="margin-left: 12px; margin-top: 15px"
icon="Download"
size="default"
type="primary"
@click="toEnd"
/>
</el-tooltip>
<el-tooltip content="打印本页" placement="right-end">
<el-button
style="margin-left: 12px; margin-top: 15px"
icon="Printer"
size="default"
type="primary"
@click="printPage"
/>
</el-tooltip>
</div>
<div id="my_dataviz" ref="printRef" style="width: 780px; background-color: white" />
</div>
</el-card>
<div v-show="false">
<temperatureSheet ref="refTemp" />
</div>
<add-tpr-dialog
ref="addTprDialogRef"
:open="openAddTpr"
:patientId="patientId"
:patientInfo="patientData"
@close="closePatientDetialDialog"
/>
<!-- </div> -->
<iframe id="printIframe" ref="printIframe" style="display:none;"></iframe>
</div>
</template>
<script setup>
// import PatientInfo from '@/components/PatientInfo'
import html2pdf from 'html2pdf.js';
import cloneDeep from 'lodash.clonedeep';
import { init } from '@/action/nurseStation/temperatureSheet/line.js';
import temperatureSheet from '../../../components/Auto/printBills/temperatureSheet';
import addTprDialog from './components/addTprDialog.vue';
// import printJS from 'print-js';
import { formatDateStr } from '@/utils';
import moment from 'moment';
import { listPatient, getVitalSignsInfo } from './components/api';
import useUserStore from '@/store/modules/user';
// import { getSignsCharts } from '@/api/signsManagement'
// import { date } from 'jszip/lib/defaults'
const userStore = useUserStore();
// 响应式数据
const printRef = ref(null);
const printIframe = ref(null);
const refTemp = ref(null);
const recordingDate = ref(undefined);
const week = ref(0);
const patientId = ref('');
const visitId = ref('');
const admissionDate = ref(undefined);
const inputData = ref({});
const openAddTpr = ref(false);
const { proxy } = getCurrentInstance();
const print = ref(null);
const total = ref(0);
const queryParams = ref({
pageNum: 1,
pageSize: 10,
searchKey: undefined,
orgId: userStore.orgId,
});
const data1 = reactive({
patientInfo: {},
grParamBOS: {
age: '',
birth: '',
cwh: '',
hosNum: '',
inDate: '',
inDiagName: '',
name: '',
deptName: '',
operaDays: '',
sex: '',
weekNo: '',
beginDate: '',
hospDays: '',
total: '',
hospDate: '',
operaDate: '',
outdate: ''
},
rows: [],
types: []
});
const patientData = ref({});
const integerPoints = [2, 6, 10, 14, 18, 22];
const closestPoint = ref(null);
const receptionTime = ref([
formatDateStr(new Date(), 'YYYY-MM-DD'),
formatDateStr(new Date(), 'YYYY-MM-DD'),
]);
const patientList = ref([]);
const chargeLoading = ref(false);
const encounterId = ref('');
const addTprDialogRef = ref(null);
const patientInfo = ref({});
// /**
// * 查看患者
// */
// function viewPatient(row) {
// console.log('接收子组件传来的数据', patientInfo);
// patientId.value = patientInfo.patientId; // 接收子组件传来的数据
// visitId.value = String(patientInfo.visitId); // 接收子组件传来的数据
// // // 入科时间存在的场合使用入科时间
// // if (patientInfo.admWardDateTime) {
// // admissionDate = patientInfo.admWardDateTime; // 接收子组件传来的数据
// // } else {
// // admissionDate = patientInfo.admissionDate; // 接收子组件传来的数据
// // }
// // data1.patientInfo = patientInfo;
// // data1.grParamBOS.patientId = patientInfo.patientId;
// // data1.grParamBOS.age = patientInfo.age;
// // data1.grParamBOS.birth = null;
// // data1.grParamBOS.cwh = patientInfo.bedLabel;
// // data1.grParamBOS.hosNum = patientInfo.hosNum;
// // // 入科时间存在的场合使用入科时间
// // if (patientInfo.admWardDateTime) {
// // data1.grParamBOS.inDate = patientInfo.admWardDateTime;
// // } else {
// // data1.grParamBOS.inDate = patientInfo.admissionDate;
// // }
// // console.log('patientInfo.admissionDate', patientInfo.admissionDate, data1.grParamBOS.inDate);
// // data1.grParamBOS.inDiagName = patientInfo.diagnosis;
// // data1.grParamBOS.name = patientInfo.name;
// // data1.grParamBOS.deptName = patientInfo.deptName;
// data1.grParamBOS.operaDays = null;
// // data1.grParamBOS.sex = patientInfo.sex;
// data1.grParamBOS.weekNo = null;
// data1.grParamBOS.beginDate = getCurrentDate();
// data1.grParamBOS.hospDays = null;
// data1.grParamBOS.total = null;
// getSignsCharts();
// }
// init1(data1);
getPatientListInfo();
// init1(data1);
/**
* 患者列表
*/
function getPatientListInfo() {
listPatient(queryParams.value).then((res) => {
console.log(userStore, 'userStore', res);
patientList.value = res.data.records;
total.value = res.data.total;
});
}
function init1(data) {
console.log('体温单初始化', data);
const inDate = data.grParamBOS.hospDate;
const outdate = data.grParamBOS.outdate;
week.value = Math.floor(dateDiff(inDate, outdate) / 7);
setTemperatureComp(data);
}
/**
* 点击患者列表行 获取患者体温单数据
*/
function viewPatient(row) {
patientInfo.value = row;
console.log('点击患者列表行 获取患者体温单数据', row);
chargeLoading.value = true;
encounterId.value = row.encounterId;
patientId.value = row.patientId; // 接收子组件传来的数据
// visitId.value = String(patientInfo.value.visitId); // 接收子组件传来的数据
// 入科时间存在的场合使用入科时间
admissionDate.value = row.admissionDate; // 接收子组件传来的数据
data1.patientInfo = row;
data1.grParamBOS.patientId = row.patientId;
data1.grParamBOS.age = row.ageString;
data1.grParamBOS.birth = row.birthDate;
data1.grParamBOS.cwh = row.bedLocationId_dictText;
data1.grParamBOS.hosNum = row.encounterId;
// 入科时间存在的场合使用入科时间
data1.grParamBOS.inDate = row.admissionDate;
console.log(
'patientInfo.admissionDate',
patientInfo.value.admissionDate,
data1.grParamBOS.inDate
);
// data1.grParamBOS.inDiagName = patientInfo.value.diagnosis;
data1.grParamBOS.name = patientInfo.value.patientName;
// data1.grParamBOS.deptName = patientInfo.value.deptName;
data1.grParamBOS.operaDays = null;
// data1.grParamBOS.sex = patientInfo.sex;
data1.grParamBOS.weekNo = null;
data1.grParamBOS.beginDate = getCurrentDate();
data1.grParamBOS.hospDays = null;
data1.grParamBOS.total = null;
// getChargeList(row.encounterId).then((res) => {
// chargeList.value = res.data;
// setTimeout(() => {
// chargeLoading.value = false;
// chargeListRef.value.toggleAllSelection();
// }, 100);
// });
getSignsCharts();
}
function getSignsCharts() {
const params = {
patientId: patientId.value,
};
getVitalSignsInfo(params).then((response) => {
console.log('体温单返回值', response);
if (response.code === 200) {
// data1.grParamBOS.hospDate = data1.grParamBOS.inDate.substring(0, 10)
data1.grParamBOS.hospDate =
response.data.hospDate && response.data.hospDate.length > 10
? response.data.hospDate.substring(0, 10)
: response.data.hospDate;
data1.grParamBOS.operaDate = response.data.operaDate;
data1.grParamBOS.outdate = response.data.outdate;
data1.rows = response.data.temperaturePulses.map((item) => ({
rowBOS: item.chartsSmalls,
weekNo: item.weekNo - 1,
}));
data1.types = response.data.others.map((item) => ({
...item, // 保留其他属性
weekNo: item.weekNo - 1, // 将 weekNo 减 1
}));
// // 取入院特殊标记的值
// const typeValue = '院,' + formatDateTo(response.data.hospDate).formattedTime;
// const newRowBOS = {
// collectionMode: null,
// date: formatDateTo(response.data.hospDate).formattedDate,
// times: formatHourTimes(response.data.hospDate, response.data.temperaturePulses)
// .formattedTime,
// typeCode: '018',
// typeValue: typeValue,
// weekNo: 1,
// };
// let foundZero = false;
// for (const item of data1.rows) {
// if (item.weekNo1 === 0) {
// item.rowBOS.push(newRowBOS);
// foundZero = true;
// break; // 找到后可以跳出循环
// }
// }
// if (!foundZero) {
// data1.rows.push({
// rowBOS: [newRowBOS],
// weekNo: 0,
// });
// }
console.log('体温单查询this.data1', data1);
init1(data1);
}
});
}
function getPatientList() {}
// 体温单控件数据设置
function setTemperatureComp(data) {
console.log(data,'体温单控件数据设置');
if (data !== undefined) {
inputData.value = data;
}
const inDate = inputData.value.grParamBOS.hospDate;
const outdate = inputData.value.grParamBOS.outdate;
const begin = moment(new Date(inDate))
.add(week.value * 7, 'day')
.format('YYYY-MM-DD HH:mm:ss');
inputData.value.grParamBOS.weekNo = week.value;
inputData.value.grParamBOS.beginDate = begin;
inputData.value.grParamBOS.hospDays = week.value * 7;
inputData.value.grParamBOS.total = Math.floor(dateDiff(inDate, outdate) / 7);
init(sliceData(inputData.value));
}
function getCurrentDate() {
// 获取当前日期
const today = new Date();
const year = today.getFullYear();
const month = (today.getMonth() + 1).toString().padStart(2, '0'); // 月份从0开始所以需要加1
const day = today.getDate().toString().padStart(2, '0');
return `${year}-${month}-${day}`; // 格式化为 YYYY-MM-DD
}
function seleteData() {
const inDate = inputData.value.grParamBOS.hospDate;
week.value = Math.floor(dateDiff(inDate, recordingDate.value) / 7);
setTemperatureComp();
}
function lastWeek() {
week.value--;
if (week.value < 0) {
week.value = 0;
}
setTemperatureComp();
}
function nextWeek() {
week.value = Number(week.value) + 1;
if (week.value > inputData.value.grParamBOS.total) {
week.value = inputData.value.grParamBOS.total;
}
setTemperatureComp();
}
function toFirst() {
week.value = 0;
setTemperatureComp();
}
function toEnd() {
week.value = inputData.value.grParamBOS.total;
setTemperatureComp();
}
// 拆分当前周数据
function sliceData(data) {
const rows = data.rows.filter((item) => item.weekNo === week.value);
const types = data.types.filter((item) => item.weekNo === week.value);
// const datas = JSON.parse(JSON.stringify(data));
const datas = cloneDeep(data);
datas.rows = rows;
datas.types = types;
console.log(datas,"666666666666666666")
return datas;
}
// 计算时间差
function dateDiff(start, end) {
let diffTime = start ? moment(new Date()).diff(moment(start.substring(0, 10))) / 1000 :start;
if (end) {
diffTime = moment(end.substring(0, 10)).diff(moment(start.substring(0, 10))) / 1000;
}
if (diffTime > 24 * 3600) {
return Math.floor(diffTime / (24 * 3600));
} else if (diffTime > 3600) {
return '0';
} else {
return '0';
}
}
// 打印体温单
function printTW() {
// this.$print(this.$refs.print);
printRef.value.focus();
printRef.value.contentWindow.print();
// this.$refs.refTemp.printPage();
}
// 打印体温单
function printPage() {
const element = printRef.value;
if (!element) {
console.error('未找到可打印的内容');
return;
}
// 创建一个克隆元素用于打印,避免修改原 DOM
const clone = element.cloneNode(true);
// 设置宽度为 A4780px ≈ 210mm高度自适应
clone.style.transform = 'scale(0.7)';
clone.style.transformOrigin = 'top left';
clone.style.width = 'calc(210mm * 1.11)';
clone.style.height = 'calc(297mm * 1.11)';
clone.style.marginLeft = '50px';
// 插入到 body 中以便 html2pdf 渲染
document.body.appendChild(clone);
// 设置 html2pdf 配置
const opt = {
margin: 0,
filename: '体温单.pdf',
image: { type: 'jpeg', quality: 1 },
html2canvas: { scale: 2, useCORS: true }, // 启用跨域资源支持
jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' },
pagebreak: { mode: ['avoid-all'] },
onclone: (clonedDoc) => {
const chart = clonedDoc.getElementById(clone.id);
if (chart) {
chart.style.width = '210mm'; // 强制 A4 宽度
chart.style.margin = '0 auto';
}
}
};
// 导出为 PDF 并打印
html2pdf().from(clone).set(opt).toPdf().get('pdf').then(function (pdf) {
pdf.autoPrint(); // 自动打印
window.open(pdf.output('bloburl'), '_blank'); // 在新窗口打开 PDF以便用户确认
}).finally(() => {
document.body.removeChild(clone); // 清理临时元素
});
}
// 转化时间
function formatDateTo(dateStr) {
const [formattedDate, timePartWithSeconds] = dateStr ? dateStr.split('T'): ['', ''];
const [formattedHour, minutePart] = timePartWithSeconds.split(':');
const formattedTime = `${formattedHour}:${minutePart}`;
// 返回格式化的日期字符串
return {
formattedDate: formattedDate,
formattedTime: formattedTime,
formattedHour: formattedHour,
};
}
// 转化时间
function formatHourTimes(dateStr, temperaturePulses) {
const formattedTime = formatDateTo(dateStr).formattedTime;
const formattedDate = formatDateTo(dateStr).formattedDate;
let times = '';
if (formattedTime >= '00:00' && formattedTime < '04:00') {
times = '02:00:00';
} else if (formattedTime >= '04:00' && formattedTime < '08:00') {
times = '06:00:00';
} else if (formattedTime >= '08:00' && formattedTime < '12:00') {
times = '10:00:00';
} else if (formattedTime >= '12:00' && formattedTime < '16:00') {
times = '14:00:00';
} else if (formattedTime >= '16:00' && formattedTime < '20:00') {
times = '18:00:00';
} else if (formattedTime >= '20:00' && formattedTime <= '23:59') {
times = '22:00:00';
}
const filteredData = temperaturePulses.filter((item) =>
item.chartsSmalls.some(
(chart) =>
chart.date === formattedDate &&
chart.times === times &&
(chart.typeCode === '9507' ||
chart.typeCode === '9505' ||
chart.typeCode === '9502' ||
chart.typeCode === '9503')
)
);
if (filteredData.length > 0) {
if (formattedTime >= '00:00' && formattedTime < '04:00') {
if (filteredData.length === 1) {
times = '06:00:00';
} else if (filteredData.length === 2) {
times = '10:00:00';
} else if (filteredData.length === 3) {
times = '14:00:00';
} else {
times = '02:00:00';
}
} else if (formattedTime >= '04:00' && formattedTime < '08:00') {
times = '02:00:00';
} else if (formattedTime >= '08:00' && formattedTime < '12:00') {
times = '06:00:00';
} else if (formattedTime >= '12:00' && formattedTime < '16:00') {
times = '10:00:00';
} else if (formattedTime >= '16:00' && formattedTime < '20:00') {
times = '18:00:00';
} else {
times = '18:00:00';
}
}
// 返回格式化的日期字符串
return {
formattedTime: times,
};
}
/**
* 打开体征录入
*/
function openAddTprDialog() {
patientData.value = patientInfo.value
openAddTpr.value = true;
// patientId.value = row.id;
nextTick(() => {
proxy.$refs['addTprDialogRef'].getPatientDetial();
});
console.log(openAddTpr.value, '打开体征录入对话框');
}
/**
* 关闭新增体征弹窗
*/
function closePatientDetialDialog(str) {
openAddTpr.value = false;
}
</script>
<style lang="scss" scoped>
.business-temperature {
// display: grid;
grid-template-columns: 100%;
background-color: white;
}
::v-deep .business-temperature .el-icon-arrow-down {
font-size: 12px;
}
.business1 {
background: white;
padding: 10px 16px;
border-radius: 6px;
height: 40%;
justify-content: center;
}
.layui-form-label {
line-height: 35px;
text-align: right;
padding-right: 10px;
}
.layui-input-inline {
display: inline-block;
}
.business-temperature-sheet {
display: grid;
grid-template-columns: 59px 1px 780px;
}
::v-deep .business-temperature-sheet .el-icon-arrow-down {
font-size: 12px;
}
#chart {
max-height: 270mm;
overflow: hidden;
}
</style>