Fix Bug #550: AI修复
This commit is contained in:
@@ -1,220 +0,0 @@
|
||||
<template>
|
||||
<div @keyup="handleKeyDown" tabindex="0" ref="tableWrapper" class="advice-base-list-wrapper">
|
||||
<Table
|
||||
ref="adviceBaseRef"
|
||||
:table-data="adviceBaseList"
|
||||
:table-columns="tableColumns"
|
||||
:highlight-current-row="true"
|
||||
:table-height="400"
|
||||
:max-height="400"
|
||||
:loading="loading"
|
||||
row-key="patientId"
|
||||
@row-click="handleRowClick"
|
||||
>
|
||||
<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 lang="ts">
|
||||
import {computed, nextTick, ref} 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';
|
||||
|
||||
interface Props {
|
||||
patientInfo: {
|
||||
inHospitalOrgId?: string;
|
||||
[key: string]: any;
|
||||
};
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
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,
|
||||
pageNo: 1,
|
||||
adviceTypes: [1, 2, 3, 6],
|
||||
searchKey: '',
|
||||
organizationId: '',
|
||||
categoryCode: '',
|
||||
});
|
||||
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',
|
||||
},
|
||||
]);
|
||||
|
||||
/**
|
||||
* 父组件主动调用此方法刷新列表
|
||||
* @param adviceType 医嘱类型(1=药品, 3=诊疗, 6=手术, ''=全部)
|
||||
* @param categoryCode 药品分类编码('1'=中成药, '2'=西药, '4'=中草药, ''=不限)
|
||||
* @param searchKey 搜索关键词
|
||||
*/
|
||||
function refresh(adviceType: any, categoryCode: string, searchKey: string) {
|
||||
// 有搜索词时跨类型搜索,避免用户输入"级护理"但因当前adviceType为药品而搜不到诊疗类护理项目
|
||||
if (searchKey) {
|
||||
queryParams.value.adviceTypes = [1, 2, 3, 6];
|
||||
} else {
|
||||
queryParams.value.adviceTypes =
|
||||
adviceType !== undefined && adviceType !== '' ? [parseInt(adviceType)] : [1, 2, 3, 6];
|
||||
}
|
||||
queryParams.value.categoryCode = categoryCode || '';
|
||||
queryParams.value.searchKey = searchKey || '';
|
||||
getList();
|
||||
}
|
||||
|
||||
function getList() {
|
||||
loading.value = true;
|
||||
// organizationId 必须为有效数字或 undefined,空字符串会导致后端 Long 类型转换失败(400)
|
||||
const orgId = props.patientInfo?.inHospitalOrgId;
|
||||
queryParams.value.organizationId = orgId ? orgId : undefined;
|
||||
// 空字符串参数不发送,避免后端类型转换错误
|
||||
if (!queryParams.value.searchKey) {
|
||||
queryParams.value.searchKey = undefined;
|
||||
}
|
||||
if (!queryParams.value.categoryCode) {
|
||||
queryParams.value.categoryCode = undefined;
|
||||
}
|
||||
|
||||
getAdviceBaseInfo(queryParams.value)
|
||||
.then((res) => {
|
||||
const records = res.data?.records || [];
|
||||
|
||||
// 药品/耗材需要有库存才显示,诊疗/手术直接显示
|
||||
adviceBaseList.value = records.filter((item: any) => {
|
||||
if (item.adviceType == 1 || item.adviceType == 2) {
|
||||
return handleQuantity(item) !== '0';
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
total.value = res.data?.total || 0;
|
||||
nextTick(() => {
|
||||
if (adviceBaseList.value.length > 0) {
|
||||
currentIndex.value = 0;
|
||||
setCurrentRow(adviceBaseList.value[0]);
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
console.warn('医嘱基础信息加载失败:', err);
|
||||
adviceBaseList.value = [];
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
}
|
||||
|
||||
// 处理键盘事件
|
||||
const handleKeyDown = (event: KeyboardEvent): void => {
|
||||
const key = event.key;
|
||||
const data = adviceBaseList.value;
|
||||
switch (key) {
|
||||
case 'ArrowUp':
|
||||
event.preventDefault();
|
||||
if (currentIndex.value > 0) {
|
||||
currentIndex.value--;
|
||||
setCurrentRow(data[currentIndex.value]);
|
||||
}
|
||||
break;
|
||||
case 'ArrowDown':
|
||||
event.preventDefault();
|
||||
if (currentIndex.value < data.length - 1) {
|
||||
currentIndex.value++;
|
||||
setCurrentRow(data[currentIndex.value]);
|
||||
}
|
||||
break;
|
||||
case 'Enter':
|
||||
event.preventDefault();
|
||||
if (currentSelectRow.value && Object.keys(currentSelectRow.value).length > 0) {
|
||||
emit('selectAdviceBase', currentSelectRow.value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
function handleQuantity(row: any): string {
|
||||
if (row.inventoryList && row.inventoryList.length > 0) {
|
||||
const totalQuantity = row.inventoryList.reduce(
|
||||
(sum: number, item: any) => sum + (item.quantity || 0),
|
||||
0
|
||||
);
|
||||
return totalQuantity.toString() + (row.minUnitCode_dictText || '');
|
||||
}
|
||||
return '0';
|
||||
}
|
||||
|
||||
const setCurrentRow = (row: any) => {
|
||||
if (adviceBaseRef.value?.tableRef) {
|
||||
adviceBaseRef.value.tableRef.setCurrentRow(row);
|
||||
nextTick(() => {
|
||||
const tableEl = adviceBaseRef.value?.tableRef?.$el;
|
||||
if (tableEl) {
|
||||
const currentRowEl = tableEl.querySelector('.current-row');
|
||||
if (currentRowEl) {
|
||||
currentRowEl.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleRowClick = (row: any): void => {
|
||||
currentIndex.value = adviceBaseList.value.findIndex((item) => item === row);
|
||||
currentSelectRow.value = row;
|
||||
emit('selectAdviceBase', row);
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
handleKeyDown,
|
||||
refresh,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.advice-base-list-wrapper {
|
||||
height: 400px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
&:focus {
|
||||
outline: 2px solid #409eff;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,301 +0,0 @@
|
||||
import request from '@/utils/request';
|
||||
|
||||
export function getPatientList(queryParams) {
|
||||
return request({
|
||||
url: '/reg-doctorstation/advice-manage/reg-patient-zk',
|
||||
method: 'get',
|
||||
params: queryParams,
|
||||
});
|
||||
}
|
||||
|
||||
// 诊断相关接口
|
||||
/**
|
||||
* 保存诊断
|
||||
*/
|
||||
export function saveDiagnosis(data) {
|
||||
return request({
|
||||
url: '/doctor-station/diagnosis/save-doctor-diagnosis',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加诊断绑定
|
||||
*/
|
||||
export function saveDiagnosisBind(data) {
|
||||
return request({
|
||||
url: '/doctor-station/diagnosis/diagnosis-belong-binding',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 删除诊断绑定
|
||||
*/
|
||||
export function deleteDiagnosisBind(id) {
|
||||
return request({
|
||||
url: '/doctor-station/diagnosis/diagnosis-belong-binding?id=' + id,
|
||||
method: 'delete',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取诊断定义列表
|
||||
*/
|
||||
export function getDiagnosisDefinitionList(queryParams) {
|
||||
return request({
|
||||
url: '/doctor-station/diagnosis/condition-definition-metadata',
|
||||
method: 'get',
|
||||
params: queryParams,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取诊断分类数据,历史诊断/个人常用诊断/科室常用诊断
|
||||
*/
|
||||
export function getConditionDefinitionInfo(patientId) {
|
||||
return request({
|
||||
url: '/doctor-station/diagnosis/get-condition-definition-class?patientId=' + patientId,
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取诊断基础下拉数据
|
||||
*/
|
||||
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',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否是食源性诊断
|
||||
*/
|
||||
export function isFoodDiseasesNew(params) {
|
||||
return request({
|
||||
url: '/external-integration/foodborne-acquisition/is-food-diseases-new',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取中医诊断
|
||||
*/
|
||||
export function getTcmCondition(params) {
|
||||
return request({
|
||||
url: '/doctor-station/chinese-medical/condition-info',
|
||||
method: 'get',
|
||||
params: params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取辩证分型
|
||||
*/
|
||||
export function getTcmSyndrome(params) {
|
||||
return request({
|
||||
url: '/doctor-station/chinese-medical/syndrome-info',
|
||||
method: 'get',
|
||||
params: params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取本次就诊中医诊断
|
||||
*/
|
||||
export function getTcmDiagnosis(params) {
|
||||
return request({
|
||||
url: '/doctor-station/chinese-medical/get-tcm-encounter-diagnosis',
|
||||
method: 'get',
|
||||
params: params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存中医诊断
|
||||
*/
|
||||
export function saveTcmDiagnosis(data) {
|
||||
return request({
|
||||
url: '/doctor-station/chinese-medical/save-tcm-diagnosis',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 获取人员慢性病诊断
|
||||
*/
|
||||
export function getChronicDisease(params) {
|
||||
return request({
|
||||
url: '/yb-request/getConditionDefinition',
|
||||
method: 'get',
|
||||
params: params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取药品列表
|
||||
*/
|
||||
export function getAdviceBaseInfo(queryParams) {
|
||||
return request({
|
||||
url: '/doctor-station/advice/advice-base-info',
|
||||
method: 'get',
|
||||
params: queryParams,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前科室已配置的药品类别列表
|
||||
*/
|
||||
export function getConfiguredCategories(organizationId) {
|
||||
// organizationId 为空时不发送该参数,避免后端 Long 类型转换 400 错误
|
||||
const params = {};
|
||||
if (organizationId !== undefined && organizationId !== null && organizationId !== '') {
|
||||
params.organizationId = organizationId;
|
||||
}
|
||||
return request({
|
||||
url: '/doctor-station/advice/configured-categories',
|
||||
method: 'get',
|
||||
params: params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存处方(单条)
|
||||
*/
|
||||
export function savePrescription(data) {
|
||||
return request({
|
||||
url: '/reg-doctorstation/advice-manage/save-reg-advice',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 签发处方
|
||||
*/
|
||||
export function savePrescriptionSign(data) {
|
||||
return request({
|
||||
url: '/reg-doctorstation/advice-manage/sign-reg-advice',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 处方签退
|
||||
*/
|
||||
export function singOut(data) {
|
||||
return request({
|
||||
url: '/reg-doctorstation/advice-manage/sign-off-reg',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 停嘱
|
||||
*/
|
||||
export function stopAdvice(data) {
|
||||
return request({
|
||||
url: '/reg-doctorstation/advice-manage/stop-reg-advice',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 获取患者本次就诊处方
|
||||
*/
|
||||
export function getPrescriptionList(encounterId) {
|
||||
return request({
|
||||
url: '/reg-doctorstation/advice-manage/reg-request-base-info?encounterId=' + encounterId,
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取费用性质
|
||||
*/
|
||||
export function getContract(params) {
|
||||
return request({
|
||||
url: '/doctor-station/advice/get-encounter-contract',
|
||||
method: 'get',
|
||||
params: params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取科室列表
|
||||
*/
|
||||
export function getOrgTree(params = {}) {
|
||||
return request({
|
||||
url: '/base-data-manage/organization/organization',
|
||||
method: 'get',
|
||||
params: { pageNo: 1, pageSize: 5000, ...params },
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
export function getEmrDetail(encounterId) {
|
||||
return request({
|
||||
url: '/doctor-station/emr/emr-detail?encounterId=' + encounterId,
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 组合/拆组
|
||||
*/
|
||||
export function updateGroupId(data) {
|
||||
return request({
|
||||
url: '/doctor-station/advice/update-groupid',
|
||||
method: 'put',
|
||||
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,
|
||||
});
|
||||
}
|
||||
@@ -1,156 +0,0 @@
|
||||
import request from '@/utils/request';
|
||||
|
||||
|
||||
// 申请单相关接口
|
||||
|
||||
/**
|
||||
* 查询检查申请单
|
||||
*/
|
||||
export function getCheck(queryParams) {
|
||||
return request({
|
||||
url: '/reg-doctorstation/request-form/get-check',
|
||||
method: 'get',
|
||||
params: queryParams,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 查询检验申请单
|
||||
*/
|
||||
export function getInspection(queryParams) {
|
||||
return request({
|
||||
url: '/reg-doctorstation/request-form/get-inspection',
|
||||
method: 'get',
|
||||
params: queryParams,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 查询输血申请单
|
||||
*/
|
||||
export function getBloodTransfusion(queryParams) {
|
||||
return request({
|
||||
url: '/reg-doctorstation/request-form/get-blood-transfusion',
|
||||
method: 'get',
|
||||
params: queryParams,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 查询手术申请单
|
||||
*/
|
||||
export function getSurgery(queryParams) {
|
||||
return request({
|
||||
url: '/reg-doctorstation/request-form/get-surgery',
|
||||
method: 'get',
|
||||
params: queryParams,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询手术申请单(全局,不需要encounterId,用于门诊手术安排查找弹窗)
|
||||
*/
|
||||
export function getSurgeryPage(queryParams) {
|
||||
return request({
|
||||
url: '/reg-doctorstation/request-form/get-surgery-page',
|
||||
method: 'get',
|
||||
params: queryParams,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询护理医嘱信息
|
||||
*/
|
||||
export function getNursingOrdersInfos() {
|
||||
return request({
|
||||
url: '/reg-doctorstation/special-advice/nursing-orders',
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存护理医嘱信息
|
||||
* @param {Object} data - 护理医嘱数据
|
||||
* @param {number} data.encounterId - 就诊id
|
||||
* @param {number} data.patientId - 患者id
|
||||
* @param {number} data.conditionId - 诊断ID
|
||||
* @param {number} data.encounterDiagnosisId - 就诊诊断id
|
||||
* @param {string} data.startTime - 医嘱开始时间 (yyyy-MM-dd HH:mm:ss)
|
||||
* @param {Array} data.nursingOrdersSaveDetailDtoList - 护理医嘱详情保存集合
|
||||
* @param {number} data.nursingOrdersSaveDetailDtoList[].definitionId - 护理项目定义ID
|
||||
* @param {number} data.nursingOrdersSaveDetailDtoList[].categoryEnum - 护理项目类别编码:
|
||||
* 26(护理级别)、38(病情)、39(护理常规)、27(膳食)、40(体位)、41(陪护)、42(隔离等级)
|
||||
*/
|
||||
export function saveNursingOrders(data) {
|
||||
return request({
|
||||
url: '/reg-doctorstation/special-advice/nursing-orders',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取患者护理状态信息(用于回显)
|
||||
*/
|
||||
export function getEncounterNursingOrders(params) {
|
||||
return request({
|
||||
url: '/reg-doctorstation/special-advice/encounter-nursing-orders',
|
||||
method: 'get',
|
||||
params: params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询检验报告 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,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询检查报告
|
||||
*/
|
||||
/**
|
||||
* 分页查询检查报告
|
||||
*/
|
||||
export function getTestResultPage(queryParams) {
|
||||
return request({
|
||||
url: '/reg-doctorstation/request-form/get-page',
|
||||
method: 'POST',
|
||||
data: queryParams,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除申请单(仅待签发状态可删除)
|
||||
*/
|
||||
export function deleteRequestForm(data) {
|
||||
return request({
|
||||
url: '/reg-doctorstation/request-form/delete',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 撤回申请单(已签发状态撤回至待签发)
|
||||
*/
|
||||
export function withdrawRequestForm(data) {
|
||||
return request({
|
||||
url: '/reg-doctorstation/request-form/withdraw',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
@@ -1,321 +0,0 @@
|
||||
<!--
|
||||
* @Author: sjjh
|
||||
* @Date: 2025-09-05 21:16:06
|
||||
* @Description: 输血申请详情
|
||||
-->
|
||||
<template>
|
||||
<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 {computed, getCurrentInstance, ref, watch} from 'vue';
|
||||
import {Refresh} from '@element-plus/icons-vue';
|
||||
import {patientInfo} from '../../store/patient.js';
|
||||
import {getBloodTransfusion} from './api';
|
||||
import {getOrgList} from '@/views/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 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;
|
||||
}
|
||||
};
|
||||
|
||||
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 = async () => {
|
||||
const res = await getOrgList();
|
||||
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 = async (row) => {
|
||||
// 确保科室数据已加载,以便将 ID 解析为名称
|
||||
if (!orgOptions.value || orgOptions.value.length === 0) {
|
||||
await getLocationInfo();
|
||||
}
|
||||
|
||||
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,
|
||||
async (val) => {
|
||||
if (val) {
|
||||
await Promise.all([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>
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,238 +0,0 @@
|
||||
<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>
|
||||
@@ -1,334 +0,0 @@
|
||||
<!--
|
||||
* @Author: sjjh
|
||||
* @Date: 2025-09-05 21:16:06
|
||||
* @Description: 手术申请详情
|
||||
-->
|
||||
<template>
|
||||
<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 label="手术单号" width="160" align="center">
|
||||
<template #default="scope">
|
||||
<el-link type="primary" @click="handleViewDetail(scope.row)">
|
||||
{{ scope.row.prescriptionNo || '-' }}
|
||||
</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<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="requesterId_dictText" label="申请者" width="120" />
|
||||
<el-table-column label="操作" align="center" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" icon="View" @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 icon="Close" @click="detailDialogVisible = false">关闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {computed, getCurrentInstance, ref, watch} from 'vue';
|
||||
import {Refresh} from '@element-plus/icons-vue';
|
||||
import {patientInfo} from '../../store/patient.js';
|
||||
import {getSurgery} from './api';
|
||||
import {getDepartmentList} from '@/api/public.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 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;
|
||||
}
|
||||
};
|
||||
|
||||
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 = async () => {
|
||||
const res = await getDepartmentList();
|
||||
orgOptions.value = res.data || [];
|
||||
};
|
||||
|
||||
const recursionFun = (targetDepartment) => {
|
||||
if (!targetDepartment || !orgOptions.value || orgOptions.value.length === 0) {
|
||||
return '';
|
||||
}
|
||||
let name = '';
|
||||
// 统一处理:扁平列表和树形结构都适用
|
||||
const findInList = (list) => {
|
||||
for (const node of list) {
|
||||
if (String(node.id) === String(targetDepartment)) {
|
||||
name = node.name;
|
||||
return true;
|
||||
}
|
||||
// 树形结构:递归查找 children
|
||||
if (node.children && node.children.length > 0) {
|
||||
if (findInList(node.children)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
findInList(orgOptions.value);
|
||||
return name;
|
||||
};
|
||||
|
||||
const handleViewDetail = async (row) => {
|
||||
// 确保科室数据已加载,以便将 ID 解析为名称
|
||||
if (!orgOptions.value || orgOptions.value.length === 0) {
|
||||
await getLocationInfo();
|
||||
}
|
||||
|
||||
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,
|
||||
async (val) => {
|
||||
if (val) {
|
||||
await Promise.all([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>
|
||||
@@ -1,798 +0,0 @@
|
||||
<!--
|
||||
* @Author: sjjh
|
||||
* @Date: 2025-09-05 21:16:06
|
||||
* @Description: 检验申请
|
||||
-->
|
||||
<template>
|
||||
<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="filter-form">
|
||||
<el-form :inline="true" :model="filterForm" class="filter-form-content">
|
||||
<el-form-item label="申请日期">
|
||||
<el-date-picker
|
||||
v-model="filterForm.dateRange"
|
||||
type="daterange"
|
||||
range-separator="至"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
value-format="YYYY-MM-DD"
|
||||
clearable
|
||||
style="width: 240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="单据状态">
|
||||
<el-select
|
||||
v-model="filterForm.status"
|
||||
placeholder="请选择"
|
||||
clearable
|
||||
style="width: 150px"
|
||||
>
|
||||
<el-option label="全部" value="" />
|
||||
<el-option label="待签发" value="0" />
|
||||
<el-option label="已签发" value="1" />
|
||||
<el-option label="已采证" value="4" />
|
||||
<el-option label="已送检" value="5" />
|
||||
<el-option label="报告已出" value="6" />
|
||||
<el-option label="已作废" value="7" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="关键字">
|
||||
<el-input
|
||||
v-model="filterForm.keyword"
|
||||
placeholder="申请单号/检验项目"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
@keyup.enter="handleSearch"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleSearch" :loading="loading">
|
||||
<el-icon><Search /></el-icon>
|
||||
查询
|
||||
</el-button>
|
||||
<el-button @click="handleReset">
|
||||
<el-icon><Refresh /></el-icon>
|
||||
重置
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="report-table-wrapper">
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="tableData"
|
||||
border
|
||||
size="small"
|
||||
height="100%"
|
||||
style="width: 100%"
|
||||
>
|
||||
<template #empty>
|
||||
<div class="empty-data">
|
||||
<el-empty description="暂无匹配记录" :image-size="80" />
|
||||
</div>
|
||||
</template>
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column prop="patientName" label="患者姓名" width="120" />
|
||||
<el-table-column label="申请单名称" width="140">
|
||||
<template #default="scope">
|
||||
<span>{{ buildApplicationName(scope.row) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="createTime" label="创建时间" width="160" />
|
||||
<el-table-column prop="prescriptionNo" label="申请单号" width="140" />
|
||||
<el-table-column label="单据状态" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<el-tag
|
||||
:type="getBillStatusTagType(scope.row)"
|
||||
effect="plain"
|
||||
round
|
||||
:class="{ 'report-status-tag': isReportStatus(scope.row) }"
|
||||
@click="handleStatusClick(scope.row)"
|
||||
>
|
||||
{{ parseBillStatus(getBillStatus(scope.row)) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="申请类型" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<span>{{ parsePriorityCode(scope.row.descJson) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="标本类型" width="120" align="center">
|
||||
<template #default="scope">
|
||||
<span>{{ parseSpecimenType(scope.row.descJson) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="requesterId_dictText" label="申请者" width="120" />
|
||||
<el-table-column label="操作" align="center" fixed="right" width="280">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" @click="handleViewDetail(scope.row)">详情</el-button>
|
||||
<template v-if="canManageRow(scope.row) && isPendingStatus(scope.row)">
|
||||
<el-button link type="primary" @click="handleEdit(scope.row)">修改</el-button>
|
||||
<el-button link type="danger" @click="handleDelete(scope.row)">删除</el-button>
|
||||
</template>
|
||||
<template v-if="canManageRow(scope.row) && isWithdrawableStatus(scope.row)">
|
||||
<el-button link type="warning" @click="handleWithdraw(scope.row)">撤回</el-button>
|
||||
</template>
|
||||
<template v-if="isReportStatus(scope.row)">
|
||||
<el-button link type="success" @click="handleViewReport(scope.row)">查看报告</el-button>
|
||||
</template>
|
||||
</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>
|
||||
|
||||
<!-- 编辑检验申请单弹窗 -->
|
||||
<el-dialog
|
||||
v-model="editDialogVisible"
|
||||
title="编辑检验申请单"
|
||||
width="1200px"
|
||||
destroy-on-close
|
||||
top="5vh"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<LaboratoryTests
|
||||
ref="editFormRef"
|
||||
@submitOk="handleEditSubmitOk"
|
||||
:editData="editRowData"
|
||||
/>
|
||||
<template #footer>
|
||||
<el-button @click="editDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="submitEditForm">确认</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {computed, getCurrentInstance, nextTick, ref, watch} from 'vue';
|
||||
import {Refresh, Search} from '@element-plus/icons-vue';
|
||||
import {patientInfo} from '../../store/patient.js';
|
||||
import {getInspection, deleteRequestForm, withdrawRequestForm, getProofResult} from './api';
|
||||
import {getDepartmentList} from '@/api/public.js';
|
||||
import LaboratoryTests from '../order/applicationForm/laboratoryTests.vue';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
import auth from '@/plugins/auth';
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
|
||||
const tableData = ref([]);
|
||||
const loading = ref(false);
|
||||
const detailDialogVisible = ref(false);
|
||||
const editDialogVisible = ref(false);
|
||||
const editRowData = ref(null);
|
||||
const editFormRef = ref(null);
|
||||
const currentDetail = ref(null);
|
||||
const descJsonData = ref(null);
|
||||
const orgOptions = ref([]);
|
||||
|
||||
// 筛选表单数据
|
||||
const filterForm = ref({
|
||||
dateRange: [], // [startDate, endDate]
|
||||
status: '', // 单据状态
|
||||
keyword: '', // 关键字搜索
|
||||
});
|
||||
|
||||
const fetchData = async () => {
|
||||
if (!patientInfo.value?.encounterId) {
|
||||
tableData.value = [];
|
||||
loading.value = false;
|
||||
return;
|
||||
}
|
||||
loading.value = true;
|
||||
try {
|
||||
// 构建查询参数
|
||||
const params = { encounterId: patientInfo.value.encounterId };
|
||||
|
||||
// 添加日期范围筛选
|
||||
if (filterForm.value.dateRange && filterForm.value.dateRange.length === 2) {
|
||||
params.startDate = filterForm.value.dateRange[0];
|
||||
params.endDate = filterForm.value.dateRange[1];
|
||||
}
|
||||
|
||||
// 添加状态筛选
|
||||
if (filterForm.value.status !== '' && filterForm.value.status !== undefined) {
|
||||
params.status = filterForm.value.status;
|
||||
}
|
||||
|
||||
// 添加关键字搜索
|
||||
if (filterForm.value.keyword && filterForm.value.keyword.trim()) {
|
||||
params.keyword = filterForm.value.keyword.trim();
|
||||
}
|
||||
|
||||
const res = await getInspection(params);
|
||||
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).sort(sortByCreateTimeDesc);
|
||||
} else {
|
||||
tableData.value = [];
|
||||
}
|
||||
} catch (e) {
|
||||
proxy.$modal?.msgError?.(e.message || '查询检验申请失败');
|
||||
tableData.value = [];
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const handleRefresh = async () => {
|
||||
if (loading.value || !patientInfo.value?.encounterId) return;
|
||||
await fetchData();
|
||||
};
|
||||
|
||||
/**
|
||||
* 查询按钮处理
|
||||
*/
|
||||
const handleSearch = async () => {
|
||||
if (!patientInfo.value?.encounterId) {
|
||||
proxy.$modal?.msgWarning?.('请先选择患者');
|
||||
return;
|
||||
}
|
||||
await fetchData();
|
||||
};
|
||||
|
||||
/**
|
||||
* 重置按钮处理
|
||||
*/
|
||||
const handleReset = () => {
|
||||
// 重置筛选条件为默认值
|
||||
filterForm.value.dateRange = [];
|
||||
filterForm.value.status = '';
|
||||
filterForm.value.keyword = '';
|
||||
// 重新加载数据
|
||||
fetchData();
|
||||
};
|
||||
|
||||
const labelMap = {
|
||||
categoryType: '项目类别',
|
||||
targetDepartment: '发往科室',
|
||||
symptom: '症状',
|
||||
sign: '体征',
|
||||
clinicalDiagnosis: '临床诊断',
|
||||
otherDiagnosis: '其他诊断',
|
||||
relatedResult: '相关结果',
|
||||
attention: '注意事项',
|
||||
applicationType: '申请类型',
|
||||
specimenName: '标本类型',
|
||||
executeTime: '执行时间',
|
||||
};
|
||||
|
||||
/**
|
||||
* 解析单据状态
|
||||
* @param {string|number} status - 状态码
|
||||
* @returns {string} 状态文本
|
||||
*/
|
||||
const getBillStatus = (row) => {
|
||||
return row?.billStatus ?? row?.status ?? row?.statusEnum ?? row?.applyStatus;
|
||||
};
|
||||
|
||||
const parseBillStatus = (status) => {
|
||||
const statusMap = {
|
||||
'0': '待签发',
|
||||
'1': '已签发',
|
||||
'2': '已采证',
|
||||
'3': '已送检',
|
||||
'4': '已采证',
|
||||
'5': '已送检',
|
||||
'6': '报告已出',
|
||||
'8': '报告已出',
|
||||
'7': '已作废',
|
||||
};
|
||||
return statusMap[String(status)] || '-';
|
||||
};
|
||||
|
||||
const getBillStatusTagType = (row) => {
|
||||
const typeMap = {
|
||||
'0': 'info',
|
||||
'1': 'primary',
|
||||
'2': 'primary',
|
||||
'3': 'warning',
|
||||
'4': 'primary',
|
||||
'5': 'warning',
|
||||
'6': 'success',
|
||||
'7': 'danger',
|
||||
'8': 'success',
|
||||
};
|
||||
return typeMap[String(getBillStatus(row))] || 'info';
|
||||
};
|
||||
|
||||
const isPendingStatus = (row) => {
|
||||
const status = getBillStatus(row);
|
||||
return status === undefined || status === null || status === '' || String(status) === '0';
|
||||
};
|
||||
|
||||
const isWithdrawableStatus = (row) => String(getBillStatus(row)) === '1';
|
||||
|
||||
const isReportStatus = (row) => ['6', '8'].includes(String(getBillStatus(row)));
|
||||
|
||||
/**
|
||||
* 是否可管理该申请单:申请者本人或管理员
|
||||
*/
|
||||
const canManageRow = (row) => {
|
||||
if (auth.hasRole('admin')) {
|
||||
return true;
|
||||
}
|
||||
const currentPractitionerId = userStore.practitionerId;
|
||||
const requesterId = row?.requesterId;
|
||||
if (!currentPractitionerId || !requesterId) {
|
||||
return false;
|
||||
}
|
||||
return String(currentPractitionerId) === String(requesterId);
|
||||
};
|
||||
|
||||
const sortByCreateTimeDesc = (a, b) => {
|
||||
const aTime = a?.createTime ? new Date(a.createTime).getTime() : 0;
|
||||
const bTime = b?.createTime ? new Date(b.createTime).getTime() : 0;
|
||||
return bTime - aTime;
|
||||
};
|
||||
|
||||
const handleStatusClick = (row) => {
|
||||
if (isReportStatus(row)) {
|
||||
handleViewReport(row);
|
||||
}
|
||||
};
|
||||
|
||||
const pickReportUrl = (data, row) => {
|
||||
if (!data) return '';
|
||||
if (typeof data === 'string') return data;
|
||||
|
||||
const raw = data.records || data;
|
||||
const list = Array.isArray(raw) ? raw : [raw];
|
||||
const matched =
|
||||
list.find((item) => {
|
||||
const reportNo = item.busNo || item.reportNo || item.applyNo || item.prescriptionNo;
|
||||
return reportNo && row.prescriptionNo && String(reportNo) === String(row.prescriptionNo);
|
||||
}) || list[0];
|
||||
|
||||
return matched?.requestUrl || matched?.pdfUrl || matched?.reportUrl || matched?.url || '';
|
||||
};
|
||||
|
||||
const handleViewReport = async (row) => {
|
||||
try {
|
||||
const res = await getProofResult({
|
||||
encounterId: row.encounterId || patientInfo.value?.encounterId,
|
||||
prescriptionNo: row.prescriptionNo,
|
||||
});
|
||||
if (res?.code === 200) {
|
||||
const url = pickReportUrl(res.data, row);
|
||||
if (url) {
|
||||
window.open(url, '_blank');
|
||||
return;
|
||||
}
|
||||
}
|
||||
proxy.$modal?.msgWarning?.('暂未获取到检验报告链接');
|
||||
} catch (e) {
|
||||
proxy.$modal?.msgError?.(e.message || '获取检验报告失败');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 解析申请类型(优先级代码)
|
||||
* @param {string} descJson - JSON字符串
|
||||
* @returns {string} 申请类型文本
|
||||
*/
|
||||
const parsePriorityCode = (descJson) => {
|
||||
if (!descJson) return '-';
|
||||
try {
|
||||
const obj = JSON.parse(descJson);
|
||||
// applicationType: 0-普通, 1-急诊
|
||||
return obj.applicationType === 1 ? '急' : '普通';
|
||||
} catch (e) {
|
||||
console.error('解析 descJson 失败:', e);
|
||||
return '-';
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 解析标本类型
|
||||
* @param {string} descJson - JSON字符串
|
||||
* @returns {string} 标本类型名称
|
||||
*/
|
||||
const parseSpecimenType = (descJson) => {
|
||||
if (!descJson) return '-';
|
||||
try {
|
||||
const obj = JSON.parse(descJson);
|
||||
// specimenName 或 sampleType 字段
|
||||
return obj.specimenName || obj.sampleType || '-';
|
||||
} catch (e) {
|
||||
console.error('解析 descJson 失败:', e);
|
||||
return '-';
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 根据申请单详情构建申请单名称
|
||||
* 单一项目:显示项目名称+数量
|
||||
* 多个项目:显示首个项目名称+数量+"等X项"
|
||||
*/
|
||||
const buildApplicationName = (row) => {
|
||||
const details = row.requestFormDetailList;
|
||||
if (!details || details.length === 0) {
|
||||
return row.name || '-';
|
||||
}
|
||||
if (details.length === 1) {
|
||||
const item = details[0];
|
||||
return `${item.adviceName}${item.quantity || ''}`;
|
||||
}
|
||||
const first = details[0];
|
||||
return `${first.adviceName}${first.quantity || ''}等${details.length}项`;
|
||||
};
|
||||
|
||||
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 = async () => {
|
||||
try {
|
||||
const res = await getDepartmentList();
|
||||
orgOptions.value = Array.isArray(res.data) ? res.data : [];
|
||||
} catch (e) {
|
||||
console.warn('科室列表加载失败:', e.message);
|
||||
orgOptions.value = [];
|
||||
}
|
||||
};
|
||||
|
||||
const recursionFun = (targetDepartment) => {
|
||||
if (!targetDepartment) return '';
|
||||
const findNode = (list, id) => {
|
||||
if (!list || list.length === 0) return '';
|
||||
for (const item of list) {
|
||||
if (item.id == id) return item.name;
|
||||
const found = findNode(item.children, id);
|
||||
if (found) return found;
|
||||
}
|
||||
return '';
|
||||
};
|
||||
return findNode(orgOptions.value, targetDepartment);
|
||||
};
|
||||
|
||||
const handleViewDetail = async (row) => {
|
||||
// 确保科室数据已加载,以便将 ID 解析为名称
|
||||
if (!orgOptions.value || orgOptions.value.length === 0) {
|
||||
await getLocationInfo();
|
||||
}
|
||||
|
||||
currentDetail.value = row;
|
||||
// 解析 descJson
|
||||
if (row.descJson) {
|
||||
try {
|
||||
const obj = JSON.parse(row.descJson);
|
||||
// 将发往科室 ID 转换为名称
|
||||
if (obj.targetDepartment) {
|
||||
const deptName = recursionFun(obj.targetDepartment);
|
||||
if (deptName) {
|
||||
obj.targetDepartment = deptName;
|
||||
}
|
||||
}
|
||||
// 转换申请类型编码为可读文本
|
||||
if (obj.applicationType === 0) obj.applicationType = '普通';
|
||||
else if (obj.applicationType === 1) obj.applicationType = '急诊';
|
||||
descJsonData.value = obj;
|
||||
} catch (e) {
|
||||
console.error('解析 descJson 失败:', e);
|
||||
descJsonData.value = null;
|
||||
}
|
||||
} else {
|
||||
descJsonData.value = null;
|
||||
}
|
||||
detailDialogVisible.value = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* 修改检验申请单(待签发状态)
|
||||
*/
|
||||
const handleEdit = async (row) => {
|
||||
editRowData.value = row;
|
||||
editDialogVisible.value = true;
|
||||
await nextTick();
|
||||
editFormRef.value?.getList?.();
|
||||
editFormRef.value?.getLocationInfo?.();
|
||||
editFormRef.value?.getDiagnosisList?.();
|
||||
};
|
||||
|
||||
/**
|
||||
* 编辑弹窗提交成功回调
|
||||
*/
|
||||
const handleEditSubmitOk = async () => {
|
||||
editDialogVisible.value = false;
|
||||
editRowData.value = null;
|
||||
proxy.$modal?.msgSuccess?.('修改成功');
|
||||
await fetchData();
|
||||
};
|
||||
|
||||
/**
|
||||
* 编辑弹窗提交按钮
|
||||
*/
|
||||
const submitEditForm = () => {
|
||||
if (editFormRef.value?.submit) {
|
||||
editFormRef.value.submit();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 删除检验申请单(仅待签发状态可删除)
|
||||
*/
|
||||
const handleDelete = async (row) => {
|
||||
try {
|
||||
await proxy.$modal?.confirm?.('确认作废该申请单吗?作废后不可撤销');
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await deleteRequestForm({ requestFormId: row.requestFormId });
|
||||
if (res?.code === 200) {
|
||||
proxy.$modal?.msgSuccess?.('删除成功');
|
||||
await fetchData();
|
||||
} else {
|
||||
proxy.$modal?.msgError?.(res?.msg || '删除失败');
|
||||
}
|
||||
} catch {
|
||||
// 响应拦截器已处理错误提示,此处静默
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 撤回检验申请单(已签发且未采证状态可撤回)
|
||||
*/
|
||||
const handleWithdraw = async (row) => {
|
||||
try {
|
||||
await proxy.$modal?.confirm?.(
|
||||
'确认撤回该申请单吗?撤回后申请单及关联医嘱将恢复为待签发状态,护士站将同步更新。'
|
||||
);
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await withdrawRequestForm({ requestFormId: row.requestFormId });
|
||||
if (res?.code === 200) {
|
||||
proxy.$modal?.msgSuccess?.('撤回成功');
|
||||
await fetchData();
|
||||
} else {
|
||||
proxy.$modal?.msgError?.(res?.msg || '撤回失败');
|
||||
}
|
||||
} catch {
|
||||
// 响应拦截器已处理错误提示,此处静默
|
||||
}
|
||||
};
|
||||
|
||||
watch(
|
||||
() => patientInfo.value?.encounterId,
|
||||
async (val) => {
|
||||
if (val) {
|
||||
// 设置默认日期范围为近7天
|
||||
const today = new Date();
|
||||
const sevenDaysAgo = new Date(today);
|
||||
sevenDaysAgo.setDate(today.getDate() - 6); // 包含今天共7天
|
||||
|
||||
// 格式化为 YYYY-MM-DD
|
||||
const formatDate = (date) => {
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
return `${year}-${month}-${day}`;
|
||||
};
|
||||
|
||||
filterForm.value.dateRange = [
|
||||
formatDate(sevenDaysAgo),
|
||||
formatDate(today)
|
||||
];
|
||||
|
||||
await Promise.all([fetchData(), getLocationInfo()]);
|
||||
} else {
|
||||
tableData.value = [];
|
||||
// 重置筛选条件
|
||||
filterForm.value.dateRange = [];
|
||||
filterForm.value.status = '';
|
||||
filterForm.value.keyword = '';
|
||||
}
|
||||
},
|
||||
{ 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;
|
||||
}
|
||||
|
||||
.filter-form {
|
||||
padding: 12px 8px;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
.filter-form-content {
|
||||
:deep(.el-form-item) {
|
||||
margin-bottom: 0;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
:deep(.el-form-item__label) {
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
.report-table-wrapper {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow: auto;
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
.empty-data {
|
||||
padding: 40px 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
|
||||
.report-status-tag {
|
||||
cursor: pointer;
|
||||
background-color: #f0f9eb !important;
|
||||
border-color: #67c23a !important;
|
||||
color: #529b2e !important;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
@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>
|
||||
@@ -1,440 +0,0 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
title="添加中医诊断"
|
||||
v-model="props.openAddDiagnosisDialog"
|
||||
width="1500px"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
@open="handleOpen"
|
||||
@close="close"
|
||||
>
|
||||
<div class="main-content">
|
||||
<!-- 左侧疾病选择区 -->
|
||||
<div class="disease-section">
|
||||
<div class="section-title">诊断</div>
|
||||
<div class="search-box">
|
||||
<el-input v-model="searchDisease" placeholder="搜索疾病名称或编码" clearable>
|
||||
<template #prefix>
|
||||
<el-icon><search /></el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</div>
|
||||
<el-table
|
||||
:data="conditionDatas"
|
||||
max-height="460"
|
||||
@row-click="handleClickRow"
|
||||
highlight-current-row
|
||||
>
|
||||
<el-table-column label="疾病名称" align="center" prop="name"></el-table-column>
|
||||
<el-table-column label="医保编码" align="center" prop="ybNo"></el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<!-- 中间疾病-证型关系区 -->
|
||||
<div class="syndrome-section">
|
||||
<div class="section-title">证候</div>
|
||||
<div class="search-box">
|
||||
<el-input v-model="searchMiddleDisease" placeholder="搜索疾病名称或编码" clearable>
|
||||
<template #prefix>
|
||||
<el-icon><search /></el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</div>
|
||||
<div v-if="selectedDisease">
|
||||
<el-table
|
||||
:data="syndromeListDatas"
|
||||
max-height="460"
|
||||
@row-click="clickSyndromeRow"
|
||||
highlight-current-row
|
||||
>
|
||||
<el-table-column label="证候名称" align="center" prop="name"></el-table-column>
|
||||
<el-table-column label="医保编码" align="center" prop="ybNo"></el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<div class="empty-state" v-else>
|
||||
<el-empty description="请从左侧选择疾病" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 右侧诊断详情区 -->
|
||||
<div class="diagnosis-section">
|
||||
<div class="section-title">诊断详情</div>
|
||||
<div class="diagnosis-list">
|
||||
<div v-for="(item, index) in tcmDiagonsisList" :key="index" class="history-item">
|
||||
<div class="history-diagnosis">
|
||||
<div>
|
||||
<strong>{{ item.conditionName }}</strong> - {{ item.syndromeName }}
|
||||
</div>
|
||||
<el-button
|
||||
size="small"
|
||||
type="danger"
|
||||
plain
|
||||
icon="close"
|
||||
@click="removeDiagnosis(item, index)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button type="primary" @click="submit">确 定</el-button>
|
||||
<el-button @click="close">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {getTcmCondition, getTcmSyndrome, saveTcmDiagnosis,} from '@/views/doctorstation/components/api';
|
||||
import {computed} from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
openAddDiagnosisDialog: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
patientInfo: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
const conditionList = ref([]);
|
||||
const syndromeList = ref([]);
|
||||
const tcmDiagonsisList = ref([]);
|
||||
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']);
|
||||
|
||||
function handleOpen() {
|
||||
getTcmCondition().then((res) => {
|
||||
conditionList.value = res.data.records;
|
||||
});
|
||||
}
|
||||
|
||||
// 搜索诊断
|
||||
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) {
|
||||
selectedDisease.value = true;
|
||||
syndromeSelected.value = false;
|
||||
timestamp.value = Date.now();
|
||||
getTcmSyndrome().then((res) => {
|
||||
syndromeList.value = res.data.records;
|
||||
});
|
||||
tcmDiagonsisSaveList.value.push({
|
||||
definitionId: row.id,
|
||||
ybNo: row.ybNo,
|
||||
syndromeGroupNo: timestamp.value,
|
||||
verificationStatusEnum: 4,
|
||||
medTypeCode: undefined, // 不设默认值
|
||||
});
|
||||
tcmDiagonsisList.value.push({
|
||||
conditionName: row.name,
|
||||
syndromeGroupNo: timestamp.value,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function clickSyndromeRow(row) {
|
||||
tcmDiagonsisSaveList.value.push({
|
||||
definitionId: row.id,
|
||||
ybNo: row.ybNo,
|
||||
syndromeGroupNo: timestamp.value,
|
||||
});
|
||||
tcmDiagonsisList.value[tcmDiagonsisList.value.length - 1].syndromeName = row.name;
|
||||
syndromeSelected.value = true;
|
||||
}
|
||||
|
||||
// 删除诊断
|
||||
function removeDiagnosis(row, index) {
|
||||
tcmDiagonsisList.value.splice(index, 1);
|
||||
tcmDiagonsisSaveList.value = tcmDiagonsisSaveList.value.filter((item) => {
|
||||
return item.syndromeGroupNo !== row.syndromeGroupNo;
|
||||
});
|
||||
}
|
||||
|
||||
function save() {
|
||||
saveTcmDiagnosis({
|
||||
patientId: props.patientInfo.patientId,
|
||||
encounterId: props.patientInfo.encounterId,
|
||||
diagnosisChildList: tcmDiagonsisSaveList.value,
|
||||
}).then((res) => {
|
||||
if (res.code == 200) {
|
||||
emit('close');
|
||||
proxy.$modal.msgSuccess('诊断已保存');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function submit() {
|
||||
if (tcmDiagonsisSaveList.value.length > 0 && syndromeSelected.value) {
|
||||
save();
|
||||
} else {
|
||||
proxy.$modal.msgWarning('请选择证候');
|
||||
}
|
||||
}
|
||||
function close() {
|
||||
emit('close');
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
:deep(.pagination-container .el-pagination) {
|
||||
right: 20px !important;
|
||||
}
|
||||
|
||||
.app-container {
|
||||
max-width: 1400px;
|
||||
margin: 20px auto;
|
||||
padding: 20px;
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 2px 20px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-bottom: 15px;
|
||||
border-bottom: 1px solid var(--el-border-color);
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.header h1 {
|
||||
color: var(--el-color-primary);
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.patient-info {
|
||||
background: var(--el-color-primary-light-9);
|
||||
padding: 15px;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.patient-info .info-row {
|
||||
display: flex;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.patient-info .info-label {
|
||||
width: 100px;
|
||||
color: var(--el-text-color-secondary);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1.2fr;
|
||||
gap: 20px;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.disease-section,
|
||||
.syndrome-section,
|
||||
.diagnosis-section {
|
||||
border: 1px solid var(--el-border-color);
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
background: white;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: var(--el-color-primary);
|
||||
margin-bottom: 15px;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 1px solid var(--el-border-color);
|
||||
}
|
||||
|
||||
.disease-list {
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.disease-item {
|
||||
padding: 12px 15px;
|
||||
border-bottom: 1px solid var(--el-border-color-lighter);
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.disease-item:hover {
|
||||
background-color: var(--el-color-primary-light-9);
|
||||
}
|
||||
|
||||
.disease-item.active {
|
||||
background-color: var(--el-color-primary-light-8);
|
||||
border-left: 3px solid var(--el-color-primary);
|
||||
}
|
||||
|
||||
.disease-name {
|
||||
font-weight: 500;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.disease-code {
|
||||
font-size: 12px;
|
||||
color: var(--el-text-color-secondary);
|
||||
}
|
||||
|
||||
.search-box {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.disease-categories {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.category-tag {
|
||||
cursor: pointer;
|
||||
padding: 5px 12px;
|
||||
border-radius: 15px;
|
||||
background: var(--el-fill-color-light);
|
||||
font-size: 13px;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.category-tag.active {
|
||||
background: var(--el-color-primary);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.relation-container {
|
||||
text-align: center;
|
||||
padding: 30px 0;
|
||||
border: 2px dashed var(--el-border-color);
|
||||
border-radius: 8px;
|
||||
margin: 20px 0;
|
||||
background: var(--el-fill-color-lighter);
|
||||
}
|
||||
|
||||
.relation-icon {
|
||||
margin-bottom: 15px;
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
|
||||
.relation-text {
|
||||
font-size: 18px;
|
||||
font-weight: 500;
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
|
||||
.syndrome-details {
|
||||
padding: 15px;
|
||||
background: var(--el-color-primary-light-9);
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--el-color-primary-light-5);
|
||||
}
|
||||
|
||||
.detail-item {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.detail-label {
|
||||
font-weight: 500;
|
||||
color: var(--el-text-color-secondary);
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 15px;
|
||||
padding-top: 20px;
|
||||
border-top: 1px solid var(--el-border-color);
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
text-align: center;
|
||||
padding: 40px 0;
|
||||
color: var(--el-text-color-secondary);
|
||||
}
|
||||
|
||||
.diagnosis-history {
|
||||
margin-top: 20px;
|
||||
border-top: 1px solid var(--el-border-color);
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
.history-title {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
margin-bottom: 12px;
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
|
||||
.history-item {
|
||||
padding: 12px;
|
||||
border-left: 3px solid var(--el-border-color);
|
||||
margin-bottom: 10px;
|
||||
background: var(--el-fill-color-lighter);
|
||||
border-radius: 0 4px 4px 0;
|
||||
}
|
||||
|
||||
.diagnosis-list {
|
||||
max-height: 520px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.history-date {
|
||||
font-size: 12px;
|
||||
color: var(--el-text-color-secondary);
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.history-diagnosis {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 14px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.history-note {
|
||||
font-size: 13px;
|
||||
color: var(--el-text-color-secondary);
|
||||
padding-top: 5px;
|
||||
border-top: 1px dashed var(--el-border-color);
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.empty-list {
|
||||
padding: 20px 0;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
@@ -1,129 +0,0 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
v-model="visible"
|
||||
top="6vh"
|
||||
:width="width"
|
||||
title="中医诊断"
|
||||
@open="openAct"
|
||||
@closed="closedAct"
|
||||
:z-index="20"
|
||||
>
|
||||
中医诊断
|
||||
<template #footer>
|
||||
<el-button size="fixed" class="margin-left-auto" @click="cancelAct">取消 </el-button>
|
||||
<el-button size="fixed" type="primary" @click="handleSubmit(signFormRef)">保存</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script setup>
|
||||
import {onMounted, reactive, ref} from 'vue'
|
||||
import {dayjs} from 'element-plus'
|
||||
// import { IInPatient } from '@/model/IInPatient'
|
||||
|
||||
const currentInPatient = ref({})
|
||||
const initCurrentInPatient = () => {
|
||||
currentInPatient.value = {
|
||||
feeType: '08',
|
||||
sexName: '男',
|
||||
age: '0',
|
||||
}
|
||||
}
|
||||
/* 初始化数据 */
|
||||
const init = () => {
|
||||
initCurrentInPatient()
|
||||
}
|
||||
|
||||
/* 入科 */
|
||||
const signForm = ref({
|
||||
visitCode: '', // 就诊流水号
|
||||
height: 0, // 身高
|
||||
weight: 0, // 体重
|
||||
temperature: 0, // 体温
|
||||
hertRate: 0, // 心率
|
||||
pulse: 0, // 脉搏
|
||||
highBloodPressure: 0, // 收缩压
|
||||
endBloodPressure: 0, // 舒张压
|
||||
loginDeptCode: '', // 当前登录科室
|
||||
bingqing: '', //患者病情
|
||||
inDeptDate: dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss'), //入院时间
|
||||
signsId: '',
|
||||
})
|
||||
const rules = reactive({
|
||||
admittedDoctor: [{ required: true, message: '请选择住院医生', trigger: ['blur', 'change'] }],
|
||||
masterNurse: [{ required: true, message: '请选择责任护士', trigger: ['blur', 'change'] }],
|
||||
})
|
||||
const printWristband = ref(false)
|
||||
const emits = defineEmits(['okAct'])
|
||||
|
||||
const visible = defineModel('visible')
|
||||
const width = '920px'
|
||||
|
||||
/* 取消 */
|
||||
const cancelAct = () => {
|
||||
visible.value = false
|
||||
}
|
||||
/* 录入患者体征*/
|
||||
const signFormRef = ref()
|
||||
const handleSubmit = async (formEl) => {
|
||||
if (!formEl) return
|
||||
await formEl.validate((valid, fields) => {
|
||||
if (valid) {
|
||||
console.log('submit!')
|
||||
try {
|
||||
// 录入患者体征方法(signForm.value).then((res: any) => {
|
||||
// ElMessage({
|
||||
// message: '登记成功!',
|
||||
// type: 'success',
|
||||
// grouping: true,
|
||||
// showClose: true,
|
||||
// })
|
||||
// emits('okAct')
|
||||
// })
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
const openAct = () => {
|
||||
init()
|
||||
}
|
||||
const closedAct = () => {
|
||||
visible.value = false
|
||||
}
|
||||
onMounted(() => {})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.transferIn-container {
|
||||
width: 100%;
|
||||
|
||||
.admission-signs,
|
||||
.admission-information {
|
||||
width: 888px;
|
||||
.unit {
|
||||
display: inline-block;
|
||||
margin-left: 10px;
|
||||
color: #bbb;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
font-family: '思源黑体 CN';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.print-wriBtn {
|
||||
margin-left: 565px;
|
||||
}
|
||||
|
||||
.w-p100 {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.w-80 {
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
.mb-90 {
|
||||
margin-bottom: 90px !important;
|
||||
}
|
||||
</style>
|
||||
@@ -1,731 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-row :gutter="24">
|
||||
<el-col :span="4" :xs="24">
|
||||
<el-input
|
||||
v-model="diagnosis"
|
||||
placeholder="诊断名称"
|
||||
clearable
|
||||
style="width: 100%; margin-bottom: 10px"
|
||||
@keyup.enter="queryDiagnosisUse"
|
||||
>
|
||||
<template #append>
|
||||
<el-button icon="Search" @click="queryDiagnosisUse" />
|
||||
</template>
|
||||
</el-input>
|
||||
<el-tree
|
||||
ref="treeRef"
|
||||
:data="tree"
|
||||
node-key="id"
|
||||
:props="{ label: 'name', children: 'children' }"
|
||||
highlight-current
|
||||
default-expand-all
|
||||
:filter-node-method="filterNode"
|
||||
@node-click="handleNodeClick"
|
||||
>
|
||||
<template #default="{ node, data }">
|
||||
<div class="custom-tree-node">
|
||||
<span>{{ node.label }}</span>
|
||||
<span class="tree-node-actions">
|
||||
<template v-if="node.level === 1 && data.name != '常用' && data.name != '历史'">
|
||||
<el-button
|
||||
style="color: #000000"
|
||||
type="text"
|
||||
size="small"
|
||||
@click.stop="addChild(data)"
|
||||
>
|
||||
<el-icon>
|
||||
<Plus />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</template>
|
||||
<el-popconfirm width="200" :hide-after="10" title="确认删除此常用诊断吗" placement="top-start"
|
||||
@confirm="deleteChild(data)">
|
||||
<template #reference>
|
||||
<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-icon>
|
||||
<Minus />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-tree>
|
||||
</el-col>
|
||||
<el-col :span="20" :xs="24">
|
||||
<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="handleImport()"> 导入慢性病诊断 </el-button>
|
||||
</div>
|
||||
|
||||
<el-form :model="form" :rules="rules" ref="formRef">
|
||||
<el-table ref="diagnosisTableRef" :data="form.diagnosisList" height="650">
|
||||
<el-table-column label="序号" width="50" >
|
||||
<template #default="scope">
|
||||
{{ scope.$index + 1 }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="诊断排序" align="center" prop="diagSrtNo" width="120">
|
||||
<template #default="scope">
|
||||
<el-form-item :prop="`diagnosisList.${scope.$index}.diagSrtNo`" :rules="rules.diagSrtNo">
|
||||
<el-input-number v-model="scope.row.diagSrtNo" controls-position="right" :controls="false"
|
||||
style="width: 80px" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="诊断类别" align="center" prop="diagSrtNo" width="180">
|
||||
<template #default="scope">
|
||||
<el-form-item :prop="`diagnosisList.${scope.$index}.medTypeCode`" :rules="rules.medTypeCode">
|
||||
<el-select v-model="scope.row.medTypeCode" placeholder=" " style="width: 150px">
|
||||
<el-option v-for="item in med_type" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="诊断名称" align="center" prop="name">
|
||||
<template #default="scope">
|
||||
<el-form-item :prop="`diagnosisList.${scope.$index}.name`" :rules="rules.name">
|
||||
<el-popover :popper-style="{ padding: '0' }" placement="bottom-start" :visible="scope.row.showPopover"
|
||||
trigger="manual" :width="800">
|
||||
<diagnosislist :diagnosisSearchkey="diagnosisSearchkey" @selectDiagnosis="handleSelsectDiagnosis" />
|
||||
<template #reference>
|
||||
<el-input v-model="scope.row.name" placeholder="请选择诊断" @input="handleChange"
|
||||
@focus="handleFocus(scope.row, scope.$index)" @blur="handleBlur(scope.row)" />
|
||||
</template>
|
||||
</el-popover>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="诊断医生" align="center" prop="diagnosisDoctor" width="120" />
|
||||
<el-table-column label="诊断时间" align="center" prop="diagnosisTime" width="150" />
|
||||
<el-table-column label="诊断代码" align="center" prop="ybNo" width="180" />
|
||||
<el-table-column label="诊断类型" align="center" prop="maindiseFlag" width="120">
|
||||
<template #default="scope">
|
||||
<div style="display:flex;flex-direction:column;align-items:center;gap:5px;">
|
||||
<el-checkbox
|
||||
label="主诊断"
|
||||
:trueLabel="1"
|
||||
:falseLabel="0"
|
||||
v-model="scope.row.maindiseFlag"
|
||||
border
|
||||
size="small"
|
||||
@change="(value) => handleMaindise(value, scope.$index)"
|
||||
/>
|
||||
<el-select
|
||||
v-model="scope.row.verificationStatusEnum"
|
||||
placeholder=" "
|
||||
style="width: 100%; padding-bottom: 5px; padding-left: 10px"
|
||||
size="small"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in diagnosisOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" width="130">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" @click="handleDeleteDiagnosis(scope.row, scope.$index)">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-form>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<diagnosisdialog
|
||||
:openDiagnosis="openDiagnosis"
|
||||
@close="closeDiagnosisDialog"
|
||||
:radio="orgOrUser"
|
||||
/>
|
||||
<AddDiagnosisDialog
|
||||
:openAddDiagnosisDialog="openAddDiagnosisDialog"
|
||||
:patientInfo="props.patientInfo"
|
||||
@close="closeDiagnosisDialog"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {getCurrentInstance} from 'vue'; // 添加 nextTick 导入
|
||||
import useUserStore from '@/store/modules/user';
|
||||
import {
|
||||
delEncounterDiagnosis,
|
||||
deleteDiagnosisBind,
|
||||
diagnosisInit,
|
||||
getChronicDisease,
|
||||
getConditionDefinitionInfo,
|
||||
getEmrDetail,
|
||||
getEncounterDiagnosis,
|
||||
getTcmDiagnosis,
|
||||
isFoodDiseasesNew,
|
||||
saveDiagnosis,
|
||||
} from '../api';
|
||||
import {deleteTcmDiagnosis} from '@/views/doctorstation/components/api.js';
|
||||
import diagnosisdialog from '../diagnosis/diagnosisdialog.vue';
|
||||
import AddDiagnosisDialog from './addDiagnosisDialog.vue';
|
||||
import diagnosislist from '../diagnosis/diagnosislist.vue';
|
||||
import {patientInfo} from '../../store/patient.js';
|
||||
import {ElMessage} from 'element-plus';
|
||||
// const diagnosisList = ref([]);
|
||||
const allowAdd = ref(false);
|
||||
const isSaving = ref(false);
|
||||
const tree = ref([]);
|
||||
const openDiagnosis = ref(false);
|
||||
const openAddDiagnosisDialog = ref(false);
|
||||
const diagnosisSearchkey = ref('');
|
||||
const diagnosisOptions = ref([]);
|
||||
const rowIndex = ref();
|
||||
const diagnosis = ref();
|
||||
const orgOrUser = ref();
|
||||
const form = ref({
|
||||
diagnosisList: [],
|
||||
});
|
||||
const props = defineProps({
|
||||
patientInfo: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
const emits = defineEmits(['diagnosisSave']);
|
||||
const { proxy } = getCurrentInstance();
|
||||
const userStore = useUserStore();
|
||||
const { med_type } = proxy.useDict('med_type');
|
||||
const rules = ref({
|
||||
name: [{ required: true, message: '请选择诊断', trigger: 'change' }],
|
||||
medTypeCode: [{ required: true, message: '请选择诊断类型', trigger: 'change' }],
|
||||
diagSrtNo: [{ required: true, message: '请输入诊断序号', trigger: 'change' }],
|
||||
});
|
||||
const diagnosisNetDatas = ref([]);
|
||||
|
||||
watch(
|
||||
() => form.value.diagnosisList,
|
||||
() => {
|
||||
// 如果正在保存,则不触发更新事件
|
||||
if (!isSaving.value) {
|
||||
emits('diagnosisSave', false);
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
// 监听患者信息变化,自动获取病历详情和诊断列表
|
||||
watch(
|
||||
() => props.patientInfo,
|
||||
(newVal) => {
|
||||
if (newVal?.encounterId) {
|
||||
getDetail(newVal.encounterId);
|
||||
getList();
|
||||
}
|
||||
},
|
||||
{ immediate: true, deep: true }
|
||||
);
|
||||
|
||||
function getDetail(encounterId) {
|
||||
if (!encounterId) {
|
||||
console.warn('未提供有效的就诊ID,无法获取病历详情');
|
||||
allowAdd.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('正在获取病历详情,encounterId:', encounterId);
|
||||
|
||||
getEmrDetail(encounterId)
|
||||
.then((res) => {
|
||||
console.log('病历详情API返回:', res);
|
||||
if (res.code === 200) {
|
||||
allowAdd.value = res.data ? true : false;
|
||||
console.log('设置 allowAdd =', allowAdd.value, ', 病历数据:', res.data);
|
||||
} else {
|
||||
allowAdd.value = false;
|
||||
console.warn('获取病历详情失败:', res.msg);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('获取病历详情异常:', error);
|
||||
allowAdd.value = false;
|
||||
});
|
||||
}
|
||||
|
||||
function getList() {
|
||||
if (!props.patientInfo || !props.patientInfo.encounterId) {
|
||||
console.warn('患者就诊信息不完整,无法获取诊断数据');
|
||||
return;
|
||||
}
|
||||
|
||||
// 初始化中医诊断列表
|
||||
const newList = [];
|
||||
|
||||
getEncounterDiagnosis(props.patientInfo.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.value.diagnosisList = datas;
|
||||
// form.value.diagnosisList = res.data;
|
||||
emits('diagnosisSave', false);
|
||||
}
|
||||
});
|
||||
getTcmDiagnosis({ encounterId: props.patientInfo.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;
|
||||
res.data.illness.forEach((item, index) => {
|
||||
newList.push({
|
||||
name: item.name + '-' + (res.data.symptom[index]?.name || ''),
|
||||
ybNo: item.ybNo,
|
||||
medTypeCode: item.medTypeCode,
|
||||
diagnosisDoctor: props.patientInfo.practitionerName || props.patientInfo.doctorName || props.patientInfo.physicianName || userStore.name,
|
||||
diagnosisTime: new Date().toLocaleString('zh-CN')
|
||||
});
|
||||
});
|
||||
|
||||
// 将新数据添加到现有列表中
|
||||
form.value.diagnosisList.push(...newList);
|
||||
|
||||
// 重新排序整个列表
|
||||
form.value.diagnosisList.sort((a, b) => {
|
||||
const aNo = typeof a.diagSrtNo === 'number' ? a.diagSrtNo : 9999;
|
||||
const bNo = typeof b.diagSrtNo === 'number' ? b.diagSrtNo : 9999;
|
||||
return aNo - bNo;
|
||||
});
|
||||
}
|
||||
emits('diagnosisSave', false);
|
||||
}
|
||||
});
|
||||
|
||||
getTree();
|
||||
}
|
||||
|
||||
init();
|
||||
function init() {
|
||||
diagnosisInit().then((res) => {
|
||||
if (res.code == 200) {
|
||||
diagnosisOptions.value = res.data.verificationStatusOptions;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function handleImport() {
|
||||
if (!props.patientInfo || !props.patientInfo.encounterId) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (props.patientInfo.contractName != '自费') {
|
||||
// 获取患者慢性病信息
|
||||
getChronicDisease({ encounterId: props.patientInfo.encounterId }).then((res) => {
|
||||
if (res.data && res.data.length > 0) {
|
||||
res.data.forEach((item, index) => {
|
||||
form.value.diagnosisList.push({
|
||||
...item,
|
||||
...{
|
||||
medTypeCode: '140104',
|
||||
verificationStatusEnum: 4,
|
||||
definitionId: item.id,
|
||||
diagSrtNo: form.value.diagnosisList.length + 1,
|
||||
iptDiseTypeCode: 2,
|
||||
diagnosisDesc: '',
|
||||
diagnosisDoctor: props.patientInfo.practitionerName || props.patientInfo.doctorName || props.patientInfo.physicianName || userStore.name,
|
||||
diagnosisTime: new Date().toLocaleString('zh-CN'),
|
||||
//添加 patientId
|
||||
patientId: props.patientInfo.patientId
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加子节点
|
||||
*/
|
||||
function addChild(data) {
|
||||
orgOrUser.value = data.name;
|
||||
openDiagnosis.value = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除子节点
|
||||
*/
|
||||
function deleteChild(data) {
|
||||
deleteDiagnosisBind(data.id).then((res) => {
|
||||
if (res.code == 200) {
|
||||
proxy.$modal.msgSuccess('删除成功');
|
||||
getTree();
|
||||
}
|
||||
});
|
||||
}
|
||||
watch(diagnosis, (val) => {
|
||||
proxy.$refs['treeRef'].filter(val);
|
||||
});
|
||||
|
||||
/** 通过条件过滤节点 */
|
||||
const filterNode = (value, data) => {
|
||||
console.log('filterNode', value, data);
|
||||
|
||||
if (!value) return true;
|
||||
return data.name.indexOf(value) !== -1;
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取诊断树列表
|
||||
*/
|
||||
function getTree() {
|
||||
const patientId = props.patientInfo?.patientId || '';
|
||||
getConditionDefinitionInfo(patientId).then((res) => {
|
||||
if (res.code == 200) {
|
||||
let list = [];
|
||||
list = res.data.patientHistoryList;
|
||||
list.children = [];
|
||||
// 手动构造树列表;
|
||||
tree.value[0] = {
|
||||
id: '1',
|
||||
name: '历史',
|
||||
children: list,
|
||||
};
|
||||
tree.value[1] = {
|
||||
id: '2',
|
||||
name: '常用',
|
||||
children: res.data.doctorCommonUseList,
|
||||
};
|
||||
tree.value[2] = {
|
||||
id: '3',
|
||||
name: '个人',
|
||||
children: res.data.userPersonalList,
|
||||
};
|
||||
tree.value[3] = {
|
||||
id: '4',
|
||||
name: '科室',
|
||||
children: res.data.organizationList,
|
||||
};
|
||||
console.log(tree.value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加西医诊断
|
||||
*/
|
||||
function handleAddDiagnosis() {
|
||||
console.log('点击新增诊断按钮,allowAdd:', allowAdd.value);
|
||||
|
||||
// 检查表单ref是否存在
|
||||
if (!proxy.$refs.formRef) {
|
||||
console.error('表单ref不存在');
|
||||
// 直接添加诊断,不经过表单验证
|
||||
addDiagnosisItem();
|
||||
return;
|
||||
}
|
||||
|
||||
proxy.$refs.formRef.validate((valid, fields) => {
|
||||
console.log('表单验证结果:', valid, '错误字段:', fields);
|
||||
if (valid) {
|
||||
if (!allowAdd.value) {
|
||||
proxy.$modal.msgWarning('请先填写病历');
|
||||
return;
|
||||
}
|
||||
addDiagnosisItem();
|
||||
} else {
|
||||
console.warn('表单验证失败:', fields);
|
||||
// 验证失败时也允许添加(因为是新增空行)
|
||||
if (allowAdd.value) {
|
||||
console.log('验证失败但允许添加,强制添加诊断');
|
||||
addDiagnosisItem();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加诊断项
|
||||
*/
|
||||
function addDiagnosisItem() {
|
||||
form.value.diagnosisList.push({
|
||||
showPopover: false,
|
||||
name: undefined,
|
||||
verificationStatusEnum: 4,
|
||||
medTypeCode: undefined,
|
||||
diagSrtNo: form.value.diagnosisList.length + 1,
|
||||
iptDiseTypeCode: 2,
|
||||
diagnosisDesc: '',
|
||||
diagnosisDoctor: props.patientInfo.practitionerName || props.patientInfo.doctorName || props.patientInfo.physicianName || userStore.name,
|
||||
diagnosisTime: new Date().toLocaleString('zh-CN'),
|
||||
|
||||
// 新增这一行:为每个诊断项添加 patientId
|
||||
patientId: props.patientInfo.patientId
|
||||
});
|
||||
|
||||
if (form.value.diagnosisList.length == 1) {
|
||||
form.value.diagnosisList[0].maindiseFlag = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// 添加中医诊断
|
||||
function handleAddTcmDiagonsis() {
|
||||
openAddDiagnosisDialog.value = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除诊断
|
||||
*/
|
||||
/**
|
||||
* 删除诊断
|
||||
*/
|
||||
function handleDeleteDiagnosis(row, index) {
|
||||
//中医诊断用-拼接 例如:疳气-表里俱实证
|
||||
const nameArr = row.name?.split('-') || [];
|
||||
if (row.conditionId) {
|
||||
if (nameArr.length > 1) {
|
||||
deleteTcmDiagnosis(row.syndromeGroupNo).then(() => {
|
||||
getList();
|
||||
getTree();
|
||||
});
|
||||
} else {
|
||||
delEncounterDiagnosis(row.conditionId).then(() => {
|
||||
getList();
|
||||
getTree();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handleMaindise(value, index) {
|
||||
if (value == 1) {
|
||||
let flag = 0;
|
||||
form.value.diagnosisList.forEach((item) => {
|
||||
console.log(item);
|
||||
if (item.maindiseFlag == 1) {
|
||||
flag++;
|
||||
}
|
||||
});
|
||||
if (flag > 1) {
|
||||
form.value.diagnosisList[index].maindiseFlag = 0;
|
||||
proxy.$modal.msgWarning('只能有一条主诊断');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存诊断
|
||||
*/
|
||||
/**
|
||||
* 保存诊断
|
||||
*/
|
||||
/**
|
||||
* 保存诊断
|
||||
*/
|
||||
/**
|
||||
* 保存诊断
|
||||
*/
|
||||
function handleSaveDiagnosis() {
|
||||
// 防止重复点击保存
|
||||
if (isSaving.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
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) {
|
||||
proxy.$modal.msgWarning('诊断不能为空');
|
||||
return;
|
||||
} else if (!form.value.diagnosisList.some((diagnosis) => diagnosis.maindiseFlag === 1)) {
|
||||
proxy.$modal.msgWarning('至少添加一条主诊断');
|
||||
return;
|
||||
}
|
||||
|
||||
// 设置保存标志,避免触发watch监听器
|
||||
isSaving.value = true;
|
||||
|
||||
// 步骤1:深拷贝并按 diagSrtNo 排序
|
||||
const sortedList = [...form.value.diagnosisList].sort((a, b) => {
|
||||
const aNo = typeof a.diagSrtNo === 'number' ? a.diagSrtNo : 9999;
|
||||
const bNo = typeof b.diagSrtNo === 'number' ? b.diagSrtNo : 9999;
|
||||
return aNo - bNo;
|
||||
});
|
||||
|
||||
// 步骤2:重新分配连续的序号(从1开始)
|
||||
sortedList.forEach((item, index) => {
|
||||
item.diagSrtNo = index + 1; // 这里是关键!把”诊断排序”改成新顺序
|
||||
});
|
||||
|
||||
// 步骤3:提交排序后的数据
|
||||
saveDiagnosis({
|
||||
patientId: props.patientInfo.patientId,
|
||||
encounterId: props.patientInfo.encounterId,
|
||||
diagnosisChildList: sortedList,
|
||||
}).then((res) => {
|
||||
if (res.code === 200) {
|
||||
emits('diagnosisSave', false);
|
||||
proxy.$modal.msgSuccess('诊断已保存');
|
||||
|
||||
// 保存成功后从服务器重新加载数据,确保前后端数据一致
|
||||
getList();
|
||||
|
||||
// 食源性疾病逻辑
|
||||
isFoodDiseasesNew({ encounterId: props.patientInfo.encounterId }).then((res2) => {
|
||||
if (res2.code === 20 && res2.data) {
|
||||
window.open(res2.data, '_blank');
|
||||
}
|
||||
});
|
||||
}
|
||||
}).finally(() => {
|
||||
setTimeout(() => {
|
||||
isSaving.value = false;
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 关闭诊断弹窗
|
||||
*/
|
||||
function closeDiagnosisDialog(str) {
|
||||
if (str === 'success') {
|
||||
proxy.$modal.msgSuccess('操作成功');
|
||||
}
|
||||
|
||||
openAddDiagnosisDialog.value = false;
|
||||
openDiagnosis.value = false;
|
||||
getTree();
|
||||
getList();
|
||||
}
|
||||
|
||||
function queryDiagnosisUse(value) { }
|
||||
|
||||
function handleChange(value) {
|
||||
diagnosisSearchkey.value = value;
|
||||
}
|
||||
/**
|
||||
* 选择诊断并赋值到列表
|
||||
*/
|
||||
function handleSelsectDiagnosis(row) {
|
||||
console.log(row);
|
||||
form.value.diagnosisList[rowIndex.value].ybNo = row.ybNo;
|
||||
form.value.diagnosisList[rowIndex.value].name = row.name;
|
||||
form.value.diagnosisList[rowIndex.value].definitionId = row.id;
|
||||
}
|
||||
/**获取焦点时 打开列表 */
|
||||
function handleFocus(row, index) {
|
||||
rowIndex.value = index;
|
||||
row.showPopover = true;
|
||||
}
|
||||
/**失去焦点时 关闭列表 */
|
||||
function handleBlur(row) {
|
||||
row.showPopover = false;
|
||||
}
|
||||
|
||||
function handleNodeClick(data) {
|
||||
console.log(data.children);
|
||||
// 检查节点是否为根节点
|
||||
if (data.children != undefined) {
|
||||
// 如果是根节点,不执行任何操作
|
||||
return;
|
||||
}
|
||||
// if (!allowAdd.value) {
|
||||
// proxy.$modal.msgWarning('请先填写病历');
|
||||
// return;
|
||||
// }
|
||||
const isDuplicate = form.value.diagnosisList.some(
|
||||
(diagnosis) => diagnosis.ybNo === data.ybNo || diagnosis.name === data.name
|
||||
);
|
||||
if (isDuplicate) {
|
||||
proxy.$modal.msgWarning('该诊断项已存在');
|
||||
return;
|
||||
}
|
||||
form.value.diagnosisList.push({
|
||||
ybNo: data.ybNo,
|
||||
name: data.name,
|
||||
verificationStatusEnum: 4,
|
||||
medTypeCode: undefined,
|
||||
diagSrtNo: form.value.diagnosisList.length + 1,
|
||||
definitionId: data.definitionId,
|
||||
diagnosisDoctor: props.patientInfo.practitionerName || props.patientInfo.doctorName || props.patientInfo.physicianName || userStore.name,
|
||||
diagnosisTime: new Date().toLocaleString('zh-CN'),
|
||||
// 添加 patientId
|
||||
patientId: props.patientInfo.patientId
|
||||
});
|
||||
if (form.value.diagnosisList.length == 1) {
|
||||
form.value.diagnosisList[0].maindiseFlag = 1;
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({ getList, getDetail, handleSaveDiagnosis });
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.el-checkbox.is-bordered.el-checkbox--small {
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.custom-tree-node {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.tree-node-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
@@ -1,126 +0,0 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:title="title"
|
||||
v-model="props.openDiagnosis"
|
||||
width="1000px"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
@close="close"
|
||||
>
|
||||
<div>
|
||||
<el-row :gutter="24" class="mb8">
|
||||
<el-col :span="12">
|
||||
<el-input
|
||||
v-model="queryParams.searchKey"
|
||||
placeholder="诊断名称/拼音码"
|
||||
clearable
|
||||
style="width: 50%; margin-bottom: 10px"
|
||||
@keyup.enter="queryDiagnosisUse"
|
||||
>
|
||||
<template #append>
|
||||
<el-button icon="Search" @click="queryDiagnosisUse" />
|
||||
</template>
|
||||
</el-input>
|
||||
</el-col>
|
||||
<!-- <el-col :span="12">
|
||||
<span>使用范围:</span>
|
||||
<el-radio-group v-model="radio">
|
||||
<el-radio :label="1" size="default">个人</el-radio>
|
||||
<el-radio :label="2" size="default">科室</el-radio>
|
||||
</el-radio-group>
|
||||
</el-col> -->
|
||||
</el-row>
|
||||
|
||||
<el-table
|
||||
ref="diagnosisDefinitionRef"
|
||||
:data="diagnosisDefinitionList"
|
||||
row-key="patientId"
|
||||
@cell-click="clickRow"
|
||||
highlight-current-row
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table-column label="诊断名称" align="center" prop="name" />
|
||||
<el-table-column label="医保编码" align="center" prop="ybNo" />
|
||||
</el-table>
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button type="primary" @click="submit">确 定</el-button>
|
||||
<el-button @click="close">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {computed} from "vue";
|
||||
import {getDiagnosisDefinitionList, saveDiagnosisBind} from "../api";
|
||||
|
||||
const radio = ref(1);
|
||||
const props = defineProps({
|
||||
openDiagnosis: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
radio: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(["close"]);
|
||||
const total = ref(0);
|
||||
const queryParams = ref({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
});
|
||||
const diagnosisDefinitionList = ref([]);
|
||||
const selectRow = ref({});
|
||||
const title = computed(() => {
|
||||
return props.radio == "个人" ? "个人常用诊断" : "科室常用诊断";
|
||||
});
|
||||
|
||||
getList();
|
||||
function getList() {
|
||||
getDiagnosisDefinitionList(queryParams.value).then((res) => {
|
||||
diagnosisDefinitionList.value = res.data.records;
|
||||
total.value = res.data.total;
|
||||
});
|
||||
}
|
||||
|
||||
function submit() {
|
||||
saveDiagnosisBind({
|
||||
definitionId: selectRow.value.id,
|
||||
definitionName: selectRow.value.name,
|
||||
bindingEnum: props.radio == "个人" ? 1 : 2,
|
||||
}).then((res) => {
|
||||
if (res.code == 200) {
|
||||
emit("close", "success");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function queryDiagnosisUse() {
|
||||
getList();
|
||||
}
|
||||
|
||||
function close() {
|
||||
emit("close");
|
||||
}
|
||||
|
||||
function clickRow(row) {
|
||||
selectRow.value = row;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
:deep( .pagination-container .el-pagination) {
|
||||
right: 20px !important;
|
||||
}
|
||||
</style>
|
||||
@@ -1,58 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-table
|
||||
ref="diagnosisDefinitionRef"
|
||||
:data="diagnosisDefinitionList"
|
||||
row-key="patientId"
|
||||
@cell-click="clickRow"
|
||||
max-height="400"
|
||||
>
|
||||
<el-table-column label="诊断名称" align="center" prop="name" />
|
||||
<el-table-column label="医保编码" align="center" prop="ybNo" />
|
||||
<el-table-column label="诊断类型" align="center" prop="typeName" width="180"/>
|
||||
</el-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {getDiagnosisDefinitionList} from '../api';
|
||||
|
||||
const props = defineProps({
|
||||
diagnosisSearchkey: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(['selectDiagnosis']);
|
||||
const total = ref(0);
|
||||
const queryParams = ref({
|
||||
pageSize: 1000,
|
||||
pageNo: 1,
|
||||
// typeCode: 1,
|
||||
});
|
||||
const diagnosisDefinitionList = ref([]);
|
||||
|
||||
watch(
|
||||
() => props.diagnosisSearchkey,
|
||||
(newValue) => {
|
||||
queryParams.value.searchKey = newValue;
|
||||
getList();
|
||||
},
|
||||
{ immdiate: true }
|
||||
);
|
||||
|
||||
getList();
|
||||
function getList() {
|
||||
getDiagnosisDefinitionList(queryParams.value).then((res) => {
|
||||
diagnosisDefinitionList.value = res.data.records;
|
||||
total.value = res.data.total;
|
||||
});
|
||||
}
|
||||
|
||||
function clickRow(row) {
|
||||
emit('selectDiagnosis', row);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
@@ -1,279 +0,0 @@
|
||||
<template>
|
||||
<div class="diagnose-container">
|
||||
<!-- 常用诊断、个人诊断、科室诊断、历史诊断、 -->
|
||||
<diagnose-folder :folder="mockData" :level="0" />
|
||||
<div class="diagnose-main">
|
||||
<div class="operate-btns">
|
||||
<el-space>
|
||||
<el-button type="primary" @click="addNewWestern">开立诊断</el-button>
|
||||
<el-button type="primary">既往诊断</el-button>
|
||||
<!-- 患者诊断 -->
|
||||
<el-button type="danger" @click="addNewChinese">中医诊断</el-button>
|
||||
</el-space>
|
||||
</div>
|
||||
<div class="diagnoseData-container">
|
||||
<el-table
|
||||
:data="diagnoseData"
|
||||
border
|
||||
row-key="id"
|
||||
style="width: 100%; height: 100%"
|
||||
highlight-current-row
|
||||
>
|
||||
<el-table-column type="selection" fixed="left" width="40" />
|
||||
<el-table-column prop="date" label="诊断类型" width="180" sortable />
|
||||
<el-table-column prop="name" label="诊断名称" width="180" />
|
||||
<el-table-column prop="address" label="主诊" />
|
||||
<el-table-column prop="address" label="复诊" />
|
||||
<el-table-column prop="address" label="疑似" />
|
||||
<el-table-column prop="address" label="传染" />
|
||||
<el-table-column prop="address" label="入院病情" width="180" />
|
||||
<el-table-column prop="address" label="转归" width="180" />
|
||||
<el-table-column prop="address" label="转归日期" width="180" />
|
||||
<el-table-column prop="address" label="诊断科室" width="180" />
|
||||
<el-table-column prop="address" label="诊断医师" width="180" />
|
||||
<el-table-column prop="address" label="诊断日期" width="180" />
|
||||
<el-table-column fixed="right" label="操作" width="120">
|
||||
<template #default="props">
|
||||
<el-space>
|
||||
<el-tooltip content="删除" placement="bottom">
|
||||
<el-icon @click="deleteDiagnose(row)"><Delete /></el-icon>
|
||||
</el-tooltip>
|
||||
<el-tooltip
|
||||
content="下移"
|
||||
placement="bottom"
|
||||
v-if="props.$index !== diagnoseData.length - 1"
|
||||
>
|
||||
<el-icon @click="download(props.row)"><Download /></el-icon>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="上移" placement="bottom" v-if="props.$index !== 0">
|
||||
<el-icon @click="upload(props.row)"><Upload /></el-icon>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="置顶" placement="bottom" v-if="props.$index !== 0">
|
||||
<el-icon @click="top(props.row)"><Top /></el-icon>
|
||||
</el-tooltip>
|
||||
<el-tooltip
|
||||
content="置底"
|
||||
placement="bottom"
|
||||
v-if="props.$index !== diagnoseData.length - 1"
|
||||
>
|
||||
<el-icon @click="bottom(props.row)"><Bottom /></el-icon>
|
||||
</el-tooltip>
|
||||
</el-space>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
<WesternMedicineDialog v-model:visible="WesternMedicineDialogVisible" />
|
||||
<ChineseMedicineDialog v-model:visible="ChineseMedicineDialogVisible" />
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import {onBeforeMount, onMounted, reactive, ref} from 'vue'
|
||||
// const { proxy } = getCurrentInstance()
|
||||
// const emits = defineEmits([])
|
||||
// const props = defineProps({})
|
||||
// import DiagnoseFolder from './diagnoseFolder.vue'
|
||||
import WesternMedicineDialog from './westernMedicineDialog.vue'
|
||||
import ChineseMedicineDialog from './chineseMedicineDialog.vue'
|
||||
|
||||
const diagnoseData = ref([
|
||||
{
|
||||
id: 1,
|
||||
sort: 1,
|
||||
name: '新冠',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
sort: 2,
|
||||
name: '新冠as',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
sort: 3,
|
||||
name: '新冠12',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
sort: 4,
|
||||
name: '新冠2121',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
sort: 5,
|
||||
name: '新冠12',
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
sort: 6,
|
||||
name: '新冠21',
|
||||
},
|
||||
])
|
||||
|
||||
// 模拟数据
|
||||
const mockData = ref([
|
||||
{
|
||||
name: '常用',
|
||||
children: [
|
||||
{
|
||||
name: '文件夹 1',
|
||||
children: [
|
||||
{
|
||||
name: '霍乱',
|
||||
},
|
||||
{
|
||||
name: '新型冠状病毒新型冠状病毒新型冠状病毒',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: '文件夹 2',
|
||||
children: [
|
||||
{
|
||||
name: '普外科',
|
||||
},
|
||||
{
|
||||
name: '骨科',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: '新型冠状病毒',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: '科室',
|
||||
children: [
|
||||
{
|
||||
name: '内科',
|
||||
children: [
|
||||
{
|
||||
name: '呼吸内科',
|
||||
},
|
||||
{
|
||||
name: '消化内科',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: '外科',
|
||||
children: [
|
||||
{
|
||||
name: '普外科',
|
||||
},
|
||||
{
|
||||
name: '骨科',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: '儿科',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: '个人',
|
||||
children: [
|
||||
{
|
||||
name: '内科',
|
||||
children: [
|
||||
{
|
||||
name: '呼吸内科',
|
||||
},
|
||||
{
|
||||
name: '消化内科',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: '外科',
|
||||
children: [
|
||||
{
|
||||
name: '普外科',
|
||||
},
|
||||
{
|
||||
name: '骨科',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: '儿科',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: '历史',
|
||||
children: [
|
||||
{
|
||||
name: '心率失常',
|
||||
},
|
||||
{
|
||||
name: '心率失常',
|
||||
},
|
||||
{
|
||||
name: '心率失常',
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
const state = reactive({})
|
||||
onBeforeMount(() => {})
|
||||
onMounted(() => {})
|
||||
defineExpose({ state })
|
||||
|
||||
// const deleteDiagnose = (row: any) => {
|
||||
// // TODO 删除
|
||||
// console.log(row)
|
||||
// }
|
||||
|
||||
// const download = (row: any) => {
|
||||
// // TODO 删除
|
||||
// }
|
||||
|
||||
// const upload = (row: any) => {
|
||||
// // TODO 删除
|
||||
// }
|
||||
|
||||
// const top = (row: any) => {
|
||||
// // TODO 删除
|
||||
// }
|
||||
|
||||
// const bottom = (row: any) => {
|
||||
// // TODO 删除
|
||||
// }
|
||||
|
||||
const addNewWestern = () => {
|
||||
WesternMedicineDialogVisible.value = true
|
||||
}
|
||||
const addNewChinese = () => {
|
||||
ChineseMedicineDialogVisible.value = true
|
||||
}
|
||||
const WesternMedicineDialogVisible = ref(false)
|
||||
const ChineseMedicineDialogVisible = ref(false)
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.diagnose-container {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
.folder-container {
|
||||
width: 200px;
|
||||
flex: none;
|
||||
}
|
||||
.diagnose-main {
|
||||
width: 300px;
|
||||
flex: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.operate-btns {
|
||||
height: 44px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: none;
|
||||
}
|
||||
.diagnoseData-container {
|
||||
flex: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,221 +0,0 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
v-model="visible"
|
||||
:width="width"
|
||||
title="西医诊断"
|
||||
@open="openAct"
|
||||
@closed="closedAct"
|
||||
:z-index="20"
|
||||
>
|
||||
<el-form :inline="true" :model="diagnoseform" class="demo-form-inline" label-width="auto">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="诊断名称" style="width: 100%">
|
||||
<el-input v-model="diagnoseform.user" placeholder="诊断名称" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="诊断类型" style="width: 100%">
|
||||
<el-select
|
||||
v-model="diagnoseform.user"
|
||||
placeholder="诊断类型"
|
||||
clearable
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option label="Zone one" value="shanghai" />
|
||||
<el-option label="Zone two" value="beijing" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="前缀" style="width: 100%">
|
||||
<el-select v-model="diagnoseform.user" placeholder="前缀" clearable style="width: 100%">
|
||||
<el-option label="Zone one" value="shanghai" />
|
||||
<el-option label="Zone two" value="beijing" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="后缀" style="width: 100%">
|
||||
<el-select v-model="diagnoseform.user" placeholder="后缀" clearable style="width: 100%">
|
||||
<el-option label="Zone one" value="shanghai" />
|
||||
<el-option label="Zone two" value="beijing" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="ICD" style="width: 100%">
|
||||
<el-input v-model="diagnoseform.user" placeholder="ICD" clearable style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="备注" style="width: 100%">
|
||||
<el-input
|
||||
v-model="diagnoseform.user"
|
||||
placeholder="备注"
|
||||
clearable
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="入院病情" style="width: 100%">
|
||||
<el-select
|
||||
v-model="diagnoseform.user"
|
||||
placeholder="入院病情"
|
||||
clearable
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option label="Zone one" value="shanghai" />
|
||||
<el-option label="Zone two" value="beijing" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="转归" style="width: 100%">
|
||||
<el-select v-model="diagnoseform.user" placeholder="转归" clearable style="width: 100%">
|
||||
<el-option label="Zone one" value="shanghai" />
|
||||
<el-option label="Zone two" value="beijing" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="转归日期" style="width: 100%">
|
||||
<el-date-picker
|
||||
v-model="diagnoseform.user"
|
||||
type="date"
|
||||
placeholder="转归日期"
|
||||
clearable
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12"> </el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="主诊断" style="width: 100%">
|
||||
<el-checkbox v-model="diagnoseform.checked1" label="" size="large" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="疑似诊断">
|
||||
<el-checkbox v-model="diagnoseform.checked1" label="" size="large" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="复诊">
|
||||
<el-checkbox v-model="diagnoseform.checked1" label="" size="large" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="子诊断">
|
||||
<el-checkbox v-model="diagnoseform.checked1" label="" size="large" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button size="fixed" class="margin-left-auto" @click="cancelAct">取消 </el-button>
|
||||
<el-button size="fixed" type="primary" @click="handleSubmit(signFormRef)">保存</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script setup>
|
||||
import {onMounted, reactive, ref} from 'vue'
|
||||
|
||||
const currentInPatient = ref({})
|
||||
const initCurrentInPatient = () => {
|
||||
currentInPatient.value = {
|
||||
feeType: '08',
|
||||
sexName: '男',
|
||||
age: '0',
|
||||
}
|
||||
}
|
||||
/* 初始化数据 */
|
||||
const init = () => {
|
||||
initCurrentInPatient()
|
||||
}
|
||||
|
||||
/* 入科 */
|
||||
const diagnoseform = ref({
|
||||
user: '',
|
||||
checked1: '',
|
||||
})
|
||||
const rules = reactive({
|
||||
admittedDoctor: [{ required: true, message: '请选择住院医生', trigger: ['blur', 'change'] }],
|
||||
masterNurse: [{ required: true, message: '请选择责任护士', trigger: ['blur', 'change'] }],
|
||||
})
|
||||
const printWristband = ref(false)
|
||||
const emits = defineEmits(['okAct'])
|
||||
|
||||
const visible = defineModel('visible')
|
||||
const width = '600px'
|
||||
|
||||
/* 取消 */
|
||||
const cancelAct = () => {
|
||||
visible.value = false
|
||||
}
|
||||
/* 录入患者体征*/
|
||||
const signFormRef = ref()
|
||||
const handleSubmit = async (formEl) => {
|
||||
if (!formEl) return
|
||||
await formEl.validate((valid, fields) => {
|
||||
if (valid) {
|
||||
console.log('submit!')
|
||||
try {
|
||||
// 录入患者体征方法(signForm.value).then((res: any) => {
|
||||
// ElMessage({
|
||||
// message: '登记成功!',
|
||||
// type: 'success',
|
||||
// grouping: true,
|
||||
// showClose: true,
|
||||
// })
|
||||
// emits('okAct')
|
||||
// })
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
const openAct = () => {
|
||||
init()
|
||||
}
|
||||
const closedAct = () => {
|
||||
visible.value = false
|
||||
}
|
||||
onMounted(() => {})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.transferIn-container {
|
||||
width: 100%;
|
||||
|
||||
.admission-signs,
|
||||
.admission-information {
|
||||
width: 888px;
|
||||
.unit {
|
||||
display: inline-block;
|
||||
margin-left: 10px;
|
||||
color: #bbb;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
font-family: '思源黑体 CN';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.print-wriBtn {
|
||||
margin-left: 565px;
|
||||
}
|
||||
|
||||
.w-p100 {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.w-80 {
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
.mb-90 {
|
||||
margin-bottom: 90px !important;
|
||||
}
|
||||
</style>
|
||||
@@ -1,700 +0,0 @@
|
||||
<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">
|
||||
总金额:{{ 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(); calculateTotalAmount(); }"
|
||||
@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(); calculateTotalAmount(); }"
|
||||
@keyup.enter.prevent="handleEnter('dose')"
|
||||
/>
|
||||
</el-form-item>
|
||||
<!-- 全部单位 -->
|
||||
<el-select
|
||||
v-model="row.doseUnitCode"
|
||||
style="width: 70px"
|
||||
placeholder=" "
|
||||
@change="() => { convertValues(); calculateTotalAmount(); }"
|
||||
>
|
||||
<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)"
|
||||
@input="calculateTotalAmount"
|
||||
@keyup.enter.prevent="handleEnter('firstDose')"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-select v-model="row.doseUnitCode" style="width: 70px" placeholder=" ">
|
||||
<el-option
|
||||
v-for="item in row.unitCodeList"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
:key="item.value"
|
||||
/>
|
||||
</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 }}
|
||||
<template v-if="row.unitPrice != null && row.unitPrice !== ''">
|
||||
(¥{{ Number(row.unitPrice).toFixed(2) }}元)
|
||||
</template>
|
||||
</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="orgTreeData"
|
||||
:props="{ value: 'id', label: 'name', children: 'children' }"
|
||||
value-key="id"
|
||||
check-strictly
|
||||
default-expand-all
|
||||
:fallback-option="orgFallbackOption"
|
||||
@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 {computed, getCurrentInstance, nextTick, onMounted, ref, watch} from 'vue';
|
||||
import Decimal from 'decimal.js';
|
||||
|
||||
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);
|
||||
|
||||
// 🔧 关键修复:计算属性,确保当前行的 orgId 始终存在于树数据中
|
||||
// 当 orgId 不在科室树中时,注入一个临时节点,让 el-tree-select 能正确显示中文名称
|
||||
const orgTreeData = computed(() => {
|
||||
const tree = props.config.organization || [];
|
||||
const orgId = props.row?.orgId;
|
||||
const orgName = props.row?.orgName || props.row?.positionName;
|
||||
if (!orgId || !orgName) return tree;
|
||||
|
||||
// 检查 orgId 是否已在树中存在
|
||||
const existsInTree = findOrgName(orgId);
|
||||
if (existsInTree) return tree;
|
||||
|
||||
// 注入临时节点到树根层级
|
||||
return [...tree, { id: String(orgId), name: orgName, children: [] }];
|
||||
});
|
||||
|
||||
// 🔧 从 organization 树中根据 orgId 查找科室名称(供 fallback-option 使用)
|
||||
function findOrgName(orgId: any): string {
|
||||
if (!orgId || !props.config.organization || props.config.organization.length === 0) return '';
|
||||
const strId = String(orgId);
|
||||
function walk(nodes: any[]): string {
|
||||
if (!nodes) return '';
|
||||
for (const node of nodes) {
|
||||
if (String(node.id) === strId) return node.name;
|
||||
// 模糊匹配:处理大 Long 精度丢失的情况
|
||||
if (typeof node.id === 'string' && node.id.length >= 16 && strId.length >= 16
|
||||
&& node.id.substring(0, 15) === strId.substring(0, 15)) {
|
||||
return node.name;
|
||||
}
|
||||
if (node.children) {
|
||||
const found = walk(node.children);
|
||||
if (found) return found;
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
return walk(props.config.organization);
|
||||
}
|
||||
|
||||
// 🔧 el-tree-select 的 fallback-option:当 orgId 匹配不到树节点时,
|
||||
// 仍然显示对应的中文科室名称而非原始数字 ID
|
||||
// 优先从科室树查找,其次用 row 上保存的 orgName/positionName 兜底
|
||||
const orgFallbackOption = (value: any) => {
|
||||
const name = findOrgName(value);
|
||||
const fallbackName = props.row?.orgName || props.row?.positionName;
|
||||
return { label: name || fallbackName || value, value };
|
||||
};
|
||||
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);
|
||||
// 直接用 row 计算总金额:数量 * 单价,避免父组件索引不匹配的问题
|
||||
const calculateTotalAmount = () => {
|
||||
nextTick(() => {
|
||||
const row = props.row;
|
||||
const qty = new Decimal(row.doseQuantity || 0);
|
||||
// 根据首次用量单位类型决定使用哪个单价
|
||||
const unitType = row.unitCodeList?.find((k) => k.value == row.doseUnitCode)?.type;
|
||||
const price = unitType == 'unit' ? row.unitPrice : row.minUnitPrice;
|
||||
const roundedPrice = new Decimal(price || 0).toDecimalPlaces(2, Decimal.ROUND_HALF_UP);
|
||||
row.totalPrice = qty.mul(roundedPrice).toDecimalPlaces(2, Decimal.ROUND_HALF_UP).toString();
|
||||
});
|
||||
};
|
||||
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>
|
||||
@@ -1,123 +0,0 @@
|
||||
import request from '@/utils/request';
|
||||
// 申请单相关接口
|
||||
|
||||
// 手术项目专用分页查询(仅手术 + 定价,无库存/草稿库存等无关逻辑)
|
||||
export function getSurgeryPage(params) {
|
||||
return request({
|
||||
url: '/doctor-station/advice/surgery-page',
|
||||
method: 'get',
|
||||
params: params,
|
||||
});
|
||||
}
|
||||
|
||||
// 检查项目专用分页查询(仅检查(23) + 定价,绕过 AOP 校验提升加载速度)
|
||||
export function getExaminationPage(params) {
|
||||
return request({
|
||||
url: '/doctor-station/advice/examination-page',
|
||||
method: 'get',
|
||||
params: params,
|
||||
});
|
||||
}
|
||||
|
||||
//医嘱大下拉
|
||||
export function getApplicationList(queryParams) {
|
||||
return request({
|
||||
url: '/doctor-station/advice/advice-base-info',
|
||||
method: 'get',
|
||||
params: queryParams,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 保存检查申请单
|
||||
*/
|
||||
export function saveCheckd(data) {
|
||||
return request({
|
||||
url: '/reg-doctorstation/request-form/save-check',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 保存检验申请单
|
||||
*/
|
||||
export function saveInspection(data) {
|
||||
return request({
|
||||
url: '/reg-doctorstation/request-form/save-inspection',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 保存输血申请单
|
||||
*/
|
||||
export function saveBloodTransfusio(data) {
|
||||
return request({
|
||||
url: '/reg-doctorstation/request-form/save-blood-transfusion',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 保存手术申请单
|
||||
*/
|
||||
export function saveSurgery(data) {
|
||||
return request({
|
||||
url: '/reg-doctorstation/request-form/save-surgery',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
// =====
|
||||
|
||||
/**
|
||||
* 查询检查申请单
|
||||
*/
|
||||
export function getCheck(data) {
|
||||
return request({
|
||||
url: '/reg-doctorstation/request-form/get-check',
|
||||
method: 'get',
|
||||
params: data,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 查询检验申请单
|
||||
*/
|
||||
export function getInspection(data) {
|
||||
return request({
|
||||
url: '/reg-doctorstation/request-form/get-inspection',
|
||||
method: 'get',
|
||||
params: data,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 查询输血申请单
|
||||
*/
|
||||
export function getBloodTransfusion(data) {
|
||||
return request({
|
||||
url: '/reg-doctorstation/request-form/get-blood-transfusion',
|
||||
method: 'get',
|
||||
params: data,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 查询手术申请单
|
||||
*/
|
||||
export function getSurgery(data) {
|
||||
return request({
|
||||
url: '/reg-doctorstation/request-form/get-surgery',
|
||||
method: 'get',
|
||||
params: data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 住院患者转科
|
||||
*/
|
||||
export function transferOrganization(data) {
|
||||
return request({
|
||||
url: '/reg-doctorstation/special-advice/transfer-organization-orders',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
@@ -1,168 +0,0 @@
|
||||
<!--
|
||||
* @Author: sjjh
|
||||
* @Date: 2025-09-05 22:32:17
|
||||
* @Description: 申请单 (检验、检查、输血、手术)
|
||||
-->
|
||||
<template>
|
||||
<div>
|
||||
<div class="applicationForm-bottom-btn">
|
||||
<el-button-group>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="showApplicationFormDialog('LaboratoryTests')"
|
||||
:disabled="!props.patientInfo?.inHospitalOrgId"
|
||||
>检验</el-button
|
||||
>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="showApplicationFormDialog('MedicalExaminations')"
|
||||
:disabled="!props.patientInfo?.inHospitalOrgId"
|
||||
>检查</el-button
|
||||
>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="showApplicationFormDialog('BloodTransfusion')"
|
||||
:disabled="!props.patientInfo?.inHospitalOrgId"
|
||||
>输血</el-button
|
||||
>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="showApplicationFormDialog('Surgery')"
|
||||
:disabled="!props.patientInfo?.inHospitalOrgId"
|
||||
>手术</el-button
|
||||
>
|
||||
</el-button-group>
|
||||
</div>
|
||||
<el-dialog
|
||||
v-model="applicationFormDialogVisible"
|
||||
destroy-on-close
|
||||
width="1200px"
|
||||
:close-on-click-modal="false"
|
||||
:title="applicationFormTitle"
|
||||
@close="closeDialog"
|
||||
>
|
||||
<component
|
||||
:is="applicationFormName"
|
||||
@submitOk="submitOk"
|
||||
ref="applicationFormNameRef"
|
||||
></component>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="applicationFormDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="submitApplicationForm"> 确认 </el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import {computed, getCurrentInstance, nextTick, onBeforeMount, onMounted, reactive, ref,} from 'vue';
|
||||
import BloodTransfusion from './bloodTransfusion.vue';
|
||||
import Surgery from './surgery.vue';
|
||||
import LaboratoryTests from './laboratoryTests.vue';
|
||||
import MedicalExaminations from './medicalExaminations.vue';
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
const emits = defineEmits(['refResh']);
|
||||
const props = defineProps({
|
||||
patientInfo: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
const state = reactive({});
|
||||
const components = ref({
|
||||
BloodTransfusion,
|
||||
Surgery,
|
||||
LaboratoryTests,
|
||||
MedicalExaminations,
|
||||
});
|
||||
const applicationFormName = ref(null);
|
||||
const applicationFormDialogVisible = ref(false);
|
||||
const applicationFormTitle = computed(() => {
|
||||
const titleMap = {
|
||||
BloodTransfusion: '输血申请单',
|
||||
Surgery: '手术申请单',
|
||||
LaboratoryTests: '检验申请单',
|
||||
MedicalExaminations: '检查申请单',
|
||||
};
|
||||
return titleMap[applicationFormName.value?.name] || '申请单';
|
||||
});
|
||||
|
||||
const closeDialog = () => {
|
||||
applicationFormName.value = null;
|
||||
applicationFormDialogVisible.value = false;
|
||||
};
|
||||
const showApplicationFormDialog = (name) => {
|
||||
if (!components.value[name]) {
|
||||
console.warn(`未找到组件: ${name}`);
|
||||
return;
|
||||
}
|
||||
// 如果点击的是当前已打开的组件,则关闭
|
||||
if (applicationFormName.value === components.value[name]) {
|
||||
applicationFormDialogVisible.value = false;
|
||||
applicationFormName.value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果当前弹窗已打开,先关闭当前弹窗,延迟后打开新的弹窗
|
||||
if (applicationFormDialogVisible.value) {
|
||||
applicationFormDialogVisible.value = false;
|
||||
setTimeout(() => {
|
||||
applicationFormName.value = components.value[name];
|
||||
applicationFormDialogVisible.value = true;
|
||||
// 列表(项目列表)
|
||||
applicationFormNameRef?.value.getList?.();
|
||||
// 科室列表
|
||||
applicationFormNameRef?.value.getLocationInfo();
|
||||
// 诊断目录列表
|
||||
applicationFormNameRef?.value.getDiagnosisList();
|
||||
}, 150);
|
||||
} else {
|
||||
applicationFormName.value = components.value[name];
|
||||
applicationFormDialogVisible.value = true;
|
||||
nextTick(() => {
|
||||
// 列表(项目列表)
|
||||
applicationFormNameRef?.value.getList?.();
|
||||
// 科室列表
|
||||
applicationFormNameRef?.value.getLocationInfo();
|
||||
// 诊断目录列表
|
||||
applicationFormNameRef?.value.getDiagnosisList();
|
||||
});
|
||||
}
|
||||
};
|
||||
onBeforeMount(() => {});
|
||||
onMounted(() => {});
|
||||
const applicationFormNameRef = ref();
|
||||
const submitApplicationForm = () => {
|
||||
console.log(applicationFormNameRef.value);
|
||||
|
||||
if (applicationFormNameRef.value?.submit) {
|
||||
applicationFormNameRef.value.submit();
|
||||
}
|
||||
};
|
||||
const submitOk = () => {
|
||||
applicationFormDialogVisible.value = false;
|
||||
applicationFormName.value = null;
|
||||
// 🔧 BugFix#318: 延迟刷新,确保后端数据已提交
|
||||
setTimeout(() => {
|
||||
emits('refResh');
|
||||
}, 500);
|
||||
};
|
||||
defineExpose({ state });
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.applicationForm-bottom-btn {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 8px 0;
|
||||
|
||||
.el-button-group {
|
||||
.el-button {
|
||||
margin: 0 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,570 +0,0 @@
|
||||
<!--
|
||||
* @Author: sjjh
|
||||
* @Date: 2025-09-05 22:37:10
|
||||
* @Description: 输血申请
|
||||
-->
|
||||
<template>
|
||||
<div class="bloodTransfusion-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-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="targetDepartment" style="width: 100%">
|
||||
<el-select
|
||||
v-model="form.targetDepartment"
|
||||
filterable
|
||||
clearable
|
||||
placeholder="请选择科室"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="opt in flatOrgOptions"
|
||||
:key="opt.value"
|
||||
:label="opt.label"
|
||||
:value="opt.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<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="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="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="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="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="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>
|
||||
</template>
|
||||
<script setup name="BloodTransfusion">
|
||||
import {computed, getCurrentInstance, nextTick, onBeforeMount, onMounted, reactive, ref, watch} from 'vue';
|
||||
import {ElMessage} from 'element-plus';
|
||||
import {patientInfo} from '../../../store/patient.js';
|
||||
import {getDepartmentList} from '@/api/public.js';
|
||||
import request from '@/utils/request';
|
||||
import {getDiagnosisTreatmentOne} from '@/views/catalog/diagnosistreatment/components/diagnosistreatment';
|
||||
import {getEncounterDiagnosis} from '../../api.js';
|
||||
import {getApplicationList, saveBloodTransfusio} from './api';
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
|
||||
/** 科室树节点 id 统一为字符串,避免大整数精度丢失导致 tree-select 无法匹配 */
|
||||
const normalizeOrgTreeIds = (nodes) => {
|
||||
if (!Array.isArray(nodes)) return [];
|
||||
return nodes.map((node) => ({
|
||||
...node,
|
||||
id: node.id != null ? String(node.id) : node.id,
|
||||
children: node.children?.length ? normalizeOrgTreeIds(node.children) : undefined,
|
||||
}));
|
||||
};
|
||||
|
||||
// 递归查找树形科室节点
|
||||
const findTreeItem = (list, id) => {
|
||||
if (!list || list.length === 0 || id == null || id === '') return null;
|
||||
const strId = String(id);
|
||||
for (const item of list) {
|
||||
if (String(item.id) === strId) return item;
|
||||
if (item.children && item.children.length > 0) {
|
||||
const found = findTreeItem(item.children, id);
|
||||
if (found) return found;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
/** 在科室树中解析 orgId(兼容 Long 转 Number 后的精度丢失) */
|
||||
const resolveOrgIdInTree = (rawOrgId) => {
|
||||
if (rawOrgId == null || rawOrgId === '') return '';
|
||||
const strOrgId = String(rawOrgId);
|
||||
const findInTree = (nodes) => {
|
||||
if (!nodes?.length) return null;
|
||||
for (const node of nodes) {
|
||||
if (String(node.id) === strOrgId) return String(node.id);
|
||||
if (
|
||||
typeof node.id === 'string' &&
|
||||
node.id.length >= 16 &&
|
||||
strOrgId.length >= 16 &&
|
||||
node.id.substring(0, 15) === strOrgId.substring(0, 15)
|
||||
) {
|
||||
return String(node.id);
|
||||
}
|
||||
if (node.children?.length) {
|
||||
const found = findInTree(node.children);
|
||||
if (found) return found;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
return findInTree(orgOptions.value) || strOrgId;
|
||||
};
|
||||
|
||||
const resolveTargetDepartmentId = (rawId) => {
|
||||
if (rawId == null || rawId === '') return '';
|
||||
const resolved = resolveOrgIdInTree(rawId);
|
||||
const node = findTreeItem(orgOptions.value, resolved);
|
||||
return node ? String(node.id) : resolved;
|
||||
};
|
||||
|
||||
/** 诊疗目录「所属科室」→ AdviceBaseDto.orgId */
|
||||
const getBelongingOrgId = (item) => {
|
||||
if (!item) return null;
|
||||
return item.orgId ?? item.org_id ?? null;
|
||||
};
|
||||
|
||||
/** 诊疗目录所属科室名称(字典翻译字段) */
|
||||
const getBelongingOrgName = (item) => {
|
||||
if (!item) return '';
|
||||
return item.orgId_dictText || item.orgName || item.org_name || '';
|
||||
};
|
||||
|
||||
/** 按机构 ID 拉取科室名称(树中无节点时兜底) */
|
||||
const fetchOrgNameById = async (orgId) => {
|
||||
if (orgId == null || orgId === '') return '';
|
||||
const fromTree = findOrgName(orgId);
|
||||
if (fromTree) return fromTree;
|
||||
try {
|
||||
const res = await request({
|
||||
url: '/base-data-manage/organization/organization-getById',
|
||||
method: 'get',
|
||||
params: { orgId },
|
||||
});
|
||||
if (res.code === 200 && res.data?.name) {
|
||||
return res.data.name;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('查询科室名称失败', e);
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
/** 从机构树解析科室名称 */
|
||||
const findOrgName = (orgId) => {
|
||||
if (orgId == null || orgId === '') return '';
|
||||
const node = findTreeItem(orgOptions.value, orgId);
|
||||
if (node?.name) return node.name;
|
||||
const resolved = resolveOrgIdInTree(orgId);
|
||||
const resolvedNode = findTreeItem(orgOptions.value, resolved);
|
||||
return resolvedNode?.name || '';
|
||||
};
|
||||
|
||||
/** 自动填充时缓存的科室名称 */
|
||||
const targetDepartmentName = ref('');
|
||||
|
||||
/** 扁平化科室选项,保证 el-select 能稳定显示 label */
|
||||
const flatOrgOptions = computed(() => {
|
||||
const options = [];
|
||||
const seen = new Set();
|
||||
const walk = (nodes) => {
|
||||
for (const node of nodes || []) {
|
||||
if (node?.id == null) continue;
|
||||
const value = String(node.id);
|
||||
if (seen.has(value)) continue;
|
||||
seen.add(value);
|
||||
options.push({ value, label: node.name || value });
|
||||
if (node.children?.length) walk(node.children);
|
||||
}
|
||||
};
|
||||
walk(orgOptions.value);
|
||||
const curId = form.targetDepartment;
|
||||
const curName = targetDepartmentName.value || findOrgName(curId);
|
||||
if (curId && curName && !seen.has(String(curId))) {
|
||||
options.unshift({ value: String(curId), label: curName });
|
||||
}
|
||||
return options;
|
||||
});
|
||||
|
||||
/** 从诊疗目录详情补全所属科室(医嘱下拉接口不带 orgId_dictText) */
|
||||
const resolveProjectOrgInfo = async (item) => {
|
||||
if (!item) return { orgId: null, orgName: '' };
|
||||
let orgId = getBelongingOrgId(item);
|
||||
let orgName = getBelongingOrgName(item);
|
||||
if ((!orgId || !orgName) && item.adviceDefinitionId) {
|
||||
try {
|
||||
const res = await getDiagnosisTreatmentOne(item.adviceDefinitionId);
|
||||
const detail = res?.data;
|
||||
if (detail) {
|
||||
orgId = orgId ?? detail.orgId ?? detail.org_id ?? null;
|
||||
orgName = orgName || detail.orgId_dictText || detail.orgName || '';
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('查询诊疗目录所属科室失败', e);
|
||||
}
|
||||
}
|
||||
if (orgId && !orgName) {
|
||||
orgName = await fetchOrgNameById(orgId);
|
||||
}
|
||||
return { orgId, orgName };
|
||||
};
|
||||
|
||||
/** 写入发往科室 */
|
||||
const applyTargetDepartment = async (belongOrgId, nameHint = '') => {
|
||||
if (belongOrgId == null || belongOrgId === '') {
|
||||
form.targetDepartment = '';
|
||||
targetDepartmentName.value = '';
|
||||
return;
|
||||
}
|
||||
const resolvedDeptId = resolveTargetDepartmentId(belongOrgId);
|
||||
const deptName =
|
||||
nameHint || findOrgName(belongOrgId) || findOrgName(resolvedDeptId) || (await fetchOrgNameById(belongOrgId));
|
||||
targetDepartmentName.value = deptName;
|
||||
form.targetDepartment = resolvedDeptId;
|
||||
};
|
||||
const emits = defineEmits(['submitOk']);
|
||||
const props = defineProps({});
|
||||
const state = reactive({});
|
||||
const applicationListAll = ref([]);
|
||||
const applicationList = ref([]);
|
||||
const loading = ref(false);
|
||||
const orgOptions = ref([]); // 科室选项
|
||||
const getList = () => {
|
||||
if (!patientInfo.value?.inHospitalOrgId) {
|
||||
applicationList.value = [];
|
||||
return;
|
||||
}
|
||||
loading.value = true;
|
||||
getApplicationList({
|
||||
pageSize: 500,
|
||||
pageNum: 1,
|
||||
categoryCode: '28',
|
||||
organizationId: patientInfo.value.inHospitalOrgId,
|
||||
adviceTypes: [3], //1 药品 2耗材 3诊疗
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.code === 200 && Array.isArray(res.data?.records)) {
|
||||
const records = res.data.records.filter((item) => item.adviceDefinitionId != null);
|
||||
applicationListAll.value = records;
|
||||
applicationList.value = records.map((item) => {
|
||||
const priceInfo = item.priceList?.[0] || {};
|
||||
const price = priceInfo.price != null ? Number(priceInfo.price).toFixed(2) : '0.00';
|
||||
const unit = item.unitCode_dictText || item.unitCode || '';
|
||||
const id = item.adviceDefinitionId;
|
||||
return {
|
||||
adviceDefinitionId: id,
|
||||
orgId: item.orgId,
|
||||
label: item.adviceName + ' (¥' + price + '/' + unit + ')',
|
||||
key: id,
|
||||
};
|
||||
});
|
||||
} else {
|
||||
proxy.$message.error(res.message || '加载输血项目失败');
|
||||
applicationListAll.value = [];
|
||||
applicationList.value = [];
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
if (transferValue.value.length > 0) {
|
||||
nextTick(async () => {
|
||||
const valid = await validateTransferOrgConsistency(transferValue.value);
|
||||
if (valid) {
|
||||
lastValidTransferValue.value = [...transferValue.value];
|
||||
fillTargetDepartmentFromSelection(transferValue.value, 1);
|
||||
} else {
|
||||
transferValue.value = [];
|
||||
lastValidTransferValue.value = [];
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
const transferValue = ref([]);
|
||||
/** 上一次通过校验的已选项目(科室不一致时回滚到此状态) */
|
||||
const lastValidTransferValue = ref([]);
|
||||
const isRevertingTransfer = ref(false);
|
||||
let transferValidateSeq = 0;
|
||||
const form = reactive({
|
||||
// categoryType: '', // 项目类别
|
||||
targetDepartment: '', // 发往科室
|
||||
symptom: '', // 症状
|
||||
sign: '', // 体征
|
||||
clinicalDiagnosis: '', // 临床诊断
|
||||
otherDiagnosis: '', // 其他诊断
|
||||
relatedResult: '', // 相关结果
|
||||
attention: '', // 注意事项
|
||||
primaryDiagnosisList: [], //主诊断目录
|
||||
otherDiagnosisList: [], //其他断目录
|
||||
});
|
||||
const rules = reactive({});
|
||||
onBeforeMount(() => {});
|
||||
onMounted(() => {
|
||||
getList();
|
||||
getLocationInfo();
|
||||
});
|
||||
const collectSelectedProjects = (selectProjectIds) => {
|
||||
return (selectProjectIds || [])
|
||||
.map((element) =>
|
||||
applicationListAll.value.find((item) => String(item.adviceDefinitionId) === String(element))
|
||||
)
|
||||
.filter(Boolean);
|
||||
};
|
||||
|
||||
/** 校验已选项目的所属科室是否一致(超过 1 项时才校验) */
|
||||
const validateTransferOrgConsistency = async (selectProjectIds) => {
|
||||
const arr = collectSelectedProjects(selectProjectIds);
|
||||
if (arr.length <= 1) {
|
||||
return true;
|
||||
}
|
||||
const orgInfoList = await Promise.all(arr.map((item) => resolveProjectOrgInfo(item)));
|
||||
const firstOrgId = orgInfoList[0]?.orgId;
|
||||
return orgInfoList.every((info) => String(info?.orgId ?? '') === String(firstOrgId ?? ''));
|
||||
};
|
||||
|
||||
/**
|
||||
* type(1:watch监听类型 2:点击保存类型)
|
||||
*/
|
||||
const fillTargetDepartmentFromSelection = async (selectProjectIds, type) => {
|
||||
const manualDept = type === 2 && form.targetDepartment ? form.targetDepartment : '';
|
||||
const arr = collectSelectedProjects(selectProjectIds);
|
||||
|
||||
if (arr.length === 0) {
|
||||
// 项目列表尚未加载完时,已选 ID 存在则先不清空(避免误清发往科室)
|
||||
if ((selectProjectIds || []).length > 0 && applicationListAll.value.length === 0) {
|
||||
return type === 2 ? !!manualDept : true;
|
||||
}
|
||||
form.targetDepartment = '';
|
||||
targetDepartmentName.value = '';
|
||||
return type === 2 ? !!manualDept : true;
|
||||
}
|
||||
|
||||
const orgInfoList = await Promise.all(arr.map((item) => resolveProjectOrgInfo(item)));
|
||||
const firstOrg = orgInfoList[0];
|
||||
const belongOrgId = firstOrg?.orgId;
|
||||
const allSameOrg = orgInfoList.every((info) => String(info?.orgId ?? '') === String(belongOrgId ?? ''));
|
||||
if (!allSameOrg) {
|
||||
if (type === 2) {
|
||||
ElMessage.error('所选项目的所属科室不一致,请分开申请');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (belongOrgId == null || belongOrgId === '') {
|
||||
if (type === 2 && manualDept) {
|
||||
await applyTargetDepartment(manualDept, findOrgName(manualDept));
|
||||
return true;
|
||||
}
|
||||
if (type === 2) {
|
||||
ElMessage.warning('所选项目未在诊疗目录配置所属科室,请手动选择发往科室');
|
||||
return false;
|
||||
}
|
||||
form.targetDepartment = '';
|
||||
targetDepartmentName.value = '';
|
||||
return true;
|
||||
}
|
||||
|
||||
if (type === 2 && manualDept) {
|
||||
await applyTargetDepartment(manualDept, findOrgName(manualDept));
|
||||
return true;
|
||||
}
|
||||
|
||||
await applyTargetDepartment(belongOrgId, firstOrg?.orgName || '');
|
||||
return true;
|
||||
};
|
||||
|
||||
// 选中项目:先校验所属科室一致,不通过则回滚穿梭框,不允许进入「已选择」
|
||||
watch(
|
||||
() => transferValue.value,
|
||||
async (newValue) => {
|
||||
if (isRevertingTransfer.value) return;
|
||||
|
||||
const seq = ++transferValidateSeq;
|
||||
const valid = await validateTransferOrgConsistency(newValue);
|
||||
if (seq !== transferValidateSeq) return;
|
||||
|
||||
if (!valid) {
|
||||
ElMessage.error('所选项目的所属科室不一致,请分开申请');
|
||||
isRevertingTransfer.value = true;
|
||||
transferValue.value = [...lastValidTransferValue.value];
|
||||
await nextTick();
|
||||
isRevertingTransfer.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
lastValidTransferValue.value = [...newValue];
|
||||
await fillTargetDepartmentFromSelection(newValue, 1);
|
||||
}
|
||||
);
|
||||
|
||||
watch(
|
||||
() => orgOptions.value,
|
||||
() => {
|
||||
if (transferValue.value.length > 0) {
|
||||
nextTick(() => {
|
||||
fillTargetDepartmentFromSelection(transferValue.value, 1);
|
||||
});
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
const submit = async () => {
|
||||
if (transferValue.value.length == 0) {
|
||||
return proxy.$message.error('请选择申请单');
|
||||
}
|
||||
if (!(await fillTargetDepartmentFromSelection(transferValue.value, 2))) {
|
||||
return;
|
||||
}
|
||||
if (!form.targetDepartment) {
|
||||
return proxy.$message.error('请选择发往科室');
|
||||
}
|
||||
let applicationListAllFilter = applicationListAll.value.filter((item) => {
|
||||
return transferValue.value.some((id) => String(id) === String(item.adviceDefinitionId));
|
||||
});
|
||||
applicationListAllFilter = applicationListAllFilter.map((item) => {
|
||||
const priceInfo = item.priceList?.[0] || {};
|
||||
return {
|
||||
adviceDefinitionId: item.adviceDefinitionId /** 诊疗定义id */,
|
||||
quantity: 1, // /** 请求数量 */
|
||||
unitCode: priceInfo.unitCode /** 请求单位编码 */,
|
||||
unitPrice: priceInfo.price /** 单价 */,
|
||||
totalPrice: priceInfo.price /** 总价 */,
|
||||
positionId: form.targetDepartment || item.positionId, //执行科室id
|
||||
ybClassEnum: item.ybClassEnum, //类别医保编码
|
||||
conditionId: item.conditionId, //诊断ID
|
||||
encounterDiagnosisId: item.encounterDiagnosisId, //就诊诊断id
|
||||
adviceType: item.adviceType, ///** 医嘱类型 */
|
||||
definitionId: priceInfo.definitionId, //费用定价主表ID */
|
||||
definitionDetailId: item.definitionDetailId, //费用定价子表ID */
|
||||
accountId: patientInfo.value.accountId, // // 账户id
|
||||
};
|
||||
});
|
||||
saveBloodTransfusio({
|
||||
activityList: applicationListAllFilter,
|
||||
patientId: patientInfo.value.patientId, //患者ID
|
||||
encounterId: patientInfo.value.encounterId, // 就诊ID
|
||||
organizationId: patientInfo.value.inHospitalOrgId, // 医疗机构ID
|
||||
requestFormId: '', // 申请单ID
|
||||
name: '输血申请单',
|
||||
descJson: JSON.stringify(form),
|
||||
categoryEnum: '23', // 21 检验 22 检查 23 输血 24 手术(避开 adviceType 1-6 碰撞)
|
||||
}).then((res) => {
|
||||
if (res.code === 200) {
|
||||
proxy.$message.success(res.msg);
|
||||
applicationList.value = [];
|
||||
applicationListAll.value = [];
|
||||
transferValue.value = [];
|
||||
lastValidTransferValue.value = [];
|
||||
emits('submitOk');
|
||||
} else {
|
||||
proxy.$message.error(res.message);
|
||||
}
|
||||
});
|
||||
};
|
||||
/** 查询科室(与检验申请单一致) */
|
||||
const getLocationInfo = () => {
|
||||
return getDepartmentList().then((res) => {
|
||||
orgOptions.value = normalizeOrgTreeIds(res?.data || []);
|
||||
if (transferValue.value.length > 0) {
|
||||
nextTick(() => fillTargetDepartmentFromSelection(transferValue.value, 1));
|
||||
}
|
||||
});
|
||||
};
|
||||
// 获取诊断目录
|
||||
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, getList });
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.bloodTransfusion-container {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
.transfer-wrapper {
|
||||
position: relative;
|
||||
min-height: 300px;
|
||||
}
|
||||
|
||||
:deep(.el-transfer) {
|
||||
--el-transfer-panel-width: 480px !important;
|
||||
display: flex !important;
|
||||
flex-direction: row !important;
|
||||
}
|
||||
|
||||
:deep(.el-transfer__buttons) {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
:deep(.el-transfer__button) {
|
||||
margin: 4px 0;
|
||||
}
|
||||
|
||||
.bloodTransfusion-form {
|
||||
padding: 8px 8px 0 8px;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,604 +0,0 @@
|
||||
<!--
|
||||
* @Author: sjjh
|
||||
* @Date: 2025-09-05 22:31:58
|
||||
* @Description: 检验
|
||||
-->
|
||||
<template>
|
||||
<div class="LaboratoryTests-container">
|
||||
<div v-loading="loading" class="transfer-wrapper">
|
||||
<!-- 远程搜索框 -->
|
||||
<div class="search-bar">
|
||||
<el-input
|
||||
v-model="searchKey"
|
||||
placeholder="输入项目代码/名称搜索"
|
||||
clearable
|
||||
@keyup.enter="handleSearch"
|
||||
@clear="handleSearch"
|
||||
style="width: 300px; margin-bottom: 10px"
|
||||
>
|
||||
<template #append>
|
||||
<el-button @click="handleSearch" :loading="loading">搜索</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
<span class="total-count">共 {{ totalCount }} 项</span>
|
||||
</div>
|
||||
<el-transfer
|
||||
v-model="transferValue"
|
||||
:data="transferData"
|
||||
: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="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="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="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="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="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="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="attention" style="width: 100%">
|
||||
<el-input v-model="form.attention" autocomplete="off" type="textarea" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<!-- 申请类型 -->
|
||||
<el-col :span="12">
|
||||
<el-form-item label="申请类型" prop="applicationType" style="width: 100%">
|
||||
<el-radio-group v-model="form.applicationType">
|
||||
<el-radio :value="0">普通</el-radio>
|
||||
<el-radio :value="1">急诊</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<!-- 标本类型 -->
|
||||
<el-col :span="12">
|
||||
<el-form-item label="标本类型" prop="specimenName" style="width: 100%">
|
||||
<el-select v-model="form.specimenName" placeholder="请选择标本类型" style="width: 100%">
|
||||
<el-option label="血液" value="血液" />
|
||||
<el-option label="尿液" value="尿液" />
|
||||
<el-option label="粪便" value="粪便" />
|
||||
<el-option label="痰液" value="痰液" />
|
||||
<el-option label="咽拭子" value="咽拭子" />
|
||||
<el-option label="脑脊液" value="脑脊液" />
|
||||
<el-option label="胸腹水" value="胸腹水" />
|
||||
<el-option label="关节液" value="关节液" />
|
||||
<el-option label="分泌物" value="分泌物" />
|
||||
<el-option label="其他" value="其他" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<!-- 执行时间 -->
|
||||
<el-col :span="12">
|
||||
<el-form-item label="执行时间" prop="executeTime" style="width: 100%">
|
||||
<el-date-picker
|
||||
v-model="form.executeTime"
|
||||
type="datetime"
|
||||
placeholder="选择执行时间"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup name="LaboratoryTests">
|
||||
import {getCurrentInstance, nextTick, onMounted, reactive, ref, watch, computed} from 'vue';
|
||||
import {patientInfo} from '../../../store/patient.js';
|
||||
import {getExaminationPage, saveInspection} from './api';
|
||||
import {ActivityCategory} from '@/utils/medicalConstants';
|
||||
import {getDepartmentList} from '@/api/public.js';
|
||||
import {getEncounterDiagnosis} from '../../api.js';
|
||||
import {ElMessage} from 'element-plus';
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
// 递归查找树形科室节点
|
||||
const findTreeItem = (list, id) => {
|
||||
if (!list || list.length === 0) return null;
|
||||
for (const item of list) {
|
||||
if (item.id == id) return item;
|
||||
if (item.children && item.children.length > 0) {
|
||||
const found = findTreeItem(item.children, id);
|
||||
if (found) return found;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
const emits = defineEmits(['submitOk']);
|
||||
const props = defineProps({
|
||||
editData: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
const isEditMode = computed(() => !!props.editData?.requestFormId);
|
||||
const state = reactive({});
|
||||
const applicationListAll = ref([]);
|
||||
const loading = ref(false);
|
||||
const orgOptions = ref([]);
|
||||
const searchKey = ref('');
|
||||
const totalCount = ref(0);
|
||||
const skipDeptAutoFill = ref(false);
|
||||
|
||||
// 将已加载的全部数据转为 transfer 组件所需的格式
|
||||
const buildTransferData = (records) => {
|
||||
return records.map((item) => {
|
||||
const price = item.price != null ? Number(item.price).toFixed(2) : '0.00';
|
||||
const unit = item.unitCodeDictText || item.unitCode || '';
|
||||
return {
|
||||
adviceDefinitionId: item.adviceDefinitionId,
|
||||
orgId: item.orgId,
|
||||
label: item.adviceName + ' (¥' + price + '/' + unit + ')',
|
||||
key: item.adviceDefinitionId,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
const selectedItemsCache = ref(new Map());
|
||||
|
||||
const loadAllData = async () => {
|
||||
if (!patientInfo.value?.inHospitalOrgId) {
|
||||
applicationListAll.value = [];
|
||||
return;
|
||||
}
|
||||
loading.value = true;
|
||||
try {
|
||||
const res = await getExaminationPage({
|
||||
pageSize: 100,
|
||||
pageNo: 1,
|
||||
categoryCode: ActivityCategory.PROOF,
|
||||
organizationId: patientInfo.value.inHospitalOrgId,
|
||||
searchKey: searchKey.value,
|
||||
});
|
||||
if (res.code !== 200) {
|
||||
proxy.$message.error(res.message);
|
||||
applicationListAll.value = [];
|
||||
return;
|
||||
}
|
||||
applicationListAll.value = res.data?.records || [];
|
||||
totalCount.value = res.data?.total || 0;
|
||||
if (!searchKey.value) {
|
||||
applyEditTransferSelection();
|
||||
}
|
||||
} catch (e) {
|
||||
proxy.$message.error('获取检验项目列表失败');
|
||||
applicationListAll.value = [];
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const transferData = computed(() => buildTransferData(applicationListAll.value));
|
||||
|
||||
const getList = async () => {
|
||||
await loadAllData();
|
||||
};
|
||||
|
||||
let searchTimer = null;
|
||||
const handleSearch = () => {
|
||||
clearTimeout(searchTimer);
|
||||
searchTimer = setTimeout(() => {
|
||||
loadAllData();
|
||||
}, 300);
|
||||
};
|
||||
// 编辑初始化标志:避免 applyEditTransferSelection 设置 transferValue 时触发 projectWithDepartment 覆盖 descJson 中的科室值
|
||||
const isInitializing = ref(false);
|
||||
const transferValue = ref([]);
|
||||
const form = reactive({
|
||||
// categoryType: '', // 项目类别
|
||||
targetDepartment: '', // 发往科室
|
||||
symptom: '', // 症状
|
||||
sign: '', // 体征
|
||||
clinicalDiagnosis: '', // 临床诊断
|
||||
otherDiagnosis: '', // 其他诊断
|
||||
relatedResult: '', // 相关结果
|
||||
attention: '', // 注意事项
|
||||
applicationType: 0, // 申请类型 0-普通 1-急诊
|
||||
specimenName: '血液', // 标本类型
|
||||
executeTime: null, // 执行时间
|
||||
primaryDiagnosisList: [], //主诊断目录
|
||||
otherDiagnosisList: [], //其他断目录
|
||||
});
|
||||
const rules = reactive({});
|
||||
|
||||
const normalizeOrgTreeIds = (nodes) => {
|
||||
if (!Array.isArray(nodes)) return [];
|
||||
return nodes.map((node) => ({
|
||||
...node,
|
||||
id: node.id != null ? String(node.id) : node.id,
|
||||
children: node.children?.length ? normalizeOrgTreeIds(node.children) : undefined,
|
||||
}));
|
||||
};
|
||||
|
||||
const resolveTargetDepartmentId = (rawId) => {
|
||||
if (rawId == null || rawId === '') return '';
|
||||
const node = findTreeItem(orgOptions.value, rawId);
|
||||
return node ? String(node.id) : String(rawId);
|
||||
};
|
||||
|
||||
const applyTargetDepartmentEcho = () => {
|
||||
if (form.targetDepartment) {
|
||||
form.targetDepartment = resolveTargetDepartmentId(form.targetDepartment);
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getLocationInfo();
|
||||
getDiagnosisList();
|
||||
getList();
|
||||
});
|
||||
/**
|
||||
* type(1:watch监听类型 2:点击保存类型)
|
||||
* selectProjectIds(选中项目的id数组)
|
||||
* */
|
||||
const projectWithDepartment = (selectProjectIds, type) => {
|
||||
//1.获取选中的项目 2.判断项目的执行科室是否相同 3.判断执行科室是否配置 4.将项目的执行科室复值到执行科室下拉选位置
|
||||
let isRelease = true;
|
||||
// 选中项目的数组
|
||||
const arr = [];
|
||||
// 根据选中的项目id查找对应的项目(从全部原始数据中查找)
|
||||
selectProjectIds.forEach((element) => {
|
||||
let searchData = applicationListAll.value.find((item) => {
|
||||
return element == item.adviceDefinitionId;
|
||||
});
|
||||
if (!searchData) {
|
||||
searchData = selectedItemsCache.value.get(element);
|
||||
}
|
||||
if (searchData) {
|
||||
const priceInfo = searchData.priceList?.[0] || {};
|
||||
const price = searchData.price != null ? Number(searchData.price).toFixed(2)
|
||||
: priceInfo.price != null ? Number(priceInfo.price).toFixed(2) : '0.00';
|
||||
const unit = searchData.unitCodeDictText || searchData.unitCode_dictText || searchData.unitCode || '';
|
||||
arr.push({
|
||||
adviceDefinitionId: searchData.adviceDefinitionId,
|
||||
orgId: searchData.orgId,
|
||||
label: searchData.adviceName + ' (¥' + price + '/' + unit + ')',
|
||||
key: searchData.adviceDefinitionId,
|
||||
});
|
||||
}
|
||||
});
|
||||
// 保存用户手动选择/回显的发往科室(提交、编辑回显时需要保留)
|
||||
const manualDept =
|
||||
type === 2 || (isEditMode.value && form.targetDepartment) ? form.targetDepartment : '';
|
||||
// 清空科室
|
||||
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 = findTreeItem(orgOptions.value, obj.orgId);
|
||||
if (!findItem) {
|
||||
// type=2(提交)时,若用户已手动选择发往科室,则允许提交
|
||||
if ((type === 2 || isEditMode.value) && manualDept) {
|
||||
form.targetDepartment = resolveTargetDepartmentId(manualDept);
|
||||
isRelease = true;
|
||||
} else if (type === 2 && !manualDept) {
|
||||
// 提交时用户未手动选择科室,才提示错误
|
||||
isRelease = false;
|
||||
ElMessage({
|
||||
type: 'error',
|
||||
message: '未找到项目执行的科室',
|
||||
});
|
||||
} else {
|
||||
// type=1(选择项目变化)时,不弹窗,仅清空科室让用户自行选择
|
||||
isRelease = false;
|
||||
}
|
||||
}
|
||||
if (findItem && isRelease) {
|
||||
// 提交时若用户已选「发往科室」,不得用项目默认执行科室覆盖
|
||||
if ((type === 2 || isEditMode.value) && manualDept) {
|
||||
form.targetDepartment = resolveTargetDepartmentId(manualDept);
|
||||
} else {
|
||||
form.targetDepartment = String(findItem.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
return isRelease;
|
||||
};
|
||||
// 监听选择项目变化
|
||||
watch(
|
||||
() => transferValue.value,
|
||||
(newValue) => {
|
||||
if (skipDeptAutoFill.value) return;
|
||||
if (isInitializing.value) return;
|
||||
newValue.forEach((id) => {
|
||||
if (!selectedItemsCache.value.has(id)) {
|
||||
const item = applicationListAll.value.find((i) => i.adviceDefinitionId == id);
|
||||
if (item) selectedItemsCache.value.set(id, item);
|
||||
}
|
||||
});
|
||||
projectWithDepartment(newValue, 1);
|
||||
}
|
||||
);
|
||||
|
||||
/** 编辑弹窗:根据申请单明细把右侧「已选择」与 transferValue 对齐(依赖 applicationListAll 已加载) */
|
||||
const applyEditTransferSelection = () => {
|
||||
const newData = props.editData
|
||||
if (!newData?.requestFormId || !newData.requestFormDetailList?.length) {
|
||||
return
|
||||
}
|
||||
if (!applicationListAll.value.length) {
|
||||
return
|
||||
}
|
||||
const selectedIds = []
|
||||
for (const detail of newData.requestFormDetailList) {
|
||||
const idFromDetail = detail.activityId ?? detail.adviceDefinitionId
|
||||
let matched = null
|
||||
if (idFromDetail != null && idFromDetail !== '') {
|
||||
matched = applicationListAll.value.find(
|
||||
(item) => String(item.adviceDefinitionId) === String(idFromDetail)
|
||||
)
|
||||
}
|
||||
if (!matched && detail.adviceName) {
|
||||
matched = applicationListAll.value.find((item) => item.adviceName === detail.adviceName)
|
||||
}
|
||||
if (!matched && detail.adviceName) {
|
||||
const norm = (s) => String(s || '').trim()
|
||||
matched = applicationListAll.value.find(
|
||||
(item) => norm(item.adviceName) === norm(detail.adviceName)
|
||||
)
|
||||
}
|
||||
if (matched) {
|
||||
selectedIds.push(matched.adviceDefinitionId)
|
||||
}
|
||||
}
|
||||
const uniq = [...new Set(selectedIds)]
|
||||
// 设置初始化标志,防止 transferValue 变化触发 projectWithDepartment 覆盖 descJson 中的科室值
|
||||
isInitializing.value = true
|
||||
skipDeptAutoFill.value = true
|
||||
transferValue.value = uniq
|
||||
nextTick(() => {
|
||||
skipDeptAutoFill.value = false
|
||||
})
|
||||
isInitializing.value = false
|
||||
if (newData.requestFormDetailList.length && uniq.length === 0) {
|
||||
console.warn(
|
||||
'[LaboratoryTests] 申请单明细未能在项目字典中匹配到项,请核对 activityId / 项目名称',
|
||||
newData.requestFormDetailList
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// 编辑模式下,回显已有数据(表单来自 descJson;项目选择在字典加载后由 applyEditTransferSelection 完成)
|
||||
watch(
|
||||
() => props.editData,
|
||||
(newData) => {
|
||||
if (!newData || !newData.requestFormId) return
|
||||
|
||||
if (newData.descJson) {
|
||||
try {
|
||||
const obj = JSON.parse(newData.descJson)
|
||||
Object.keys(form).forEach((key) => {
|
||||
if (obj[key] !== undefined) {
|
||||
form[key] = obj[key]
|
||||
}
|
||||
})
|
||||
applyTargetDepartmentEcho()
|
||||
} catch (e) {
|
||||
console.error('解析 descJson 失败:', e)
|
||||
}
|
||||
}
|
||||
|
||||
applyEditTransferSelection()
|
||||
},
|
||||
{ immediate: true, deep: true }
|
||||
)
|
||||
|
||||
watch(
|
||||
() => orgOptions.value,
|
||||
() => {
|
||||
applyTargetDepartmentEcho()
|
||||
}
|
||||
)
|
||||
|
||||
// 编辑模式下,项目字典首次加载完成后回显已选项目(搜索刷新不重置)
|
||||
watch(
|
||||
() => applicationListAll.value,
|
||||
() => {
|
||||
if (!props.editData?.requestFormId) return;
|
||||
if (!props.editData.requestFormDetailList?.length) return;
|
||||
if (!applicationListAll.value.length) return;
|
||||
if (searchKey.value) return;
|
||||
|
||||
const selectedIds = [];
|
||||
props.editData.requestFormDetailList.forEach((detail) => {
|
||||
const matched = applicationListAll.value.find(
|
||||
(item) => item.adviceName === detail.adviceName
|
||||
);
|
||||
if (matched) {
|
||||
selectedIds.push(matched.adviceDefinitionId);
|
||||
}
|
||||
});
|
||||
isInitializing.value = true;
|
||||
transferValue.value = selectedIds;
|
||||
isInitializing.value = false;
|
||||
applyEditTransferSelection();
|
||||
}
|
||||
);
|
||||
|
||||
const submit = () => {
|
||||
if (transferValue.value.length == 0) {
|
||||
return proxy.$message.error('请选择申请单');
|
||||
}
|
||||
if (!projectWithDepartment(transferValue.value, 2)) {
|
||||
return;
|
||||
}
|
||||
let applicationListAllFilter = transferValue.value.map((id) => {
|
||||
let item = applicationListAll.value.find((i) => i.adviceDefinitionId == id);
|
||||
if (!item) {
|
||||
item = selectedItemsCache.value.get(id);
|
||||
}
|
||||
if (!item) return null;
|
||||
const priceInfo = item.priceList?.[0] || {};
|
||||
return {
|
||||
adviceDefinitionId: item.adviceDefinitionId /** 诊疗定义id */,
|
||||
quantity: 1, // /** 请求数量 */
|
||||
unitCode: item.unitCode || priceInfo.unitCode || '' /** 请求单位编码 */,
|
||||
unitPrice: item.price ?? priceInfo.price ?? 0 /** 单价 */,
|
||||
totalPrice: item.price ?? priceInfo.price ?? 0 /** 总价 */,
|
||||
positionId: form.targetDepartment || item.positionId, // 用户指定发往科室优先于项目默认执行科室
|
||||
ybClassEnum: item.ybClassEnum || '', //类别医保编码
|
||||
conditionId: item.conditionId || '', //诊断ID
|
||||
encounterDiagnosisId: item.encounterDiagnosisId || '', //就诊诊断id
|
||||
adviceType: item.adviceType || 3, ///** 医嘱类型 */
|
||||
definitionId: item.chargeItemDefinitionId || priceInfo.definitionId || '', //费用定价主表ID */
|
||||
definitionDetailId: item.definitionDetailId || priceInfo.definitionDetailId || '', //费用定价子表ID */
|
||||
accountId: patientInfo.value.accountId, // // 账户id
|
||||
};
|
||||
}).filter(Boolean);
|
||||
const params = {
|
||||
activityList: applicationListAllFilter,
|
||||
patientId: patientInfo.value.patientId, //患者ID
|
||||
encounterId: patientInfo.value.encounterId, // 就诊ID
|
||||
organizationId: patientInfo.value.inHospitalOrgId, // 医疗机构ID
|
||||
requestFormId: isEditMode.value ? props.editData.requestFormId : '', // 申请单ID(编辑模式传入,新增为空)
|
||||
name: '检验申请单',
|
||||
descJson: JSON.stringify(form),
|
||||
categoryEnum: '21', // 21 检验 22 检查 23 输血 24 手术(避开 adviceType 1-6 碰撞)
|
||||
};
|
||||
saveInspection(params).then((res) => {
|
||||
if (res.code === 200) {
|
||||
proxy.$message.success(isEditMode.value ? '修改成功' : res.msg);
|
||||
transferValue.value = [];
|
||||
selectedItemsCache.value.clear();
|
||||
emits('submitOk');
|
||||
} else {
|
||||
proxy.$message.error(res.message);
|
||||
}
|
||||
});
|
||||
};
|
||||
/** 查询科室 */
|
||||
const getLocationInfo = () => {
|
||||
return getDepartmentList().then((res) => {
|
||||
orgOptions.value = normalizeOrgTreeIds(res.data || []);
|
||||
applyTargetDepartmentEcho();
|
||||
});
|
||||
};
|
||||
// 获取诊断目录
|
||||
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, getList });
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.LaboratoryTests-container {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
.transfer-wrapper {
|
||||
position: relative;
|
||||
min-height: 300px;
|
||||
|
||||
.search-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-bottom: 8px;
|
||||
|
||||
.total-count {
|
||||
font-size: 13px;
|
||||
color: #909399;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.el-transfer {
|
||||
--el-transfer-panel-width: 480px !important;
|
||||
}
|
||||
|
||||
.bloodTransfusion-form {
|
||||
padding: 8px 8px 0 8px;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,127 +0,0 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
v-model="dialogVisible"
|
||||
destroy-on-close
|
||||
width="600px"
|
||||
:close-on-click-modal="false"
|
||||
title="出院申请"
|
||||
@close="closeDialog"
|
||||
>
|
||||
<div style="padding: 0 80px">
|
||||
<el-form :model="form" :rules="rules" ref="formRef">
|
||||
<el-form-item label="出院方式" prop="outpatientType">
|
||||
<el-select v-model="form.outpatientType">
|
||||
<el-option
|
||||
v-for="(item, index) in dscg_way"
|
||||
:key="index"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="出院时间" prop="outpatientTime">
|
||||
<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>
|
||||
<el-form-item label="出院描述" prop="outpatientDescription"
|
||||
><el-input v-model="form.outpatientDescription" type="textarea" rows="5" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="submitApplicationForm"> 确认 </el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
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']);
|
||||
const form = reactive({
|
||||
outpatientType: [],
|
||||
outpatientTime: '',
|
||||
outpatientDescription: '',
|
||||
});
|
||||
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');
|
||||
}
|
||||
|
||||
function openDialog() {
|
||||
dialogVisible.value = true;
|
||||
}
|
||||
|
||||
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>
|
||||
@@ -1,349 +0,0 @@
|
||||
<!--
|
||||
* @Author: sjjh
|
||||
* @Date: 2025-09-05 22:38:55
|
||||
* @Description: 手术
|
||||
-->
|
||||
<template>
|
||||
<div class="surgery-container">
|
||||
<div class="transfer-wrapper" style="min-height: 300px;">
|
||||
<!-- 搜索框:≥3字触发后端搜索 -->
|
||||
<div style="padding: 6px 0;">
|
||||
<el-input
|
||||
v-model="searchKey"
|
||||
placeholder="请输入3个字及以上搜索"
|
||||
clearable
|
||||
@input="onSearchInput"
|
||||
style="width: 320px;"
|
||||
/>
|
||||
</div>
|
||||
<!-- 加载提示不阻塞穿梭框操作 -->
|
||||
<div v-if="loading" style="padding:8px 0; color:#909399; font-size:13px;">
|
||||
<el-icon class="is-loading"><Loading /></el-icon> 手术项目加载中...
|
||||
</div>
|
||||
<el-transfer
|
||||
ref="transferRef"
|
||||
v-model="transferValue"
|
||||
:data="applicationList"
|
||||
:titles="['待选择', '已选择']"
|
||||
:format="leftPanelFormat"
|
||||
/>
|
||||
</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="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="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="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="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="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="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="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>
|
||||
</template>
|
||||
<script setup name="Surgery">
|
||||
import {computed, getCurrentInstance, onBeforeMount, onMounted, reactive, ref, watch} from 'vue';
|
||||
import {patientInfo} from '../../../store/patient.js';
|
||||
import {getDepartmentList} from '@/api/public.js';
|
||||
import {getEncounterDiagnosis} from '../../api.js';
|
||||
import {getSurgeryPage, saveSurgery} from './api';
|
||||
import {ElMessage} from 'element-plus';
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
// 模块级缓存:避免每次打开弹窗都重新请求手术项目列表
|
||||
let surgeryRecordsCache = null; // 原始 API 记录
|
||||
let surgeryMappedCache = null; // 映射后的 el-transfer 数据
|
||||
let searchDebounceTimer = null; // 搜索防抖
|
||||
const transferRef = ref(null);
|
||||
const dbTotal = ref(0); // 数据库中的手术项目总数
|
||||
const searchKey = ref(''); // 搜索关键字
|
||||
const checkedCount = computed(() => transferValue.value.length);
|
||||
const leftPanelFormat = computed(() => ({
|
||||
noChecked: ` 0/${dbTotal.value}`,
|
||||
hasChecked: ` \${checked}/${dbTotal.value}`,
|
||||
}));
|
||||
// 递归查找树形科室节点
|
||||
const findTreeItem = (list, id) => {
|
||||
if (!list || list.length === 0) return null;
|
||||
for (const item of list) {
|
||||
if (item.id == id) return item;
|
||||
if (item.children && item.children.length > 0) {
|
||||
const found = findTreeItem(item.children, id);
|
||||
if (found) return found;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
const emits = defineEmits(['submitOk']);
|
||||
const props = defineProps({});
|
||||
const state = reactive({});
|
||||
const applicationListAll = ref();
|
||||
const applicationList = ref([]);
|
||||
const orgOptions = ref([]); // 科室选项
|
||||
const loading = ref(false); // 加载状态
|
||||
const mapToTransferItem = (item) => {
|
||||
const price = item.price != null ? Number(item.price).toFixed(2) : '0.00';
|
||||
const unit = item.unitCodeDictText || item.unitCode || '';
|
||||
return {
|
||||
adviceDefinitionId: item.adviceDefinitionId,
|
||||
orgId: item.orgId,
|
||||
label: item.adviceName + ' (¥' + price + '/' + unit + ')',
|
||||
key: item.adviceDefinitionId,
|
||||
};
|
||||
};
|
||||
const getList = () => {
|
||||
if (!patientInfo.value?.inHospitalOrgId) {
|
||||
applicationList.value = [];
|
||||
return;
|
||||
}
|
||||
// 命中内存缓存时直接使用
|
||||
if (surgeryMappedCache && surgeryMappedCache.length > 0) {
|
||||
applicationList.value = surgeryMappedCache;
|
||||
applicationListAll.value = surgeryRecordsCache;
|
||||
loading.value = false;
|
||||
return;
|
||||
}
|
||||
loadPage('');
|
||||
};
|
||||
|
||||
/**
|
||||
* 加载手术项目分页数据
|
||||
* @param {string} key 搜索关键字(可选)
|
||||
*/
|
||||
const loadPage = (key) => {
|
||||
const orgId = patientInfo.value.inHospitalOrgId;
|
||||
loading.value = true;
|
||||
getSurgeryPage({ organizationId: orgId, pageNo: 1, pageSize: 100, searchKey: key || '' })
|
||||
.then((res) => {
|
||||
if (res.code !== 200 || !res.data?.records) {
|
||||
applicationList.value = [];
|
||||
dbTotal.value = 0;
|
||||
loading.value = false;
|
||||
return;
|
||||
}
|
||||
dbTotal.value = res.data.total || 0;
|
||||
const records = res.data.records;
|
||||
applicationListAll.value = records;
|
||||
applicationList.value = records
|
||||
.filter(item => item.adviceDefinitionId != null)
|
||||
.map(mapToTransferItem);
|
||||
// 仅在无搜索时缓存
|
||||
if (!key) {
|
||||
surgeryRecordsCache = records;
|
||||
surgeryMappedCache = applicationList.value;
|
||||
}
|
||||
loading.value = false;
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error('手术项目加载失败:', e);
|
||||
applicationList.value = [];
|
||||
dbTotal.value = 0;
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 搜索输入框变化处理(防抖300ms,≥3字触发后端搜索)
|
||||
*/
|
||||
const onSearchInput = () => {
|
||||
clearTimeout(searchDebounceTimer);
|
||||
const val = searchKey.value.trim();
|
||||
if (!val) {
|
||||
// 清空搜索框,恢复初始数据
|
||||
loadPage('');
|
||||
return;
|
||||
}
|
||||
if (val.length >= 3) {
|
||||
searchDebounceTimer = setTimeout(() => {
|
||||
loadPage(val);
|
||||
}, 300);
|
||||
}
|
||||
};
|
||||
|
||||
const transferValue = ref([]);
|
||||
const form = reactive({
|
||||
// categoryType: '', // 项目类别
|
||||
targetDepartment: '', // 发往科室
|
||||
symptom: '', // 症状
|
||||
sign: '', // 体征
|
||||
clinicalDiagnosis: '', // 临床诊断
|
||||
otherDiagnosis: '', // 其他诊断
|
||||
relatedResult: '', // 相关结果
|
||||
attention: '', // 注意事项
|
||||
primaryDiagnosisList: [], //主诊断目录
|
||||
otherDiagnosisList: [], //其他断目录
|
||||
});
|
||||
const rules = reactive({});
|
||||
onBeforeMount(() => {});
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
/**
|
||||
* type(1:watch监听类型 2:点击保存类型)
|
||||
* selectProjectIds(选中项目的id数组)
|
||||
* */
|
||||
const projectWithDepartment = (selectProjectIds) => {
|
||||
if (!selectProjectIds || selectProjectIds.length === 0) {
|
||||
form.targetDepartment = '';
|
||||
}
|
||||
};
|
||||
// 监听选择项目变化
|
||||
watch(() => transferValue.value, (newValue) => {
|
||||
projectWithDepartment(newValue);
|
||||
});
|
||||
const submit = () => {
|
||||
if (transferValue.value.length == 0) {
|
||||
return proxy.$message.error('请选择手术项目');
|
||||
}
|
||||
if (!form.targetDepartment) {
|
||||
return proxy.$message.error('请选择发往科室');
|
||||
}
|
||||
let applicationListAllFilter = applicationListAll.value.filter((item) => {
|
||||
return transferValue.value.includes(item.adviceDefinitionId);
|
||||
});
|
||||
applicationListAllFilter = applicationListAllFilter.map((item) => {
|
||||
return {
|
||||
adviceDefinitionId: item.adviceDefinitionId,
|
||||
adviceDefinitionName: item.adviceName,
|
||||
quantity: 1,
|
||||
unitCode: item.unitCode,
|
||||
unitPrice: item.price,
|
||||
totalPrice: item.price,
|
||||
positionId: form.targetDepartment || item.positionId, // 用户手动选择的发往科室优先于项目默认执行科室
|
||||
definitionId: item.chargeItemDefinitionId,
|
||||
accountId: patientInfo.value.accountId,
|
||||
};
|
||||
});
|
||||
saveSurgery({
|
||||
activityList: applicationListAllFilter,
|
||||
patientId: patientInfo.value.patientId, //患者ID
|
||||
encounterId: patientInfo.value.encounterId, // 就诊ID
|
||||
organizationId: patientInfo.value.inHospitalOrgId, // 医疗机构ID
|
||||
requestFormId: '', // 申请单ID
|
||||
name: '手术申请单',
|
||||
descJson: JSON.stringify(form),
|
||||
categoryEnum: '24', // 21 检验 22 检查 23 输血 24 手术(避开 adviceType 1-6 碰撞)
|
||||
}).then((res) => {
|
||||
if (res.code === 200) {
|
||||
proxy.$message.success(res.msg);
|
||||
applicationList.value = [];
|
||||
emits('submitOk');
|
||||
} else {
|
||||
proxy.$message.error(res.message);
|
||||
}
|
||||
});
|
||||
};
|
||||
/** 查询科室 */
|
||||
const getLocationInfo = () => {
|
||||
getDepartmentList().then((res) => {
|
||||
orgOptions.value = res.data || [];
|
||||
});
|
||||
};
|
||||
// 获取诊断目录
|
||||
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, getList });
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.surgery-container {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
.transfer-wrapper {
|
||||
position: relative;
|
||||
min-height: 300px;
|
||||
}
|
||||
|
||||
.el-transfer {
|
||||
--el-transfer-panel-width: 480px !important;
|
||||
}
|
||||
|
||||
.bloodTransfusion-form {
|
||||
padding: 8px 8px 0 8px;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,149 +0,0 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
v-model="dialogVisible"
|
||||
destroy-on-close
|
||||
width="600px"
|
||||
:close-on-click-modal="false"
|
||||
title="转科申请"
|
||||
@close="closeDialog"
|
||||
>
|
||||
<div style="padding: 0 80px">
|
||||
<el-form :model="form" :rules="rules" ref="formRef">
|
||||
<el-form-item label="转入科室" prop="targetOrganizationId">
|
||||
<el-select
|
||||
v-model="form.targetOrganizationId"
|
||||
@change="fetchWardList"
|
||||
placeholder="请选择转入科室"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in deptList"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="转入病区" prop="targetLocationId">
|
||||
<el-select v-model="form.targetLocationId" no-data-text="请先选择科室" placeholder="请选择转入病区">
|
||||
<el-option
|
||||
v-for="item in wardList"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="转科时间" prop="startTime">
|
||||
<el-radio-group v-model="form.startTime">
|
||||
<el-radio :value="today">今日</el-radio>
|
||||
<el-radio :value="tomorrow">明日</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="转科原因" prop="reasonText">
|
||||
<el-input
|
||||
v-model="form.reasonText"
|
||||
type="textarea"
|
||||
rows="5"
|
||||
placeholder="请输入转科原因"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="submitApplicationForm"> 确认 </el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {transferOrganization} from './api.js';
|
||||
import {getOrgList, getWardList} from '@/api/public.js';
|
||||
import {patientInfo} from '../../../store/patient.js';
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
const dialogVisible = ref(false);
|
||||
const deptList = ref([]); // 科室列表
|
||||
const wardList = ref([]); // 病区列表
|
||||
const today = ref(proxy.formatDateStr(new Date(),'YYYY-MM-DD HH:mm:ss'))
|
||||
const tomorrow = ref(proxy.formatDateStr(new Date().setDate(new Date + 1),'YYYY-MM-DD HH:mm:ss'))
|
||||
|
||||
const form = reactive({
|
||||
targetOrganizationId: '',
|
||||
targetLocationId: '',
|
||||
startTime: '',
|
||||
reasonText: '',
|
||||
});
|
||||
|
||||
// 表单校验规则
|
||||
const rules = ref({
|
||||
targetOrganizationId: [{ required: true, message: '请选择转入科室', trigger: 'change' }],
|
||||
targetLocationId: [{ required: true, message: '请选择转入病区', trigger: 'change' }],
|
||||
startTime: [{ required: true, message: '请选择转科时间', trigger: 'change' }],
|
||||
reasonText: [{ required: false }],
|
||||
});
|
||||
|
||||
// 获取科室列表
|
||||
function fetchDeptList() {
|
||||
getOrgList().then((response) => {
|
||||
deptList.value = response.data;
|
||||
});
|
||||
}
|
||||
|
||||
// 获取病区列表
|
||||
function fetchWardList() {
|
||||
getWardList({ orgId: form.targetOrganizationId }).then((response) => {
|
||||
wardList.value = response.data;
|
||||
});
|
||||
}
|
||||
|
||||
function openDialog() {
|
||||
dialogVisible.value = true;
|
||||
// 打开对话框时获取数据
|
||||
fetchDeptList();
|
||||
}
|
||||
|
||||
// 提交表单
|
||||
function submitApplicationForm() {
|
||||
proxy.$refs.formRef.validate((valid) => {
|
||||
console.log(patientInfo.value);
|
||||
if (valid) {
|
||||
form.encounterId = patientInfo.value.encounterId
|
||||
form.patientId = patientInfo.value.patientId
|
||||
// 表单校验通过,执行提交逻辑
|
||||
transferOrganization(form).then((res) => {
|
||||
if (res.code == 200) {
|
||||
proxy.$modal.msgSuccess('转科申请已提交');
|
||||
dialogVisible.value = false;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 表单校验不通过
|
||||
proxy.$modal.msgWarning('请完善必填信息');
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 关闭对话框
|
||||
function closeDialog() {
|
||||
// 重置表单
|
||||
proxy.$refs.formRef.resetFields();
|
||||
// 重置数据
|
||||
Object.assign(form, {
|
||||
targetOrganizationId: '',
|
||||
targetLocationId: '',
|
||||
startTime: '',
|
||||
reasonText: '',
|
||||
});
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
openDialog,
|
||||
});
|
||||
</script>
|
||||
@@ -1,188 +0,0 @@
|
||||
<!--
|
||||
* @Author: sjjh
|
||||
* @Date: 2025-04-07 23:47:54
|
||||
* @Description:
|
||||
-->
|
||||
<template>
|
||||
<div class="advice-container">
|
||||
<div class="operate-btns">
|
||||
<el-space>
|
||||
<el-button type="primary" @click="addNew">新增</el-button>
|
||||
<el-button type="primary">签发</el-button>
|
||||
<el-button type="danger">撤回</el-button>
|
||||
<el-button type="danger">作废</el-button>
|
||||
<el-button type="danger">停止</el-button>
|
||||
<el-button>复制</el-button>
|
||||
<el-button>粘贴</el-button>
|
||||
</el-space>
|
||||
</div>
|
||||
<div class="operate-btns">
|
||||
<el-space>
|
||||
<el-radio-group v-model="searchForm.orderType">
|
||||
<el-radio-button label="全部" value="New York" />
|
||||
<el-radio-button label="长期" value="Washington" />
|
||||
<el-radio-button label="临时" value="Los Angeles" />
|
||||
</el-radio-group>
|
||||
<el-select v-model="searchForm.orderClassCode" placeholder="医嘱类型" style="width: 240px">
|
||||
<el-option
|
||||
v-for="item in typeOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
<el-select v-model="searchForm.orderStatus" placeholder="医嘱状态" style="width: 240px">
|
||||
<el-option
|
||||
v-for="item in statusOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-space>
|
||||
</div>
|
||||
<div class="orderTableData-container">
|
||||
<el-table
|
||||
:data="orderTableData"
|
||||
border
|
||||
row-key="id"
|
||||
style="width: 100%; height: 100%"
|
||||
highlight-current-row
|
||||
:expand-row-keys="expandOrder"
|
||||
>
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column prop="date" label="状态" width="180" sortable />
|
||||
<el-table-column prop="orderTypeName" label="类型" width="180" />
|
||||
<el-table-column prop="address" label="医嘱内容" />
|
||||
<el-table-column prop="address" label="时间" />
|
||||
<el-table-column prop="address" label="执行科室" />
|
||||
<el-table-column prop="address" label="停止、作废人/时间" width="180" />
|
||||
<el-table-column fixed="right" label="操作" width="120">
|
||||
<template #default="props">
|
||||
<el-button link type="primary" size="small" @click="editRow(props.row)">
|
||||
查看
|
||||
</el-button>
|
||||
<el-button link type="primary" size="small">编辑</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column type="expand" width="1" style="width: 0">
|
||||
<template #default="props">
|
||||
<div m="4">
|
||||
<p m="t-0 b-2">State: {{ props.row.state }}</p>
|
||||
<p m="t-0 b-2">City: {{ props.row.city }}</p>
|
||||
<p m="t-0 b-2">Address: {{ props.row.address }}</p>
|
||||
<p m="t-0 b-2">Zip: {{ props.row.zip }}</p>
|
||||
<h3>Family</h3>
|
||||
<el-button type="primary" @click="save">保存</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import {onBeforeMount, onMounted, reactive, ref} from 'vue'
|
||||
// const { proxy } = getCurrentInstance()
|
||||
// const emits = defineEmits([])
|
||||
// const props = defineProps({})
|
||||
import {orderTableData} from './useOrder'
|
||||
import {ElMessage} from 'element-plus'
|
||||
|
||||
const state = reactive({})
|
||||
onBeforeMount(() => {})
|
||||
onMounted(() => {})
|
||||
defineExpose({ state })
|
||||
|
||||
const typeOptions = [
|
||||
{
|
||||
value: 'Option1',
|
||||
label: '中药',
|
||||
},
|
||||
{
|
||||
value: 'Option2',
|
||||
label: '西药',
|
||||
},
|
||||
{
|
||||
value: 'Option3',
|
||||
label: '检查',
|
||||
},
|
||||
{
|
||||
value: 'Option4',
|
||||
label: '检验',
|
||||
},
|
||||
{
|
||||
value: 'Option5',
|
||||
label: '处置',
|
||||
},
|
||||
]
|
||||
const statusOptions = [
|
||||
{
|
||||
value: 'Option1',
|
||||
label: '暂存',
|
||||
},
|
||||
{
|
||||
value: 'Option2',
|
||||
label: '签署',
|
||||
},
|
||||
{
|
||||
value: 'Option3',
|
||||
label: '回退',
|
||||
},
|
||||
{
|
||||
value: 'Option4',
|
||||
label: '停止',
|
||||
},
|
||||
{
|
||||
value: 'Option5',
|
||||
label: '作废',
|
||||
},
|
||||
]
|
||||
const searchForm = reactive({
|
||||
orderType: '',
|
||||
orderClassCode: '',
|
||||
orderStatus: '',
|
||||
})
|
||||
|
||||
const expandOrder = ref([]) //目前的展开行
|
||||
const newId = ref('')
|
||||
/* ==== 操作 */
|
||||
// 新增
|
||||
const addNew = () => {
|
||||
if (!newId.value) {
|
||||
newId.value = '1111112222'
|
||||
orderTableData.unshift({ id: '1111112222' })
|
||||
expandOrder.value = ['1111112222']
|
||||
} else {
|
||||
ElMessage({
|
||||
message: '请先操作当前编辑的医嘱!',
|
||||
type: 'warning',
|
||||
})
|
||||
}
|
||||
}
|
||||
// 新增
|
||||
const editRow = (row) => {
|
||||
expandOrder.value = [row.id]
|
||||
}
|
||||
const save = (row) => {
|
||||
expandOrder.value = []
|
||||
newId.value = undefined
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.advice-container {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.operate-btns {
|
||||
height: 44px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: none;
|
||||
}
|
||||
.orderTableData-container {
|
||||
flex: auto;
|
||||
height: calc(100% - 88px);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user