提交merge1.3

This commit is contained in:
2025-12-27 15:30:25 +08:00
parent 8c607c8749
commit 088861f66e
1245 changed files with 220442 additions and 77616 deletions

View File

@@ -1,72 +1,89 @@
<template>
<div @keyup="handleKeyDown" tabindex="0" ref="tableWrapper">
<el-table
<div @keyup="handleKeyDown" tabindex="0" ref="tableWrapper" class="advice-base-list-wrapper">
<Table
ref="adviceBaseRef"
height="400"
:data="adviceBaseList"
highlight-current-row
@current-change="handleCurrentChange"
:table-data="adviceBaseList"
:table-columns="tableColumns"
:highlight-current-row="true"
:table-height="400"
:max-height="400"
:loading="loading"
row-key="patientId"
@cell-click="clickRow"
@row-click="handleRowClick"
>
<el-table-column label="名称" align="center" prop="adviceName" />
<el-table-column label="类型" align="center" prop="activityType_enumText" />
<el-table-column label="包装单位" align="center" prop="unitCode_dictText" />
<el-table-column label="最小单位" align="center" prop="minUnitCode_dictText" />
<el-table-column label="规格" align="center" prop="volume" />
<el-table-column label="用法" align="center" prop="methodCode_dictText" />
<el-table-column label="库存数量" align="center">
<template #default="scope">{{ handleQuantity(scope.row) }}</template>
</el-table-column>
<el-table-column label="频次" align="center" prop="rateCode_dictText" />
<!-- <el-table-column label="单次剂量" align="center" prop="dose" /> -->
<!-- <el-table-column label="剂量单位" align="center" prop="doseUnitCode_dictText" /> -->
<el-table-column label="注射药品" align="center" prop="injectFlag_enumText" />
<el-table-column label="皮试" align="center" prop="skinTestFlag_enumText" />
<el-table-column label="医保码" align="center" prop="ybNo" />
<!-- <el-table-column label="限制使用标志" align="center" prop="useLimitFlag" /> -->
<el-table-column
label="限制使用范围"
align="center"
:show-overflow-tooltip="true"
prop="useScope"
>
<template #default="scope">
<span v-if="scope.row.useLimitFlag === 1">{{ scope.row.useScope }}</span>
<span v-else>{{ '-' }}</span>
</template>
</el-table-column>
</el-table>
<template #quantity="{ row }">
{{ handleQuantity(row) }}
</template>
<template #useScope="{ row }">
<span v-if="row.useLimitFlag === 1">{{ row.useScope }}</span>
<span v-else>{{ '-' }}</span>
</template>
</Table>
</div>
</template>
<script setup>
import { nextTick } from 'vue';
import { getAdviceBaseInfo } from './api';
<script setup lang="ts">
import { ref, nextTick, watch, computed } from 'vue';
import { throttle } from 'lodash-es';
import Table from '@/components/TableLayout/Table.vue';
import { getAdviceBaseInfo } from './api';
import type { TableColumn } from '@/components/types/TableLayout.d';
const props = defineProps({
adviceQueryParams: {
type: Object,
default: '',
},
interface Props {
adviceQueryParams?: {
searchKey?: string;
adviceType?: string;
};
patientInfo: {
type: Object,
required: true,
},
inHospitalOrgId?: string;
[key: string]: any;
};
}
const props = withDefaults(defineProps<Props>(), {
adviceQueryParams: () => ({}),
});
const emit = defineEmits(['selectAdviceBase']);
const total = ref(0);
const adviceBaseRef = ref();
const tableWrapper = ref();
const currentIndex = ref(0); // 当前选中行索引
const currentSelectRow = ref({});
const emit = defineEmits<{
selectAdviceBase: [row: any];
}>();
const total = ref<number>(0);
const loading = ref<boolean>(false);
const adviceBaseRef = ref<InstanceType<typeof Table> | null>(null);
const tableWrapper = ref<HTMLDivElement | null>(null);
const currentIndex = ref<number>(0);
const currentSelectRow = ref<any>({});
const queryParams = ref({
pageSize: 100,
pageNum: 1,
adviceTypes: '1,3'
adviceTypes: '1,3',
searchKey: '',
organizationId: '',
});
const adviceBaseList = ref([]);
const adviceBaseList = ref<any[]>([]);
// 表格列配置
const tableColumns = computed<TableColumn[]>(() => [
{ label: '名称', prop: 'adviceName', align: 'center', width: 200 },
{ label: '类型', prop: 'activityType_enumText', align: 'center' },
{ label: '包装单位', prop: 'unitCode_dictText', align: 'center' },
{ label: '最小单位', prop: 'minUnitCode_dictText', align: 'center' },
{ label: '规格', prop: 'volume', align: 'center' },
{ label: '用法', prop: 'methodCode_dictText', align: 'center' },
{ label: '库存数量', prop: 'quantity', align: 'center', slot: 'quantity' },
{ label: '频次', prop: 'rateCode_dictText', align: 'center' },
{ label: '注射药品', prop: 'injectFlag_enumText', align: 'center' },
{ label: '皮试', prop: 'skinTestFlag_enumText', align: 'center' },
{ label: '医保码', prop: 'ybNo', align: 'center' },
{
label: '限制使用范围',
prop: 'useScope',
align: 'center',
showOverflowTooltip: true,
slot: 'useScope',
},
]);
// 节流函数
const throttledGetList = throttle(
() => {
@@ -88,39 +105,52 @@ watch(
getList();
function getList() {
loading.value = true;
queryParams.value.organizationId = props.patientInfo.inHospitalOrgId;
getAdviceBaseInfo(queryParams.value).then((res) => {
if (res.data.records.length > 0) {
adviceBaseList.value = res.data.records.filter((item) => {
if (item.adviceType == 1 || item.adviceType == 2) {
return handleQuantity(item) != 0;
} else {
return true;
}
});
total.value = res.data.total;
nextTick(() => {
currentIndex.value = 0;
adviceBaseRef.value.setCurrentRow(adviceBaseList.value[0]);
});
}
});
getAdviceBaseInfo(queryParams.value)
.then((res) => {
console.log(res.data.records);
if (res.data.records.length > 0) {
adviceBaseList.value = res.data.records.filter((item) => {
if (item.adviceType == 1 || item.adviceType == 2) {
return handleQuantity(item) != 0;
} else {
return true;
}
});
total.value = res.data.total;
nextTick(() => {
if (adviceBaseList.value.length > 0) {
currentIndex.value = 0;
setCurrentRow(adviceBaseList.value[0]);
}
});
} else {
adviceBaseList.value = [];
}
})
.catch(() => {
adviceBaseList.value = [];
})
.finally(() => {
loading.value = false;
});
}
// 处理键盘事件
const handleKeyDown = (event) => {
const handleKeyDown = (event: KeyboardEvent): void => {
const key = event.key;
const data = adviceBaseList.value;
switch (key) {
case 'ArrowUp': // 上箭头
event.preventDefault(); // 阻止默认滚动行为
event.preventDefault();
if (currentIndex.value > 0) {
currentIndex.value--;
setCurrentRow(data[currentIndex.value]);
}
break;
case 'ArrowDown': // 下箭头`
case 'ArrowDown': // 下箭头
event.preventDefault();
if (currentIndex.value < data.length - 1) {
currentIndex.value++;
@@ -128,52 +158,84 @@ const handleKeyDown = (event) => {
}
break;
case 'Enter': // 回车键
// const currentRow = adviceBaseRef.value.getSelectionRows();
event.preventDefault();
if (currentSelectRow.value) {
// 这里可以触发自定义逻辑,如弹窗、跳转等
if (currentSelectRow.value && Object.keys(currentSelectRow.value).length > 0) {
emit('selectAdviceBase', currentSelectRow.value);
}
break;
}
};
function handleQuantity(row) {
function handleQuantity(row: any): string {
if (row.inventoryList && row.inventoryList.length > 0) {
const totalQuantity = row.inventoryList.reduce((sum, item) => sum + (item.quantity || 0), 0);
return totalQuantity.toString() + row.minUnitCode_dictText;
const totalQuantity = row.inventoryList.reduce(
(sum: number, item: any) => sum + (item.quantity || 0),
0
);
return totalQuantity.toString() + (row.minUnitCode_dictText || '');
}
return 0;
return '0';
}
// 设置选中行(带滚动)
const setCurrentRow = (row) => {
adviceBaseRef.value.setCurrentRow(row);
// 滚动到选中行
const tableBody = adviceBaseRef.value.$el.querySelector('.el-table__body-wrapper');
const currentRowEl = adviceBaseRef.value.$el.querySelector('.current-row');
if (tableBody && currentRowEl) {
currentRowEl.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
const setCurrentRow = (row: any) => {
if (adviceBaseRef.value?.tableRef) {
adviceBaseRef.value.tableRef.setCurrentRow(row);
// 滚动到选中行
nextTick(() => {
const tableEl = adviceBaseRef.value?.tableRef?.$el;
if (tableEl) {
const tableBody = tableEl.querySelector('.el-table__body-wrapper');
const currentRowEl = tableEl.querySelector('.current-row');
if (tableBody && currentRowEl) {
currentRowEl.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}
}
});
}
};
// 当前行变化时更新索引
const handleCurrentChange = (currentRow) => {
currentIndex.value = adviceBaseList.value.findIndex((item) => item === currentRow);
currentSelectRow.value = currentRow;
// 行点击事件
const handleRowClick = (row: any): void => {
currentIndex.value = adviceBaseList.value.findIndex((item) => item === row);
currentSelectRow.value = row;
emit('selectAdviceBase', row);
};
function clickRow(row) {
emit('selectAdviceBase', row);
}
// 监听表格当前行变化(通过 el-table 的 current-change 事件)
watch(
() => adviceBaseRef.value?.tableRef,
(tableRef) => {
if (tableRef) {
// 通过 $el 访问原生 el-table 并监听 current-change
const elTable = tableRef.$el?.querySelector('.el-table');
if (elTable) {
// 使用 MutationObserver 或直接监听 DOM 变化来检测当前行变化
// 或者通过 watch 监听 currentSelectRow 的变化
}
}
},
{ immediate: true }
);
defineExpose({
handleKeyDown,
});
</script>
<style scoped>
.popover-table-wrapper:focus {
outline: 2px solid #409eff; /* 聚焦时的高亮效果 */
<style scoped lang="scss">
.advice-base-list-wrapper {
height: 400px;
overflow: hidden;
display: flex;
flex-direction: column;
&:focus {
outline: 2px solid #409eff;
}
}
</style>
.popover-table-wrapper:focus {
outline: 2px solid #409eff;
}
</style>

View File

@@ -1,11 +1,11 @@
import request from '@/utils/request'
import request from '@/utils/request';
export function getPatientList(queryParams) {
return request({
url: '/reg-doctorstation/advice-manage/reg-patient-zk',
method: 'get',
params: queryParams
})
params: queryParams,
});
}
// 诊断相关接口
@@ -16,8 +16,8 @@ export function saveDiagnosis(data) {
return request({
url: '/doctor-station/diagnosis/save-doctor-diagnosis',
method: 'post',
data: data
})
data: data,
});
}
/**
@@ -27,8 +27,8 @@ export function saveDiagnosisBind(data) {
return request({
url: '/doctor-station/diagnosis/diagnosis-belong-binding',
method: 'post',
data: data
})
data: data,
});
}
/**
* 删除诊断绑定
@@ -37,7 +37,7 @@ export function deleteDiagnosisBind(id) {
return request({
url: '/doctor-station/diagnosis/diagnosis-belong-binding?id=' + id,
method: 'delete',
})
});
}
/**
@@ -47,8 +47,8 @@ export function getDiagnosisDefinitionList(queryParams) {
return request({
url: '/doctor-station/diagnosis/condition-definition-metadata',
method: 'get',
params: queryParams
})
params: queryParams,
});
}
/**
@@ -58,7 +58,7 @@ export function getConditionDefinitionInfo(patientId) {
return request({
url: '/doctor-station/diagnosis/get-condition-definition-class?patientId=' + patientId,
method: 'get',
})
});
}
/**
@@ -68,29 +68,29 @@ export function diagnosisInit() {
return request({
url: '/doctor-station/diagnosis/init',
method: 'get',
})
});
}
/**
*
*
* 获取诊断回显数据
*/
export function getEncounterDiagnosis(encounterId) {
return request({
url: '/doctor-station/diagnosis/get-encounter-diagnosis?encounterId=' + encounterId,
method: 'get',
})
});
}
/**
*
*
* 删除就诊诊断
*/
export function delEncounterDiagnosis(conditionId) {
return request({
url: '/doctor-station/diagnosis/encounter-diagnosis?conditionId=' + conditionId,
method: 'delete',
})
});
}
/**
@@ -112,8 +112,8 @@ export function getTcmCondition(params) {
return request({
url: '/doctor-station/chinese-medical/condition-info',
method: 'get',
params: params
})
params: params,
});
}
/**
@@ -123,8 +123,8 @@ export function getTcmSyndrome(params) {
return request({
url: '/doctor-station/chinese-medical/syndrome-info',
method: 'get',
params: params
})
params: params,
});
}
/**
@@ -134,8 +134,8 @@ export function getTcmDiagnosis(params) {
return request({
url: '/doctor-station/chinese-medical/get-tcm-encounter-diagnosis',
method: 'get',
params: params
})
params: params,
});
}
/**
@@ -145,8 +145,8 @@ export function saveTcmDiagnosis(data) {
return request({
url: '/doctor-station/chinese-medical/save-tcm-diagnosis',
method: 'post',
data: data
})
data: data,
});
}
/**
* 获取人员慢性病诊断
@@ -155,11 +155,10 @@ export function getChronicDisease(params) {
return request({
url: '/yb-request/getConditionDefinition',
method: 'get',
params: params
})
params: params,
});
}
/**
* 获取药品列表
*/
@@ -167,8 +166,8 @@ export function getAdviceBaseInfo(queryParams) {
return request({
url: '/doctor-station/advice/advice-base-info',
method: 'get',
params: queryParams
})
params: queryParams,
});
}
/**
@@ -178,8 +177,8 @@ export function savePrescription(data) {
return request({
url: '/reg-doctorstation/advice-manage/save-reg-advice',
method: 'post',
data: data
})
data: data,
});
}
/**
* 签发处方
@@ -188,8 +187,8 @@ export function savePrescriptionSign(data) {
return request({
url: '/reg-doctorstation/advice-manage/sign-reg-advice',
method: 'post',
data: data
})
data: data,
});
}
/**
* 处方签退
@@ -198,8 +197,8 @@ export function singOut(data) {
return request({
url: '/reg-doctorstation/advice-manage/sign-off-reg',
method: 'post',
data: data
})
data: data,
});
}
/**
* 停嘱
@@ -208,8 +207,8 @@ export function stopAdvice(data) {
return request({
url: '/reg-doctorstation/advice-manage/stop-reg-advice',
method: 'post',
data: data
})
data: data,
});
}
/**
* 获取患者本次就诊处方
@@ -218,7 +217,7 @@ export function getPrescriptionList(encounterId) {
return request({
url: '/reg-doctorstation/advice-manage/reg-request-base-info?encounterId=' + encounterId,
method: 'get',
})
});
}
/**
@@ -228,8 +227,8 @@ export function getContract(params) {
return request({
url: '/doctor-station/advice/get-encounter-contract',
method: 'get',
params: params
})
params: params,
});
}
/**
@@ -239,7 +238,7 @@ export function getOrgTree() {
return request({
url: '/base-data-manage/organization/organization',
method: 'get',
})
});
}
@@ -258,6 +257,28 @@ export function updateGroupId(data) {
return request({
url: '/doctor-station/advice/update-groupid',
method: 'put',
data: data
})
data: data,
});
}
/**
* 查询项目绑定信息
*/
export function getBindDevice(data) {
return request({
url: '/doctor-station/advice/order-bind-info',
method: 'get',
params: data,
});
}
/**
* 出院
*/
export function leaveHospital(data) {
return request({
url: '/reg-doctorstation/special-advice/leave-hospital-orders',
method: 'post',
data: data,
});
}

View File

@@ -1,5 +1,9 @@
<<<<<<< HEAD
import request from '@/utils/request'
=======
import request from '@/utils/request';
>>>>>>> v1.3
// 申请单相关接口
/**
@@ -9,8 +13,8 @@ export function getCheck(queryParams) {
return request({
url: '/reg-doctorstation/request-form/get-check',
method: 'get',
params: queryParams
})
params: queryParams,
});
}
/**
* 查询检验申请单
@@ -19,8 +23,8 @@ export function getInspection(queryParams) {
return request({
url: '/reg-doctorstation/request-form/get-inspection',
method: 'get',
params: queryParams
})
params: queryParams,
});
}
/**
* 查询输血申请单
@@ -29,8 +33,8 @@ export function getBloodTransfusion(queryParams) {
return request({
url: '/reg-doctorstation/request-form/get-blood-transfusion',
method: 'get',
params: queryParams
})
params: queryParams,
});
}
/**
* 查询手术申请单
@@ -39,12 +43,22 @@ export function getSurgery(queryParams) {
return request({
url: '/reg-doctorstation/request-form/get-surgery',
method: 'get',
params: queryParams
})
params: queryParams,
});
}
/**
* 查询护理医嘱信息
*/
export function getNursingOrdersInfos() {
return request({
url: '/reg-doctorstation/special-advice/nursing-orders',
method: 'get',
});
}
/**
<<<<<<< HEAD
* 查询护理医嘱信息
*/
export function getNursingOrdersInfos() {
@@ -55,6 +69,8 @@ export function getNursingOrdersInfos() {
}
/**
=======
>>>>>>> v1.3
* 保存护理医嘱信息
* @param {Object} data - 护理医嘱数据
* @param {number} data.encounterId - 就诊id
@@ -71,8 +87,13 @@ export function saveNursingOrders(data) {
return request({
url: '/reg-doctorstation/special-advice/nursing-orders',
method: 'post',
<<<<<<< HEAD
data: data
})
=======
data: data,
});
>>>>>>> v1.3
}
/**
@@ -82,8 +103,33 @@ export function getEncounterNursingOrders(params) {
return request({
url: '/reg-doctorstation/special-advice/encounter-nursing-orders',
method: 'get',
<<<<<<< HEAD
params: params
})
=======
params: params,
});
>>>>>>> v1.3
}
/**
* 查询检验报告 url
*/
export function getProofResult(queryParams) {
return request({
url: '/doctor-station/advice/proof-result',
method: 'get',
params: queryParams,
});
}
/**
* 查询检查报告 url
*/
export function getTestResult(queryParams) {
return request({
url: '/doctor-station/advice/test-result',
method: 'get',
params: queryParams,
});
}

View File

@@ -1,87 +1,318 @@
<!--
* @Author: sjjh
* @Date: 2025-09-05 21:16:06
* @Description: 输血申请详情
-->
<template>
<div class="applicationShow-container">
<div class="applicationShow-container-header">
<el-button @click="getInfo">刷新</el-button>
</div>
<div class="applicationShow-container-content">
<el-descriptions title="输血申请详情" :column="2">
<el-descriptions-item label="Username">kooriookami</el-descriptions-item>
<el-descriptions-item label="患者姓名">{{ patientInfoValue?.patientName || '-' }}</el-descriptions-item>
<el-descriptions-item label="患者性别">{{ patientInfoValue?.patientSex || '-' }}</el-descriptions-item>
<el-descriptions-item label="患者年龄">{{ patientInfoValue?.patientAge || '-' }}</el-descriptions-item>
<el-descriptions-item label="患者手机号">{{ patientInfoValue?.patientPhone || '-' }}</el-descriptions-item>
<el-descriptions-item label="患者身份证号">{{ patientInfoValue?.patientIdCard || '-' }}</el-descriptions-item>
<el-descriptions-item label="患者地址">{{ patientInfoValue?.patientAddress || '-' }}</el-descriptions-item>
</el-descriptions>
</div>
<div class="applicationShow-container-table">
<el-table :data="dataList">
<el-table-column label="医嘱名称" prop="adviceName" />
<el-table-column label="输血数量" prop="adviceDefinitionId" />
</el-table>
<div class="report-container">
<div class="report-section">
<div class="report-title">
<span>输血申请</span>
<el-icon
class="report-refresh-icon"
:class="{ 'is-loading': loading }"
@click="handleRefresh"
>
<Refresh />
</el-icon>
</div>
<div class="report-table-wrapper">
<el-table
v-loading="loading"
:data="tableData"
border
size="small"
height="100%"
style="width: 100%"
>
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="patientName" label="患者姓名" width="120" />
<el-table-column prop="name" label="申请单名称" width="140" />
<el-table-column prop="createTime" label="创建时间" width="160" />
<el-table-column prop="prescriptionNo" label="处方号" width="140" />
<el-table-column prop="requesterId_dictText" label="申请者" width="120" />
<el-table-column label="操作" align="center" fixed="right">
<template #default="scope">
<el-button link type="primary" @click="handleViewDetail(scope.row)">详情</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
<!-- 详情弹窗 -->
<el-dialog
v-model="detailDialogVisible"
title="输血申请详情"
width="800px"
destroy-on-close
top="5vh"
:close-on-click-modal="false"
>
<div v-if="currentDetail" class="applicationShow-container">
<div class="applicationShow-container-content">
<el-descriptions title="基本信息" :column="2">
<el-descriptions-item label="患者姓名">{{
currentDetail.patientName || '-'
}}</el-descriptions-item>
<el-descriptions-item label="申请单名称">{{
currentDetail.name || '-'
}}</el-descriptions-item>
<el-descriptions-item label="创建时间">{{
currentDetail.createTime || '-'
}}</el-descriptions-item>
<el-descriptions-item label="处方号">{{
currentDetail.prescriptionNo || '-'
}}</el-descriptions-item>
<el-descriptions-item label="申请者">{{
currentDetail.requesterId_dictText || '-'
}}</el-descriptions-item>
<el-descriptions-item label="就诊ID">{{
currentDetail.encounterId || '-'
}}</el-descriptions-item>
<el-descriptions-item label="申请单ID">{{
currentDetail.requestFormId || '-'
}}</el-descriptions-item>
</el-descriptions>
</div>
<div v-if="descJsonData && hasMatchedFields" class="applicationShow-container-content">
<el-descriptions title="申请单描述" :column="2">
<template v-for="(value, key) in descJsonData" :key="key">
<el-descriptions-item v-if="isFieldMatched(key)" :label="getFieldLabel(key)">
{{ value || '-' }}
</el-descriptions-item>
</template>
</el-descriptions>
</div>
<div
v-if="currentDetail.requestFormDetailList && currentDetail.requestFormDetailList.length"
class="applicationShow-container-table"
>
<el-table :data="currentDetail.requestFormDetailList" border>
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="adviceName" label="医嘱名称" />
<el-table-column prop="quantity" label="数量" width="80" align="center" />
<el-table-column prop="unitCode_dictText" label="单位" width="100" />
<el-table-column prop="totalPrice" label="总价" width="100" align="right" />
</el-table>
</div>
</div>
<template #footer>
<el-button @click="detailDialogVisible = false">关闭</el-button>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { getCurrentInstance, onBeforeMount, onMounted, reactive, ref, computed } from 'vue'
import { getBloodTransfusion } from './api';
import { getCurrentInstance, ref, watch, computed } from 'vue';
import { Refresh } from '@element-plus/icons-vue';
import { patientInfo } from '../../store/patient.js';
import { getBloodTransfusion } from './api';
import { getOrgList } from '../../../../doctorstation/components/api.js';
const { proxy } = getCurrentInstance();
const emits = defineEmits([])
const props = defineProps({
})
const state = reactive({
const tableData = ref([]);
const loading = ref(false);
const detailDialogVisible = ref(false);
const currentDetail = ref(null);
const descJsonData = ref(null);
const orgOptions = ref([]);
})
// 使用计算属性确保安全访问
const patientInfoValue = computed(() => {
return patientInfo.value || {};
});
const dataList = ref([])
const getInfo = () => {
if (patientInfo.value?.inHospitalOrgId) {
getBloodTransfusion({
encounterId: patientInfo.value.encounterId,
}).then((res) => {
if (res.code === 200) {
dataList.value = res.data
} else {
}
});
const fetchData = async () => {
if (!patientInfo.value?.encounterId) {
tableData.value = [];
loading.value = false;
return;
}
loading.value = true;
try {
const res = await getBloodTransfusion({ encounterId: patientInfo.value.encounterId });
if (res.code === 200 && res.data) {
const raw = res.data?.records || res.data;
const list = Array.isArray(raw) ? raw : [raw];
tableData.value = list.filter(Boolean);
} else {
tableData.value = [];
}
} catch (e) {
proxy.$modal?.msgError?.(e.message || '查询输血申请失败');
tableData.value = [];
} finally {
loading.value = false;
}
};
onBeforeMount(() => {
})
onMounted(() => {
getInfo()
})
defineExpose({ state })
const handleRefresh = async () => {
if (loading.value || !patientInfo.value?.encounterId) return;
await fetchData();
};
const labelMap = {
categoryType: '项目类别',
targetDepartment: '发往科室',
symptom: '症状',
sign: '体征',
clinicalDiagnosis: '临床诊断',
otherDiagnosis: '其他诊断',
relatedResult: '相关结果',
attention: '注意事项',
};
const isFieldMatched = (key) => {
return key in labelMap;
};
const getFieldLabel = (key) => {
return labelMap[key] || key;
};
const hasMatchedFields = computed(() => {
if (!descJsonData.value) return false;
return Object.keys(descJsonData.value).some((key) => isFieldMatched(key));
});
/** 查询科室 */
const getLocationInfo = () => {
getOrgList().then((res) => {
orgOptions.value = res.data.records;
});
};
const recursionFun = (targetDepartment) => {
let name = '';
for (let index = 0; index < orgOptions.value.length; index++) {
const obj = orgOptions.value[index];
if (obj.id == targetDepartment) {
name = obj.name;
}
const subObjArray = obj['children'];
for (let index = 0; index < subObjArray.length; index++) {
const item = subObjArray[index];
if (item.id == targetDepartment) {
name = item.name;
}
}
}
return name;
};
const handleViewDetail = (row) => {
currentDetail.value = row;
// 解析 descJson
if (row.descJson) {
try {
// descJsonData.value = JSON.parse(row.descJson);
const obj = JSON.parse(row.descJson);
obj.targetDepartment = recursionFun(obj.targetDepartment);
descJsonData.value = obj;
} catch (e) {
console.error('解析 descJson 失败:', e);
descJsonData.value = null;
}
} else {
descJsonData.value = null;
}
detailDialogVisible.value = true;
};
watch(
() => patientInfo.value?.encounterId,
(val) => {
if (val) {
fetchData();
getLocationInfo();
} else {
tableData.value = [];
}
},
{ immediate: true }
);
defineExpose({
refresh: fetchData,
});
</script>
<style lang="scss" scoped>
<style scoped lang="scss">
.report-container {
display: flex;
flex-direction: column;
gap: 12px;
padding: 8px 0;
height: 100%;
}
.report-section {
background: #fff;
flex: 1;
min-height: 0;
display: flex;
flex-direction: column;
}
.report-title {
font-weight: 600;
margin-bottom: 8px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 8px;
}
.report-table-wrapper {
flex: 1;
min-height: 0;
overflow: auto;
padding: 0 8px;
}
.report-refresh-icon {
cursor: pointer;
color: #909399;
transition: color 0.2s;
font-size: 18px;
}
.report-refresh-icon:hover {
color: #409eff;
}
.report-refresh-icon.is-loading {
animation: rotating 2s linear infinite;
}
@keyframes rotating {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
:deep(.el-dialog__body) {
padding-top: 0 !important;
}
.applicationShow-container {
display: flex;
flex-direction: column;
height: 100%;
max-height: 70vh;
width: 100%;
overflow-y: auto;
.applicationShow-container-header{
height: 44px;
display: flex;
align-items: center;
gap:8px;
padding: 0 16px;
.applicationShow-container-content {
flex-shrink: 0;
margin-bottom: 0px;
}
.applicationShow-container-content{
flex: 1;
}
.applicationShow-container-table{
height: 400px;
flex:auto
.applicationShow-container-table {
flex-shrink: 0;
max-height: 300px;
overflow: auto;
}
}
</style>
</style>

View File

@@ -4,42 +4,316 @@
* @Description: 检查申请详情
-->
<template>
<div class="container">
<el-button @click="getInfo">查询</el-button>
<div class="report-container">
<div class="report-section">
<div class="report-title">
<span>检查申请</span>
<el-icon
class="report-refresh-icon"
:class="{ 'is-loading': loading }"
@click="handleRefresh"
>
<Refresh />
</el-icon>
</div>
<div class="report-table-wrapper">
<el-table
v-loading="loading"
:data="tableData"
border
size="small"
height="100%"
style="width: 100%"
>
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="patientName" label="患者姓名" width="120" />
<el-table-column prop="name" label="申请单名称" width="140" />
<el-table-column prop="createTime" label="创建时间" width="160" />
<el-table-column prop="prescriptionNo" label="处方号" width="140" />
<el-table-column prop="requesterId_dictText" label="申请者" width="120" />
<el-table-column label="操作" align="center" fixed="right">
<template #default="scope">
<el-button link type="primary" @click="handleViewDetail(scope.row)">详情</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
<!-- 详情弹窗 -->
<el-dialog
v-model="detailDialogVisible"
title="检查申请详情"
width="800px"
destroy-on-close
top="5vh"
:close-on-click-modal="false"
>
<div v-if="currentDetail" class="applicationShow-container">
<div class="applicationShow-container-content">
<el-descriptions title="基本信息" :column="2">
<el-descriptions-item label="患者姓名">{{
currentDetail.patientName || '-'
}}</el-descriptions-item>
<el-descriptions-item label="申请单名称">{{
currentDetail.name || '-'
}}</el-descriptions-item>
<el-descriptions-item label="创建时间">{{
currentDetail.createTime || '-'
}}</el-descriptions-item>
<el-descriptions-item label="处方号">{{
currentDetail.prescriptionNo || '-'
}}</el-descriptions-item>
<el-descriptions-item label="申请者">{{
currentDetail.requesterId_dictText || '-'
}}</el-descriptions-item>
<el-descriptions-item label="就诊ID">{{
currentDetail.encounterId || '-'
}}</el-descriptions-item>
<el-descriptions-item label="申请单ID">{{
currentDetail.requestFormId || '-'
}}</el-descriptions-item>
</el-descriptions>
</div>
<div v-if="descJsonData && hasMatchedFields" class="applicationShow-container-content">
<el-descriptions title="申请单描述" :column="2">
<template v-for="(value, key) in descJsonData" :key="key">
<el-descriptions-item v-if="isFieldMatched(key)" :label="getFieldLabel(key)">
{{ value || '-' }}
</el-descriptions-item>
</template>
</el-descriptions>
</div>
<div
v-if="currentDetail.requestFormDetailList && currentDetail.requestFormDetailList.length"
class="applicationShow-container-table"
>
<el-table :data="currentDetail.requestFormDetailList" border>
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="adviceName" label="医嘱名称" />
<el-table-column prop="quantity" label="数量" width="80" align="center" />
<el-table-column prop="unitCode_dictText" label="单位" width="100" />
<el-table-column prop="totalPrice" label="总价" width="100" align="right" />
</el-table>
</div>
</div>
<template #footer>
<el-button @click="detailDialogVisible = false">关闭</el-button>
</template>
</el-dialog>
</div>
</template>
<script setup >
import { getCurrentInstance, onBeforeMount, onMounted, reactive } from 'vue'
import { getCheck } from './api';
</template>
<script setup>
import { getCurrentInstance, ref, watch, computed } from 'vue';
import { Refresh } from '@element-plus/icons-vue';
import { patientInfo } from '../../store/patient.js';
const { proxy } = getCurrentInstance();
const emits = defineEmits([])
const props = defineProps({
})
const state = reactive({
})
const getInfo = () => {
if (patientInfo.value?.inHospitalOrgId) {
getCheck({
encounterId: patientInfo.value.encounterId,
}).then((res) => {
if (res.code === 200) {
} else {
}
});
import { getCheck } from './api';
import { getOrgList } from '../../../../doctorstation/components/api.js';
const { proxy } = getCurrentInstance();
const tableData = ref([]);
const loading = ref(false);
const detailDialogVisible = ref(false);
const currentDetail = ref(null);
const descJsonData = ref(null);
const orgOptions = ref([]);
const fetchData = async () => {
if (!patientInfo.value?.encounterId) {
tableData.value = [];
loading.value = false;
return;
}
loading.value = true;
try {
const res = await getCheck({ encounterId: patientInfo.value.encounterId });
if (res.code === 200 && res.data) {
const raw = res.data?.records || res.data;
const list = Array.isArray(raw) ? raw : [raw];
tableData.value = list.filter(Boolean);
} else {
tableData.value = [];
}
} catch (e) {
proxy.$modal?.msgError?.(e.message || '查询检查申请失败');
tableData.value = [];
} finally {
loading.value = false;
}
};
onBeforeMount(() => {
})
onMounted(() => {
getInfo()
})
defineExpose({ state })
</script>
<style lang="scss" scoped>
</style>
const handleRefresh = async () => {
if (loading.value || !patientInfo.value?.encounterId) return;
await fetchData();
};
const labelMap = {
categoryType: '项目类别',
targetDepartment: '发往科室',
symptom: '症状',
sign: '体征',
clinicalDiagnosis: '临床诊断',
otherDiagnosis: '其他诊断',
relatedResult: '相关结果',
attention: '注意事项',
};
const isFieldMatched = (key) => {
return key in labelMap;
};
const getFieldLabel = (key) => {
return labelMap[key] || key;
};
const hasMatchedFields = computed(() => {
if (!descJsonData.value) return false;
return Object.keys(descJsonData.value).some((key) => isFieldMatched(key));
});
/** 查询科室 */
const getLocationInfo = () => {
getOrgList().then((res) => {
orgOptions.value = res.data.records;
});
};
const recursionFun = (targetDepartment) => {
let name = '';
for (let index = 0; index < orgOptions.value.length; index++) {
const obj = orgOptions.value[index];
if (obj.id == targetDepartment) {
name = obj.name;
}
const subObjArray = obj['children'];
for (let index = 0; index < subObjArray.length; index++) {
const item = subObjArray[index];
if (item.id == targetDepartment) {
name = item.name;
}
}
}
return name;
};
const handleViewDetail = (row) => {
console.log('targetDepartment========>', JSON.stringify(row));
currentDetail.value = row;
// 解析 descJson
if (row.descJson) {
try {
const obj = JSON.parse(row.descJson);
obj.targetDepartment = recursionFun(obj.targetDepartment);
descJsonData.value = obj;
} catch (e) {
console.error('解析 descJson 失败:', e);
descJsonData.value = null;
}
} else {
descJsonData.value = null;
}
detailDialogVisible.value = true;
};
watch(
() => patientInfo.value?.encounterId,
(val) => {
if (val) {
fetchData();
getLocationInfo();
} else {
tableData.value = [];
}
},
{ immediate: true }
);
defineExpose({
refresh: fetchData,
});
</script>
<style scoped lang="scss">
.report-container {
display: flex;
flex-direction: column;
gap: 12px;
padding: 8px 0;
height: 100%;
}
.report-section {
background: #fff;
flex: 1;
min-height: 0;
display: flex;
flex-direction: column;
}
.report-title {
font-weight: 600;
margin-bottom: 8px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 8px;
}
.report-table-wrapper {
flex: 1;
min-height: 0;
overflow: auto;
padding: 0 8px;
}
.report-refresh-icon {
cursor: pointer;
color: #909399;
transition: color 0.2s;
font-size: 18px;
}
.report-refresh-icon:hover {
color: #409eff;
}
.report-refresh-icon.is-loading {
animation: rotating 2s linear infinite;
}
@keyframes rotating {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
:deep(.el-dialog__body) {
padding-top: 0 !important;
}
.applicationShow-container {
display: flex;
flex-direction: column;
max-height: 70vh;
width: 100%;
overflow-y: auto;
.applicationShow-container-content {
flex-shrink: 0;
margin-bottom: 0px;
}
.applicationShow-container-table {
flex-shrink: 0;
max-height: 300px;
overflow: auto;
}
}
</style>

View File

@@ -24,7 +24,16 @@
<el-table-column prop="item" label="项目" width="180" align="center" />
<el-table-column prop="currentStatus" label="当前状态" width="260" align="center">
<template #default="scope">
<<<<<<< HEAD
<el-tag :type="getStatusType(scope.row.currentStatus)" size="small" class="status-tag">
=======
<el-tag
v-if="scope.row.currentStatus"
:type="getStatusType(scope.row.currentStatus)"
size="small"
class="status-tag"
>
>>>>>>> v1.3
{{ scope.row.currentStatus }}
</el-tag>
</template>
@@ -139,8 +148,13 @@
</el-table>
<!-- 操作按钮区域 -->
<div class="nursing-status-actions">
<<<<<<< HEAD
<el-button @click="handleCancel" size="small">取消</el-button>
<el-button type="primary" @click="handleConfirm" size="small">确定</el-button>
=======
<el-button @click="handleCancel" size="medium">取消</el-button>
<el-button type="primary" @click="handleConfirm" size="medium">确定</el-button>
>>>>>>> v1.3
</div>
</template>
</div>
@@ -376,8 +390,22 @@ const fetchNursingStatusData = () => {
loading.value = false;
if (res.code === 200 && res.data) {
<<<<<<< HEAD
// 填充各列表数据
nursingLevelList.value = res.data.nursingList || [];
=======
let nursingList = [];
let nursingOrderNameList = ['I级护理', 'II级护理', 'III级护理', '特级护理'];
nursingOrderNameList.forEach((str) => {
(res.data.nursingList || []).forEach((item) => {
if (item.nursingOrderName == str) {
nursingList.push(item);
}
});
});
// 填充各列表数据
nursingLevelList.value = nursingList || [];
>>>>>>> v1.3
conditionList.value = res.data.conditionList || [];
dietList.value = res.data.dietList || [];
positionList.value = res.data.positionList || [];

View File

@@ -0,0 +1,238 @@
<template>
<div class="report-container">
<div class="report-section">
<div class="report-title">
<span>检查报告</span>
<el-icon
class="report-refresh-icon"
:class="{ 'is-loading': loadingCheck }"
@click="handleRefreshCheck"
>
<Refresh />
</el-icon>
</div>
<div class="report-table-wrapper">
<el-table
v-loading="loadingCheck"
:data="checkReportList"
border
size="small"
height="100%"
style="width: 100%"
>
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="adviceName" label="报告名称" width="140" />
<el-table-column prop="reportNo" label="报告号" width="140" />
<el-table-column label="链接" min-width="140">
<template #default="scope">
<a
v-if="scope.row.requestUrl"
class="report-link"
:href="scope.row.requestUrl"
target="_blank"
rel="noopener noreferrer"
>
查看报告
</a>
<span v-else class="report-link-disabled">暂无链接</span>
</template>
</el-table-column>
</el-table>
</div>
</div>
<div class="report-section">
<div class="report-title">
<span>检验报告</span>
<el-icon
class="report-refresh-icon"
:class="{ 'is-loading': loadingInspection }"
@click="handleRefreshInspection"
>
<Refresh />
</el-icon>
</div>
<div class="report-table-wrapper">
<el-table
v-loading="loadingInspection"
:data="inspectionReportList"
border
size="small"
height="100%"
style="width: 100%"
>
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="adviceName" label="报告名称" width="140" />
<el-table-column prop="reportNo" label="报告号" width="140" />
<el-table-column label="链接" min-width="140">
<template #default="scope">
<a
v-if="scope.row.requestUrl"
class="report-link"
:href="scope.row.requestUrl"
target="_blank"
rel="noopener noreferrer"
>
查看报告
</a>
<span v-else class="report-link-disabled">暂无链接</span>
</template>
</el-table-column>
</el-table>
</div>
</div>
</div>
</template>
<script setup>
import { getCurrentInstance, ref, watch } from 'vue';
import { Refresh } from '@element-plus/icons-vue';
import { patientInfo } from '../../store/patient.js';
import { getProofResult, getTestResult } from './api';
const { proxy } = getCurrentInstance();
const checkReportList = ref([]);
const inspectionReportList = ref([]);
const loadingCheck = ref(false);
const loadingInspection = ref(false);
const fetchCheckReport = async () => {
if (!patientInfo.value?.encounterId) return;
const res = await getTestResult({ encounterId: patientInfo.value.encounterId });
if (res.code === 200 && res.data) {
const raw = res.data?.records || res.data;
const list = Array.isArray(raw) ? raw : [raw];
checkReportList.value = list.filter(Boolean).map((item) => ({
reportNo: item.busNo,
requestUrl: item.requestUrl,
adviceName: item.adviceName,
_raw: item,
}));
} else {
checkReportList.value = [];
}
};
const fetchInspectionReport = async () => {
if (!patientInfo.value?.encounterId) return;
const res = await getProofResult({ encounterId: patientInfo.value.encounterId });
if (res.code === 200 && res.data) {
const raw = res.data?.records || res.data;
const list = Array.isArray(raw) ? raw : [raw];
inspectionReportList.value = list.filter(Boolean).map((item) => ({
reportNo: item.busNo,
requestUrl: item.requestUrl,
adviceName: item.adviceName,
_raw: item,
}));
} else {
inspectionReportList.value = [];
}
};
const fetchAll = async () => {
if (!patientInfo.value?.encounterId) {
checkReportList.value = [];
inspectionReportList.value = [];
loadingCheck.value = false;
loadingInspection.value = false;
return;
}
loadingCheck.value = true;
loadingInspection.value = true;
try {
await Promise.all([fetchCheckReport(), fetchInspectionReport()]);
} catch (e) {
proxy.$modal?.msgError?.(e.message || '查询报告失败');
} finally {
loadingCheck.value = false;
loadingInspection.value = false;
}
};
const handleRefreshCheck = async () => {
if (loadingCheck.value || !patientInfo.value?.encounterId) return;
loadingCheck.value = true;
try {
await fetchCheckReport();
} finally {
loadingCheck.value = false;
}
};
const handleRefreshInspection = async () => {
if (loadingInspection.value || !patientInfo.value?.encounterId) return;
loadingInspection.value = true;
try {
await fetchInspectionReport();
} finally {
loadingInspection.value = false;
}
};
watch(
() => patientInfo.value?.encounterId,
(val) => {
if (val) {
fetchAll();
} else {
checkReportList.value = [];
inspectionReportList.value = [];
}
},
{ immediate: true }
);
</script>
<style scoped lang="scss">
.report-container {
display: flex;
flex-direction: column;
gap: 12px;
padding: 8px 0;
height: 100%;
}
.report-section {
background: #fff;
flex: 1;
max-height: 55%;
min-height: 0;
display: flex;
flex-direction: column;
}
.report-title {
font-weight: 600;
margin-bottom: 8px;
display: flex;
align-items: center;
justify-content: space-between;
}
.report-table-wrapper {
flex: 1;
min-height: 0;
overflow: auto;
}
.report-refresh-icon {
cursor: pointer;
color: #909399;
transition: color 0.2s;
}
.report-refresh-icon:hover {
color: #409eff;
}
.report-link {
color: #409eff;
cursor: pointer;
text-decoration: underline;
}
.report-link-disabled {
color: #c0c4cc;
}
</style>

View File

@@ -4,33 +4,315 @@
* @Description: 手术申请详情
-->
<template>
<div class="container">
<el-button @click="getInfo">查询</el-button>
<div class="report-container">
<div class="report-section">
<div class="report-title">
<span>手术申请</span>
<el-icon
class="report-refresh-icon"
:class="{ 'is-loading': loading }"
@click="handleRefresh"
>
<Refresh />
</el-icon>
</div>
<div class="report-table-wrapper">
<el-table
v-loading="loading"
:data="tableData"
border
size="small"
height="100%"
style="width: 100%"
>
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="patientName" label="患者姓名" width="120" />
<el-table-column prop="name" label="申请单名称" width="140" />
<el-table-column prop="createTime" label="创建时间" width="160" />
<el-table-column prop="prescriptionNo" label="处方号" width="140" />
<el-table-column prop="requesterId_dictText" label="申请者" width="120" />
<el-table-column label="操作" align="center" fixed="right">
<template #default="scope">
<el-button link type="primary" @click="handleViewDetail(scope.row)">详情</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
<!-- 详情弹窗 -->
<el-dialog
v-model="detailDialogVisible"
title="手术申请详情"
width="800px"
destroy-on-close
top="5vh"
:close-on-click-modal="false"
>
<div v-if="currentDetail" class="applicationShow-container">
<div class="applicationShow-container-content">
<el-descriptions title="基本信息" :column="2">
<el-descriptions-item label="患者姓名">{{
currentDetail.patientName || '-'
}}</el-descriptions-item>
<el-descriptions-item label="申请单名称">{{
currentDetail.name || '-'
}}</el-descriptions-item>
<el-descriptions-item label="创建时间">{{
currentDetail.createTime || '-'
}}</el-descriptions-item>
<el-descriptions-item label="处方号">{{
currentDetail.prescriptionNo || '-'
}}</el-descriptions-item>
<el-descriptions-item label="申请者">{{
currentDetail.requesterId_dictText || '-'
}}</el-descriptions-item>
<el-descriptions-item label="就诊ID">{{
currentDetail.encounterId || '-'
}}</el-descriptions-item>
<el-descriptions-item label="申请单ID">{{
currentDetail.requestFormId || '-'
}}</el-descriptions-item>
</el-descriptions>
</div>
<div v-if="descJsonData && hasMatchedFields" class="applicationShow-container-content">
<el-descriptions title="申请单描述" :column="2">
<template v-for="(value, key) in descJsonData" :key="key">
<el-descriptions-item v-if="isFieldMatched(key)" :label="getFieldLabel(key)">
{{ value || '-' }}
</el-descriptions-item>
</template>
</el-descriptions>
</div>
<div
v-if="currentDetail.requestFormDetailList && currentDetail.requestFormDetailList.length"
class="applicationShow-container-table"
>
<el-table :data="currentDetail.requestFormDetailList" border>
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="adviceName" label="医嘱名称" />
<el-table-column prop="quantity" label="数量" width="80" align="center" />
<el-table-column prop="unitCode_dictText" label="单位" width="100" />
<el-table-column prop="totalPrice" label="总价" width="100" align="right" />
</el-table>
</div>
</div>
<template #footer>
<el-button @click="detailDialogVisible = false">关闭</el-button>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { getCurrentInstance, onBeforeMount, onMounted, reactive } from 'vue';
import { getSurgery } from './api';
import { getCurrentInstance, ref, watch, computed } from 'vue';
import { Refresh } from '@element-plus/icons-vue';
import { patientInfo } from '../../store/patient.js';
import { getSurgery } from './api';
import { getOrgList } from '../../../../doctorstation/components/api.js';
const { proxy } = getCurrentInstance();
const emits = defineEmits([]);
const props = defineProps({});
const state = reactive({});
const getInfo = () => {
if (patientInfo.value?.inHospitalOrgId) {
getSurgery({
encounterId: patientInfo.value.encounterId,
}).then((res) => {
if (res.code === 200) {
} else {
}
});
const tableData = ref([]);
const loading = ref(false);
const detailDialogVisible = ref(false);
const currentDetail = ref(null);
const descJsonData = ref(null);
const orgOptions = ref([]);
const fetchData = async () => {
if (!patientInfo.value?.encounterId) {
tableData.value = [];
loading.value = false;
return;
}
loading.value = true;
try {
const res = await getSurgery({ encounterId: patientInfo.value.encounterId });
if (res.code === 200 && res.data) {
const raw = res.data?.records || res.data;
const list = Array.isArray(raw) ? raw : [raw];
tableData.value = list.filter(Boolean);
} else {
tableData.value = [];
}
} catch (e) {
proxy.$modal?.msgError?.(e.message || '查询手术申请失败');
tableData.value = [];
} finally {
loading.value = false;
}
};
onBeforeMount(() => {});
onMounted(() => {
getInfo();
const handleRefresh = async () => {
if (loading.value || !patientInfo.value?.encounterId) return;
await fetchData();
};
const labelMap = {
categoryType: '项目类别',
targetDepartment: '发往科室',
symptom: '症状',
sign: '体征',
clinicalDiagnosis: '临床诊断',
otherDiagnosis: '其他诊断',
relatedResult: '相关结果',
attention: '注意事项',
};
const isFieldMatched = (key) => {
return key in labelMap;
};
const getFieldLabel = (key) => {
return labelMap[key] || key;
};
const hasMatchedFields = computed(() => {
if (!descJsonData.value) return false;
return Object.keys(descJsonData.value).some((key) => isFieldMatched(key));
});
/** 查询科室 */
const getLocationInfo = () => {
getOrgList().then((res) => {
orgOptions.value = res.data.records;
});
};
const recursionFun = (targetDepartment) => {
let name = '';
for (let index = 0; index < orgOptions.value.length; index++) {
const obj = orgOptions.value[index];
if (obj.id == targetDepartment) {
name = obj.name;
}
const subObjArray = obj['children'];
for (let index = 0; index < subObjArray.length; index++) {
const item = subObjArray[index];
if (item.id == targetDepartment) {
name = item.name;
}
}
}
return name;
};
const handleViewDetail = (row) => {
currentDetail.value = row;
// 解析 descJson
if (row.descJson) {
try {
// descJsonData.value = JSON.parse(row.descJson);
const obj = JSON.parse(row.descJson);
obj.targetDepartment = recursionFun(obj.targetDepartment);
descJsonData.value = obj;
} catch (e) {
console.error('解析 descJson 失败:', e);
descJsonData.value = null;
}
} else {
descJsonData.value = null;
}
detailDialogVisible.value = true;
};
watch(
() => patientInfo.value?.encounterId,
(val) => {
if (val) {
fetchData();
getLocationInfo();
} else {
tableData.value = [];
}
},
{ immediate: true }
);
defineExpose({
refresh: fetchData,
});
defineExpose({ state });
</script>
<style lang="scss" scoped></style>
<style scoped lang="scss">
.report-container {
display: flex;
flex-direction: column;
gap: 12px;
padding: 8px 0;
height: 100%;
}
.report-section {
background: #fff;
flex: 1;
min-height: 0;
display: flex;
flex-direction: column;
}
.report-title {
font-weight: 600;
margin-bottom: 8px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 8px;
}
.report-table-wrapper {
flex: 1;
min-height: 0;
overflow: auto;
padding: 0 8px;
}
.report-refresh-icon {
cursor: pointer;
color: #909399;
transition: color 0.2s;
font-size: 18px;
}
.report-refresh-icon:hover {
color: #409eff;
}
.report-refresh-icon.is-loading {
animation: rotating 2s linear infinite;
}
@keyframes rotating {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
:deep(.el-dialog__body) {
padding-top: 0 !important;
}
.applicationShow-container {
display: flex;
flex-direction: column;
max-height: 70vh;
width: 100%;
overflow-y: auto;
.applicationShow-container-content {
flex-shrink: 0;
margin-bottom: 0px;
}
.applicationShow-container-table {
flex-shrink: 0;
max-height: 300px;
overflow: auto;
}
}
</style>

View File

@@ -4,34 +4,315 @@
* @Description: 检验申请
-->
<template>
<div class="container">
<el-button @click="getInfo">查询</el-button>
<div class="report-container">
<div class="report-section">
<div class="report-title">
<span>检验申请</span>
<el-icon
class="report-refresh-icon"
:class="{ 'is-loading': loading }"
@click="handleRefresh"
>
<Refresh />
</el-icon>
</div>
<div class="report-table-wrapper">
<el-table
v-loading="loading"
:data="tableData"
border
size="small"
height="100%"
style="width: 100%"
>
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="patientName" label="患者姓名" width="120" />
<el-table-column prop="name" label="申请单名称" width="140" />
<el-table-column prop="createTime" label="创建时间" width="160" />
<el-table-column prop="prescriptionNo" label="处方号" width="140" />
<el-table-column prop="requesterId_dictText" label="申请者" width="120" />
<el-table-column label="操作" align="center" fixed="right">
<template #default="scope">
<el-button link type="primary" @click="handleViewDetail(scope.row)">详情</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
<!-- 详情弹窗 -->
<el-dialog
v-model="detailDialogVisible"
title="检验申请详情"
width="800px"
destroy-on-close
top="5vh"
:close-on-click-modal="false"
>
<div v-if="currentDetail" class="applicationShow-container">
<div class="applicationShow-container-content">
<el-descriptions title="基本信息" :column="2">
<el-descriptions-item label="患者姓名">{{
currentDetail.patientName || '-'
}}</el-descriptions-item>
<el-descriptions-item label="申请单名称">{{
currentDetail.name || '-'
}}</el-descriptions-item>
<el-descriptions-item label="创建时间">{{
currentDetail.createTime || '-'
}}</el-descriptions-item>
<el-descriptions-item label="处方号">{{
currentDetail.prescriptionNo || '-'
}}</el-descriptions-item>
<el-descriptions-item label="申请者">{{
currentDetail.requesterId_dictText || '-'
}}</el-descriptions-item>
<el-descriptions-item label="就诊ID">{{
currentDetail.encounterId || '-'
}}</el-descriptions-item>
<el-descriptions-item label="申请单ID">{{
currentDetail.requestFormId || '-'
}}</el-descriptions-item>
</el-descriptions>
</div>
<div v-if="descJsonData && hasMatchedFields" class="applicationShow-container-content">
<el-descriptions title="申请单描述" :column="2">
<template v-for="(value, key) in descJsonData" :key="key">
<el-descriptions-item v-if="isFieldMatched(key)" :label="getFieldLabel(key)">
{{ value || '-' }}
</el-descriptions-item>
</template>
</el-descriptions>
</div>
<div
v-if="currentDetail.requestFormDetailList && currentDetail.requestFormDetailList.length"
class="applicationShow-container-table"
>
<el-table :data="currentDetail.requestFormDetailList" border>
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="adviceName" label="医嘱名称" />
<el-table-column prop="quantity" label="数量" width="80" align="center" />
<el-table-column prop="unitCode_dictText" label="单位" width="100" />
<el-table-column prop="totalPrice" label="总价" width="100" align="right" />
</el-table>
</div>
</div>
<template #footer>
<el-button @click="detailDialogVisible = false">关闭</el-button>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { getCurrentInstance, onBeforeMount, onMounted, reactive } from 'vue';
import { getInspection } from './api';
import { getCurrentInstance, ref, watch, computed } from 'vue';
import { Refresh } from '@element-plus/icons-vue';
import { patientInfo } from '../../store/patient.js';
import { getInspection } from './api';
import { getOrgList } from '../../../../doctorstation/components/api.js';
const { proxy } = getCurrentInstance();
const emits = defineEmits([]);
const props = defineProps({});
const state = reactive({});
const getInfo = () => {
if (patientInfo.value?.inHospitalOrgId) {
getInspection({
encounterId: patientInfo.value.encounterId,
}).then((res) => {
if (res.code === 200) {
} else {
}
});
const tableData = ref([]);
const loading = ref(false);
const detailDialogVisible = ref(false);
const currentDetail = ref(null);
const descJsonData = ref(null);
const orgOptions = ref([]);
const fetchData = async () => {
if (!patientInfo.value?.encounterId) {
tableData.value = [];
loading.value = false;
return;
}
loading.value = true;
try {
const res = await getInspection({ encounterId: patientInfo.value.encounterId });
if (res.code === 200 && res.data) {
const raw = res.data?.records || res.data;
const list = Array.isArray(raw) ? raw : [raw];
tableData.value = list.filter(Boolean);
} else {
tableData.value = [];
}
} catch (e) {
proxy.$modal?.msgError?.(e.message || '查询检验申请失败');
tableData.value = [];
} finally {
loading.value = false;
}
};
onBeforeMount(() => {});
onMounted(() => {
getInfo();
const handleRefresh = async () => {
if (loading.value || !patientInfo.value?.encounterId) return;
await fetchData();
};
const labelMap = {
categoryType: '项目类别',
targetDepartment: '发往科室',
symptom: '症状',
sign: '体征',
clinicalDiagnosis: '临床诊断',
otherDiagnosis: '其他诊断',
relatedResult: '相关结果',
attention: '注意事项',
};
const isFieldMatched = (key) => {
return key in labelMap;
};
const getFieldLabel = (key) => {
return labelMap[key] || key;
};
const hasMatchedFields = computed(() => {
if (!descJsonData.value) return false;
return Object.keys(descJsonData.value).some((key) => isFieldMatched(key));
});
/** 查询科室 */
const getLocationInfo = () => {
getOrgList().then((res) => {
orgOptions.value = res.data.records;
});
};
const recursionFun = (targetDepartment) => {
let name = '';
for (let index = 0; index < orgOptions.value.length; index++) {
const obj = orgOptions.value[index];
if (obj.id == targetDepartment) {
name = obj.name;
}
const subObjArray = obj['children'];
for (let index = 0; index < subObjArray.length; index++) {
const item = subObjArray[index];
if (item.id == targetDepartment) {
name = item.name;
}
}
}
return name;
};
const handleViewDetail = (row) => {
currentDetail.value = row;
// 解析 descJson
if (row.descJson) {
try {
const obj = JSON.parse(row.descJson);
obj.targetDepartment = recursionFun(obj.targetDepartment);
descJsonData.value = obj;
// descJsonData.value = JSON.parse(row.descJson);
} catch (e) {
console.error('解析 descJson 失败:', e);
descJsonData.value = null;
}
} else {
descJsonData.value = null;
}
detailDialogVisible.value = true;
};
watch(
() => patientInfo.value?.encounterId,
(val) => {
if (val) {
fetchData();
getLocationInfo();
} else {
tableData.value = [];
}
},
{ immediate: true }
);
defineExpose({
refresh: fetchData,
});
defineExpose({ state });
</script>
<style lang="scss" scoped></style>
<style scoped lang="scss">
.report-container {
display: flex;
flex-direction: column;
gap: 12px;
padding: 8px 0;
height: 100%;
}
.report-section {
background: #fff;
flex: 1;
min-height: 0;
display: flex;
flex-direction: column;
}
.report-title {
font-weight: 600;
margin-bottom: 8px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 8px;
}
.report-table-wrapper {
flex: 1;
min-height: 0;
overflow: auto;
padding: 0 8px;
}
.report-refresh-icon {
cursor: pointer;
color: #909399;
transition: color 0.2s;
font-size: 18px;
}
.report-refresh-icon:hover {
color: #409eff;
}
.report-refresh-icon.is-loading {
animation: rotating 2s linear infinite;
}
@keyframes rotating {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
:deep(.el-dialog__body) {
padding-top: 0 !important;
}
.applicationShow-container {
display: flex;
flex-direction: column;
max-height: 70vh;
width: 100%;
overflow-y: auto;
.applicationShow-container-content {
flex-shrink: 0;
margin-bottom: 0px;
}
.applicationShow-container-table {
flex-shrink: 0;
max-height: 300px;
overflow: auto;
}
}
</style>

View File

@@ -20,7 +20,7 @@
</el-input>
</div>
<el-table
:data="conditionList"
:data="conditionDatas"
max-height="460"
@row-click="handleClickRow"
highlight-current-row
@@ -33,7 +33,7 @@
<div class="syndrome-section">
<div class="section-title">证候</div>
<div class="search-box">
<el-input v-model="searchDisease" placeholder="搜索疾病名称或编码" clearable>
<el-input v-model="searchMiddleDisease" placeholder="搜索疾病名称或编码" clearable>
<template #prefix>
<el-icon><search /></el-icon>
</template>
@@ -41,7 +41,7 @@
</div>
<div v-if="selectedDisease">
<el-table
:data="syndromeList"
:data="syndromeListDatas"
max-height="460"
@row-click="clickSyndromeRow"
highlight-current-row
@@ -85,13 +85,14 @@
</template>
</el-dialog>
</template>
<script setup>
import {
getTcmCondition,
getTcmSyndrome,
saveTcmDiagnosis,
} from '@/views/doctorstation/components/api';
import { computed } from 'vue';
const props = defineProps({
openAddDiagnosisDialog: {
@@ -111,6 +112,8 @@ const tcmDiagonsisSaveList = ref([]);
const syndromeSelected = ref(false); // 当前诊断是否选择对应证候
const timestamp = ref('');
const selectedDisease = ref(false);
const searchDisease = ref('');
const searchMiddleDisease = ref('');
const { proxy } = getCurrentInstance();
const emit = defineEmits(['close']);
@@ -120,6 +123,26 @@ function handleOpen() {
});
}
// 搜索诊断
const conditionDatas = computed(() => {
return conditionList.value.filter((item) => {
if (searchDisease.value) {
return searchDisease.value == item.name || searchDisease.value == item.ybNo;
}
return conditionList;
});
});
// 后证
const syndromeListDatas = computed(() => {
return syndromeList.value.filter((item) => {
if (searchMiddleDisease.value) {
return searchMiddleDisease.value == item.name || searchMiddleDisease.value == item.ybNo;
}
return syndromeList;
});
});
// 点击诊断列表处理,点击以后才显示证候列表
function handleClickRow(row) {
if (syndromeSelected.value || tcmDiagonsisList.value == 0) {
@@ -156,7 +179,7 @@ function clickSyndromeRow(row) {
// 删除诊断
function removeDiagnosis(row, index) {
tcmDiagonsisList.value.splice(index, 1);
tcmDiagonsisSaveList.value = tcmDiagonsisSaveList.filter((item) => {
tcmDiagonsisSaveList.value = tcmDiagonsisSaveList.value.filter((item) => {
return item.syndromeGroupNo !== row.syndromeGroupNo;
});
}
@@ -418,4 +441,4 @@ function close() {
padding: 20px 0;
text-align: center;
}
</style>
</style>

View File

@@ -28,7 +28,16 @@
<span>{{ node.label }}</span>
<span class="tree-node-actions">
<template v-if="node.level === 1 && data.name != '常用' && data.name != '历史'">
<<<<<<< HEAD
<el-button style="color: #000000" type="text" size="small" @click.stop="addChild(data)">
=======
<el-button
style="color: #000000"
type="text"
size="small"
@click.stop="addChild(data)"
>
>>>>>>> v1.3
<el-icon>
<Plus />
</el-icon>
@@ -37,11 +46,25 @@
<el-popconfirm width="200" :hide-after="10" title="确认删除此常用诊断吗" placement="top-start"
@confirm="deleteChild(data)">
<template #reference>
<<<<<<< HEAD
<el-button style="color: #000000" v-if="
node.level === 2 &&
node.parent.data.name != '常用' &&
node.parent.data.name != '历史'
" type="text" size="small" @click.stop="">
=======
<el-button
style="color: #000000"
v-if="
node.level === 2 &&
node.parent.data.name != '常用' &&
node.parent.data.name != '历史'
"
type="text"
size="small"
@click.stop=""
>
>>>>>>> v1.3
<el-icon>
<Minus />
</el-icon>
@@ -57,7 +80,7 @@
<div style="margin-bottom: 10px">
<el-button type="primary" plain @click="handleAddDiagnosis()"> 新增诊断 </el-button>
<el-button type="primary" plain @click="handleSaveDiagnosis()"> 保存诊断 </el-button>
<el-button type="primary" plain @click="handleAddTcmDiagonsis()"> 中医诊断 </el-button>
<!-- <el-button type="primary" plain @click="handleAddTcmDiagonsis()"> 中医诊断 </el-button> -->
<el-button type="primary" plain @click="handleImport()"> 导入慢性病诊断 </el-button>
</div>
@@ -170,9 +193,15 @@ import {
delEncounterDiagnosis,
isFoodDiseasesNew,
} from '../api';
import { deleteTcmDiagnosis } from '../../../../doctorstation/components/api.js';
import diagnosisdialog from '../diagnosis/diagnosisdialog.vue';
import AddDiagnosisDialog from './addDiagnosisDialog.vue';
import diagnosislist from '../diagnosis/diagnosislist.vue';
<<<<<<< HEAD
=======
import { patientInfo } from '../../store/patient.js';
import { ElMessage } from 'element-plus';
>>>>>>> v1.3
// const diagnosisList = ref([]);
const allowAdd = ref(false);
const tree = ref([]);
@@ -201,7 +230,12 @@ const rules = ref({
medTypeCode: [{ required: true, message: '请选择诊断类型', trigger: 'change' }],
diagSrtNo: [{ required: true, message: '请输入诊断序号', trigger: 'change' }],
});
<<<<<<< HEAD
const isSaving = ref(false);
=======
const diagnosisNetDatas = ref([]);
>>>>>>> v1.3
watch(
() => form.value.diagnosisList,
() => {
@@ -232,6 +266,7 @@ function getList() {
getEncounterDiagnosis(props.patientInfo.encounterId).then((res) => {
if (res.code == 200) {
<<<<<<< HEAD
// 为每个诊断项添加默认的诊断医生和时间(如果不存在)
const diagnosisList = res.data.map(item => ({
...item,
@@ -255,6 +290,28 @@ function getList() {
if (res.code == 200) {
if (res.data.illness && res.data.illness.length > 0 && res.data.symptom) {
const newList = [];
=======
const datas = (res.data || []).map((item) => {
let obj = {
...item,
};
if (obj.diagSrtNo == null) {
obj.diagSrtNo = '1';
}
return obj;
});
form.value.diagnosisList = datas;
// form.value.diagnosisList = res.data;
emits('diagnosisSave', false);
}
});
getTcmDiagnosis({ encounterId: patientInfo.value.encounterId }).then((res) => {
console.log('getTcmDiagnosis=======>', JSON.stringify(res.data.illness));
if (res.code == 200) {
if (res.data.illness.length > 0) {
diagnosisNetDatas.value = res.data.illness;
>>>>>>> v1.3
res.data.illness.forEach((item, index) => {
newList.push({
name: item.name + '-' + (res.data.symptom[index]?.name || ''),
@@ -428,7 +485,10 @@ function handleAddTcmDiagonsis() {
* 删除诊断
*/
function handleDeleteDiagnosis(row, index) {
//中医诊断用-拼接 例如:疳气-表里俱实证
const nameArr = row.name?.split('-') || [];
if (row.conditionId) {
<<<<<<< HEAD
delEncounterDiagnosis(row.conditionId).then(() => {
// 不要立即调用getList(),而是从当前列表中移除
form.value.diagnosisList.splice(index, 1);
@@ -448,8 +508,39 @@ function handleDeleteDiagnosis(row, index) {
form.value.diagnosisList = sortedList.map(item => ({ ...item }));
getTree();
});
=======
if (nameArr.length > 1) {
deleteTcmDiagnosis(row.syndromeGroupNo).then(() => {
getList();
getTree();
});
} else {
delEncounterDiagnosis(row.conditionId).then(() => {
getList();
getTree();
});
}
>>>>>>> v1.3
} else {
form.value.diagnosisList.splice(index, 1);
console.log('row============>', JSON.stringify(row));
console.log('item============>', index);
if (nameArr.length > 1) {
let obj = null;
for (let index = 0; index < diagnosisNetDatas.value.length; index++) {
const item = diagnosisNetDatas.value[index];
console.log('item.name============>', item.name);
console.log('row.name============>', row.name);
if (item.ybNo == row.ybNo) {
obj = item;
}
}
deleteTcmDiagnosis(obj.syndromeGroupNo).then(() => {
getList();
getTree();
});
} else {
form.value.diagnosisList.splice(index, 1);
}
}
}
@@ -482,6 +573,18 @@ function handleMaindise(value, index) {
* 保存诊断
*/
function handleSaveDiagnosis() {
console.log('form.value.diagnosisList=======>', JSON.stringify(form.value.diagnosisList));
for (let index = 0; index < (form.value.diagnosisList || []).length; index++) {
const item = form.value.diagnosisList[index];
if (!item.diagSrtNo) {
ElMessage({
type: 'error',
message: '请录入诊断序号',
});
break;
}
}
proxy.$refs.formRef.validate((valid) => {
if (valid) {
if (form.value.diagnosisList.length === 0) {
@@ -546,6 +649,7 @@ function closeDiagnosisDialog(str) {
openAddDiagnosisDialog.value = false;
openDiagnosis.value = false;
getTree();
getList();
}
function queryDiagnosisUse(value) { }
@@ -579,10 +683,10 @@ function handleNodeClick(data) {
// 如果是根节点,不执行任何操作
return;
}
if (!allowAdd.value) {
proxy.$modal.msgWarning('请先填写病历');
return;
}
// if (!allowAdd.value) {
// proxy.$modal.msgWarning('请先填写病历');
// return;
// }
const isDuplicate = form.value.diagnosisList.some(
(diagnosis) => diagnosis.ybNo === data.ybNo || diagnosis.name === data.name
);
@@ -625,4 +729,7 @@ defineExpose({ getList, getDetail, handleSaveDiagnosis });
align-items: center;
}
</style>
<<<<<<< HEAD
=======
>>>>>>> v1.3

View File

@@ -0,0 +1,633 @@
<template>
<el-form :model="row" :rules="rules" :ref="(el) => (formRef = el)" :label-width="100">
<div class="expend_div" style="padding: 16px; background: #f8f9fa; border-radius: 8px">
<template v-if="row.adviceType == 1">
<div style="display: flex; align-items: center; margin-bottom: 16px; gap: 16px">
<span class="medicine-title">
{{
row.adviceName +
' ' +
row.volume +
' [' +
Number(row.unitPrice).toFixed(2) +
' 元' +
'/' +
row.unitCode_dictText +
']'
}}
</span>
<el-form-item prop="lotNumber" label="药房:">
<el-select
v-model="row.inventoryId"
style="width: 330px; margin-right: 20px"
placeholder="药房"
>
<el-option
v-for="item in row.stockList"
:key="item.inventoryId"
:value="item.inventoryId"
:label="`${item.locationName} 批次号: ${item.lotNumber ?? '-'} 库存:${stockFormat(
row.partPercent,
row.unitCodeList,
item.quantity
)}`"
@click="handleNumberClick(item)"
>
<div style="display: flex; gap: 8px; align-items: center">
<span>{{ item.locationName }}</span>
<span>批次号: {{ item.lotNumber ?? '-' }}</span>
<span>
库存{{ stockFormat(row.partPercent, row.unitCodeList, item.quantity) }}
</span>
</div>
</el-option>
</el-select>
</el-form-item>
<el-form-item
label="执行次数:"
prop="executeNum"
class="required-field"
data-prop="executeNum"
v-if="row.injectFlag == 1"
>
<el-input-number
:min="1"
v-model="row.executeNum"
controls-position="right"
:controls="false"
:ref="(el) => setInputRef('executeNum', el)"
@keyup.enter.prevent="handleEnter('executeNum')"
style="width: 70px; margin-right: 20px"
/>
</el-form-item>
<span class="medicine-info"> 诊断{{ config.diagnosisName }} </span>
<span class="medicine-info"> 皮试{{ row.skinTestFlag_enumText }} </span>
<span class="medicine-info"> 注射药品{{ row.injectFlag_enumText }} </span>
<span class="total-amount" v-if="row.therapyEnum == '2'">
总金额{{ row.totalPrice ? Number(row.totalPrice).toFixed(2) + ' ' : '0.00 ' }}
</span>
</div>
<div style="display: flex; align-items: center; gap: 12px; flex-wrap: wrap">
<div class="form-group">
<!-- 单次剂量 -->
<el-form-item
label="单次用量:"
prop="doseQuantity"
class="required-field"
data-prop="doseQuantity"
>
<el-input-number
:min="0"
v-model="row.doseQuantity"
controls-position="right"
:controls="false"
style="width: 70px"
:ref="(el) => setInputRef('doseQuantity', el)"
@input="convertValues"
@keyup.enter.prevent="handleEnter('doseQuantity')"
/>
</el-form-item>
<!-- 剂量单位 -->
<el-select
v-model="row.minUnitCode"
style="width: 70px; margin-right: 32px"
placeholder=" "
>
<template v-for="item in row.unitCodeList" :key="item.value">
<el-option
v-if="item.type == config.unitMap['minUnit']"
:value="item.value"
:label="item.label"
/>
</template>
</el-select>
<span>=</span>
<!-- 单次剂量 -->
<el-form-item prop="dose" class="required-field" data-prop="dose" label-width="0">
<el-input-number
v-model="row.dose"
controls-position="right"
:controls="false"
style="width: 70px; margin-left: 32px"
:ref="(el) => setInputRef('dose', el)"
@input="convertDoseValues"
@keyup.enter.prevent="handleEnter('dose')"
/>
</el-form-item>
<!-- 全部单位 -->
<el-select
v-model="row.doseUnitCode"
style="width: 70px"
placeholder=" "
@change="convertValues"
>
<el-option
v-for="item in row.unitCodeList"
:value="item.value"
:label="item.label"
:key="item.value"
/>
</el-select>
</div>
<div class="form-group">
<el-form-item
label="给药途径:"
prop="methodCode"
class="required-field"
data-prop="methodCode"
>
<el-select
v-model="row.methodCode"
placeholder="给药途径"
clearable
filterable
:ref="(el) => setInputRef('methodCode', el)"
style="width: 120px"
@keyup.enter.prevent="
() => {
if (row.methodCode) {
handleEnter('methodCode');
}
}
"
>
<el-option
v-for="dict in config.methodCode"
@click="() => (row.methodCode_dictText = dict.label)"
@keyup="handleEnter('methodCode')"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item
label="用药频次:"
prop="rateCode"
class="required-field"
data-prop="rateCode"
>
<el-select
v-model="row.rateCode"
placeholder="频次"
style="width: 120px"
filterable
:disabled="row.therapyEnum == '2'"
@keyup.enter.prevent="
() => {
if (row.rateCode) {
handleEnter('rateCode');
}
}
"
:ref="(el) => setInputRef('rateCode', el)"
>
<el-option
v-for="dict in config.rateCode"
@click="() => (row.rateCode_dictText = dict.label)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</div>
</div>
<div
style="display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 10px"
>
<div class="form-group">
<template v-if="row.therapyEnum == '2'">
<el-form-item
label="用药天数:"
prop="dispensePerDuration"
class="required-field"
data-prop="dispensePerDuration"
>
<el-input-number
v-model="row.dispensePerDuration"
style="width: 148px"
:min="1"
controls-position="right"
:controls="false"
:ref="(el) => setInputRef('dispensePerDuration', el)"
@keyup.enter.prevent="handleEnter('dispensePerDuration')"
>
<template #suffix></template>
</el-input-number>
</el-form-item>
<el-form-item
label="总量:"
prop="quantity"
class="required-field"
data-prop="quantity"
label-width="80"
>
<el-input-number
v-model="row.quantity"
style="width: 70px"
controls-position="right"
:controls="false"
:ref="(el) => setInputRef('quantity', el)"
@keyup.enter.prevent="handleEnter('quantity')"
@input="calculateTotalPrice"
/>
</el-form-item>
<el-select
v-model="row.unitCode"
style="width: 70px"
placeholder=" "
@change="calculateTotalAmount"
>
<template v-for="item in row.unitCodeList" :key="item.value">
<el-option
v-if="checkUnit(item)"
:value="item.value"
:label="item.label"
@click="
() => {
if (item.type == config.unitMap['minUnit']) {
row.unitPrice = row.minUnitPrice;
} else {
row.unitPrice = row.unitTempPrice;
}
row.unitCode_dictText = item.label;
}
"
/>
</template>
</el-select>
</template>
<template v-if="row.therapyEnum == '1'">
<el-form-item
label="首次用量:"
prop="firstDose"
class="required-field"
data-prop="firstDose"
>
<el-input-number
v-model="row.firstDose"
style="width: 70px"
controls-position="right"
:controls="false"
:ref="(el) => setInputRef('firstDose', el)"
@keyup.enter.prevent="handleEnter('firstDose')"
/>
</el-form-item>
<el-select v-model="row.unitCode" style="width: 70px" placeholder=" ">
<template v-for="item in row.unitCodeList" :key="item.value">
<el-option v-if="checkUnit(item)" :value="item.value" :label="item.label" />
</template>
</el-select>
</template>
</div>
<div class="form-actions">
<el-button type="primary" @click="handleSave">确定</el-button>
<el-button @click="handleCancel">取消</el-button>
</div>
</div>
</template>
<template v-else-if="row.adviceType == 2">
<div style="display: flex; align-items: center; margin-bottom: 16px; gap: 16px">
<span style="font-size: 16px; font-weight: 600">
{{
row.adviceName +
' ' +
row.volume +
' ' +
row.unitPrice +
' 元/' +
row.unitCode_dictText
}}
</span>
<div class="form-group">
<el-select
v-model="row.lotNumber"
style="width: 180px; margin-right: 20px"
placeholder="药房"
>
<el-option
v-for="item in row.stockList"
:key="item.inventoryId"
:value="item.inventoryId"
:label="`${item.locationName} 批次号: ${item.lotNumber ?? '-'} 库存:${stockFormat(
row.partPercent,
row.unitCodeList,
item.quantity
)}`"
@click="handleNumberClick(item)"
>
<div style="display: flex; gap: 8px; align-items: center">
<span>{{ item.locationName }}</span>
<span>批次号: {{ item.lotNumber ?? '-' }}</span>
<span>
库存{{ stockFormat(row.partPercent, row.unitCodeList, item.quantity) }}
</span>
</div>
</el-option>
</el-select>
<el-form-item
label="数量:"
prop="quantity"
class="required-field"
data-prop="quantity"
>
<el-input-number
placeholder="数量"
v-model="row.quantity"
style="width: 70px"
controls-position="right"
:controls="false"
@keyup.enter.prevent="handleEnter('quantity')"
@input="calculateTotalAmount"
/>
</el-form-item>
<el-select
v-model="row.unitCode"
style="width: 70px; margin-right: 20px"
placeholder=" "
@change="calculateTotalAmount"
>
<template v-for="item in row.unitCodeList" :key="item.value">
<el-option
v-if="item.type != config.unitMap['dose']"
:value="item.value"
:label="item.label"
@click="() => (row.unitCode_dictText = item.label)"
/>
</template>
</el-select>
<span class="total-amount" v-if="row.therapyEnum == '2'">
总金额{{ row.totalPrice ? Number(row.totalPrice).toFixed(2) + ' ' : '0.00 ' }}
</span>
</div>
<div class="form-actions">
<el-button type="primary" @click="handleSave">确定</el-button>
<el-button @click="handleCancel">取消</el-button>
</div>
</div>
</template>
<template v-else>
<div style="display: flex; align-items: center; margin-bottom: 16px; gap: 16px">
<span style="font-size: 16px; font-weight: 600">
{{ row.adviceName }}
{{ row.unitPrice ? Number(row.unitPrice).toFixed(2) + '/次' : '-' + '元' }}
</span>
<div class="form-group">
<el-form-item
label="执行次数:"
prop="quantity"
class="required-field"
data-prop="quantity"
>
<el-input-number
placeholder="执行次数"
style="width: 100px; margin: 0 20px"
v-model="row.quantity"
controls-position="right"
:controls="false"
@keyup.enter.prevent="handleEnter('quantity')"
@input="calculateTotalPrice"
/>
</el-form-item>
<el-form-item label="执行科室:" prop="orgId" class="required-field" data-prop="orgId">
<el-tree-select
clearable
v-model="row.orgId"
style="width: 200px"
:data="config.organization"
:props="{ value: 'id', label: 'name', children: 'children' }"
value-key="id"
check-strictly
default-expand-all
@change="handleOrgChange"
placeholder="请选择执行科室"
/>
</el-form-item>
<span class="total-amount" v-if="row.therapyEnum == '2'">
总金额{{ row.totalPrice ? Number(row.totalPrice).toFixed(2) + ' ' : '0.00 ' }}
</span>
<span style="font-size: 16px; font-weight: 600">
<!-- 金额: {{ row.priceList[0].price }} -->
</span>
</div>
<div class="form-actions">
<el-button type="primary" @click="handleSave">确定</el-button>
<el-button @click="handleCancel">取消</el-button>
</div>
</div>
</template>
</div>
</el-form>
</template>
<script setup lang="ts">
import { ref, computed, nextTick, getCurrentInstance, watch, onMounted } from 'vue';
interface Config {
diagnosisName: string; // 仅用于显示
methodCode: any[];
rateCode: any[];
organization: any[];
unitMap: {
dose: string;
minUnit: string;
unit: string;
};
}
interface Handlers {
handleEnter: (prop: string, row: any, index: number) => void;
handleNumberClick: (item: any, index: number, row: any) => void;
handleOrgChange: (value: any, index: number) => void;
convertValue: (type: 'dose' | 'doseQuantity', row: any, index: number) => void;
calculateTotal: (type: 'price' | 'amount', row: any, index: number) => void;
setInputRef: (prop: string, el: any) => void;
}
interface Props {
row: any;
index: number;
formRefName: string;
rules: any;
config: Config;
handlers: Handlers;
}
interface Emits {
(e: 'save', row: any, index: number): void;
(e: 'cancel', row: any, index: number): void;
}
const props = defineProps<Props>();
const emit = defineEmits<Emits>();
const { proxy } = getCurrentInstance() as any;
// 创建表单 ref
const formRef = ref();
// 将表单 ref 注册到父组件的 $refs 上,以便父组件可以通过 proxy.$refs['formRef' + index] 访问
const registerFormRef = () => {
if (formRef.value && proxy?.$parent?.$refs) {
proxy.$parent.$refs[props.formRefName] = formRef.value;
}
};
// 监听 formRef 变化,确保注册
watch(
() => formRef.value,
() => {
if (formRef.value) {
nextTick(() => {
registerFormRef();
});
}
},
{ immediate: true }
);
onMounted(() => {
nextTick(() => {
registerFormRef();
});
if (props.row.therapyEnum == '2' && !props.row.rateCode) {
setRateCodeToST();
}
});
watch(
() => props.row.therapyEnum,
(newVal) => {
if (newVal == '2') {
setRateCodeToST();
} else if (newVal == '1') {
props.row.rateCode = '';
props.row.rateCode_dictText = '';
}
}
);
const setRateCodeToST = () => {
if (Array.isArray(props.config.rateCode)) {
const stOption = props.config.rateCode.find((item) => item.value === 'ST');
if (stOption) {
props.row.rateCode = 'ST';
props.row.rateCode_dictText = stOption.label;
} else {
props.row.rateCode = 'ST';
props.row.rateCode_dictText = '立即';
}
}
};
// 格式化库存显示
const stockFormat = (partPercent: number, unitList: any[], quantity: number): string => {
const unitCode = unitList.find((item) => item.type == 'unit')?.label;
const minUnitCode = unitList.find((item) => item.type == 'minUnit')?.label;
const a = quantity % partPercent;
const b = Math.floor(quantity / partPercent);
if (a == 0) {
return b + ' ' + unitCode;
}
return b + ' ' + unitCode + ' ' + a + ' ' + minUnitCode;
};
// 检查单位
const checkUnit = (item: any): boolean => {
if (item.type == 'dose') {
return false;
} else if (props.row.partAttributeEnum == '2' && item.type == 'minUnit') {
return false;
} else {
return true;
}
};
const handleEnter = (prop: string) => props.handlers.handleEnter(prop, props.row, props.index);
const handleSave = () => {
nextTick(() => {
if (!formRef.value) {
console.error('Form ref not found');
return;
}
formRef.value.validate((valid: boolean) => {
if (valid) {
emit('save', props.row, props.index);
} else {
if (proxy?.$modal?.msgWarning) {
proxy.$modal.msgWarning('请完善必填信息');
}
}
});
});
};
const handleCancel = () => {
emit('cancel', props.row, props.index);
};
const handleNumberClick = (item: any) =>
props.handlers.handleNumberClick(item, props.index, props.row);
const handleOrgChange = (value: any) => props.handlers.handleOrgChange(value, props.index);
const convertValues = () => props.handlers.convertValue('doseQuantity', props.row, props.index);
const convertDoseValues = () => props.handlers.convertValue('dose', props.row, props.index);
const calculateTotalPrice = () => props.handlers.calculateTotal('price', props.row, props.index);
const calculateTotalAmount = () => props.handlers.calculateTotal('amount', props.row, props.index);
const setInputRef = props.handlers.setInputRef;
defineExpose({
stockFormat,
checkUnit,
formRef,
});
</script>
<style scoped lang="scss">
.medicine-title {
font-size: 16px;
font-weight: 600;
min-width: 280px;
display: inline-block;
}
.total-amount {
font-size: 16px;
font-weight: 600;
color: #409eff;
white-space: nowrap;
}
.medicine-info {
font-size: 15px;
font-weight: 600;
color: #606266;
white-space: nowrap;
}
.form-group {
display: flex;
align-items: center;
gap: 8px;
background: #fff;
padding: 6px 10px;
border-radius: 4px;
border: 1px solid #ebeef5;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.04);
}
.form-actions {
display: inline-flex;
align-items: center;
gap: 0px;
}
.expend_div {
:deep(.el-form-item--default) {
margin-bottom: 0px;
}
:deep(.el-input-number .el-input__inner) {
text-align: center;
}
}
</style>

View File

@@ -1,4 +1,4 @@
import request from '@/utils/request'
import request from '@/utils/request';
// 申请单相关接口
//医嘱大下拉
@@ -6,8 +6,8 @@ export function getApplicationList(queryParams) {
return request({
url: '/doctor-station/advice/advice-base-info',
method: 'get',
params: queryParams
})
params: queryParams,
});
}
/**
* 保存检查申请单
@@ -16,8 +16,8 @@ export function saveCheckd(data) {
return request({
url: '/reg-doctorstation/request-form/save-check',
method: 'post',
data: data
})
data: data,
});
}
/**
* 保存检验申请单
@@ -26,18 +26,18 @@ export function saveInspection(data) {
return request({
url: '/reg-doctorstation/request-form/save-inspection',
method: 'post',
data: data
})
data: data,
});
}
/**
* 保存输血申请单
*/
export function saveBloodTransfusio(data) {
return request({
url: '/reg-doctorstation/request-form/save-blood-transfusio',
url: '/reg-doctorstation/request-form/save-blood-transfusion',
method: 'post',
data: data
})
data: data,
});
}
/**
* 保存手术申请单
@@ -46,11 +46,11 @@ export function saveSurgery(data) {
return request({
url: '/reg-doctorstation/request-form/save-surgery',
method: 'post',
data: data
})
data: data,
});
}
// =====
// =====
/**
* 查询检查申请单
@@ -59,8 +59,8 @@ export function getCheck(data) {
return request({
url: '/reg-doctorstation/request-form/get-check',
method: 'get',
params: data
})
params: data,
});
}
/**
* 查询检验申请单
@@ -69,8 +69,8 @@ export function getInspection(data) {
return request({
url: '/reg-doctorstation/request-form/get-inspection',
method: 'get',
params: data
})
params: data,
});
}
/**
* 查询输血申请单
@@ -79,18 +79,18 @@ export function getBloodTransfusion(data) {
return request({
url: '/reg-doctorstation/request-form/get-blood-transfusion',
method: 'get',
params: data
})
params: data,
});
}
/**
* 查询手术申请单
*/
export function geturger(data) {
export function getSurgery(data) {
return request({
url: '/reg-doctorstation/request-form/get-surgery',
method: 'get',
params: data
})
params: data,
});
}
/**
@@ -100,6 +100,7 @@ export function transferOrganization(data) {
return request({
url: '/reg-doctorstation/special-advice/transfer-organization-orders',
method: 'post',
<<<<<<< HEAD
data: data
})
}
@@ -108,3 +109,8 @@ export function transferOrganization(data) {
=======
data: data,
});
}
>>>>>>> v1.3

View File

@@ -56,14 +56,27 @@
</div>
</template>
<script setup>
<<<<<<< HEAD
import { getCurrentInstance, onBeforeMount, onMounted, reactive, ref, computed } from 'vue';
import BloodTransfusion from './bloodTransfusion';
=======
import {
getCurrentInstance,
onBeforeMount,
onMounted,
reactive,
ref,
computed,
nextTick,
} from 'vue';
import BloodTransfusion from './bloodTransfusion.vue';
>>>>>>> v1.3
import { patientInfo } from '../../../store/patient.js';
import Surgery from './surgery.vue';
import LaboratoryTests from './laboratoryTests.vue';
import MedicalExaminations from './medicalExaminations.vue';
const { proxy } = getCurrentInstance();
const emits = defineEmits([]);
const emits = defineEmits(['refResh']);
const props = defineProps({});
const state = reactive({});
const components = ref({
@@ -87,7 +100,7 @@ const applicationFormTitle = computed(() => {
const closeDialog = () => {
applicationFormName.value = null;
applicationFormDialogVisible.value = false;
}
};
const showApplicationFormDialog = (name) => {
if (!components.value[name]) {
console.warn(`未找到组件: ${name}`);
@@ -106,10 +119,20 @@ const showApplicationFormDialog = (name) => {
setTimeout(() => {
applicationFormName.value = components.value[name];
applicationFormDialogVisible.value = true;
// 科室列表
applicationFormNameRef?.value.getLocationInfo();
// 诊断目录列表
applicationFormNameRef?.value.getDiagnosisList();
}, 150);
} else {
applicationFormName.value = components.value[name];
applicationFormDialogVisible.value = true;
nextTick(() => {
// 科室列表
applicationFormNameRef?.value.getLocationInfo();
// 诊断目录列表
applicationFormNameRef?.value.getDiagnosisList();
});
}
};
onBeforeMount(() => {});
@@ -125,6 +148,7 @@ const submitApplicationForm = () => {
const submitOk = () => {
applicationFormDialogVisible.value = false;
applicationFormName.value = null;
emits('refResh');
};
defineExpose({ state });
</script>

View File

@@ -5,49 +5,71 @@
-->
<template>
<div class="bloodTransfusion-container">
<el-transfer v-model="transferValue" :data="applicationList" filter-placeholder="项目代码/名称" filterable
:titles="['未选择', '已选择']" />
<div v-loading="loading" class="transfer-wrapper">
<el-transfer
v-model="transferValue"
:data="applicationList"
filter-placeholder="项目代码/名称"
filterable
:titles="['未选择', '已选择']"
/>
</div>
<div class="bloodTransfusion-form">
<el-form :model="form" :rules="rules" ref="formRef" label-width="120px" class="demo-ruleForm">
<el-row :gutter="20">
<!-- <el-col :span="12">
<el-form-item label="项目类别" prop="categoryType" style="width: 100%">
<el-input v-model="form.categoryType" autocomplete="off" />
</el-form-item>
</el-col> -->
<el-col :span="12">
<el-form-item label="项目类别" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" />
<el-form-item label="发往科室" prop="targetDepartment" style="width: 100%">
<!-- <el-input v-model="form.targetDepartment" autocomplete="off" /> -->
<el-tree-select
clearable
style="width: 100%"
v-model="form.targetDepartment"
filterable
:data="orgOptions"
:props="{
value: 'id',
label: 'name',
children: 'children',
}"
value-key="id"
check-strictly
placeholder="请选择科室"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="发往科室" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" />
<el-form-item label="症状" prop="symptom" style="width: 100%">
<el-input v-model="form.symptom" autocomplete="off" type="textarea" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="症状" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" type="textarea" />
<el-form-item label="体征" prop="sign" style="width: 100%">
<el-input v-model="form.sign" autocomplete="off" type="textarea" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="体征" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" type="textarea" />
<el-form-item label="临床诊断" prop="clinicalDiagnosis" style="width: 100%">
<el-input disabled v-model="form.clinicalDiagnosis" autocomplete="off" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="临床诊断" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" />
<el-form-item label="其他诊断" prop="otherDiagnosis" style="width: 100%">
<el-input disabled v-model="form.otherDiagnosis" autocomplete="off" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="其他诊断" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" />
<el-form-item label="相关结果" prop="relatedResult" style="width: 100%">
<el-input v-model="form.relatedResult" autocomplete="off" type="textarea" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="相关结果" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" type="textarea" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="注意事项" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" type="textarea" />
<el-form-item label="注意事项" prop="attention" style="width: 100%">
<el-input v-model="form.attention" autocomplete="off" type="textarea" />
</el-form-item>
</el-col>
</el-row>
@@ -56,9 +78,10 @@
</div>
</template>
<script setup name="BloodTransfusion">
import { getCurrentInstance, onBeforeMount, onMounted, reactive, ref } from 'vue';
import { patientInfo } from '../../../store/patient.js';
import { getOrgList } from '../../../../../basicmanage/ward/components/api.js';
import { getEncounterDiagnosis } from '../../api.js';
const { proxy } = getCurrentInstance();
const emits = defineEmits(['submitOk']);
const props = defineProps({});
@@ -66,20 +89,28 @@ import { getApplicationList, saveBloodTransfusio } from './api';
const state = reactive({});
const applicationListAll = ref();
const applicationList = ref();
const loading = ref(false);
const orgOptions = ref([]); // 科室选项
const getList = () => {
if (patientInfo.value?.inHospitalOrgId) {
getApplicationList({
pageSize: 10000,
pageNum: 1,
categoryCode: '28',
organizationId: patientInfo.value.inHospitalOrgId,
adviceTypes: '3', //1 药品 2耗材 3诊疗
}).then((res) => {
if (!patientInfo.value?.inHospitalOrgId) {
applicationList.value = [];
return;
}
loading.value = true;
getApplicationList({
pageSize: 10000,
pageNum: 1,
categoryCode: '28',
organizationId: patientInfo.value.inHospitalOrgId,
adviceTypes: '3', //1 药品 2耗材 3诊疗
})
.then((res) => {
if (res.code === 200) {
applicationListAll.value = res.data.records;
applicationList.value = res.data.records.map((item) => {
applicationList.value = res.data.records.map((item) => {
return {
adviceDefinitionId: item.adviceDefinitionId,
orgId: item.orgId,
label: item.adviceName + item.adviceDefinitionId,
key: item.adviceDefinitionId,
};
@@ -88,45 +119,112 @@ const getList = () => {
proxy.$message.error(res.message);
applicationList.value = [];
}
})
.finally(() => {
loading.value = false;
});
}
};
const transferValue = ref([]);
const form = reactive({
patientName: '',
patientSex: '',
patientAge: '',
patientPhone: '',
patientAddress: '',
// categoryType: '', // 项目类别
targetDepartment: '', // 发往科室
symptom: '', // 症状
sign: '', // 体征
clinicalDiagnosis: '', // 临床诊断
otherDiagnosis: '', // 其他诊断
relatedResult: '', // 相关结果
attention: '', // 注意事项
primaryDiagnosisList: [], //主诊断目录
otherDiagnosisList: [], //其他断目录
});
const rules = reactive({});
onBeforeMount(() => { });
onBeforeMount(() => {});
onMounted(() => {
getList();
});
/**
* type(1watch监听类型 2:点击保存类型)
* selectProjectIds(选中项目的id数组)
* */
const projectWithDepartment = (selectProjectIds, type) => {
//1.获取选中的项目 2.判断项目的执行科室是否相同 3.判断执行科室是否配置 4.将项目的执行科室复值到执行科室下拉选位置
let isRelease = true;
// 选中项目的数组
const arr = [];
// 根据选中的项目id查找对应的项目
selectProjectIds.forEach((element) => {
const searchData = applicationList.value.find((item) => {
return element == item.adviceDefinitionId;
});
arr.push(searchData);
});
// 清空科室
form.targetDepartment = '';
if (arr.length > 0) {
const obj = arr[0];
// 判断科室是否相同
const isCompare = arr.every((item) => {
return item.orgId == obj.orgId;
});
if (!isCompare) {
ElMessage({
type: 'error',
message: '执行科室不同',
});
isRelease = false;
}
// 选中项目中的执行科室id与全部科室数据做匹配
const findItem = orgOptions.value.find((item) => {
return item.id == obj.orgId;
});
if (!findItem) {
isRelease = false;
ElMessage({
type: 'error',
message: '未找到项目执行的科室',
});
}
if (type == 1) {
if (isRelease) {
form.targetDepartment = findItem.id;
}
}
}
return isRelease;
};
// 监听选择项目变化
watch(
() => transferValue.value,
(newValue) => {
projectWithDepartment(newValue, 1);
}
);
const submit = () => {
if (transferValue.value.length == 0) {
return proxy.$message.error('请选择申请单');
}
if (!projectWithDepartment(transferValue.value, 2)) {
return;
}
let applicationListAllFilter = applicationListAll.value.filter((item) => {
return transferValue.value.includes(item.adviceDefinitionId);
});
applicationListAllFilter = applicationListAllFilter.map((item) => {
return {
adviceDefinitionId: item.adviceDefinitionId, /** 诊疗定义id */
quantity: 1,// /** 请求数量 */
unitCode: item.priceList[0].unitCode, /** 请求单位编码 */
unitPrice: item.priceList[0].price, /** 单价 */
totalPrice: item.priceList[0].price, /** 总价 */
positionId: item.positionId,//执行科室id
ybClassEnum: item.ybClassEnum,//类别医保编码
conditionId: item.conditionId,//诊断ID
encounterDiagnosisId: item.encounterDiagnosisId,//就诊诊断id
adviceType: item.adviceType,///** 医嘱类型 */
definitionId: item.priceList[0].definitionId,//费用定价主表ID */
definitionDetailId: item.definitionDetailId,//费用定价子表ID */
accountId: patientInfo.value.accountId,// // 账户id
adviceDefinitionId: item.adviceDefinitionId /** 诊疗定义id */,
quantity: 1, // /** 请求数量 */
unitCode: item.priceList[0].unitCode /** 请求单位编码 */,
unitPrice: item.priceList[0].price /** 单价 */,
totalPrice: item.priceList[0].price /** 总价 */,
positionId: item.positionId, //执行科室id
ybClassEnum: item.ybClassEnum, //类别医保编码
conditionId: item.conditionId, //诊断ID
encounterDiagnosisId: item.encounterDiagnosisId, //就诊诊断id
adviceType: item.adviceType, ///** 医嘱类型 */
definitionId: item.priceList[0].definitionId, //费用定价主表ID */
definitionDetailId: item.definitionDetailId, //费用定价子表ID */
accountId: patientInfo.value.accountId, // // 账户id
};
});
saveBloodTransfusio({
@@ -137,7 +235,7 @@ const submit = () => {
requestFormId: '', // 申请单ID
name: '输血申请单',
descJson: JSON.stringify(form),
categoryEnum: '1', // 1 检验 2 检查 3 输血 4 手术
categoryEnum: '3', // 1 检验 2 检查 3 输血 4 手术
}).then((res) => {
if (res.code === 200) {
proxy.$message.success(res.msg);
@@ -147,19 +245,63 @@ const submit = () => {
proxy.$message.error(res.message);
}
});
};
defineExpose({ state, submit });
/** 查询科室 */
const getLocationInfo = () => {
getOrgList().then((res) => {
orgOptions.value = res.data?.records[0]?.children;
});
};
// 获取诊断目录
function getDiagnosisList() {
getEncounterDiagnosis(patientInfo.value.encounterId).then((res) => {
console.log('诊断目录========>', JSON.stringify(res.data));
if (res.code == 200) {
const datas = (res.data || []).map((item) => {
let obj = {
...item,
};
if (obj.diagSrtNo == null) {
obj.diagSrtNo = '1';
}
return obj;
});
// 主诊断
form.primaryDiagnosisList = datas.filter((item) => {
return item?.maindiseFlag == 1;
});
console.log('@@@@@@========>', form.primaryDiagnosisList);
if (form.primaryDiagnosisList.length == 1) {
const obj = form.primaryDiagnosisList[0];
form.clinicalDiagnosis = obj.name;
}
//其他诊断
form.otherDiagnosisList = datas.filter((item) => {
return item?.maindiseFlag !== 1;
});
const otherDiagnosisNameList = form.otherDiagnosisList.map((item) => {
return item.name;
});
form.otherDiagnosis = otherDiagnosisNameList.join(',');
}
});
}
defineExpose({ state, submit, getLocationInfo, getDiagnosisList });
</script>
<style lang="scss" scoped>
.bloodTransfusion-container {
height: 100%;
width: 100%;
.transfer-wrapper {
position: relative;
min-height: 300px;
}
.el-transfer {
--el-transfer-panel-width: 400px !important;
}
height: 100%;
width: 100%;
.bloodTransfusion-form {
padding: 8px 8px 0 8px;
height: 100%;

View File

@@ -5,54 +5,71 @@
-->
<template>
<div class="LaboratoryTests-container">
<el-transfer
v-model="transferValue"
:data="applicationList"
filter-placeholder="项目代码/名称"
filterable
:titles="['未选择', '已选择']"
/>
<div v-loading="loading" class="transfer-wrapper">
<el-transfer
v-model="transferValue"
:data="applicationList"
filter-placeholder="项目代码/名称"
filterable
:titles="['未选择', '已选择']"
/>
</div>
<div class="bloodTransfusion-form">
<el-form :model="form" :rules="rules" ref="formRef" label-width="120px" class="demo-ruleForm">
<el-row :gutter="20">
<!-- <el-col :span="12">
<el-form-item label="项目类别" prop="categoryType" style="width: 100%">
<el-input v-model="form.categoryType" autocomplete="off" />
</el-form-item>
</el-col> -->
<el-col :span="12">
<el-form-item label="项目类别" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" />
<el-form-item label="发往科室" prop="targetDepartment" style="width: 100%">
<!-- <el-input v-model="form.targetDepartment" autocomplete="off" /> -->
<el-tree-select
clearable
style="width: 100%"
v-model="form.targetDepartment"
filterable
:data="orgOptions"
:props="{
value: 'id',
label: 'name',
children: 'children',
}"
value-key="id"
check-strictly
placeholder="请选择科室"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="发往科室" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" />
<el-form-item label="症状" prop="symptom" style="width: 100%">
<el-input v-model="form.symptom" autocomplete="off" type="textarea" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="症状" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" type="textarea" />
<el-form-item label="体征" prop="sign" style="width: 100%">
<el-input v-model="form.sign" autocomplete="off" type="textarea" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="体征" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" type="textarea" />
<el-form-item label="临床诊断" prop="clinicalDiagnosis" style="width: 100%">
<el-input disabled v-model="form.clinicalDiagnosis" autocomplete="off" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="临床诊断" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" />
<el-form-item label="其他诊断" prop="otherDiagnosis" style="width: 100%">
<el-input disabled v-model="form.otherDiagnosis" autocomplete="off" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="其他诊断" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" />
<el-form-item label="相关结果" prop="relatedResult" style="width: 100%">
<el-input v-model="form.relatedResult" autocomplete="off" type="textarea" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="相关结果" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" type="textarea" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="注意事项" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" type="textarea" />
<el-form-item label="注意事项" prop="attention" style="width: 100%">
<el-input v-model="form.attention" autocomplete="off" type="textarea" />
</el-form-item>
</el-col>
</el-row>
@@ -61,104 +78,232 @@
</div>
</template>
<script setup name="LaboratoryTests">
import { getCurrentInstance, onBeforeMount, onMounted, reactive } from 'vue';
import { getCurrentInstance, onBeforeMount, onMounted, reactive, watch } from 'vue';
import { patientInfo } from '../../../store/patient.js';
const { proxy } = getCurrentInstance();
const emits = defineEmits(['submitOk']);
const props = defineProps({});
import { getApplicationList, saveCheckd } from './api';
import { getApplicationList, saveInspection } from './api';
import { getOrgList } from '../../../../../basicmanage/ward/components/api.js';
import { getEncounterDiagnosis } from '../../api.js';
import { ElMessage } from 'element-plus';
const state = reactive({});
const applicationListAll = ref();
const applicationList = ref();
const loading = ref(false);
const orgOptions = ref([]); // 科室选项
const getList = () => {
if (patientInfo.value?.inHospitalOrgId) {
getApplicationList({
pageSize: 10000,
pageNum: 1,
categoryCode: '23',
organizationId: patientInfo.value.inHospitalOrgId,
adviceTypes: '3', //1 药品 2耗材 3诊疗
}).then((res) => {
if (!patientInfo.value?.inHospitalOrgId) {
applicationList.value = [];
return;
}
loading.value = true;
getApplicationList({
pageSize: 10000,
pageNum: 1,
categoryCode: '22',
organizationId: patientInfo.value.inHospitalOrgId,
adviceTypes: '3', //1 药品 2耗材 3诊疗
})
.then((res) => {
if (res.code === 200) {
applicationListAll.value = res.data.records;
applicationList.value = res.data.records.map((item) => {
return {
adviceDefinitionId: item.adviceDefinitionId,
orgId: item.orgId,
label: item.adviceName + item.adviceDefinitionId,
key: item.adviceDefinitionId,
};
});
console.log('applicationList========>', JSON.stringify(res.data.records));
} else {
proxy.$message.error(res.message);
applicationList.value = [];
}
})
.finally(() => {
loading.value = false;
});
}
};
const transferValue = ref([]);
const form = reactive({
patientName: '',
patientSex: '',
patientAge: '',
patientPhone: '',
patientAddress: '',
// categoryType: '', // 项目类别
targetDepartment: '', // 发往科室
symptom: '', // 症状
sign: '', // 体征
clinicalDiagnosis: '', // 临床诊断
otherDiagnosis: '', // 其他诊断
relatedResult: '', // 相关结果
attention: '', // 注意事项
primaryDiagnosisList: [], //主诊断目录
otherDiagnosisList: [], //其他断目录
});
const rules = reactive({});
onBeforeMount(() => {});
onMounted(() => {
getList();
});
/**
* type(1watch监听类型 2:点击保存类型)
* selectProjectIds(选中项目的id数组)
* */
const projectWithDepartment = (selectProjectIds, type) => {
//1.获取选中的项目 2.判断项目的执行科室是否相同 3.判断执行科室是否配置 4.将项目的执行科室复值到执行科室下拉选位置
let isRelease = true;
// 选中项目的数组
const arr = [];
// 根据选中的项目id查找对应的项目
selectProjectIds.forEach((element) => {
const searchData = applicationList.value.find((item) => {
return element == item.adviceDefinitionId;
});
arr.push(searchData);
});
// 清空科室
form.targetDepartment = '';
if (arr.length > 0) {
const obj = arr[0];
// 判断科室是否相同
const isCompare = arr.every((item) => {
return item.orgId == obj.orgId;
});
if (!isCompare) {
ElMessage({
type: 'error',
message: '执行科室不同',
});
isRelease = false;
}
// 选中项目中的执行科室id与全部科室数据做匹配
const findItem = orgOptions.value.find((item) => {
return item.id == obj.orgId;
});
if (!findItem) {
isRelease = false;
ElMessage({
type: 'error',
message: '未找到项目执行的科室',
});
}
if (type == 1) {
if (isRelease) {
form.targetDepartment = findItem.id;
}
}
}
return isRelease;
};
// 监听选择项目变化
watch(
() => transferValue.value,
(newValue) => {
projectWithDepartment(newValue, 1);
}
);
const submit = () => {
if (transferValue.value.length == 0) {
return proxy.$message.error('请选择申请单');
}
if (!projectWithDepartment(transferValue.value, 2)) {
return;
}
let applicationListAllFilter = applicationListAll.value.filter((item) => {
return transferValue.value.includes(item.adviceDefinitionId);
});
applicationListAllFilter = applicationListAllFilter.map((item) => {
return {
adviceDefinitionId: item.adviceDefinitionId, /** 诊疗定义id */
quantity: 1,// /** 请求数量 */
unitCode: item.priceList[0].unitCode, /** 请求单位编码 */
unitPrice: item.priceList[0].price, /** 单价 */
totalPrice: item.priceList[0].price, /** 总价 */
positionId: item.positionId,//执行科室id
ybClassEnum: item.ybClassEnum,//类别医保编码
conditionId: item.conditionId,//诊断ID
encounterDiagnosisId: item.encounterDiagnosisId,//就诊诊断id
adviceType: item.adviceType,///** 医嘱类型 */
definitionId: item.priceList[0].definitionId,//费用定价主表ID */
definitionDetailId: item.definitionDetailId,//费用定价子表ID */
accountId: patientInfo.value.accountId,// // 账户id
adviceDefinitionId: item.adviceDefinitionId /** 诊疗定义id */,
quantity: 1, // /** 请求数量 */
unitCode: item.priceList[0].unitCode /** 请求单位编码 */,
unitPrice: item.priceList[0].price /** 单价 */,
totalPrice: item.priceList[0].price /** 总价 */,
positionId: item.positionId, //执行科室id
ybClassEnum: item.ybClassEnum, //类别医保编码
conditionId: item.conditionId, //诊断ID
encounterDiagnosisId: item.encounterDiagnosisId, //就诊诊断id
adviceType: item.adviceType, ///** 医嘱类型 */
definitionId: item.priceList[0].definitionId, //费用定价主表ID */
definitionDetailId: item.definitionDetailId, //费用定价子表ID */
accountId: patientInfo.value.accountId, // // 账户id
};
});
saveCheckd({
const params = {
activityList: applicationListAllFilter,
patientId: patientInfo.value.patientId, //患者ID
encounterId: patientInfo.value.encounterId, // 就诊ID
organizationId: patientInfo.value.inHospitalOrgId, // 医疗机构ID
requestFormId: '', // 申请单ID
name: '检申请单',
name: '检申请单',
descJson: JSON.stringify(form),
categoryEnum: '1', // 1 检验 2 检查 3 输血 4 手术
}).then((res) => {
};
saveInspection(params).then((res) => {
if (res.code === 200) {
proxy.$message.success(res.msg);
applicationList.value = [];
emits('submitOk');
proxy.$message.success(res.msg);
applicationList.value = [];
emits('submitOk');
} else {
proxy.$message.error(res.message);
}
});
};
defineExpose({ state, submit });
/** 查询科室 */
const getLocationInfo = () => {
getOrgList().then((res) => {
orgOptions.value = res.data?.records[0]?.children;
console.log('科室========>', JSON.stringify(orgOptions.value));
});
};
// 获取诊断目录
function getDiagnosisList() {
getEncounterDiagnosis(patientInfo.value.encounterId).then((res) => {
if (res.code == 200) {
const datas = (res.data || []).map((item) => {
let obj = {
...item,
};
if (obj.diagSrtNo == null) {
obj.diagSrtNo = '1';
}
return obj;
});
// 主诊断
form.primaryDiagnosisList = datas.filter((item) => {
return item?.maindiseFlag == 1;
});
console.log('@@@@@@========>', form.primaryDiagnosisList);
if (form.primaryDiagnosisList.length == 1) {
const obj = form.primaryDiagnosisList[0];
form.clinicalDiagnosis = obj.name;
}
//其他诊断
form.otherDiagnosisList = datas.filter((item) => {
return item?.maindiseFlag !== 1;
});
const otherDiagnosisNameList = form.otherDiagnosisList.map((item) => {
return item.name;
});
form.otherDiagnosis = otherDiagnosisNameList.join(',');
}
});
}
defineExpose({ state, submit, getLocationInfo, getDiagnosisList });
</script>
<style lang="scss" scoped>
.LaboratoryTests-container {
height: 100%;
width: 100%;
.transfer-wrapper {
position: relative;
min-height: 300px;
}
.el-transfer {
--el-transfer-panel-width: 400px !important;
}
height: 100%;
width: 100%;
.bloodTransfusion-form {
padding: 8px 8px 0 8px;
height: 100%;

View File

@@ -9,7 +9,11 @@
>
<div style="padding: 0 80px">
<el-form :model="form" :rules="rules" ref="formRef">
<<<<<<< HEAD
<el-form-item label="出院方式">
=======
<el-form-item label="出院方式" prop="outpatientType">
>>>>>>> v1.3
<el-select v-model="form.outpatientType">
<el-option
v-for="(item, index) in dscg_way"
@@ -19,13 +23,21 @@
/>
</el-select>
</el-form-item>
<<<<<<< HEAD
<el-form-item label="出院时间">
=======
<el-form-item label="出院时间" prop="outpatientTime">
>>>>>>> v1.3
<el-radio-group v-model="form.outpatientTime">
<el-radio value="1">今日</el-radio>
<el-radio value="2">明日</el-radio>
</el-radio-group>
</el-form-item>
<<<<<<< HEAD
<el-form-item label="出院描述"
=======
<el-form-item label="出院描述" prop="outpatientDescription"
>>>>>>> v1.3
><el-input v-model="form.outpatientDescription" type="textarea" rows="5" />
</el-form-item>
</el-form>
@@ -40,20 +52,105 @@
</template>
<script setup>
<<<<<<< HEAD
const { proxy } = getCurrentInstance();
const { dscg_way } = proxy.useDict('dscg_way');
const dialogVisible = ref(false);
=======
import { toRaw } from 'vue';
import { leaveHospital } from '../../api';
import { dayjs } from 'element-plus';
const props = defineProps({
encounterId: {
type: [String, Number],
required: false,
},
patientId: {
type: [String, Number],
required: false,
},
conditionId: {
type: [String, Number],
required: false,
},
encounterDiagnosisId: {
type: [String, Number],
required: false,
},
});
const { proxy } = getCurrentInstance();
const { dscg_way } = proxy.useDict('dscg_way');
const dialogVisible = ref(false);
const formRef = ref(null);
const emit = defineEmits(['success']);
>>>>>>> v1.3
const form = reactive({
outpatientType: [],
outpatientTime: '',
outpatientDescription: '',
});
<<<<<<< HEAD
=======
const rules = {
outpatientType: [{ required: true, message: '请选择出院方式', trigger: 'change' }],
outpatientTime: [{ required: true, message: '请选择出院时间', trigger: 'change' }],
outpatientDescription: [{ required: true, message: '请输入出院描述', trigger: 'blur' }],
};
function getEndTime() {
let date = dayjs();
if (form.outpatientTime === '2') {
date = date.add(1, 'day');
}
return date.format('YYYY-MM-DD HH:mm:ss');
}
>>>>>>> v1.3
function openDialog() {
dialogVisible.value = true;
}
<<<<<<< HEAD
defineExpose({
openDialog,
});
</script>
</script>
=======
const submitApplicationForm = async () => {
if (!formRef.value) return;
try {
await formRef.value.validate();
const res = await leaveHospital({
endTime: getEndTime(),
outWayCode: form.outpatientType,
reasonText: form.outpatientDescription,
encounterId: props.encounterId,
patientId: props.patientId,
conditionId: props.conditionId,
encounterDiagnosisId: props.encounterDiagnosisId,
});
proxy.$modal.msgSuccess(res.msg);
closeDialog();
emit('success');
} catch (error) {
console.log(error);
}
};
const closeDialog = () => {
dialogVisible.value = false;
Object.assign(form, {
outpatientType: [],
outpatientTime: '',
outpatientDescription: '',
});
formRef.value?.resetFields();
};
defineExpose({
openDialog,
});
</script>
>>>>>>> v1.3

View File

@@ -5,62 +5,71 @@
-->
<template>
<div class="medicalExaminations-container">
<el-transfer
v-model="transferValue"
:data="applicationList"
style="width: 100%"
filter-placeholder="项目代码/名称"
filterable
:titles="['未选择', '已选择']"
/>
<div v-loading="loading" class="transfer-wrapper">
<el-transfer
v-model="transferValue"
:data="applicationList"
filter-placeholder="项目代码/名称"
filterable
:titles="['未选择', '已选择']"
/>
</div>
<div class="bloodTransfusion-form">
<el-form
:model="form"
:rules="rules"
ref="formRef"
label-width="120px"
class="demo-ruleForm"
inline
>
<el-form :model="form" :rules="rules" ref="formRef" label-width="120px" class="demo-ruleForm">
<el-row :gutter="20">
<!-- <el-col :span="12">
<el-form-item label="项目类别" prop="categoryType" style="width: 100%">
<el-input v-model="form.categoryType" autocomplete="off" />
</el-form-item>
</el-col> -->
<el-col :span="12">
<el-form-item label="项目类别" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" />
<el-form-item label="发往科室" prop="targetDepartment" style="width: 100%">
<!-- <el-input v-model="form.targetDepartment" autocomplete="off" /> -->
<el-tree-select
clearable
style="width: 100%"
v-model="form.targetDepartment"
filterable
:data="orgOptions"
:props="{
value: 'id',
label: 'name',
children: 'children',
}"
value-key="id"
check-strictly
placeholder="请选择科室"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="发往科室" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" />
<el-form-item label="症状" prop="symptom" style="width: 100%">
<el-input v-model="form.symptom" autocomplete="off" type="textarea" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="症状" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" type="textarea" />
<el-form-item label="体征" prop="sign" style="width: 100%">
<el-input v-model="form.sign" autocomplete="off" type="textarea" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="体征" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" type="textarea" />
<el-form-item label="临床诊断" prop="clinicalDiagnosis" style="width: 100%">
<el-input disabled v-model="form.clinicalDiagnosis" autocomplete="off" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="临床诊断" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" />
<el-form-item label="其他诊断" prop="otherDiagnosis" style="width: 100%">
<el-input disabled v-model="form.otherDiagnosis" autocomplete="off" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="其他诊断" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" />
<el-form-item label="相关结果" prop="relatedResult" style="width: 100%">
<el-input v-model="form.relatedResult" autocomplete="off" type="textarea" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="相关结果" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" type="textarea" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="注意事项" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" type="textarea" />
<el-form-item label="注意事项" prop="attention" style="width: 100%">
<el-input v-model="form.attention" autocomplete="off" type="textarea" />
</el-form-item>
</el-col>
</el-row>
@@ -69,30 +78,40 @@
</div>
</template>
<script setup name="MedicalExaminations">
import { getCurrentInstance, onBeforeMount, onMounted, reactive } from 'vue';
import { getCurrentInstance, onBeforeMount, onMounted, reactive, watch } from 'vue';
import { patientInfo } from '../../../store/patient.js';
import { getOrgList } from '../../../../../basicmanage/ward/components/api.js';
import { getEncounterDiagnosis } from '../../api.js';
const { proxy } = getCurrentInstance();
const emits = defineEmits(['submitOk']);
const props = defineProps({});
import { getApplicationList, saveInspection } from './api';
const orgOptions = ref([]); // 科室选项
import { getApplicationList, saveCheckd } from './api';
import { ElMessage } from 'element-plus';
const state = reactive({});
const applicationListAll = ref();
const applicationList = ref();
const loading = ref(false);
const getList = () => {
// console.log(patientInfo.value);
if (patientInfo.value?.inHospitalOrgId) {
getApplicationList({
pageSize: 10000,
pageNum: 1,
categoryCode: '23',
organizationId: patientInfo.value.inHospitalOrgId,
adviceTypes: '3', //1 药品 2耗材 3诊疗
}).then((res) => {
if (!patientInfo.value?.inHospitalOrgId) {
applicationList.value = [];
return;
}
loading.value = true;
getApplicationList({
pageSize: 10000,
pageNum: 1,
categoryCode: '23',
organizationId: patientInfo.value.inHospitalOrgId,
adviceTypes: '3', //1 药品 2耗材 3诊疗
})
.then((res) => {
if (res.code === 200) {
applicationListAll.value = res.data.records;
applicationList.value = res.data.records.map((item) => {
return {
adviceDefinitionId: item.adviceDefinitionId,
orgId: item.orgId,
label: item.adviceName + item.adviceDefinitionId,
key: item.adviceDefinitionId,
};
@@ -101,75 +120,189 @@ const getList = () => {
proxy.$message.error(res.message);
applicationList.value = [];
}
})
.finally(() => {
loading.value = false;
});
}
};
const transferValue = ref([]);
const form = reactive({
patientName: '',
patientSex: '',
patientAge: '',
patientPhone: '',
patientAddress: '',
// categoryType: '', // 项目类别
targetDepartment: '', // 发往科室
symptom: '', // 症状
sign: '', // 体征
clinicalDiagnosis: '', // 临床诊断
otherDiagnosis: '', // 其他诊断
relatedResult: '', // 相关结果
attention: '', // 注意事项
primaryDiagnosisList: [], //主诊断目录
otherDiagnosisList: [], //其他断目录
});
const rules = reactive({});
onBeforeMount(() => {});
onMounted(() => {
getList();
});
/**
* type(1watch监听类型 2:点击保存类型)
* selectProjectIds(选中项目的id数组)
* */
const projectWithDepartment = (selectProjectIds, type) => {
//1.获取选中的项目 2.判断项目的执行科室是否相同 3.判断执行科室是否配置 4.将项目的执行科室复值到执行科室下拉选位置
let isRelease = true;
// 选中项目的数组
const arr = [];
// 根据选中的项目id查找对应的项目
selectProjectIds.forEach((element) => {
const searchData = applicationList.value.find((item) => {
return element == item.adviceDefinitionId;
});
arr.push(searchData);
});
// 清空科室
form.targetDepartment = '';
if (arr.length > 0) {
const obj = arr[0];
// 判断科室是否相同
const isCompare = arr.every((item) => {
return item.orgId == obj.orgId;
});
if (!isCompare) {
ElMessage({
type: 'error',
message: '执行科室不同',
});
isRelease = false;
}
// 选中项目中的执行科室id与全部科室数据做匹配
const findItem = orgOptions.value.find((item) => {
return item.id == obj.orgId;
});
if (!findItem) {
isRelease = false;
ElMessage({
type: 'error',
message: '未找到项目执行的科室',
});
}
if (type == 1) {
if (isRelease) {
form.targetDepartment = findItem.id;
}
}
}
return isRelease;
};
// 监听选择项目变化
watch(
() => transferValue.value,
(newValue) => {
projectWithDepartment(newValue, 1);
}
);
const submit = () => {
if (transferValue.value.length == 0) {
return proxy.$message.error('请选择申请单');
}
if (!projectWithDepartment(transferValue.value, 2)) {
return;
}
let applicationListAllFilter = applicationListAll.value.filter((item) => {
return transferValue.value.includes(item.adviceDefinitionId);
});
applicationListAllFilter = applicationListAllFilter.map((item) => {
return {
adviceDefinitionId: item.adviceDefinitionId, /** 诊疗定义id */
quantity: 1,// /** 请求数量 */
unitCode: item.priceList[0].unitCode, /** 请求单位编码 */
unitPrice: item.priceList[0].price, /** 单价 */
totalPrice: item.priceList[0].price, /** 总价 */
positionId: item.positionId,//执行科室id
ybClassEnum: item.ybClassEnum,//类别医保编码
conditionId: item.conditionId,//诊断ID
encounterDiagnosisId: item.encounterDiagnosisId,//就诊诊断id
adviceType: item.adviceType,///** 医嘱类型 */
definitionId: item.priceList[0].definitionId,//费用定价主表ID */
definitionDetailId: item.definitionDetailId,//费用定价子表ID */
accountId: patientInfo.value.accountId,// // 账户id
adviceDefinitionId: item.adviceDefinitionId /** 诊疗定义id */,
quantity: 1, // /** 请求数量 */
unitCode: item.priceList[0].unitCode /** 请求单位编码 */,
unitPrice: item.priceList[0].price /** 单价 */,
totalPrice: item.priceList[0].price /** 总价 */,
positionId: item.positionId, //执行科室id
ybClassEnum: item.ybClassEnum, //类别医保编码
conditionId: item.conditionId, //诊断ID
encounterDiagnosisId: item.encounterDiagnosisId, //就诊诊断id
adviceType: item.adviceType, ///** 医嘱类型 */
definitionId: item.priceList[0].definitionId, //费用定价主表ID */
definitionDetailId: item.definitionDetailId, //费用定价子表ID */
accountId: patientInfo.value.accountId, // // 账户id
};
});
saveInspection({
saveCheckd({
activityList: applicationListAllFilter,
patientId: patientInfo.value.patientId, //患者ID
encounterId: patientInfo.value.encounterId, // 就诊ID
organizationId: patientInfo.value.inHospitalOrgId, // 医疗机构ID
requestFormId: '', // 申请单ID
name: '检申请单',
name: '检申请单',
descJson: JSON.stringify(form),
categoryEnum: '1', // 1 检验 2 检查 3 输血 4 手术
categoryEnum: '2', // 1 检验 2 检查 3 输血 4 手术
}).then((res) => {
if (res.code === 200) {
proxy.$message.success(res.msg);
applicationList.value = [];
emits('submitOk');
proxy.$message.success(res.msg);
applicationList.value = [];
emits('submitOk');
} else {
proxy.$message.error(res.message);
}
});
};
defineExpose({ state, submit });
/** 查询科室 */
const getLocationInfo = () => {
getOrgList().then((res) => {
orgOptions.value = res.data?.records[0]?.children;
});
};
// 获取诊断目录
function getDiagnosisList() {
getEncounterDiagnosis(patientInfo.value.encounterId).then((res) => {
console.log('诊断目录========>', JSON.stringify(res.data));
if (res.code == 200) {
const datas = (res.data || []).map((item) => {
let obj = {
...item,
};
if (obj.diagSrtNo == null) {
obj.diagSrtNo = '1';
}
return obj;
});
// 主诊断
form.primaryDiagnosisList = datas.filter((item) => {
return item?.maindiseFlag == 1;
});
console.log('@@@@@@========>', form.primaryDiagnosisList);
if (form.primaryDiagnosisList.length == 1) {
const obj = form.primaryDiagnosisList[0];
form.clinicalDiagnosis = obj.name;
}
//其他诊断
form.otherDiagnosisList = datas.filter((item) => {
return item?.maindiseFlag !== 1;
});
const otherDiagnosisNameList = form.otherDiagnosisList.map((item) => {
return item.name;
});
form.otherDiagnosis = otherDiagnosisNameList.join(',');
}
});
}
defineExpose({ state, submit, getLocationInfo, getDiagnosisList });
</script>
<style lang="scss" scoped>
.medicalExaminations-container {
height: 100%;
width: 100%;
.transfer-wrapper {
position: relative;
min-height: 300px;
}
.el-transfer {
--el-transfer-panel-width: 400px !important;
}
height: 100%;
width: 100%;
.bloodTransfusion-form {
padding: 8px 8px 0 8px;
height: 100%;

View File

@@ -4,133 +4,228 @@
* @Description: 手术
-->
<template>
<div class="surgery-container">
<el-transfer v-model="value" :data="applicationList" filter-placeholder="项目代码/名称" filterable :titles="['未选择', '已选择']" />
<div class="surgery-container">
<div v-loading="loading" class="transfer-wrapper">
<el-transfer
v-model="transferValue"
:data="applicationList"
filter-placeholder="项目代码/名称"
filterable
:titles="['未选择', '已选择']"
/>
</div>
<div class="bloodTransfusion-form">
<el-form :model="form" :rules="rules" ref="formRef" label-width="120px" class="demo-ruleForm">
<el-row :gutter="20">
<el-row :gutter="20">
<!-- <el-col :span="12">
<el-form-item label="项目类别" prop="categoryType" style="width: 100%">
<el-input v-model="form.categoryType" autocomplete="off" />
</el-form-item>
</el-col> -->
<el-col :span="12">
<el-form-item label="项目类别" prop="patientName" style="width:100%">
<el-input v-model="form.patientName" autocomplete="off" />
<el-form-item label="发往科室" prop="targetDepartment" style="width: 100%">
<!-- <el-input v-model="form.targetDepartment" autocomplete="off" /> -->
<el-tree-select
clearable
style="width: 100%"
v-model="form.targetDepartment"
filterable
:data="orgOptions"
:props="{
value: 'id',
label: 'name',
children: 'children',
}"
value-key="id"
check-strictly
placeholder="请选择科室"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="发往科室" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" />
<el-form-item label="症状" prop="symptom" style="width: 100%">
<el-input v-model="form.symptom" autocomplete="off" type="textarea" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="症状" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" type="textarea" />
<el-form-item label="体征" prop="sign" style="width: 100%">
<el-input v-model="form.sign" autocomplete="off" type="textarea" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="体征" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" type="textarea" />
<el-col :span="12">
<el-form-item label="临床诊断" prop="clinicalDiagnosis" style="width: 100%">
<el-input disabled v-model="form.clinicalDiagnosis" autocomplete="off" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="临床诊断" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" />
<el-col :span="12">
<el-form-item label="其他诊断" prop="otherDiagnosis" style="width: 100%">
<el-input disabled v-model="form.otherDiagnosis" autocomplete="off" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="其他诊断" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" />
<el-col :span="12">
<el-form-item label="相关结果" prop="relatedResult" style="width: 100%">
<el-input v-model="form.relatedResult" autocomplete="off" type="textarea" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="相关结果" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" type="textarea" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="注意事项" prop="patientName" style="width: 100%">
<el-input v-model="form.patientName" autocomplete="off" type="textarea" />
<el-col :span="12">
<el-form-item label="注意事项" prop="attention" style="width: 100%">
<el-input v-model="form.attention" autocomplete="off" type="textarea" />
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
</div>
</div>
</template>
<script setup name="Surgery">
import { getCurrentInstance, onBeforeMount, onMounted, reactive } from 'vue'
import { getCurrentInstance, onBeforeMount, onMounted, reactive } from 'vue';
import { patientInfo } from '../../../store/patient.js';
import { getOrgList } from '../../../../../basicmanage/ward/components/api.js';
import { getEncounterDiagnosis } from '../../api.js';
const { proxy } = getCurrentInstance();
const emits = defineEmits(['submitOk'])
const props = defineProps({
})
import { getApplicationList,saveSurgery } from './api'
const state = reactive({
})
const emits = defineEmits(['submitOk']);
const props = defineProps({});
import { getApplicationList, saveSurgery } from './api';
import { ElMessage } from 'element-plus';
const state = reactive({});
const applicationListAll = ref();
const applicationList=ref()
const getList= ()=> {
if (patientInfo.value?.inHospitalOrgId) {
getApplicationList({
const applicationList = ref();
const loading = ref(false);
const orgOptions = ref([]); // 科室选项
const getList = () => {
if (!patientInfo.value?.inHospitalOrgId) {
applicationList.value = [];
return;
}
loading.value = true;
getApplicationList({
pageSize: 10000,
pageNum: 1,
categoryCode: '24',
organizationId: patientInfo.value.inHospitalOrgId,
adviceTypes:'3'//1 药品 2耗材 3诊疗
}
).then((res) => {
if (res.code === 200) {
applicationListAll.value = res.data.records;
applicationList.value = res.data.records.map((item) => {
adviceTypes: '3', //1 药品 2耗材 3诊疗
})
.then((res) => {
if (res.code === 200) {
applicationListAll.value = res.data.records;
applicationList.value = res.data.records.map((item) => {
return {
adviceDefinitionId: item.adviceDefinitionId,
orgId: item.orgId,
label: item.adviceName + item.adviceDefinitionId,
key: item.adviceDefinitionId,
};
});
} else {
proxy.$message.error(res.message);
applicationList.value = []
}
})
}
}
} else {
proxy.$message.error(res.message);
applicationList.value = [];
}
})
.finally(() => {
loading.value = false;
});
};
const transferValue = ref([]);
const form = reactive({
patientName: '',
patientSex: '',
patientAge: '',
patientPhone: '',
patientAddress: '',
})
const rules = reactive({
})
onBeforeMount(() => {
})
// categoryType: '', // 项目类别
targetDepartment: '', // 发往科室
symptom: '', // 症状
sign: '', // 体征
clinicalDiagnosis: '', // 临床诊断
otherDiagnosis: '', // 其他诊断
relatedResult: '', // 相关结果
attention: '', // 注意事项
primaryDiagnosisList: [], //主诊断目录
otherDiagnosisList: [], //其他断目录
});
const rules = reactive({});
onBeforeMount(() => {});
onMounted(() => {
getList()
})
getList();
});
/**
* type(1watch监听类型 2:点击保存类型)
* selectProjectIds(选中项目的id数组)
* */
const projectWithDepartment = (selectProjectIds, type) => {
//1.获取选中的项目 2.判断项目的执行科室是否相同 3.判断执行科室是否配置 4.将项目的执行科室复值到执行科室下拉选位置
let isRelease = true;
// 选中项目的数组
const arr = [];
// 根据选中的项目id查找对应的项目
selectProjectIds.forEach((element) => {
const searchData = applicationList.value.find((item) => {
return element == item.adviceDefinitionId;
});
arr.push(searchData);
});
// 清空科室
form.targetDepartment = '';
if (arr.length > 0) {
const obj = arr[0];
// 判断科室是否相同
const isCompare = arr.every((item) => {
return item.orgId == obj.orgId;
});
if (!isCompare) {
ElMessage({
type: 'error',
message: '执行科室不同',
});
isRelease = false;
}
// 选中项目中的执行科室id与全部科室数据做匹配
const findItem = orgOptions.value.find((item) => {
return item.id == obj.orgId;
});
if (!findItem) {
isRelease = false;
ElMessage({
type: 'error',
message: '未找到项目执行的科室',
});
}
if (type == 1) {
if (isRelease) {
form.targetDepartment = findItem.id;
}
}
}
return isRelease;
};
// 监听选择项目变化
watch(
() => transferValue.value,
(newValue) => {
projectWithDepartment(newValue, 1);
}
);
const submit = () => {
if (transferValue.value.length == 0) {
return proxy.$message.error('请选择申请单');
}
if (!projectWithDepartment(transferValue.value, 2)) {
return;
}
let applicationListAllFilter = applicationListAll.value.filter((item) => {
return transferValue.value.includes(item.adviceDefinitionId);
});
applicationListAllFilter = applicationListAllFilter.map((item) => {
return {
adviceDefinitionId: item.adviceDefinitionId, /** 诊疗定义id */
quantity: 1,// /** 请求数量 */
unitCode: item.priceList[0].unitCode, /** 请求单位编码 */
unitPrice: item.priceList[0].price, /** 单价 */
totalPrice: item.priceList[0].price, /** 总价 */
positionId: item.positionId,//执行科室id
ybClassEnum: item.ybClassEnum,//类别医保编码
conditionId: item.conditionId,//诊断ID
encounterDiagnosisId: item.encounterDiagnosisId,//就诊诊断id
adviceType: item.adviceType,///** 医嘱类型 */
definitionId: item.priceList[0].definitionId,//费用定价主表ID */
definitionDetailId: item.definitionDetailId,//费用定价子表ID */
accountId: patientInfo.value.accountId,// // 账户id
adviceDefinitionId: item.adviceDefinitionId /** 诊疗定义id */,
quantity: 1, // /** 请求数量 */
unitCode: item.priceList[0].unitCode /** 请求单位编码 */,
unitPrice: item.priceList[0].price /** 单价 */,
totalPrice: item.priceList[0].price /** 总价 */,
positionId: item.positionId, //执行科室id
ybClassEnum: item.ybClassEnum, //类别医保编码
conditionId: item.conditionId, //诊断ID
encounterDiagnosisId: item.encounterDiagnosisId, //就诊诊断id
adviceType: item.adviceType, ///** 医嘱类型 */
definitionId: item.priceList[0].definitionId, //费用定价主表ID */
definitionDetailId: item.definitionDetailId, //费用定价子表ID */
accountId: patientInfo.value.accountId, // // 账户id
};
});
saveSurgery({
@@ -139,37 +234,80 @@ const submit = () => {
encounterId: patientInfo.value.encounterId, // 就诊ID
organizationId: patientInfo.value.inHospitalOrgId, // 医疗机构ID
requestFormId: '', // 申请单ID
name: '检验申请单',
name: '手术申请单',
descJson: JSON.stringify(form),
categoryEnum: '1', // 1 检验 2 检查 3 输血 4 手术
}).then((res) => {
if (res.code === 200) {
proxy.$message.success(res.msg);
applicationList.value = [];
emits('submitOk');
categoryEnum: '4', // 1 检验 2 检查 3 输血 4 手术
}).then((res) => {
if (res.code === 200) {
proxy.$message.success(res.msg);
applicationList.value = [];
emits('submitOk');
} else {
proxy.$message.error(res.message);
}
});
});
};
defineExpose({ state, submit });
</script>
/** 查询科室 */
const getLocationInfo = () => {
getOrgList().then((res) => {
orgOptions.value = res.data?.records[0]?.children;
});
};
// 获取诊断目录
function getDiagnosisList() {
getEncounterDiagnosis(patientInfo.value.encounterId).then((res) => {
console.log('诊断目录========>', JSON.stringify(res.data));
if (res.code == 200) {
const datas = (res.data || []).map((item) => {
let obj = {
...item,
};
if (obj.diagSrtNo == null) {
obj.diagSrtNo = '1';
}
return obj;
});
// 主诊断
form.primaryDiagnosisList = datas.filter((item) => {
return item?.maindiseFlag == 1;
});
console.log('@@@@@@========>', form.primaryDiagnosisList);
if (form.primaryDiagnosisList.length == 1) {
const obj = form.primaryDiagnosisList[0];
form.clinicalDiagnosis = obj.name;
}
//其他诊断
form.otherDiagnosisList = datas.filter((item) => {
return item?.maindiseFlag !== 1;
});
const otherDiagnosisNameList = form.otherDiagnosisList.map((item) => {
return item.name;
});
form.otherDiagnosis = otherDiagnosisNameList.join(',');
}
});
}
defineExpose({ state, submit, getLocationInfo, getDiagnosisList });
</script>
<style lang="scss" scoped>
.surgery-container {
height: 100%;
padding: 8px;
.el-transfer {
--el-transfer-panel-width: 400px !important;
}
.surgery-container {
height: 100%;
width: 100%;
.bloodTransfusion-form {
.transfer-wrapper {
position: relative;
min-height: 300px;
}
.el-transfer {
--el-transfer-panel-width: 400px !important;
}
.bloodTransfusion-form {
padding: 8px 8px 0 8px;
height: 100%;
width: 100%;
display: flex;
}
}
</style>
</style>

View File

@@ -1,108 +0,0 @@
<!--
* @Author: sjjh
* @Date: 2025-04-09 17:55:05
* @Description:
-->
<template>
<div class="patient-card" v-for="item in data" :key="item.encounterId" :id="item.encounterId">
<patient-parent-card :activeId="modelValue" :type="type" :data="item" @click="parentClick">
</patient-parent-card>
<!-- // TODO 是否考虑孩子 -->
<!-- <div v-if="item.children">
<div
style="margin-top: 8px"
v-for="citem in item.children"
:key="citem.id"
:id="citem.id"
>
<patient-child-card
:active-id="modelValue"
:data="citem"
:parentData="item"
@click="childClick"
>
</patient-child-card>
</div>
</div> -->
</div>
</template>
<script setup>
import { ref, watch } from 'vue';
import PatientParentCard from './patientParentCard.vue';
// import PatientChildCard from './PatientChildCard.vue'
defineOptions({
name: 'PatientCard',
});
const props = defineProps({
modelValue: '',
data: [],
type: 0,
keyChild: '',
auto: true,
});
const value = ref(props.modelValue);
// const childClick = (node: any, parentVal: any) => {
// if (props.auto) {
// value.value = node.id
// }
// emits('click', value.value, node, parentVal)
// }
const diagnosisInit = inject('diagnosisInit')
const getAdviceList = inject('getAdviceList')
const adviceDiagnoInit = inject('adviceDiagnoInit')
// 调用方法
const parentClick = (node) => {
value.value = node.encounterId;
emits('click', value.value, node, null);
setTimeout(() => {
diagnosisInit()
getAdviceList()
adviceDiagnoInit()
}, 0);
};
const parentNode = ref();
const getItem = (val) => {
parentNode.value = null;
const re = props.data.find((item) => {
return item.encounterId === val;
});
if (re) return re;
else {
let rec;
props.data.forEach((item) => {
if (item.children) {
item.children.find((citem) => {
if (citem.encounterId === val) {
parentNode.value = item;
rec = citem;
}
});
}
});
return rec;
}
};
const emits = defineEmits(['click', 'change', 'update:modelValue']);
watch(props, (newValue) => {
value.value = newValue.modelValue;
});
watch(value, (val) => {
emits('update:modelValue', val);
emits('change', val, getItem(val), parentNode.value);
});
</script>
<style lang="scss" scoped>
.patient-card {
user-select: none;
& + .patient-card {
margin-top: 8px;
}
}
</style>

View File

@@ -1,107 +0,0 @@
<!--
* @Author: yangbo@bjgoodwill.com
* @Date: 2024-10-23 09:37:17
* @Description: 患者卡片-孩子节点
-->
<template>
<div @click="clickAct" style="display: flex">
<div class="patient-child_broken"></div>
<div
class="child-card"
:style="{
backgroundColor:
activeId === data.id ? 'rgba(19,192,179,0.05)' : '#ffffff',
borderColor: activeId === data.id ? '#13C0B3' : '#eeeeee',
}"
>
<div class="child-bed">
{{ data.bedName }}
</div>
<div class="child-line"></div>
<div class="child-name">
{{ data.name }}
<div class="child-age">{{ data.sexName }}/{{ data.age }}</div>
</div>
</div>
</div>
</template>
<script setup>
defineOptions({
name: 'PatientChildCard',
});
const props = defineProps({
data: {},
activeId: '',
parentData: {}
});
const emits = defineEmits(['click']);
const clickAct = () => {
emits('click', props.data, props.parentData);
};
</script>
<style lang="scss" scoped>
// 孩子节点
.child-card {
position: relative;
width: 214px;
height: 80px;
margin-left: 4px;
border: 1px solid;
border-radius: 4px;
box-shadow: 0 2px 2px 0 rgba(57.55, 69.04, 86.28, 20%);
cursor: pointer;
.child-bed {
position: absolute;
top: 8px;
left: 16px;
display: flex;
color: #333;
font-weight: 600;
font-size: 16px;
}
.child-line {
position: absolute;
top: 38px;
left: 16px;
width: 182px;
border-bottom: 1px dashed #ddd;
}
.child-num {
position: absolute;
top: 9px;
right: 16px;
color: #666;
font-size: 14px;
}
.child-name {
position: absolute;
top: 48px;
left: 16px;
display: flex;
color: #333;
font-size: 16px;
.child-age {
margin-top: 2.5px;
margin-left: 16px;
color: #666;
font-size: 14px;
}
}
}
// 折线
.patient-child_broken {
width: 17px;
height: 21px;
margin-top: 18px;
border-bottom: 1px solid #ddd;
border-left: 1px solid #ddd;
}
</style>

View File

@@ -1,243 +0,0 @@
<!--
* @Author: yangbo@bjgoodwill.com
* @Date: 2024-10-23 09:39:24
* @Description: 患者卡片-父节点
-->
<template>
<div
@click="clickAct"
class="patient-card"
:class="{
actived: activeId === data.encounterId,
}"
>
<!-- //跨科 考虑不考虑 -->
<div class="main-info-container">
<div class="bed-container">
<!-- 患者床号 -->
<div class="bed">
<el-text truncated :tclass="bedfont" width="auto">{{ data.bedName }}</el-text>
</div>
<!-- 新入院患者标志 -->
<!-- <div class="bed_new" /> -->
</div>
<div class="indepatient-code-container">
<!-- 患者重/危标识符 -->
<!-- <div
class="sign"
:style="{
backgroundColor: data?.criticalCarePatientName === '危' ? '#BA7BC8' : '#E95657',
}"
>
{{ data.criticalCarePatientName }}
</div> -->
<!-- 住院号 -->
<span style="margin-left: 4px"> {{ data.busNo }} </span>
</div>
</div>
<div class="doctor-parent-line" />
<div class="personal-info-container">
<div class="name-container">
<!-- 患者姓名 -->
<div class="name" style="max-width: 70px">
<el-text :text="data.patientName" tclass="name" width="auto">
{{ data.patientName }}
</el-text>
</div>
<!-- 患者性别/年龄 -->
<div class="age">{{ data.genderEnum_enumText }}/{{ data.age }}</div>
</div>
</div>
<div class="dept">
<div class="doctor">
<el-icon size="20px">
<UserFilled />
</el-icon>
<!-- // TODO 医生图标 -->
<div class="doctor_name">{{ data.admittedDoctorName }}</div>
</div>
<div class="deptNurseName">
<el-icon size="20px">
<Avatar />
</el-icon>
<!-- // TODO 护士图标 -->
{{ data.deptNurseName }}
</div>
</div>
</div>
</template>
<script setup>
defineOptions({
name: 'PatientParentCard',
})
const bedfont = 'bed-font'
const props = defineProps({
data: {},
// type0:在科、1:出院、2:转科、3:会诊、
type: 0,
activeId: ''
})
const emits = defineEmits(['click'])
const clickAct = () => {
emits('click', props.data)
}
</script>
<style lang="scss" scoped>
.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%);
cursor: pointer;
&.actived {
background-color: rgb(7, 155, 140, 5%);
border-color: var(--el-color-primary);
}
.cross-dept {
height: 24px;
padding: 0 16px;
color: #fff;
font-size: 14px;
line-height: 24px;
background-color: #256d95;
}
.main-info-container {
display: flex;
align-items: center;
justify-content: space-between;
height: 24px;
margin: 7px 0;
padding: 0 16px;
.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;
}
}
}
.doctor-parent-line {
margin: 0 16px;
border-bottom: 1px dashed #ddd;
}
.personal-info-container {
display: flex;
align-items: center;
justify-content: space-between;
margin: 10px 0;
padding: 0 16px;
.name-container {
display: flex;
align-items: center;
height: 24px;
.name {
color: #333;
font-size: 16px;
}
.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;
}
}
}
</style>

View File

@@ -1,385 +0,0 @@
<!--
* @Author:
* @Description: 患者列表
-->
<template>
<div class="patientList-container">
<div class="patientList-operate" :class="{ 'patientList-operate-unexpand': !expand }">
<el-space>
<el-icon icon-class="Refresh" size="24" @click="getList">
<Refresh />
</el-icon>
<el-icon class="svg-sty-menu" size="24" @click="updateExpand">
<Expand v-if="!expand" />
<Fold v-if="expand" />
</el-icon>
</el-space>
</div>
<div class="patientList-list" v-if="expand">
<div class="search-operate">
<!-- 在科 -->
<el-input
placeholder="床号/住院号/姓名"
v-model="searchData.keyword"
@keyup.enter="queryPatientData"
:prefix-icon="Search"
>
</el-input>
</div>
<div class="patient-cards" v-loading="queryloading">
<template v-if="filteredCardData.length > 0">
<el-scrollbar ref="expandScrollbarRef" class="patient-cards-scrollbar">
<patient-card
v-model="cardId"
:data="filteredCardData"
:type="active"
@change="cardChange"
>
</patient-card>
</el-scrollbar>
</template>
<el-empty v-else description="暂无数据" />
</div>
</div>
<div class="patientList-list" v-loading="queryloading" v-else>
<el-scrollbar ref="contractScrollbarRef" class="patient-cards-scrollbar">
<el-tooltip
v-for="item in filteredCardData"
:show-after="200"
:key="item.encounterId"
:show-arrow="true"
placement="right"
effect="light"
:offset="4"
>
<template #content>
<div class="card-tooltip">
<span class="f-16">{{ item.bedName }}</span>
<span class="f-14">{{ item.name }}</span>
<el-icon v-if="item.sexName === '女'" :size="24"> <Female /></el-icon>
<el-icon v-else icon-class="headMale" :size="24"><Male /></el-icon>
</div>
</template>
<div>
<div
class="card-small"
:class="{ 'patient-active': cardId === item.encounterId }"
@click="smallCardClick(item)"
:key="item.encounterId"
>
{{ item.bedName }}
</div>
<div class="patient-card-small-border"></div>
</div>
</el-tooltip>
</el-scrollbar>
</div>
</div>
</template>
<script setup>
import { ref, reactive, onMounted, computed } from 'vue'
// import { store } from '@hip/portal'
import { patientInfo, updatePatientInfo } from '../store/patient'
import PatientCard from './patientCard/index.vue'
import { Search } from '@element-plus/icons-vue'
import { getPatientList } from './api'
// const props = defineProps({
// })
const expand = defineModel('expand')
// const emit = defineEmits(['update:expand'])
const active = ref(0)
const searchData = reactive({
keyword: '',
patientType: 1,
type: 1,
timeLimit: 3,
})
// const { userInfo } = store.useGlobalStore()
// 卡片
const cardId = ref('')
// 所有卡片数据
const cardAllData = ref([
// {
// id: '1',
// name: '张三',
// sexName: '女',
// bedName: '1-1床',
// deptNurseName: '护士甲',
// crossDeptFlag: false,
// criticalCarePatientName: '危',
// inpatientCode: '1212121212',
// age: '30',
// admittedDoctorName: '医生乙',
// },
// {
// id: '2',
// name: '李四',
// sexName: '男',
// bedName: '1-2床',
// deptNurseName: '护士甲',
// crossDeptFlag: false,
// criticalCarePatientName: '重',
// inpatientCode: '1212121212',
// age: '30',
// admittedDoctorName: '医生乙',
// },
])
// 过滤后的卡片数据
const filteredCardData = computed(() => {
// switch (active.value) {
// case 0:
// return cardAllData.value.filter((item: IInPatient) => {
// // const staffId = userInfo?.staffId
// // 在科患者-我的患者 住院/主治/主任医生只要有一个对应即可显示
// if (searchData.patientType === 1) {
// if (
// staffId !== item.directorDoctor &&
// staffId !== item.masterDoctor &&
// staffId !== item.admittedDoctor
// ) {
// return false
// }
// }
// // 在科患者-科室患者 全部/婴儿/非婴儿
// if (searchData.type === 2) {
// // 婴儿
// if (!(item.children && item.children.length > 0)) {
// return false
// }
// } else if (searchData.type === 3) {
// // 非婴儿
// if (item.children && item.children.length > 0) {
// return false
// }
// }
// // 关键字
// if (
// searchData.keyword &&
// !(
// item.bedName.includes(searchData.keyword) ||
// item.name.includes(searchData.keyword) ||
// item.inpatientCode.includes(searchData.keyword)
// )
// ) {
// return false
// }
// return true
// })
// default:
// return cardAllData.value
// }
return cardAllData.value
})
// 是否初始化激活状态
const isInitActive = ref(true)
// 展开患者列表Ref
const expandScrollbarRef = ref()
// 收缩患者列表Ref
const contractScrollbarRef = ref()
const queryloading = ref(false)
onMounted(() => {
cardId.value = patientInfo.value?.encounterId || ''
queryPatientData()
})
const getList = () => {
getPatientList({ status: 5 }).then((res) => {
cardAllData.value = res.data.records
})
}
/**
* 滚动到选中位置
* @param {*} value
*/
const scrollToSelected = () => {
// 如果不是第一次定位,则不进行滚动
if (!isInitActive.value) return
const currentRef = props.expand === true ? expandScrollbarRef : contractScrollbarRef
if (!currentRef.value) return
const value = getSelectedOffsetTop(currentRef)
currentRef.value.setScrollTop(value || 0)
isInitActive.value = false
}
/**
* 获取选中元素位置
* @param {*} ref
*/
const getSelectedOffsetTop = (ref) => {
const childrenNodeArray = ref?.value?.wrapRef?.children[0]?.children
if (!childrenNodeArray?.length) return 0
// TODO 当有子元素时候需要优化
const targetNode = Array.from(childrenNodeArray).find((childrenNode) => {
return childrenNode?.__vnode?.key === cardId.value
})
return targetNode?.offsetTop || 0
}
/**
* 更新展开状态
*/
const updateExpand = () => {
// emit('update:expand', !props.expand)
expand.value = !expand.value
}
const cardChange = (val, node, parent) => {
updatePatientInfo(node)
}
const smallCardClick = (val) => {
cardId.value = val.encounterId
updatePatientInfo(val)
}
// TODO 从后端获取数据
const queryPatientData = async () => {
if (queryloading.value) return
try {
// queryloading.value = true
// const res: IInPatient[] = []
// // TODO 获取患者列表
// // 设置patMiCode和patCode实际是同一字段
// res.forEach((item: IInPatient) => {
// item.patMiCode = item.patCode
// })
// cardAllData.value = res
// scrollToSelected()
} catch (error) {
cardAllData.value = []
} finally {
queryloading.value = false
}
}
getList()
</script>
<style lang="scss" scoped>
.patientList-container {
height: 100%;
display: flex;
flex-direction: column;
height: 100%;
border-right: 1px solid #ebeef5;
background-color: #ffffff;
.patientList-operate {
display: flex;
align-items: center;
justify-content: flex-end;
height: 44px;
padding: 0 8px;
border-bottom: 1px solid #ebeef5;
flex: none;
&-unexpand {
justify-content: space-around;
padding: 0 8px;
}
}
.patientList-list {
display: flex;
flex: 1;
flex-direction: column;
height: 0;
.search-operate {
padding: 0 8px;
height: 48px;
display: flex;
align-items: center;
flex: none;
}
.patient-cards {
flex: 1;
padding: 0 8px;
overflow: hidden;
:deep(.patient-cards-scrollbar) {
width: 100%;
height: 100%;
.el-scrollbar__bar {
width: 0;
}
}
}
.patient-active {
background-color: var(--el-color-primary);
}
.card-small {
height: 44px;
padding-right: 4px;
padding-left: 12px;
overflow: hidden;
font-size: 16px;
line-height: 44px;
white-space: nowrap;
text-overflow: ellipsis;
border-right: none;
cursor: pointer;
&-active {
background-color: rgb(243, 252, 251);
}
// &:hover {
// background-color: #f8f8f8;
// }
}
.patient-card-small-border {
display: block;
width: 100%;
height: 2px;
background-color: #f1faff;
}
}
}
.card-tooltip {
display: inline-flex;
align-items: center;
height: 45px;
padding: 0 10px;
}
.svg-gray {
fill: var(--hip-color-text-unit);
}
:deep(.scrollbar) {
width: 100%;
height: 100%;
.el-scrollbar__bar {
width: 0;
}
}
.f-16 {
font-weight: 600;
font-size: 16px;
}
.f-14 {
font-size: 14px;
}
.empty-wrap {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
.empty-text-sty {
margin-top: 0;
}
}
</style>

View File

@@ -1,18 +1,34 @@
/*
* @Author: sjjh
* @Date: 2025-09-20 17:02:37
* @Description:
* @Description:
*/
import request from '@/utils/request'
import request from '@/utils/request';
// ====== 文书记录
// 新记录
// 保存或更新记录
export function saveOrUpdateRecord(data) {
return request({
url: '/document/record/saveOrUpdateRecord',
method: 'post',
data,
});
}
// 新增记录
export function addRecord(data) {
return request({
url: '/document/record/addRecord',
method: 'post',
data
})
data,
});
}
// 删除历史记录
export function deleteRecord(ids) {
return request({
url: '/document/record/deleteRecord',
method: 'delete',
data: ids,
});
}
// 根据患者ID或就诊ID获取文书记录列表,只针对不需返回患者具体信息的列表,体温单除外,单独处理
@@ -20,15 +36,15 @@ export function getRecordByEncounterIdList(params) {
return request({
url: '/document/record/getRecordByEncounterIdList',
method: 'get',
params
})
params,
});
}
// 初始化文书定义
export function init() {
return request({
url: '/document/record/init',
method: 'get',
})
});
}
// ====== 文书模板
@@ -37,24 +53,22 @@ export function addTemplate(data) {
return request({
url: '/document/template/add',
method: 'post',
data
})
data,
});
}
//
export function getListByDefinitionId(definitionId) {
return request({
url: '/document/template/getListByDefinitionId',
method: 'get',
params: {definitionId}
})
params: { definitionId },
});
}
// 更新模板
export function updateTemplate(data) {
return request({
url: '/document/template/update',
method: 'put',
data
})
data,
});
}

View File

@@ -8,14 +8,25 @@
</el-input>
</div>
<el-scrollbar class="emr-history-scrollbar-container" style="width: 100%">
<div v-for="item in historyData" :key="item.id" class="scrollbar-item">
<el-tooltip
effect="dark"
:content="`${item.name}(${item.recordTime})`"
placement="bottom"
>
<div
v-for="item in historyData"
:key="item.id"
class="scrollbar-item"
:class="{ 'selected-history-item': item.id === props.selectedRecordId }"
>
<el-tooltip effect="dark" :content="`${item.name}(${item.recordTime})`" placement="bottom">
<el-text class="w-150px mb-2" truncated @click="handleNodeClick(item)">
{{ item.name }}({{ item.recordTime }})
<el-icon
class="ml-2"
style="margin-left: 26px; cursor: pointer"
:disabled="item.printCount && item.printCount > 0"
:class="{ 'disabled-icon': item.printCount && item.printCount > 0 }"
@click.stop="handleDelete(item)"
>
<Delete />
</el-icon>
</el-text>
</el-tooltip>
</div>
@@ -24,10 +35,11 @@
</template>
<script setup>
import { ref, reactive, defineEmits, unref } from 'vue';
import { getRecordByEncounterIdList } from '../api';
import { ref, reactive, defineEmits, unref, nextTick } from 'vue';
import { getRecordByEncounterIdList, deleteRecord } from '../api';
import { ElTree } from 'element-plus';
import { ElMessageBox, ElMessage, ElLoading } from 'element-plus';
import { Delete } from '@element-plus/icons-vue';
import { patientInfo } from '../../store/patient.js';
const emits = defineEmits(['historyClick']);
const props = defineProps({
@@ -35,6 +47,10 @@ const props = defineProps({
type: String,
default: '',
},
selectedRecordId: {
type: String,
default: '',
},
});
const definitionId = defineModel('definitionId', {
type: String,
@@ -51,7 +67,7 @@ const queryParams = ref({
const historyData = ref([]);
const queryList = async () => {
try {
if (patientInfo.value.encounterId && unref(definitionId)&&unref(definitionId) !== '') {
if (patientInfo.value.encounterId && unref(definitionId) && unref(definitionId) !== '') {
const res = await getRecordByEncounterIdList({
...queryParams.value,
encounterId: patientInfo.value.encounterId,
@@ -59,46 +75,76 @@ const queryList = async () => {
definitionId: unref(definitionId),
});
historyData.value = res.data || [];
}else{
} else {
historyData.value = [];
}
} catch (error) {
ElMessage.error('获取模板树失败');
// 不显示错误消息,避免干扰用户体验
historyData.value = [];
}
};
// 更新选中的历史记录ID
const updateSelectedRecord = (recordId) => {
// 这个函数可以供父组件调用,用于更新选中状态
nextTick(() => {
// 选中状态会通过props.selectedRecordId自动更新
});
};
// 删除历史记录
const handleDelete = async (item) => {
try {
// 检查是否已打印
if (item.printCount && item.printCount > 0) {
ElMessage.warning('已打印的记录不允许删除');
return;
}
await deleteRecord([item.id]);
ElMessage.success('删除成功');
queryList();
} catch (error) {
ElMessage.error('删除失败');
}
};
const handleNodeClick = (data) => {
emits('historyClick', data);
};
const currentSelectTemplate = ref({});
defineExpose({ queryList });
defineExpose({ queryList, updateSelectedRecord });
</script>
<style lang="scss" scoped>
.emr-history-container {
height: 100%;
// padding: 8px;
.search-box {
height: 40px;
line-height: 40px;
}
.emr-history-scrollbar-container{
padding: 8px;
height: calc(100% - 40px);
.scrollbar-item {
height: 100%;
// padding: 8px;
.search-box {
height: 40px;
line-height: 40px;
border-radius: 4px;
cursor: pointer;
background: var(--el-color-primary-light-9);
& + .scrollbar-item {
margin-top: 8px;
}
.emr-history-scrollbar-container {
padding: 8px;
height: calc(100% - 40px);
.scrollbar-item {
height: 40px;
line-height: 40px;
border-radius: 4px;
cursor: pointer;
background: var(--el-color-primary-light-9);
& + .scrollbar-item {
margin-top: 8px;
}
transition: all 0.3s ease;
}
.selected-history-item {
background-color: rgb(194, 231, 255);
}
.disabled-icon {
color: #d9d9d9;
cursor: not-allowed;
opacity: 0.6;
}
}
}
}
</style>

View File

@@ -9,17 +9,15 @@
</div> -->
<el-scrollbar class="emr-template-scrollbar-container" style="width: 100%">
<div v-for="item in templateData" :key="item.id" class="scrollbar-item">
<el-tooltip
effect="dark"
:content="`${item.name}`"
placement="bottom"
>
<el-tooltip effect="dark" :content="`${item.name}`" placement="bottom">
<el-text class="2" truncated @click="handleNodeClick(item)">
<div class="template-item">{{ item.name }}
<el-space>
<el-icon><Edit @click="handleEdit(item)" /></el-icon>
</el-space></div>
<div class="template-item">
{{ item.name }}
<el-space>
<el-icon><Edit @click="handleEdit(item)" /></el-icon>
<el-icon><Delete @click="handleDelete(item)" /></el-icon>
</el-space>
</div>
</el-text>
</el-tooltip>
</div>
@@ -33,7 +31,8 @@ import { getListByDefinitionId } from '../api';
import { ElTree } from 'element-plus';
import { ElMessageBox, ElMessage, ElLoading } from 'element-plus';
import { patientInfo } from '../../store/patient.js';
const emits = defineEmits(['templateClick','edit']);
import { Edit } from '@element-plus/icons-vue';
const emits = defineEmits(['templateClick', 'edit']);
const props = defineProps({
definitionId: {
type: String,
@@ -55,13 +54,12 @@ const queryParams = ref({
const templateData = ref([]);
const queryList = async () => {
try {
if ( unref(definitionId)&&unref(definitionId) !== '') {
if (unref(definitionId) && unref(definitionId) !== '') {
const res = await getListByDefinitionId(unref(definitionId));
templateData.value = res.data || [];
}else{
} else {
templateData.value = [];
}
} catch (error) {
ElMessage.error('获取模板失败');
templateData.value = [];
@@ -73,40 +71,60 @@ const handleNodeClick = (data) => {
const handleEdit = (data) => {
emits('edit', data);
};
// 删除模板
const handleDelete = async (item) => {
try {
ElMessageBox.confirm('确定要删除该模板吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(async () => {
await deleteTemplate(item.id);
ElMessage.success('删除成功');
queryList();
});
} catch (error) {
if (error !== 'cancel') {
ElMessage.error('删除失败');
}
}
};
const currentSelectTemplate = ref({});
defineExpose({ queryList });
</script>
<style lang="scss" scoped>
.emr-template-container {
height: 100%;
// padding: 8px;
.emr-template-scrollbar-container{
height: 100%;
// padding: 8px;
.emr-template-scrollbar-container {
padding: 8px;
height: 100%;
.scrollbar-item {
height: 40px;
line-height: 40px;
border-radius: 4px;
cursor: pointer;
background: var(--el-color-primary-light-9);
& + .scrollbar-item {
margin-top: 8px;
}
.el-text{
width: calc(100% - 0px);
display: flex;
justify-content: space-between;
padding: 0 8px;
}
.template-item{
width: 100%;
display: flex;
justify-content: space-between;
.scrollbar-item {
height: 40px;
line-height: 40px;
border-radius: 4px;
cursor: pointer;
background: var(--el-color-primary-light-9);
& + .scrollbar-item {
margin-top: 8px;
}
transition: all 0.3s ease;
.el-text {
width: calc(100% - 0px);
display: flex;
justify-content: space-between;
padding: 0 8px;
}
.template-item {
width: 100%;
display: flex;
justify-content: space-between;
}
}
}
}
}
</style>

View File

@@ -7,7 +7,7 @@
destroy-on-close
@open="handleOpen"
>
<!-- 使用el-form包裹表单 -->
<!-- 使用el-form包裹表单 -->
<el-form :model="formData" ref="formRef" :rules="rules" label-width="120px">
<el-row :gutter="24" class="mb8">
<el-col :span="24">

View File

@@ -5,8 +5,25 @@
-->
<template>
<div class="emr-use-container">
<<<<<<< HEAD
<div class="disBtn" :class="{'disLeftBtnNor':leftShow,'disLeftBtnAct':!leftShow}" @click="disNode"><img src="../../../../assets/icons/svg/foldup.svg"></div>
<div class="disBtn" :class="{'disRightBtnNor':rightShow,'disRightBtnAct':!rightShow}" @click="disNode_R"><img src="../../../../assets/icons/svg/foldup.svg"></div>
=======
<div
class="disBtn"
:class="{ disLeftBtnNor: leftShow, disLeftBtnAct: !leftShow }"
@click="disNode"
>
<img src="../../../../assets/icons/svg/foldup.svg" />
</div>
<div
class="disBtn"
:class="{ disRightBtnNor: rightShow, disRightBtnAct: !rightShow }"
@click="disNode_R"
>
<img src="../../../../assets/icons/svg/foldup.svg" />
</div>
>>>>>>> v1.3
<transition name="el-zoom-in-left">
<div class="template-tree-container" v-if="leftShow">
<div class="search-box">
@@ -18,6 +35,7 @@
</div>
<el-scrollbar class="template-tree-scrollbar">
<el-tree
<<<<<<< HEAD
ref="templateTree"
:data="templateData"
:props="defaultProps"
@@ -25,6 +43,15 @@
node-key="id"
@node-click="handleNodeClick"
class="template-tree"
=======
ref="templateTree"
:data="templateData"
:props="defaultProps"
auto-expand-parent
node-key="id"
@node-click="handleNodeClick"
class="template-tree"
>>>>>>> v1.3
></el-tree>
</el-scrollbar>
</div>
@@ -36,12 +63,25 @@
<!-- <el-button type="primary" @click="newEmr">新建</el-button> -->
<el-button type="primary" @click="saveAsModel">存为模版</el-button>
<el-button @click="refresh">刷新</el-button>
<el-button @click="resetForm">重置</el-button>
<el-button type="primary" @click="save">保存</el-button>
<el-button type="primary" @click="onPrint">打印表单</el-button>
<!-- <el-button type="primary" @click="" disabled>病案上传</el-button>
<el-button type="primary" @click="">结算上传</el-button> -->
<!-- <el-button type="primary" @click="onNursingStatus">护理状态</el-button> -->
<!-- <el-button type="primary" @click="print">打印</el-button> -->
</el-space>
</div>
<div class="operate-main">
<el-scrollbar class="template-tree-scrollbar">
<component :is="currentComponent" ref="emrComponentRef" @submitOk="handleSubmitOk" />
<div v-loading="loading" class="loading-container">
<component
:is="currentComponent"
ref="emrComponentRef"
:patientInfo="patientInfo"
@submitOk="handleSubmitOk"
/>
</div>
</el-scrollbar>
</div>
</div>
@@ -51,17 +91,31 @@
<el-tabs v-model="quicklyactiveName" type="card">
<el-tab-pane label="历史" name="history">
<History
<<<<<<< HEAD
@historyClick="handleHistoryClick"
ref="historyRef"
v-model:definitionId="currentSelectTemplate.id"
=======
@historyClick="handleHistoryClick"
ref="historyRef"
v-model:definitionId="currentSelectTemplate.id"
:selectedRecordId="selectedHistoryRecordId"
>>>>>>> v1.3
/>
</el-tab-pane>
<el-tab-pane label="模版" name="model">
<Template
<<<<<<< HEAD
@templateClick="handleTemplateClick"
ref="templateRef"
v-model:definitionId="currentSelectTemplate.id"
@edit="templateEdit"
=======
@templateClick="handleTemplateClick"
ref="templateRef"
v-model:definitionId="currentSelectTemplate.id"
@edit="templateEdit"
>>>>>>> v1.3
/>
</el-tab-pane>
</el-tabs>
@@ -74,15 +128,28 @@
v-model:dialogVisible="templateEditVisible"
@submitOk="templateEditSubmitOk"
/>
<el-drawer v-model="openDrawer" size="100%">
<template #default>
<div>
<NursingStatus></NursingStatus>
</div>
</template>
</el-drawer>
</div>
</template>
<script setup>
import { getCurrentInstance, onBeforeMount, onMounted, reactive, ref } from 'vue';
import { getCurrentInstance, nextTick, onBeforeMount, onMounted, reactive, ref, watch } from 'vue';
import { ElMessageBox, ElMessage, ElLoading } from 'element-plus';
import { getTreeList } from '@/views/basicmanage/caseTemplates/api';
import { addRecord, addTemplate } from './api';
import { saveOrUpdateRecord, addTemplate, getRecordByEncounterIdList } from './api';
import { patientInfo } from '../store/patient.js';
import NursingStatus from '@/views/inpatientDoctor/home/components/applicationShow/nursingStatus.vue';
import dayjs from 'dayjs';
// 打印工具
import { simplePrint, PRINT_TEMPLATE } from '@/utils/printUtils.js';
import useUserStore from '@/store/modules/user';
const userStore = useUserStore();
// 移除未使用的变量
// const { proxy } = getCurrentInstance();
const emits = defineEmits([]);
@@ -91,20 +158,36 @@ const state = reactive({});
import History from './components/history';
import Template from './components/template';
import TemplateEdit from './components/templateEdit.vue';
import formDataJs from '../../../doctorstation/components/store/medicalpage.js';
// 定义响应式变量
const templateData = ref([]);
const queryParams = ref({
name: '',
useRanges: [1, 2], // 0 暂不使用 1 全院 2 科室 3 个人
organizationId: userStore.orgId,
});
const loading = ref(false); // 数据加载状态
const currentSelectTemplate = ref({
id: '',
});
const openDrawer = ref(false);
const currentComponent = ref('');
const emrComponentRef = ref(null);
const quicklyactiveName = ref('history');
const leftShow = ref(true);
const rightShow = ref(true);
<<<<<<< HEAD
=======
watch(patientInfo, () => {
historyRef.value?.queryList();
templateRef.value?.queryList();
});
const templateTree = ref(null);
// 当前选中的历史病历ID用于在History组件中高亮显示
const selectedHistoryRecordId = ref('');
>>>>>>> v1.3
// 树配置(模板树)
const defaultProps = {
@@ -118,6 +201,11 @@ const queryTemplateTree = async () => {
try {
const res = await getTreeList(queryParams.value);
templateData.value = res.data || [];
// 组件挂载后,如果有患者信息,默认选中门诊病历模板
if (patientInfo.value && patientInfo.value.patientId && templateData.value.length > 0) {
selectOutpatientMedicalRecordTemplate();
}
} catch (error) {
ElMessage.error('获取模板树失败');
templateData.value = [];
@@ -137,8 +225,19 @@ const handleNodeClick = (data, node) => {
};
// currentComponent.value = null;
}
historyRef.value?.queryList();
templateRef.value?.queryList();
// 确保组件状态更新后再查询历史记录
nextTick(() => {
setTimeout(() => {
historyRef.value?.queryList();
templateRef.value?.queryList();
// 选择任何病历模板后,都加载该病历类型的最新历史记录
if (node.isLeaf && patientInfo.value && patientInfo.value.patientId) {
loadLatestMedicalRecord();
}
}, 100);
});
};
const newEmr = () => {
@@ -177,8 +276,9 @@ const editTemplateForm = ref({
contextJson: '',
definitionId: '',
useRange: 2,
organizationId: '',
organizationId: userStore.orgId,
userId: '',
useRanges: [1], // 默认全院使用
remark: '',
});
@@ -197,10 +297,18 @@ const handleSubmitOk = async (data) => {
editForm.value.encounterId = patientInfo.value.encounterId;
editForm.value.patientId = patientInfo.value.patientId;
editForm.value.recordTime = dayjs().format('YYYY-MM-DD HH:mm:ss');
await addRecord(editForm.value);
ElMessage.success('病历保存成功');
await saveOrUpdateRecord(editForm.value);
// ElMessage.success('保存成功');
// 刷新历史记录列表
historyRef.value?.queryList();
templateRef.value?.queryList();
// 等待历史记录列表更新后,重新加载最新病历并更新选中状态
setTimeout(() => {
loadLatestMedicalRecord();
}, 100);
ElMessage.success('保存成功');
} catch (error) {
ElMessage.error('提交失败');
console.log(error);
@@ -209,13 +317,147 @@ const handleSubmitOk = async (data) => {
// 新增或者编辑模板
// editTemplateForm.value.id=
editTemplateForm.value.name =
currentSelectTemplate.value.name + dayjs().format('YYYY/MM/DD HH:mm');
currentSelectTemplate.value.name + dayjs().format('YYYY/MM/DD HH:mm');
editTemplateForm.value.contextJson = JSON.stringify(data);
editTemplateForm.value.definitionId = currentSelectTemplate.value.id;
editTemplateForm.value.organizationId = userStore.orgId;
editTemplateForm.value.useRanges = [1]; // 默认全院使用
templateEditVisible.value = true;
}
};
// 定义病历模板类型与打印模板的映射关系
const templateToPrintTemplateMap = {
// 手术记录相关模板
手术记录: PRINT_TEMPLATE.OPERATIVE_RECORD,
'手术记录(1.0.0)': PRINT_TEMPLATE.OPERATIVE_RECORD,
tySurgicalRecord: PRINT_TEMPLATE.OPERATIVE_RECORD,
// 门诊病历相关模板
门诊病历: PRINT_TEMPLATE.HQOUTPATIENT_MEDICAL_RECORD,
'门诊病历(1.0.0)': PRINT_TEMPLATE.HQOUTPATIENT_MEDICAL_RECORD,
测试新增: PRINT_TEMPLATE.HQOUTPATIENT_MEDICAL_RECORD,
};
// 根据模板名称获取对应的打印模板
const getPrintTemplateByTemplateName = (templateName) => {
// 默认使用红旗门诊病历模板
let printTemplate = PRINT_TEMPLATE.HQOUTPATIENT_MEDICAL_RECORD;
if (templateName) {
for (const [key, value] of Object.entries(templateToPrintTemplateMap)) {
if (templateName.includes(key)) {
printTemplate = value;
break;
}
}
}
return printTemplate;
};
// 辅助函数:将嵌套对象扁平化为单层结构
const flattenObject = (obj, prefix = '') => {
const flattened = {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
const newKey = prefix ? `${prefix}_${key}` : key;
if (typeof obj[key] === 'object' && obj[key] !== null && !Array.isArray(obj[key])) {
// 递归处理嵌套对象
Object.assign(flattened, flattenObject(obj[key], newKey));
} else if (Array.isArray(obj[key])) {
// 数组转换为字符串
flattened[newKey] = JSON.stringify(obj[key]);
} else {
// 基本类型直接赋值
flattened[newKey] = obj[key];
}
}
}
return flattened;
};
// 打印
const print = async () => {
try {
if (!currentSelectTemplate.value || !currentSelectTemplate.value.id) {
ElMessage.warning('请先选择病历模板');
return;
}
console.log('打印模板:', currentSelectTemplate.value.name);
console.log('打印病历ID:', editForm.value.id);
// 检查是否已保存
if (!editForm.value.id || editForm.value.id === '') {
ElMessage.warning('请先保存病历后再进行打印');
return;
}
// 获取当前病历组件的表单数据
const formData = emrComponentRef.value?.formData || {};
// 获取当前模板名称
const templateName = currentSelectTemplate.value.name || '';
// 根据模板名称获取对应的打印模板
const selectedPrintTemplate = getPrintTemplateByTemplateName(templateName);
// 打印数据
const printData = {
// 模板信息
templateName: currentSelectTemplate.value.name || '住院病历',
templateId: currentSelectTemplate.value.id || '',
// 医生信息
doctorName: userStore.nickName,
// 患者信息
patientName: patientInfo.value.patientName || '',
patientId: patientInfo.value.patientId || '',
medicalRecordNo: patientInfo.value.medicalRecordNo || '',
gender: patientInfo.value.gender || '',
age: patientInfo.value.age || '',
genderEnum_enumText: patientInfo.value.genderEnum_enumText || '',
idCard: patientInfo.value.idCard || '',
phone: patientInfo.value.phone || '',
registerTime: patientInfo.value.registerTime || '',
// 就诊信息
encounterId: patientInfo.value.encounterId || '',
department: patientInfo.value.department || '',
attendingDoctor: patientInfo.value.attendingDoctor || '',
// 病历信息
documentName: currentSelectTemplate.value.name || '住院病历',
documentId: currentSelectTemplate.value.id || '',
recordTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
printTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
//病历号
busNo: patientInfo.value.busNo || '',
//费用类型
contractName: patientInfo.value.contractName || '',
// 表单数据 - 需要将嵌套结构展开
...flattenObject(formData),
};
console.log('打印数据:', printData);
// 执行打印,使用根据模板类型选择的打印模板
await simplePrint(selectedPrintTemplate, printData);
// 刷新历史记录列表
historyRef.value?.queryList();
ElMessage.success('打印成功');
} catch (error) {
console.error('打印失败:', error);
ElMessage.error('打印失败: ' + (error.message || '未知错误'));
}
};
const refresh = () => {
queryTemplateTree();
historyRef.value?.queryList();
@@ -230,32 +472,221 @@ const deleteEmr = async () => {
ElMessage.error('删除失败');
}
};
// 重置表单数据
const resetForm = async () => {
ElMessageBox.confirm('确定要重置吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(async () => {
try {
// 重置editForm为初始值
editForm.value = {
id: '',
definitionId: '',
definitionBusNo: '',
contentJson: '',
statusEnum: 1,
organizationId: 0,
encounterId: '',
patientId: '',
recordTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
createBy: '',
source: '',
printCount: 0,
};
// 清空选中的历史记录ID
selectedHistoryRecordId.value = '';
// 先将组件设置为空,强制卸载
const currentComponentName = currentComponent.value;
if (currentComponentName) {
currentComponent.value = '';
// 等待DOM更新
await nextTick();
// 重新加载组件
currentComponent.value = currentComponentName;
// 再次等待DOM更新后设置空数据
await nextTick();
console.log('组件已重新加载,正在清空数据');
}
// 重置动态组件表单数据
if (emrComponentRef.value && emrComponentRef.value.setFormData) {
console.log('重置表单数据', emrComponentRef.value);
emrComponentRef.value.setFormData({});
}
ElMessage.success('表单已重置');
} catch (error) {
console.error('重置表单失败:', error);
ElMessage.error('重置表单失败');
}
});
};
// 打开护理状态页面
const onNursingStatus = () => {
openDrawer.value = true;
};
const save = async () => {
try {
currentOperate.value = 'add';
await emrComponentRef.value?.submit();
} catch (error) {
console.log('error=============>', error);
ElMessage.error('保存失败');
}
};
const historyRef = ref(null);
const handleHistoryClick = (data) => {
newEmr();
editForm.value = data;
// 默认选中门诊病历模板
// 这个函数现在已被selectDefaultTemplate替代保留用于兼容性
const selectOutpatientMedicalRecordTemplate = async () => {
// 直接调用新的selectDefaultTemplate函数
selectDefaultTemplate();
};
// 加载最新的病历数据并回显
const loadLatestMedicalRecord = async () => {
if (!patientInfo.value.encounterId || !currentSelectTemplate.value.id) return;
editForm.value.id = '';
loading.value = true;
try {
// 获取患者的历史病历记录
const res = await getRecordByEncounterIdList({
isPage: 0,
encounterId: patientInfo.value.encounterId,
patientId: patientInfo.value.patientId,
definitionId: currentSelectTemplate.value.id,
});
const historyRecords = res.data || [];
if (historyRecords.length > 0) {
// 按时间排序,获取最新的病历记录
historyRecords.sort((a, b) => new Date(b.recordTime) - new Date(a.recordTime));
const latestRecord = historyRecords[0];
// 保存最新病历ID用于在History组件中高亮显示
selectedHistoryRecordId.value = latestRecord.id;
// 自动回显最新病历数据到模板
editForm.value = latestRecord;
nextTick(() => {
if (emrComponentRef.value && latestRecord.contentJson) {
emrComponentRef.value.setFormData(JSON.parse(latestRecord.contentJson));
}
// 通知History组件更新选中状态
if (historyRef.value && typeof historyRef.value.updateSelectedRecord === 'function') {
historyRef.value.updateSelectedRecord(latestRecord.id);
}
});
} else {
// 清空选中状态
selectedHistoryRecordId.value = '';
// 病案首页切换晴空逻辑
emrComponentRef.value.setFormData?.({});
loading.value = false;
}
} catch (error) {
ElMessage.error('加载最新病历数据失败=====>', error);
// 出错时也清空选中状态
selectedHistoryRecordId.value = '';
// 病案首页切换晴空逻辑
emrComponentRef.value.setFormData?.({});
loading.value = false;
} finally {
loading.value = false;
}
};
// 选择默认模板 - 获取住院病历分类下的第一个模板
const selectDefaultTemplate = () => {
nextTick(() => {
emrComponentRef.value?.setFormData(JSON.parse(editForm.value.contentJson));
if (!templateData.value || templateData.value.length === 0) {
console.log('模板数据为空,无法选择默认模板');
return;
}
// 查找住院病历分类节点,然后获取其下的第一个模板
const findInpatientRecordCategoryAndFirstTemplate = (nodes) => {
for (const node of nodes) {
// 检查是否是住院病历分类节点
if (!node.document && node.name && node.name.includes('住院病历')) {
// 这是一个分类节点,检查是否有子节点
if (node.children && node.children.length > 0) {
// 返回第一个有document属性的子节点即第一个模板
for (const child of node.children) {
if (child.document) {
return child;
}
}
}
}
// 递归查找子节点
if (node.children && node.children.length > 0) {
const found = findInpatientRecordCategoryAndFirstTemplate(node.children);
if (found) {
return found;
}
}
}
return null;
};
const defaultTemplate = findInpatientRecordCategoryAndFirstTemplate(templateData.value);
if (defaultTemplate) {
nextTick(() => {
templateTree.value?.setCurrentKey(defaultTemplate.id);
// 模拟点击节点
const mockNode = {
isLeaf: true,
};
handleNodeClick(defaultTemplate, mockNode);
// 直接加载最新病历数据不再使用额外的setTimeout延迟
// 因为handleNodeClick中已经有nextTick和setTimeout处理组件渲染
loadLatestMedicalRecord();
});
} else {
console.log('未找到住院病历模板');
}
});
};
const historyRef = ref(null);
const handleHistoryClick = async (data) => {
try {
newEmr();
editForm.value = data;
nextTick(() => {
emrComponentRef.value?.setFormData(JSON.parse(editForm.value.contentJson));
});
// 更新选中的历史记录ID
selectedHistoryRecordId.value = data.id;
} catch (error) {
ElMessage.error('设置历史数据失败');
console.error('设置历史数据失败:', error);
}
};
const templateRef = ref(null);
const handleTemplateClick = (data) => {
newEmr();
editForm.value = data;
nextTick(() => {
emrComponentRef.value?.setFormData(JSON.parse(editForm.value.contextJson));
});
const handleTemplateClick = async (data) => {
try {
newEmr();
editForm.value = data;
nextTick(() => {
emrComponentRef.value?.setFormData(JSON.parse(editForm.value.contextJson));
});
} catch (error) {
ElMessage.error('设置模板数据失败');
console.error('设置模板数据失败:', error);
}
};
const templateEdit = (data) => {
editTemplateForm.value = data;
@@ -263,27 +694,117 @@ const templateEdit = (data) => {
};
// ====dialog
const templateEditVisible = ref(false);
const templateEditSubmitOk = () => {
templateEditVisible.value = false;
historyRef.value?.queryList();
templateRef.value?.queryList();
const templateEditSubmitOk = async () => {
try {
// 根据是否存在ID来决定是新增还是编辑
if (!editTemplateForm.value.id) {
// 新增模板
const addResult = await addTemplate(editTemplateForm.value);
if (addResult && addResult.code === 200) {
ElMessage.success('模板新增成功');
// 刷新模板列表
if (templateRef.value && typeof templateRef.value.queryList === 'function') {
templateRef.value.queryList();
}
// 关闭模板编辑弹窗
templateEditVisible.value = false;
// 清空模板编辑表单
Object.assign(editTemplateForm.value, {
id: '',
name: '',
displayOrder: 0,
contextJson: '',
definitionId: '',
useRange: 2,
organizationId: userStore.orgId,
userId: '',
useRanges: [1],
remark: '',
});
} else {
ElMessage.error('模板新增失败');
console.error('模板新增失败:', addResult);
}
} else {
// 编辑模板 - 暂不实现编辑功能,只支持新增
ElMessage.warning('暂不支持编辑模板');
}
} catch (error) {
console.error('处理模板编辑提交失败:', error);
ElMessage.error('处理模板编辑提交失败: ' + (error.message || '未知错误'));
} finally {
// 无论成功失败都刷新列表
historyRef.value?.queryList();
templateRef.value?.queryList();
}
};
// onBeforeMount(() => {});
onMounted(() => {
queryTemplateTree();
// 监听患者信息变化,实现联动显示
watch(
() => patientInfo.value,
(newPatientInfo) => {
// 当患者信息变化时,默认选中住院病历模板并加载最新病历数据
if (newPatientInfo && newPatientInfo.patientId && Object.keys(newPatientInfo).length > 0) {
// 确保模板树已经加载
if (templateData.value && templateData.value.length > 0) {
// 优先尝试使用更精确的selectDefaultTemplate函数
selectDefaultTemplate();
} else {
// 重新加载模板树
queryTemplateTree().then(() => {
// 使用nextTick确保DOM更新移除setTimeout避免多次渲染
nextTick(() => {
selectDefaultTemplate();
});
});
}
}
},
{ deep: true, immediate: true }
);
onMounted(async () => {
// 移除日志
await queryTemplateTree();
// 组件挂载完成后,如果已有患者信息,默认选中住院病历模板
if (
patientInfo.value &&
patientInfo.value.patientId &&
Object.keys(patientInfo.value).length > 0
) {
// 使用nextTick确保模板树数据已更新
nextTick(() => {
selectDefaultTemplate();
});
}
});
// 打印
const onPrint = () => {
if (emrComponentRef?.value.printFun) {
emrComponentRef?.value.printFun();
}
};
defineExpose({ state });
const disNode = () => {
leftShow.value = !leftShow.value;
<<<<<<< HEAD
}
const disNode_R = () => {
rightShow.value = !rightShow.value;
}
=======
};
const disNode_R = () => {
rightShow.value = !rightShow.value;
};
>>>>>>> v1.3
</script>
<style lang="scss" scoped>
.emr-use-container {
position: relative;
display: flex;
height: 100%;
img {
@@ -306,7 +827,11 @@ const disNode_R = () => {
height: 60px;
z-index: 1111;
img {
<<<<<<< HEAD
transform: rotate(-90deg) ;
=======
transform: rotate(-90deg);
>>>>>>> v1.3
}
}
.disLeftBtnAct {
@@ -367,6 +892,13 @@ const disNode_R = () => {
height: calc(100% - 48px);
flex: auto;
}
// 加载容器样式
.loading-container {
min-height: 400px;
width: 100%;
position: relative;
}
}
.operate-container {
@@ -388,6 +920,38 @@ const disNode_R = () => {
.operate-main {
height: calc(100% - 40px);
flex: auto;
display: flex;
flex-direction: column;
min-height: 0;
.template-tree-scrollbar {
height: 100%;
flex: 1 1 auto;
min-height: 0;
}
.loading-container {
height: 100%;
min-height: 0;
width: 100%;
display: flex;
flex-direction: column;
}
:deep(.loading-container > *) {
flex: 1 1 auto;
min-height: 0;
}
:deep(.template-tree-scrollbar .el-scrollbar__wrap) {
height: 100%;
}
:deep(.template-tree-scrollbar .el-scrollbar__view) {
height: 100%;
display: flex;
flex-direction: column;
min-height: 0;
}
}
}

View File

@@ -3,6 +3,7 @@
* @Date: 2025-04-07 12:58:22
* @Description:
*/
<<<<<<< HEAD
import PatientList from './components/patientList.vue'
import PatientCard from './components/patientCard/index.vue'
import Advice from './components/order/index.vue'
@@ -13,3 +14,23 @@ import SurgeryApplication from './components/applicationShow/surgeryApplication.
import TestApplication from './components/applicationShow/testApplication.vue'
import NursingStatus from './components/applicationShow/nursingStatus.vue'
export { PatientList, PatientCard, Advice,Diagnose, BloodTtransfusionAapplication, ExamineApplication, SurgeryApplication, TestApplication, NursingStatus }
=======
import Advice from './components/order/index.vue';
import Diagnose from './components/diagnosis/diagnosis.vue';
import BloodTtransfusionAapplication from './components/applicationShow/bloodTtransfusionAapplication.vue';
import ExamineApplication from './components/applicationShow/examineApplication.vue';
import SurgeryApplication from './components/applicationShow/surgeryApplication.vue';
import TestApplication from './components/applicationShow/testApplication.vue';
import NursingStatus from './components/applicationShow/nursingStatus.vue';
import ReportQuery from './components/applicationShow/reportQuery.vue';
export {
Advice,
Diagnose,
BloodTtransfusionAapplication,
ExamineApplication,
SurgeryApplication,
TestApplication,
NursingStatus,
ReportQuery,
};
>>>>>>> v1.3

View File

@@ -1,23 +1,21 @@
<!--
* @Author: sjjh
* @Date: 2025-04-07 11:49:37
* @Description:
-->
<template>
<div class="inpatientDoctor-home-container">
<el-container>
<!-- 患者列表 -->
<el-aside minWidth="83px" :width="`${patientAside ? '254px' : '83px'}`">
<PatientList v-model:expand="patientAside" />
</el-aside>
<!-- main-->
<PatientList :selected-patient="patientInfo" :on-select="handleItemClick" />
<el-container class="inpatientDoctor-home-main">
<el-header height="auto"><inPatientBarDoctorFold /></el-header>
<el-main>
<el-tabs v-model="activeTabName" type="card" class="patient-tabs">
<el-tab-pane label="住院病历" name="inhospitalEmr">
<Emr ref="inhospitalEmrRef" />
</el-tab-pane>
<el-tab-pane label="诊断录入" name="diagnosis">
<Diagnose ref="diagnosisRef" :patientInfo="currentPatientInfo" />
</el-tab-pane>
<el-tab-pane label="临床医嘱" name="prescription">
<Advice ref="adviceRef" />
</el-tab-pane>
<<<<<<< HEAD
<el-tab-pane label="诊断录入" name="diagnosis">
<Diagnose ref="diagnosisRef" :patientInfo="patientInfo" />
</el-tab-pane>
@@ -25,21 +23,33 @@
<Emr ref="inhospitalEmrRef"/>
</el-tab-pane>
<el-tab-pane label="医技报告" name="fourth">Task</el-tab-pane>
=======
<!-- <el-tab-pane label="医技报告" name="fourth">Task</el-tab-pane> -->
>>>>>>> v1.3
<el-tab-pane label="检验申请" name="test">
<TestApplication />
<TestApplication ref="testApplicationRef" />
</el-tab-pane>
<el-tab-pane label="检查申请" name="examine">
<ExamineApplication />
<ExamineApplication ref="examineApplicationRef" />
</el-tab-pane>
<el-tab-pane label="手术申请" name="surgery">
<SurgeryApplication />
<SurgeryApplication ref="surgeryApplicationRef" />
</el-tab-pane>
<el-tab-pane label="输血申请" name="blood">
<BloodTtransfusionAapplication />
<BloodTtransfusionAapplication ref="bloodTtransfusionAapplicationRef" />
</el-tab-pane>
<<<<<<< HEAD
<el-tab-pane label="护理状态" name="nursing">
<NursingStatus />
</el-tab-pane>
=======
<el-tab-pane label="报告查询" name="report">
<ReportQuery />
</el-tab-pane>
<!-- <el-tab-pane label="护理状态" name="nursing">
<NursingStatus />
</el-tab-pane> -->
>>>>>>> v1.3
</el-tabs>
</el-main>
</el-container>
@@ -47,14 +57,32 @@
</div>
</template>
<script setup>
<<<<<<< HEAD
import { getCurrentInstance, onBeforeMount, onMounted, reactive, ref } from 'vue';
// const { proxy } = getCurrentInstance()
// const emits = defineEmits([])
// const props = defineProps({})
import Emr from './emr/index.vue';
import inPatientBarDoctorFold from '@/components/patientBar/inPatientBarDoctorFold.vue';
=======
>>>>>>> v1.3
import {
getCurrentInstance,
onBeforeMount,
onMounted,
reactive,
ref,
watch,
provide,
computed,
} from 'vue';
import Emr from './emr/index.vue';
import inPatientBarDoctorFold from '@/components/patientBar/inPatientBarDoctorFold.vue';
import PatientList from '@/components/PatientList/patient-list.vue';
import { patientInfo, updatePatientInfo } from './store/patient';
import { getPatientList } from './components/api';
import {
PatientList,
Advice,
Diagnose,
BloodTtransfusionAapplication,
@@ -62,18 +90,121 @@ import {
SurgeryApplication,
TestApplication,
NursingStatus,
<<<<<<< HEAD
=======
ReportQuery,
>>>>>>> v1.3
} from './index.js';
const state = reactive({});
onBeforeMount(() => {});
onMounted(() => {});
onMounted(() => {
// 如果 store 中已有患者信息,使用 store 中的
if (patientInfo.value?.encounterId) {
cardId.value = patientInfo.value.encounterId;
isFirstLoad.value = false;
}
queryPatientData();
getList();
});
defineExpose({ state });
const activeTabName = ref('prescription');
const activeTabName = ref('inhospitalEmr');
const diagnosisRef = ref();
const adviceRef = ref();
const patientAside = ref(true);
const patientInfo = ref({});
const currentPatientInfo = ref({});
const testApplicationRef = ref();
const examineApplicationRef = ref();
const surgeryApplicationRef = ref();
const bloodTtransfusionAapplicationRef = ref();
// 患者列表相关逻辑
const searchData = reactive({
keyword: '',
patientType: 1,
type: 1,
timeLimit: 3,
});
const cardId = ref('');
const cardAllData = ref([]);
const isFirstLoad = ref(true);
const filteredCardData = computed(() => {
return cardAllData.value;
});
const queryloading = ref(false);
const getList = () => {
queryloading.value = true;
getPatientList({ status: 5, searchKey: searchData.keyword })
.then((res) => {
cardAllData.value = res.data.records || [];
})
.finally(() => {
queryloading.value = false;
});
};
watch(
() => filteredCardData.value,
(newData) => {
// 如果有数据且当前没有选中患者,且是首次加载,默认选择第一条
if (
newData &&
newData.length > 0 &&
!cardId.value &&
isFirstLoad.value &&
!patientInfo.value?.encounterId
) {
const firstPatient = newData[0];
if (firstPatient?.encounterId) {
handleItemClick(firstPatient);
isFirstLoad.value = false;
}
}
},
{ immediate: true }
);
const handleItemClick = (node) => {
cardId.value = node.encounterId;
updatePatientInfo(node);
diagnosisRef.value?.getList();
adviceRef.value?.getListInfo();
adviceRef.value?.getDiagnosisInfo();
};
const handleSearch = (keyword) => {
searchData.keyword = keyword;
getList();
};
const queryPatientData = async () => {
if (queryloading.value) return;
try {
} catch (error) {
cardAllData.value = [];
} finally {
queryloading.value = false;
}
};
// 监听 tab 切换,刷新对应的列表
watch(activeTabName, (newTab) => {
if (newTab === 'test' && testApplicationRef.value?.refresh) {
testApplicationRef.value.refresh();
} else if (newTab === 'examine' && examineApplicationRef.value?.refresh) {
examineApplicationRef.value.refresh();
} else if (newTab === 'surgery' && surgeryApplicationRef.value?.refresh) {
surgeryApplicationRef.value.refresh();
} else if (newTab === 'blood' && bloodTtransfusionAapplicationRef.value?.refresh) {
bloodTtransfusionAapplicationRef.value.refresh();
}
});
provide('diagnosisInit', (value) => {
patientInfo.value = value;
currentPatientInfo.value = value;
diagnosisRef.value.getList();
});
provide('getAdviceList', (value) => {

View File

@@ -1,23 +1,20 @@
/*
* @Author: sjjh
* @Date: 2025-04-09 17:55:05
* @Description:
* @Description:
*/
// import { IInPatient } from '@/model/IInPatient'
import { ref } from 'vue'
import { ref } from 'vue';
// 定义护士等级(没接口前mock)
export const nursingLevel = ref('0')
export const nursingLevel = ref('0');
export function updateNursingLevel(level) {
nursingLevel.value = level
nursingLevel.value = level;
}
// 选择患者信息
export const patientInfo = ref()
export const patientInfo = ref();
export function updatePatientInfo(info) {
console.log(123111);
patientInfo.value = info
patientInfo.value = info;
}