解决合并冲突

This commit is contained in:
2025-12-10 14:20:24 +08:00
parent e1385cb3e6
commit 18f6a845e6
804 changed files with 61881 additions and 13577 deletions

View File

@@ -36,8 +36,10 @@
<el-table-column label="单次剂量" align="center">
<template #default="scope">
<span>
{{
parseFloat(scope.row.dose).toFixed(2) === '0.00'
{{
!scope.row.dose || isNaN(parseFloat(scope.row.dose))
? '-'
: parseFloat(scope.row.dose).toFixed(2) === '0.00'
? '-'
: parseFloat(scope.row.dose).toFixed(2) + scope.row.doseUnitCode_dictText
}}
@@ -46,8 +48,13 @@
</el-table-column>
<el-table-column label="规格" align="center" prop="volume" />
<el-table-column label="用法" align="center" prop="methodCode_dictText" />
<el-table-column label="库存名称" align="center">
<template #default="scope">{{ getLocationName(scope.row) }}</template>
<!-- 修改价格列从inventoryList中获取价格 -->
<el-table-column label="价格" align="center">
<template #default="scope">
<span>
{{ getPriceFromInventory(scope.row) }}
</span>
</template>
</el-table-column>
<el-table-column label="库存数量" align="center">
<template #default="scope">{{ handleQuantity(scope.row) }}</template>
@@ -199,19 +206,31 @@ watch(
// 全部类型
queryParams.value.adviceTypes = '1,2,3';
}
// 设置categoryCode筛选条件用于筛选西药和中成药
if (newValue.categoryCode) {
queryParams.value.categoryCode = newValue.categoryCode;
} else {
queryParams.value.categoryCode = undefined;
}
console.log('发送请求参数:', queryParams.value);
getList();
throttledGetList();
},
{ deep: true, immediate: true }
{ deep: true }
);
getList();
function getList() {
queryParams.value.organizationId = props.patientInfo.orgId;
getAdviceBaseInfo(queryParams.value).then((res) => {
if (res.data.records.length > 0) {
adviceBaseList.value = res.data.records.filter((item) => {
if (item.adviceType == 1 || item.adviceType == 2) {
return handleQuantity(item) != 0;
} else {
return true;
}
});
total.value = res.data.total;
nextTick(() => {
currentIndex.value = 0;
// adviceBaseRef.value.setCurrentRow(adviceBaseList.value[0]);
});
}
});
}
// 从priceList列表中获取价格
function getPriceFromInventory(row) {
if (row.priceList && row.priceList.length > 0) {
@@ -441,6 +460,7 @@ defineExpose({
<style scoped>
.popover-table-wrapper:focus {
outline: 2px solid #409eff; /* 聚焦时的高亮效果 */
outline: 2px solid #409eff;
/* 聚焦时的高亮效果 */
}
</style>

View File

@@ -543,6 +543,16 @@ export function saveTcmDiagnosis(data) {
})
}
/**
* 删除中医诊断
*/
export function deleteTcmDiagnosis(syndromeGroupNo) {
return request({
url: '/doctor-station/chinese-medical/tcm-diagnosis?syndromeGroupNo=' + syndromeGroupNo,
method: 'delete',
})
}
/**
* 保存中医医嘱
*/
@@ -707,11 +717,11 @@ export function getOrderGroup(data) {
}
/**
* 查询诊疗项目耗材绑定信息
* 查询项目绑定信息
*/
export function getActivityBindDevice(data) {
export function getBindDevice(data) {
return request({
url: '/doctor-station/advice/activity-bind-device-info',
url: '/doctor-station/advice/order-bind-info',
method: 'get',
params: data
})

View File

@@ -2,61 +2,36 @@
<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"
>
<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"
>
<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 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)"
>
<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 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>
@@ -78,25 +53,15 @@
<el-table-column label="序号" type="index" width="50" />
<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 :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-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 diag_type"
@@ -111,25 +76,12 @@
<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"
/>
<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)"
/>
<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>
@@ -169,11 +121,7 @@
</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 link type="primary" @click="handleDeleteDiagnosis(scope.row, scope.$index)">
删除
</el-button>
</template>
@@ -182,16 +130,9 @@
</el-form>
</el-col>
</el-row>
<diagnosisdialog
:openDiagnosis="openDiagnosis"
@close="closeDiagnosisDialog"
:radio="orgOrUser"
/>
<AddDiagnosisDialog
:openAddDiagnosisDialog="openAddDiagnosisDialog"
:patientInfo="props.patientInfo"
@close="closeDiagnosisDialog"
/>
<diagnosisdialog :openDiagnosis="openDiagnosis" @close="closeDiagnosisDialog" :radio="orgOrUser" />
<AddDiagnosisDialog :openAddDiagnosisDialog="openAddDiagnosisDialog" :patientInfo="props.patientInfo"
@close="closeDiagnosisDialog" />
</div>
</template>
@@ -208,6 +149,7 @@ import {
getChronicDisease,
getTcmDiagnosis,
delEncounterDiagnosis,
deleteTcmDiagnosis,
isFoodDiseasesNew,
} from '../api';
import diagnosisdialog from '../diagnosis/diagnosisdialog.vue';
@@ -280,7 +222,6 @@ function getList() {
form.value.diagnosisList.sort((a, b) => (a.diagSrtNo || 0) - (b.diagSrtNo || 0));
emits('diagnosisSave', false);
console.log(form.value.diagnosisList);
}
});
@@ -298,7 +239,6 @@ function getList() {
});
}
emits('diagnosisSave', false);
console.log(form.value.diagnosisList);
}
});
@@ -553,7 +493,7 @@ function closeDiagnosisDialog(str) {
getTree();
}
function queryDiagnosisUse(value) {}
function queryDiagnosisUse(value) { }
function handleChange(value) {
diagnosisSearchkey.value = value;
@@ -627,6 +567,7 @@ defineExpose({ getList, getDetail, handleSaveDiagnosis });
.el-checkbox.is-bordered.el-checkbox--small {
background-color: #ffffff;
}
.custom-tree-node {
display: flex;
align-items: center;

View File

@@ -9,8 +9,8 @@
@cell-click="clickRow"
>
<el-table-column label="模板名称" align="center" prop="templateName" />
<el-table-column label="使用范围" align="center" prop="useScopeCode" />
<el-table-column label="操作" align="center">
<!-- <el-table-column label="使用范围" align="center" prop="useScopeCode" /> -->
<el-table-column label="操作" align="center" width="100">
<template #default="scope">
<el-button link type="primary" @click.stop="handelDelete(scope.row)">删除</el-button>
</template>
@@ -43,7 +43,11 @@ const props = defineProps({
required: true,
},
});
<<<<<<< HEAD
getList();
=======
getList();
>>>>>>> upstream/develop
function getList() {
queryParams.value.useScopeCode = 1;
getEmrTemplateList(queryParams.value).then((res) => {

View File

@@ -743,7 +743,6 @@ function selectMedRow(key, row, index) {
const item = list.sort((a, b) => {
return new Date(b.begndate) - new Date(a.begndate);
});
//debugger
if (item.length > 0) {
if (item[0].medChrgitmType != '11' && item[0].medChrgitmType != '09') {
form.medicationInfoList.shift();

View File

@@ -11,14 +11,8 @@
</div>
<div>处方信息</div>
<el-table
max-height="650"
ref="eprescriptionRef"
:data="prescriptionList"
row-key="prescriptionNo"
border
@selection-change="handleSelectionChange"
>
<el-table max-height="650" ref="eprescriptionRef" :data="prescriptionList" row-key="prescriptionNo" border
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" align="center" :selectable="selectable" />
<el-table-column label="处方号" align="center" prop="prescriptionNo" width="200" sortable>
<template #default="scope">
@@ -46,16 +40,8 @@
<span v-if="!scope.row.isEdit">
{{ scope.row.validityDays }}
</span>
<el-input-number
v-else
:min="0"
controls-position="right"
:controls="false"
v-model="scope.row.validityDays"
placeholder=""
@input="handleValidityDaysChange(scope.$index, $event)"
style="width: 90%"
/>
<el-input-number v-else :min="0" controls-position="right" :controls="false" v-model="scope.row.validityDays"
placeholder="" @input="handleValidityDaysChange(scope.$index, $event)" style="width: 90%" />
</template>
</el-table-column>
<el-table-column label="状态" align="center" prop="statusEnum_enumText" width="80">
@@ -65,13 +51,7 @@
</span>
</template>
</el-table-column>
<el-table-column
label="开方医师"
align="center"
prop="practitionerName"
header-align="center"
width="90"
>
<el-table-column label="开方医师" align="center" prop="practitionerName" header-align="center" width="90">
<template #default="scope">
<span v-if="!scope.row.isEdit">
{{ scope.row.practitionerName }}
@@ -138,44 +118,19 @@
<el-table-column label="操作" align="center" width="220" fixed="right">
<template #default="scope">
<el-button link type="primary" icon="View" @click="handleView(scope.row)">查看</el-button>
<el-button
link
type="primary"
icon="Edit"
@click="handleEdit(scope.row)"
:disabled="scope.row.statusEnum == 2 || scope.row.statusEnum == 3 || scope.row.statusEnum == 6"
>编辑</el-button
>
<el-button
link
type="primary"
icon="Plus"
@click="savePrescriptionData(scope.row, scope.$index)"
:disabled="!scope.row.isEdit"
>保存</el-button
>
<el-button link type="primary" icon="Edit" @click="handleEdit(scope.row)"
:disabled="scope.row.statusEnum == 2 || scope.row.statusEnum == 3 || scope.row.statusEnum == 6">编辑</el-button>
<el-button link type="primary" icon="Plus" @click="savePrescriptionData(scope.row, scope.$index)"
:disabled="!scope.row.isEdit">保存</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
style="margin-bottom: 5px"
/>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
@pagination="getList" style="margin-bottom: 5px" />
<eprescriptiondialog
ref="prescriptionDialogRef"
:openPrescription="openPrescription"
:patient="props.patientInfo"
:prescriptionType="prescriptionTypeList"
:medicationInfo="medicationInfoList"
:prescriptionData="prescriptionInfo"
:title="title"
@close="closePrescriptionDialog"
/>
<eprescriptiondialog ref="prescriptionDialogRef" :openPrescription="openPrescription" :patient="props.patientInfo"
:prescriptionType="prescriptionTypeList" :medicationInfo="medicationInfoList" :prescriptionData="prescriptionInfo"
:title="title" @close="closePrescriptionDialog" />
</div>
</template>
@@ -285,20 +240,12 @@ getElepPrescriptionInit();
/** 处方信息取得 */
function getList() {
console.log(
queryParams.value,
'queryParams.value电子处方',
props.patientInfo,
'props.patientInfo'
);
prescriptionList.value = [];
medicationInfoList.value = [];
prescriptionNoTemp.value = undefined;
queryParams.value.patientId = props.patientInfo.patientId;
console.log(queryParams.value, 'queryParams.value电子处方');
getPrescriptionInfo(queryParams.value).then((res) => {
prescriptionList.value = res.data.records;
console.log(res, '电子处方列表');
total.value = res.data.total;
});
}
@@ -307,13 +254,11 @@ function getList() {
function getElepPrescriptionInit() {
elepPrescriptionInit().then((res) => {
prescriptionTypeList.value = res.data.rxTypeCodeListOptions;
console.log(res, '电子处方下拉框');
});
}
/** 选择条数 */
function handleSelectionChange(selection) {
console.log(selection, 'selection');
selectDataList.value = selection.map((item) => ({ ...item })); // 存储选择的行数据
prescriptionNos.value = selection.map((item) => item.prescriptionNo);
ids.value = selection
@@ -341,7 +286,6 @@ function handleAddPrescription() {
*/
function selectable(row, index) {
// 返回 true 表示该行可选,返回 false 表示该行不可选
// console.log(row, 'selectable', rowIndex.value);
return ![2, 3, 6].includes(row.statusEnum);
}
@@ -359,7 +303,6 @@ function handleView(row) {
prescriptionInfo.value.extensionReason = row.extensionReason;
prescriptionInfo.value.rxTypeCode = row.rxTypeCode;
prescriptionInfo.value.prescriptionNo = row.prescriptionNo;
console.log(queryMedicationParams.value, '处方详细的药品信息参数', row.prescriptionNo);
getMedicationInfo(queryMedicationParams.value).then((response) => {
medicationInfoList.value = response.data.records;
medicationInfoList.value.forEach((medicationInfo) => {
@@ -369,7 +312,6 @@ function handleView(row) {
prescriptionInfo.value.conditionId = response.data.records[0].conditionId;
openPrescriptionDialog();
console.log(response, '处方详细的药品信息', medicationInfoList.value);
});
}
@@ -385,7 +327,6 @@ function handleEdit(row) {
prescriptionInfo.value.extensionReason = row.extensionReason;
prescriptionInfo.value.rxTypeCode = row.rxTypeCode;
prescriptionInfo.value.prescriptionNo = row.prescriptionNo;
console.log(queryMedicationParams.value, '处方详细的药品信息参数', row.prescriptionNo);
getMedicationInfo(queryMedicationParams.value).then((response) => {
medicationInfoList.value = response.data.records;
medicationInfoList.value.forEach((medicationInfo) => {
@@ -393,7 +334,6 @@ function handleEdit(row) {
});
prescriptionInfo.value.conditionId = response.data.records[0].conditionId;
openPrescriptionDialog();
console.log(response, '处方详细的药品信息', medicationInfoList.value);
});
}
@@ -419,7 +359,6 @@ function openPrescriptionDialog() {
nextTick(() => {
proxy.$refs['prescriptionDialogRef'].getPrescriptionNoInit();
});
console.log(openPrescription.value, '打开新增处方弹窗');
}
/**
@@ -456,10 +395,8 @@ async function savePrescriptionData(row, index) {
rxTypeCode: row.rxTypeCode,
};
console.log(updateParam, ' 保存处方updateParam');
updatePrescriptionInfo(updateParam).then((response) => {
if (response.code == 200) {
console.log(response, '保存成功');
proxy.$modal.msgSuccess('保存成功');
getList();
} else {
@@ -467,7 +404,6 @@ async function savePrescriptionData(row, index) {
}
});
// } catch (error) {
// console.log('验证失败:', error);
// // 验证失败,不执行保存
// }
}
@@ -513,7 +449,6 @@ function deletePrescription(index) {
idList: ids.value,
prescriptionNoList: prescriptionNos.value,
};
console.log('deletePrescription删除', data);
proxy.$modal
.confirm('是否确认删除以上数据!')
.then(function () {
@@ -530,13 +465,12 @@ function deletePrescription(index) {
// form.value.medicationInfoList.forEach((medicationInfo) => {
// medicationInfo.isEdit = false;
// });
// console.log(response, '处方详细的药品信息', form.value.medicationInfoList);
// totalMedication.value = response.data.total;
// });
// }
proxy.$modal.msgSuccess('删除成功');
})
.catch(() => {});
.catch(() => { });
}
defineExpose({ getList });

View File

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

View File

@@ -0,0 +1,96 @@
<template>
<div class="emr-history-container">
<div class="search-box">
<el-input placeholder="病历名称搜索..." v-model="queryParams.searchKey">
<template #append>
<el-button @click="queryList">查询</el-button>
</template>
</el-input>
</div>
<el-scrollbar class="emr-history-scrollbar-container" style="width: 100%">
<div v-for="item in historyData" :key="item.id" class="scrollbar-item">
<el-tooltip effect="dark" :content="`${item.name}(${item.recordTime})`" placement="bottom">
<el-text class="w-150px mb-2" truncated @click="handleNodeClick(item)">
{{ item.name }}({{ item.recordTime }})
</el-text>
</el-tooltip>
</div>
</el-scrollbar>
</div>
</template>
<script setup>
import { ref, reactive, defineEmits, unref } from 'vue';
import { getRecordByEncounterIdList } from '../api';
import { ElTree } from 'element-plus';
import { ElMessageBox, ElMessage, ElLoading } from 'element-plus';
import { patientInfo } from '../../store/patient.js';
const emits = defineEmits(['historyClick']);
const props = defineProps({
definitionId: {
type: String,
default: '',
},
});
const definitionId = defineModel('definitionId', {
type: String,
default: '',
});
const defaultProps = {
children: 'children',
label: 'name',
};
const queryParams = ref({
searchKey: '',
isPage: 0,
});
const historyData = ref([]);
const queryList = async () => {
try {
if (patientInfo.value.encounterId && unref(definitionId) && unref(definitionId) !== '') {
const res = await getRecordByEncounterIdList({
...queryParams.value,
encounterId: patientInfo.value.encounterId,
patientId: patientInfo.value.patientId,
definitionId: unref(definitionId),
});
historyData.value = res.data || [];
} else {
historyData.value = [];
}
} catch (error) {
// ElMessage.error('获取模板树失败');
historyData.value = [];
}
};
const handleNodeClick = (data) => {
emits('historyClick', data);
};
const currentSelectTemplate = ref({});
defineExpose({ queryList });
</script>
<style lang="scss" scoped>
.emr-history-container {
height: 100%;
// padding: 8px;
.search-box {
height: 40px;
line-height: 40px;
}
.emr-history-scrollbar-container {
padding: 8px;
height: calc(100% - 40px);
.scrollbar-item {
height: 40px;
line-height: 40px;
border-radius: 4px;
cursor: pointer;
background: var(--el-color-primary-light-9);
& + .scrollbar-item {
margin-top: 8px;
}
}
}
}
</style>

View File

@@ -0,0 +1,112 @@
<template>
<div class="emr-template-container">
<!-- <div class="search-box">
<el-input placeholder="病历名称搜索..." v-model="queryParams.searchKey">
<template #append>
<el-button @click="queryList">查询</el-button>
</template>
</el-input>
</div> -->
<el-scrollbar class="emr-template-scrollbar-container" style="width: 100%">
<div v-for="item in templateData" :key="item.id" class="scrollbar-item">
<el-tooltip
effect="dark"
:content="`${item.name}`"
placement="bottom"
>
<el-text class="2" truncated @click="handleNodeClick(item)">
<div class="template-item">{{ item.name }}
<el-space>
<el-icon><Edit @click="handleEdit(item)" /></el-icon>
</el-space></div>
</el-text>
</el-tooltip>
</div>
</el-scrollbar>
</div>
</template>
<script setup>
import { ref, reactive, defineEmits, unref } from 'vue';
import { getListByDefinitionId } from '../api';
import { ElTree } from 'element-plus';
import { ElMessageBox, ElMessage, ElLoading } from 'element-plus';
import { patientInfo } from '../../store/patient.js';
const emits = defineEmits(['templateClick','edit']);
const props = defineProps({
definitionId: {
type: String,
default: '',
},
});
const definitionId = defineModel('definitionId', {
type: String,
default: '',
});
const defaultProps = {
children: 'children',
label: 'name',
};
const queryParams = ref({
searchKey: '',
isPage: 0,
});
const templateData = ref([]);
const queryList = async () => {
try {
if ( unref(definitionId)&&unref(definitionId) !== '') {
const res = await getListByDefinitionId(unref(definitionId));
templateData.value = res.data || [];
}else{
templateData.value = [];
}
} catch (error) {
ElMessage.error('获取模板失败');
templateData.value = [];
}
};
const handleNodeClick = (data) => {
emits('templateClick', data);
};
const handleEdit = (data) => {
emits('edit', data);
};
const currentSelectTemplate = ref({});
defineExpose({ queryList });
</script>
<style lang="scss" scoped>
.emr-template-container {
height: 100%;
// padding: 8px;
.emr-template-scrollbar-container{
padding: 8px;
height: 100%;
.scrollbar-item {
height: 40px;
line-height: 40px;
border-radius: 4px;
cursor: pointer;
background: var(--el-color-primary-light-9);
& + .scrollbar-item {
margin-top: 8px;
}
.el-text{
width: calc(100% - 0px);
display: flex;
justify-content: space-between;
padding: 0 8px;
}
.template-item{
width: 100%;
display: flex;
justify-content: space-between;
}
}
}
}
</style>

View File

@@ -0,0 +1,133 @@
<template>
<!-- 病历文件基本信息弹窗 -->
<el-dialog
:title="formData.id ? '编辑模板' : '新增模板'"
v-model="dialogVisible"
width="900px"
destroy-on-close
@open="handleOpen"
>
<!-- 使用el-form包裹表单 -->
<el-form :model="formData" ref="formRef" :rules="rules" label-width="120px">
<el-row :gutter="24" class="mb8">
<el-col :span="24">
<el-form-item label="模板名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入模板名称"></el-input>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="使用范围" prop="useRange">
<el-radio-group v-model="formData.useRange">
<el-radio :value="0" size="large">全院</el-radio>
<el-radio :value="1" size="large">指定机构</el-radio>
<el-radio :value="2" size="large">指定用户</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="备注" prop="remark">
<el-input v-model="formData.remark" placeholder="请输入版本"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<div class="dialog-footer"></div>
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitForm">确定</el-button>
</template>
</el-dialog>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import useUserStore from '@/store/modules/user';
import { addTemplate, updateTemplate } from '../api';
import { ElMessage } from 'element-plus';
import { components } from '@/template';
const emits = defineEmits(['submitOk']);
const props = defineProps({
formData: {
type: Object,
default: () => ({}),
},
});
const formRef = ref(null);
const dialogVisible = defineModel('dialogVisible', {
type: Boolean,
default: false,
});
// 表单数据
const formData = ref({
id: 0,
name: '',
displayOrder: 0,
contextJson: '',
definitionId: 0,
useRange: 2,
organizationId: 0,
userId: 0,
remark: '',
});
// 表单验证规则(响应式,支持动态验证)
const rules = reactive({
name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
});
const handleOpen = () => {
if (props.formData) {
formData.value = props.formData;
} else {
resetForm();
}
};
// 提交表单
const submitForm = () => {
formRef.value.validate((valid) => {
if (valid) {
// 表单验证通过,执行保存操作
saveForm();
} else {
// 表单验证失败
ElMessage.error('请填写必填项');
return false;
}
});
};
// 保存表单
const saveForm = async () => {
try {
// 如果有当前节点数据,表示是编辑操作
if (formData.value.id && formData.value.id !== '') {
const res = await updateTemplate(formData.value);
if (res.code == 200) {
ElMessage.success('更新成功');
emits('submitOk');
} else {
ElMessage.error('更新失败', error);
}
} else {
// 新建操作
const res = await addTemplate(formData.value);
if (res.code == 200) {
ElMessage.success('保存成功');
emits('submitOk');
} else {
ElMessage.error('保存失败', error);
}
}
} catch (error) {
console.log(error);
// ElMessage.error('保存失败',error);
}
};
// 重置表单
const resetForm = () => {
formRef.value?.resetFields();
};
onMounted(() => {});
</script>
<style lang="scss" scoped></style>

View File

@@ -0,0 +1,584 @@
<!--
* @Author: sjjh
* @Date: 2025-09-18 15:41:10
* @Description: 门诊病历组件
-->
<template>
<div class="emr-use-container">
<div
class="disBtn"
:class="{ disLeftBtnNor: leftShow, disLeftBtnAct: !leftShow }"
@click="disNode"
>
<img src="../../../../assets/icons/svg/foldup.svg" />
</div>
<div
class="disBtn"
:class="{ disRightBtnNor: rightShow, disRightBtnAct: !rightShow }"
@click="disNode_R"
>
<img src="../../../../assets/icons/svg/foldup.svg" />
</div>
<transition name="el-zoom-in-left">
<div class="template-tree-container" v-if="leftShow">
<div class="search-box">
<el-input placeholder="病历名称搜索..." v-model="queryParams.name">
<template #append>
<el-button @click="queryTemplateTree">查询</el-button>
</template>
</el-input>
</div>
<el-scrollbar class="template-tree-scrollbar">
<el-tree
ref="templateTree"
:data="templateData"
:props="defaultProps"
auto-expand-parent
node-key="id"
@node-click="handleNodeClick"
class="template-tree"
></el-tree>
</el-scrollbar>
</div>
</transition>
<div class="operate-container">
<div class="operate-btns">
<el-space>
<!-- <el-button type="primary" @click="newEmr">新建</el-button> -->
<el-button type="primary" @click="saveAsModel">存为模版</el-button>
<el-button @click="refresh">刷新</el-button>
<el-button type="primary" @click="save">保存</el-button>
<!-- <el-button type="primary" @click="print">打印</el-button> -->
</el-space>
</div>
<div class="operate-main">
<el-scrollbar class="template-tree-scrollbar">
<component
:is="currentComponent"
ref="emrComponentRef"
:patientInfo="props.patientInfo"
@submitOk="handleSubmitOk"
/>
</el-scrollbar>
</div>
</div>
<transition name="el-zoom-in-left">
<div class="quickly-container" v-if="rightShow">
<el-tabs v-model="quicklyactiveName" type="card">
<el-tab-pane label="历史" name="history">
<History
@historyClick="handleHistoryClick"
ref="historyRef"
v-model:definitionId="currentSelectTemplate.id"
/>
</el-tab-pane>
<el-tab-pane label="模版" name="model">
<Template
@templateClick="handleTemplateClick"
ref="templateRef"
v-model:definitionId="currentSelectTemplate.id"
@edit="templateEdit"
/>
</el-tab-pane>
</el-tabs>
</div>
</transition>
<TemplateEdit
ref="templateEditRef"
:formData="editTemplateForm"
v-model:dialogVisible="templateEditVisible"
@submitOk="templateEditSubmitOk"
/>
</div>
</template>
<script setup>
import { getCurrentInstance, nextTick, onBeforeMount, onMounted, reactive, ref } from 'vue';
import { ElMessageBox, ElMessage, ElLoading } from 'element-plus';
import { getTreeList } from '@/views/basicmanage/caseTemplates/api';
import { addRecord, addTemplate } from './api';
import { patientInfo } from '../store/patient.js';
import dayjs from 'dayjs';
// 打印工具
// import { simplePrint, PRINT_TEMPLATE } from '@/utils/printUtils.js';
const { proxy } = getCurrentInstance();
const emits = defineEmits(['emrSaved']);
const props = defineProps({
/** 患者信息 doctorStation 传递信息*/
patientInfo: {
type: Object,
required: true,
},
activeTab: {
type: String,
},
});
const state = reactive({});
import History from './components/history';
import Template from './components/template';
import TemplateEdit from './components/templateEdit.vue';
import useUserStore from '@/store/modules/user';
const userStore = useUserStore();
// 定义响应式变量
const templateData = ref([]);
const queryParams = ref({
name: '',
useRanges: [1, 2], // 0 暂不使用 1 全院 2 科室 3 个人
organizationId: userStore.orgId,
});
const currentSelectTemplate = ref({
id: '',
});
const currentComponent = ref('');
const emrComponentRef = ref(null);
const quicklyactiveName = ref('history');
const leftShow = ref(true);
const rightShow = ref(true);
// 树配置(模板树)
const defaultProps = {
children: 'children',
label: 'name',
value: 'id',
};
/** 初始化病历模板树(按科室筛选) */
const queryTemplateTree = async () => {
try {
const res = await getTreeList(queryParams.value);
templateData.value = res.data || [];
} catch (error) {
// ElMessage.error('获取模板树失败');
templateData.value = [];
}
};
// 处理节点点击,根据后台返回的路径加载组件
const handleNodeClick = (data, node) => {
if (node.isLeaf) {
// 存储当前节点数据
currentSelectTemplate.value = data.document;
currentComponent.value = currentSelectTemplate.value.vueRouter || '';
// currentComponent.value = data.document.vueRouter || '';
} else {
currentSelectTemplate.value = {
id: '',
};
// currentComponent.value = null;
}
historyRef.value?.queryList();
templateRef.value?.queryList();
};
const newEmr = () => {
if (currentSelectTemplate.value) {
currentComponent.value = currentSelectTemplate.value.vueRouter || '';
return;
}
ElMessage.error('请选择模版!');
};
const saveAsModel = async () => {
try {
currentOperate.value = 'addTemplate';
await emrComponentRef.value?.submit();
} catch (error) {
ElMessage.error('存为模版失败');
}
};
const editForm = ref({
id: '',
definitionId: '',
definitionBusNo: '',
contentJson: '',
statusEnum: 1, // 0草稿/暂存 1提交 2归档 3修改
organizationId: 0,
encounterId: '',
patientId: '',
recordTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
createBy: '',
source: '',
});
const editTemplateForm = ref({
id: '',
name: '',
displayOrder: 0,
contextJson: '',
definitionId: '',
useRange: 2,
organizationId: '',
userId: '',
remark: '',
});
const currentOperate = ref('add');
const handleSubmitOk = async (data) => {
if (currentOperate.value === 'add') {
//
try {
if (!patientInfo.value?.encounterId || !patientInfo.value?.patientId) {
ElMessage.error('请先选择患者!');
return;
}
editForm.value.definitionId = currentSelectTemplate.value.id;
editForm.value.definitionBusNo = currentSelectTemplate.value.busNo;
editForm.value.contentJson = JSON.stringify(data);
editForm.value.encounterId = patientInfo.value.encounterId;
editForm.value.patientId = patientInfo.value.patientId;
editForm.value.recordTime = dayjs().format('YYYY-MM-DD HH:mm:ss');
await addRecord(editForm.value);
ElMessage.success('病历保存成功');
historyRef.value?.queryList();
templateRef.value?.queryList();
// 通知父组件病历保存成功
emits('emrSaved', true);
} catch (error) {
ElMessage.error('提交失败');
console.log(error);
}
} else if (currentOperate.value === 'addTemplate') {
// 新增或者编辑模板
// editTemplateForm.value.id=
editTemplateForm.value.name =
currentSelectTemplate.value.name + dayjs().format('YYYY/MM/DD HH:mm');
editTemplateForm.value.contextJson = JSON.stringify(data);
editTemplateForm.value.definitionId = currentSelectTemplate.value.id;
templateEditVisible.value = true;
}
};
const refresh = () => {
queryTemplateTree();
historyRef.value?.queryList();
templateRef.value?.queryList();
};
const deleteEmr = async () => {
try {
// 这里应该添加实际的删除逻辑
ElMessage.success('删除成功!');
} catch (error) {
ElMessage.error('删除失败');
}
};
const save = async () => {
try {
currentOperate.value = 'add';
await emrComponentRef.value?.submit();
} catch (error) {
ElMessage.error('保存失败');
}
};
const historyRef = ref(null);
const handleHistoryClick = (data) => {
newEmr();
editForm.value = data;
nextTick(() => {
emrComponentRef.value?.setFormData(JSON.parse(editForm.value.contentJson));
});
};
const templateRef = ref(null);
const handleTemplateClick = (data) => {
newEmr();
editForm.value = data;
nextTick(() => {
emrComponentRef.value?.setFormData(JSON.parse(editForm.value.contextJson));
});
};
const templateEdit = (data) => {
editTemplateForm.value = data;
templateEditVisible.value = true;
};
// ====dialog
const templateEditVisible = ref(false);
// const templateEditSubmitOk = () => {};
// 打印方法实现
const print = async () => {
try {
// 检查是否有选中的病历模板
if (!currentSelectTemplate.value || !currentSelectTemplate.value.id) {
ElMessage.warning('请先选择病历模板');
return;
}
// 获取当前病历组件的表单数据
const formData = emrComponentRef.value?.formData || {};
// 准备打印数据不依赖子组件的getPrintData方法
// const printData = {
// // 使用当前选中的模板信息
// templateInfo: currentSelectTemplate.value,
// // 添加患者信息
// patientInfo: props.patientInfo,
// // 添加打印时间
// printTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
// // 添加基本病历信息
// emrInfo: {
// documentName: currentSelectTemplate.value.name || '住院病历',
// documentId: currentSelectTemplate.value.id || '',
// encounterId: props.patientInfo.encounterId || '',
// patientId: props.patientInfo.patientId || '',
// recordTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
// },
// // 添加病历表单数据(包含红框内的所有字段)
// formData: formData,
// doctorName: userStore.nickName,
// };
const printData = {
// 模板信息
templateName: currentSelectTemplate.value.name || '住院病历',
templateId: currentSelectTemplate.value.id || '',
// 医生信息
doctorName: userStore.nickName,
// 患者信息
patientName: props.patientInfo.patientName || '',
patientId: props.patientInfo.patientId || '',
medicalRecordNo: props.patientInfo.medicalRecordNo || '',
gender: props.patientInfo.gender || '',
age: props.patientInfo.age || '',
genderEnum_enumText: props.patientInfo.genderEnum_enumText || '',
idCard: props.patientInfo.idCard || '',
phone: props.patientInfo.phone || '',
registerTime: props.patientInfo.registerTime || '',
// 就诊信息
encounterId: props.patientInfo.encounterId || '',
department: props.patientInfo.department || '',
attendingDoctor: props.patientInfo.attendingDoctor || '',
// 病历信息
documentName: currentSelectTemplate.value.name || '住院病历',
documentId: currentSelectTemplate.value.id || '',
recordTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
printTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
// 表单数据 - 需要将嵌套结构展开
...flattenObject(formData),
};
// 执行打印
await simplePrint(PRINT_TEMPLATE.OUTPATIENT_MEDICAL_RECORD, printData);
ElMessage.success('打印成功');
} catch (error) {
console.error('打印失败:', error);
ElMessage.error('打印失败: ' + (error.message || '未知错误'));
}
};
// 辅助函数:将嵌套对象扁平化为单层结构
const flattenObject = (obj, prefix = '') => {
const flattened = {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
const newKey = prefix ? `${prefix}_${key}` : key;
if (typeof obj[key] === 'object' && obj[key] !== null && !Array.isArray(obj[key])) {
// 递归处理嵌套对象
Object.assign(flattened, flattenObject(obj[key], newKey));
} else if (Array.isArray(obj[key])) {
// 数组转换为字符串
flattened[newKey] = JSON.stringify(obj[key]);
} else {
// 基本类型直接赋值
flattened[newKey] = obj[key];
}
}
}
return flattened;
};
// 重新添加被覆盖的函数定义
const templateEditSubmitOk = () => {
templateEditVisible.value = false;
historyRef.value?.queryList();
templateRef.value?.queryList();
};
// onBeforeMount(() => {});
// 刚进页面默认显示门诊病历
const selectDefaultTemplate = () => {
nextTick(() => {
// 查找门诊病历(1.0.0)节点
const findTemplate = (nodes) => {
for (const node of nodes) {
if (node.children && node.children.length > 0) {
const found = findTemplate(node.children);
if (found) {
return found;
}
}
// 根据ID查找门诊病历模板
if (node.document && node.document.id === '1963474077201162242') {
return node;
}
}
return null;
};
const defaultTemplate = findTemplate(templateData.value);
if (defaultTemplate) {
// 模拟点击节点
const mockNode = {
isLeaf: true,
};
handleNodeClick(defaultTemplate, mockNode);
}
});
};
onMounted(async () => {
console.log('hospitalizationEmr mounted', userStore);
await queryTemplateTree();
selectDefaultTemplate();
});
defineExpose({ state });
const disNode = () => {
leftShow.value = !leftShow.value;
};
const disNode_R = () => {
rightShow.value = !rightShow.value;
};
</script>
<style lang="scss" scoped>
.emr-use-container {
display: flex;
height: 100%;
img {
width: 200%;
height: 200%;
}
.disBtn {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
overflow: hidden;
}
.disLeftBtnNor {
cursor: pointer;
position: absolute;
top: 40%;
left: 18%;
width: 20px;
height: 60px;
z-index: 1111;
img {
transform: rotate(-90deg);
}
}
.disLeftBtnAct {
cursor: pointer;
position: absolute;
top: 40%;
left: 0;
width: 20px;
height: 60px;
z-index: 1111;
img {
transform: rotate(90deg);
}
}
.disRightBtnNor {
cursor: pointer;
position: absolute;
top: 40%;
right: 18.5%;
width: 20px;
height: 60px;
z-index: 1111;
img {
transform: rotate(90deg);
}
}
.disRightBtnAct {
cursor: pointer;
position: absolute;
top: 40%;
right: 0;
width: 20px;
height: 60px;
z-index: 1111;
img {
transform: rotate(-90deg);
}
}
.template-tree-container {
border-right: 1px solid #ebeef5;
width: 300px;
flex: none;
height: 100%;
padding: 0 8px 8px 0;
display: flex;
flex-direction: column;
.search-box {
height: 40px;
display: flex;
align-items: center;
flex: none;
border-bottom: 1px solid #ebeef5;
}
.template-tree-scrollbar {
height: calc(100% - 48px);
flex: auto;
overflow-y: auto;
}
}
.operate-container {
width: 100%;
//width: 300px;
//flex: auto;
display: flex;
flex-direction: column;
padding: 0 8px 8px 8px;
.operate-btns {
height: 40px;
flex: none;
display: flex;
align-items: center;
border-bottom: 1px solid #ebeef5;
}
.operate-main {
height: calc(100vh - 150px);
flex: auto;
}
.operate-main .template-tree-scrollbar {
height: 100%;
overflow-y: auto;
}
}
.quickly-container {
border-left: 1px solid #ebeef5;
width: 300px;
padding: 0 8px 8px 8px;
flex: none;
.el-tabs {
height: 100%;
}
}
}
@layer utilities {
.transition-width {
transition-property: width;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 300ms;
}
}
</style>

View File

@@ -0,0 +1,210 @@
<!-- consumableDialog.vue -->
<template>
<el-dialog
v-model="dialogVisible"
title="绑定耗材"
width="700px"
:close-on-click-modal="false"
:before-close="handleClose"
>
<div class="consumable-dialog">
<div class="dialog-header">
<el-alert
title="该诊疗项目已绑定所需耗材,可修改数量或删除不需要的耗材,点击确定将自动添加到医嘱列表"
type="warning"
show-icon
:closable="false"
/>
</div>
<div class="table-container">
<el-table
ref="consumableTableRef"
:data="consumableList"
row-key="orderDefinitionId"
border
style="width: 100%"
>
<el-table-column type="selection" width="50" align="center" />
<el-table-column prop="orderDefinitionName" align="center" label="项目名称" />
<el-table-column prop="unitCodeName" label="单位" align="center" width="80">
<template #default="scope">
{{ scope.row.unitCodeName || '-' }}
</template>
</el-table-column>
<el-table-column label="数量/执行次数" align="center" width="120">
<template #default="scope">
<el-input-number
v-model="scope.row.quantity"
:min="1"
size="small"
controls-position="right"
style="width: 100%"
@change="handleQuantityChange(scope.row)"
/>
</template>
</el-table-column>
<el-table-column label="操作" width="80" align="center" fixed="right">
<template #default="scope">
<el-button type="danger" link size="small" @click="handleDeleteRow(scope.row)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
</div>
<!-- 下次不再提示复选框 -->
<div class="dont-show-again">
<el-checkbox v-model="dontShowAgain" @change="handleDontShowAgainChange">
下次不再提示
</el-checkbox>
</div>
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="handleClose">取消</el-button>
<el-button ref="submitRef" type="primary" @click="handleSubmit">确定</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup>
import { ElMessageBox, ElMessage } from 'element-plus';
import { ref, nextTick, onBeforeUnmount } from 'vue';
import useUserStore from '@/store/modules/user';
const dialogVisible = ref(false);
const consumableList = ref([]);
const consumableTableRef = ref();
const submitRef = ref();
const dontShowAgain = ref(false); // 下次不再提示的状态
const userStore = useUserStore();
// 定义事件
const emit = defineEmits(['submit']);
// 键盘事件处理函数
const handleKeyDown = (event) => {
// 检查是否按下了回车键
if (event.key === 'Enter' && dialogVisible.value) {
event.preventDefault();
handleSubmit();
}
};
// 打开弹窗方法
const open = (data) => {
consumableList.value = data;
dialogVisible.value = true;
// 默认全选
nextTick(() => {
if (consumableTableRef.value) {
consumableList.value.forEach((row) => {
consumableTableRef.value.toggleRowSelection(row, true);
});
}
// 注册键盘事件监听器
document.addEventListener('keydown', handleKeyDown);
});
};
// 关闭弹窗方法
const handleClose = () => {
// 移除键盘事件监听器
document.removeEventListener('keydown', handleKeyDown);
dialogVisible.value = false;
consumableList.value = [];
};
// 页面卸载前清理事件监听器
onBeforeUnmount(() => {
document.removeEventListener('keydown', handleKeyDown);
});
// 数量变化处理
const handleQuantityChange = (row) => {
if (row.quantity < 1) {
row.quantity = 1;
}
};
// 删除行处理
const handleDeleteRow = (row) => {
ElMessageBox.confirm(`确定要删除 "${row.orderDefinitionName}" 吗?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
const index = consumableList.value.findIndex(
(item) => item.orderDefinitionId === row.orderDefinitionId
);
if (index > -1) {
consumableList.value.splice(index, 1);
}
});
};
// 提交处理
const handleSubmit = () => {
const selectedRows = consumableTableRef.value.getSelectionRows();
// 保存到本地存储
localStorage.setItem('doctor' + userStore.id.toString(), dontShowAgain.value);
if (selectedRows.length === 0) {
ElMessage.warning('请至少选择一项耗材');
return;
}
// 发送事件给父组件
emit('submit', selectedRows);
// 关闭弹窗并清理事件监听器
document.removeEventListener('keydown', handleKeyDown);
dialogVisible.value = false;
consumableList.value = [];
};
// 暴露方法给父组件
defineExpose({
open,
close: handleClose,
});
</script>
<style lang="scss" scoped>
.consumable-dialog {
.dialog-header {
margin-bottom: 20px;
}
.table-container {
margin-bottom: 20px;
}
.dont-show-again {
margin-top: 10px;
text-align: left;
}
.dialog-footer-summary {
text-align: right;
.summary-text {
font-size: 14px;
color: #606266;
.total-amount {
font-size: 16px;
font-weight: bold;
color: #e64545;
}
}
}
}
.dialog-footer {
display: flex;
justify-content: flex-end;
align-items: center;
}
</style>

View File

@@ -42,7 +42,7 @@ const props = defineProps({
organizationId: {
type: String,
required: true,
}
},
});
const drawer = ref(false);
@@ -59,7 +59,7 @@ function handleOpen() {
getList();
}
function handelRadioChange(value){
function handelRadioChange(value) {
switch (value) {
case 1:
orderList.value = result.value.personalList;
@@ -74,24 +74,14 @@ function handelRadioChange(value){
}
function handleUseOrderGroup(row) {
// let value = JSON.parse(row.groupJson);
// value = value.map((item) => {
// return {
// ...item,
// conditionId: props.diagnosis.conditionId,
// conditionDefinitionId: props.diagnosis.definitionId,
// };
// });
// value.conditionId = props.diagnosis.conditionId;
// value.conditionDefinitionId = props.diagnosis.definitionId;
emit('useOrderGroup', row.detailList);
drawer.value = false;
}
function getList() {
getOrderGroup({ organizationId: props.organizationId }).then((res) => {
result.value = res.data
orderList.value = res.data.organizationList;
result.value = res.data;
handelRadioChange(queryParams.value.rangeCode);
});
}

View File

@@ -19,7 +19,7 @@
<span>{{ item.prescriptionNo }}</span>
</div>
<div style="text-align: center">
<h2>医院</h2>
<h2>长春大学医院</h2>
</div>
<div style="text-align: center">
<h3>处方单</h3>
@@ -76,7 +76,7 @@
<div class="medicen-list">
<div
style="margin-bottom: 3px"
v-for="(medItem, index) in item.prescriptionInfoDetail"
v-for="(medItem, index) in item.prescriptionInfoDetailList"
:key="medItem.requestId"
>
<span>{{ index + 1 + '. ' }}</span>
@@ -104,7 +104,7 @@
<div style="display: flex; justify-content: space-between">
<div>
<span class="item-label">医师</span>
<span class="item-value"></span>
<span class="item-value">{{ item.practitionerName }}</span>
</div>
<div>
<span class="item-label">收费</span>
@@ -112,7 +112,7 @@
</div>
<div>
<span class="item-label">合计</span>
<span class="item-value"></span>
<span class="item-value">{{ getTotalPrice(item) }}</span>
</div>
</div>
<div style="display: flex; justify-content: space-between">
@@ -139,9 +139,11 @@
</template>
</el-dialog>
</template>
<script setup>
import { formatDateStr } from '@/utils/index';
//高精度库
import Decimal from 'decimal.js';
const props = defineProps({
open: {
type: Boolean,
@@ -154,6 +156,17 @@ const props = defineProps({
});
const emit = defineEmits(['close']);
//合计
function getTotalPrice(item) {
let totalPrice = new Decimal(0);
item.prescriptionInfoDetailList.forEach((medItem) => {
const price = new Decimal(medItem.totalPrice);
const qty = new Decimal(medItem.quantity);
totalPrice = totalPrice.plus(price.times(qty));
});
return totalPrice.toNumber();
}
function close() {
emit('close');
}
@@ -202,4 +215,4 @@ function clickRow(row) {
width: 87px;
display: inline-block;
}
</style>
</style>

View File

@@ -126,7 +126,7 @@
<el-form-item prop="lotNumber" label="药房">
<el-select
v-model="scope.row.inventoryId"
style="width: 400px; margin-right: 20px"
style="width: 330px; margin-right: 20px"
placeholder="药房"
>
<el-option
@@ -167,7 +167,11 @@
</el-form-item>
<span class="medicine-info"> 注射药品:{{ scope.row.injectFlag_enumText }} </span>
<span class="total-amount">
总金额:{{ scope.row.totalPrice ? scope.row.totalPrice + ' 元' : '0.00 元' }}
总金额:{{
scope.row.totalPrice
? Number(scope.row.totalPrice).toFixed(2) + ' 元'
: '0.00 元'
}}
</span>
</div>
<div style="display: flex; align-items: center; gap: 12px; flex-wrap: wrap">
@@ -198,11 +202,7 @@
>
<template v-for="item in scope.row.unitCodeList" :key="item.value">
<el-option
v-if="
scope.row.unitCodeList.length == 3
? item.type == unitMap['minUnit']
: item.type == unitMap['unit']
"
v-if="item.type == unitMap['minUnit']"
:value="item.value"
:label="item.label"
/>
@@ -264,6 +264,8 @@
>
<el-option
v-for="dict in method_code"
@click="() => (scope.row.methodCode_dictText = dict.label)"
@keyup="handleEnter('methodCode', scope.row, scope.$index)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
@@ -292,12 +294,14 @@
if (!value) {
handleEnter('rateCode', scope.row, scope.$index);
}
// inputRefs.rateCode.blur();
}
"
:ref="(el) => { if (!inputRefs[scope.$index]) inputRefs[scope.$index] = {}; inputRefs[scope.$index].rateCode = el; }"
>
<el-option
v-for="dict in rate_code"
@click="() => (scope.row.rateCode_dictText = dict.label)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
@@ -371,7 +375,7 @@
>
<template v-for="item in scope.row.unitCodeList" :key="item.value">
<el-option
v-if="item.type != unitMap['dose']"
v-if="checkUnit(item, scope.row)"
:value="item.value"
:label="item.label"
@click="
@@ -750,7 +754,12 @@
/>
</el-form-item>
<span class="total-amount">
总金额:{{ scope.row.totalPrice ? scope.row.totalPrice + ' 元' : '0.00 元' }}
总金额:
{{
scope.row.totalPrice
? Number(scope.row.totalPrice).toFixed(2) + ' 元'
: '0.00 元'
}}
</span>
<span style="font-size: 16px; font-weight: 600">
<!-- 金额: {{ scope.row.priceList[0].price }} -->
@@ -798,7 +807,7 @@
<!-- 医嘱类型列 -->
<el-table-column label="医嘱类型" align="center" width="120">
<template #default="scope">
<template v-if="getRowDisabled(scope.row)">
<template v-if="scope.row.isEdit">
<el-select
v-model="scope.row.adviceType"
:ref="'adviceTypeRef_' + prescription.id + '_' + scope.$index"
@@ -832,7 +841,11 @@
:popoverVisible="scope.row.showPopover"
:adviceQueryParams="adviceQueryParams"
:patientInfo="props.patientInfo"
@selectAdviceBase="(row) => selectAdviceBase(scope.row.uniqueKey, row)"
@selectAdviceBase="
(row) => {
selectAdviceBase(scope.row.uniqueKey, row);
}
"
/>
<template #reference>
<el-input
@@ -841,6 +854,7 @@
placeholder="请选择项目"
@input="handleChange"
@click="handleFocus(scope.row, scope.$index)"
@blur="handleBlur(scope.row)"
@keyup.enter.stop="handleFocus(scope.row, scope.$index)"
@keydown="handleInputKeyDown(scope.row, $event)"
@blur="handleBlur(scope.row)"
@@ -964,9 +978,38 @@
:patientInfo="props.patientInfo"
@userPrescriptionHistory="handleSaveHistory"
/>
<OrderBindInfo ref="orderBindInfoRef" @submit="handleOrderBindInfo" />
</div>
<!-- 打印机选择对话框 -->
<!-- <el-dialog
v-model="isPrinterDialogVisible"
title="选择打印机"
width="400px"
:before-close="cancelPrinter"
>
<div class="printer-dialog-content">
<el-form label-position="top">
<el-form-item label="可用打印机">
<el-select v-model="selectedPrinter" placeholder="请选择打印机" style="width: 100%">
<el-option
v-for="printer in printerList"
:key="printer.name"
:label="printer.name"
:value="printer.name"
/>
</el-select>
</el-form-item>
</el-form>
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="cancelPrinter">取消</el-button>
<el-button type="primary" @click="confirmPrinter">确定</el-button>
</span>
</template>
</el-dialog> -->
</template>
<script setup>
import {
getDiagnosisDefinitionList,
@@ -981,16 +1024,25 @@ import {
updateGroupId,
getContract,
getAdviceBaseInfo,
getActivityBindDevice,
getBindDevice,
} from '../api';
import adviceBaseList from '../adviceBaseList.vue';
import { computed, getCurrentInstance, nextTick, watch, unref, reactive } from 'vue';
import { calculateQuantityByDays, formatNumber } from '@/utils/his';
import OrderGroupDrawer from './orderGroupDrawer';
import PrescriptionHistory from './prescriptionHistory';
import OrderBindInfo from './orderBindInfo';
import Decimal from 'decimal.js';
import useUserStore from '@/store/modules/user';
import { ElMessageBox } from 'element-plus';
import { ElMessageBox, ElMessage } from 'element-plus';
import { ArrowDown } from '@element-plus/icons-vue';
import { advicePrint } from '@/api/public';
// import printUtils, {
// PRINT_TEMPLATE,
// getPrinterList,
// getCachedPrinter,
// savePrinterToCache,
// } from '@/utils/printUtils';
const emit = defineEmits(['selectDiagnosis']);
const total = ref(0);
@@ -1006,7 +1058,6 @@ const adviceQueryParams = ref({
});
const rowIndex = ref(-1);
const groupIndex = ref(1);
const groupIndexList = ref([]);
const diagnosisList = ref([]);
const nextId = ref(1);
const unitCodeList = ref([]);
@@ -1047,6 +1098,7 @@ const props = defineProps({
},
});
const isAdding = ref(false);
const isSaving = ref(false);
const prescriptionRef = ref();
const expandOrder = ref([]); //目前的展开行
const stockList = ref([]);
@@ -1054,6 +1106,7 @@ const contractList = ref([]);
const conditionId = ref('');
const accountId = ref('');
const checkAll = ref(false);
const bindMethod = ref({});
const { proxy } = getCurrentInstance();
const inputRefs = ref({}); // 存储输入框实例,格式: { rowIndex: { fieldName: el } }
const requiredProps = ref([]); // 存储必填项 prop 顺序
@@ -1164,7 +1217,6 @@ watch(
() => prescriptionList.value,
(newVlaue) => {
if (newVlaue && newVlaue.length > 0) {
console.log(prescriptionList.value, 'prescriptionList.value');
handleTotalAmount();
}
},
@@ -1256,16 +1308,16 @@ function handleAdviceTypeChange(row, index) {
function handleTotalAmount() {
totalAmount.value = prescriptionList.value.reduce((accumulator, currentRow) => {
if (currentRow.chargeStatus != 8) {
return accumulator + (Number(currentRow.totalPrice) || 0);
return new Decimal(accumulator).add(currentRow.totalPrice || 0);
} else {
return 0;
// 跳过已退费项目,保持累加结果不变
return accumulator;
}
}, 0);
}, new Decimal(0));
}
getList();
function getList() {
getDiagnosisDefinitionList(queryParams.value).then((res) => {
// prescriptionList.value = res.data.records;
total.value = res.data.total;
});
}
@@ -1565,6 +1617,16 @@ function clickRow(row, column, cell, event, prescriptionId) {
emit('selectDiagnosis', row);
}
function checkUnit(item, row) {
if (item.type == 'dose') {
return false;
} else if (row.partAttributeEnum == '2' && item.type == 'minUnit') {
return false;
} else {
return true;
}
}
// 行双击打开编辑块,仅待发送的可编辑
function clickRowDb(row, event, prescriptionId) {
// 如果传入了处方ID先切换到该处方
@@ -1573,9 +1635,7 @@ function clickRowDb(row, event, prescriptionId) {
}
if (row.statusEnum == 1) {
row = { ...row, ...JSON.parse(row.contentJson), uniqueKey: row.uniqueKey };
row.isEdit = true;
row.doseUnitCode == JSON.parse(JSON.stringify(row.minUnitCode));
const index = prescriptionList.value.findIndex((item) => item.uniqueKey === row.uniqueKey);
prescriptionList.value[index] = row;
// 确保只有当前行展开先清空数组再添加当前行的uniqueKey
@@ -2018,11 +2078,12 @@ function handleDelete(prescriptionId) {
let sum = 0; // 未保存总数量
for (let i = prescriptionList.value.length - 1; i >= 0; i--) {
let deleteItem = prescriptionList.value[i];
let index = selectRows.findIndex((item) => item.uniqueKey === deleteItem.uniqueKey);
// 通过requestId判断是否已保存如果选中项未保存 直接从数组中移除,如果已保存,调接口删除
if (deleteItem.check && deleteItem.statusEnum == 1 && !deleteItem.requestId) {
if (index != -1 && deleteItem.statusEnum == 1 && !deleteItem.requestId) {
prescriptionList.value.splice(i, 1);
sum++;
} else if (deleteItem.check && deleteItem.statusEnum == 1 && deleteItem.requestId) {
} else if (index != -1 && deleteItem.statusEnum == 1 && deleteItem.requestId) {
deleteList.push({
requestId: deleteItem.requestId,
dbOpType: '3',
@@ -2037,14 +2098,12 @@ function handleDelete(prescriptionId) {
adviceQueryParams.value.categoryCode = undefined;
if (sum == selectRow.length) {
proxy.$modal.msgSuccess('删除成功');
groupIndexList.value = [];
return;
}
if (deleteList.length > 0) {
savePrescription({ adviceSaveList: deleteList }).then((res) => {
if (res.code == 200) {
proxy.$modal.msgSuccess('删除成功');
groupIndexList.value = [];
getListInfo(false);
}
});
@@ -2052,7 +2111,6 @@ function handleDelete(prescriptionId) {
proxy.$modal.msgWarning('所选医嘱不可删除,请先撤回后再删除');
return;
}
groupMarkers.value = getGroupMarkers(prescriptionList.value); // 删除行会出现组号混乱的情况,所以这里重新更新标记
}
// 选择药房/耗材房处理
@@ -2173,9 +2231,11 @@ function handleEmrTreatment() {
// 病历辅助检查字符串拼接
let auxiliaryExamination = '';
let auxiliaryExaminationIndex = 1;
prescriptionList.value.forEach((item, index) => {
if (item.chargeStatus != 8) {
if (item.adviceType == 1) {
// 药品处方
treatment += '处方[' + (index + 1) + ']' + ' ';
treatment += item.adviceName + ' ' + item.volume + ' ';
treatment +=
@@ -2188,9 +2248,22 @@ function handleEmrTreatment() {
item.methodCode_dictText +
' ';
treatmentIndex++;
} else if (item.adviceType == 2) {
// 诊疗项目
treatment += '诊疗[' + (index + 1) + ']' + ' ';
treatment += item.adviceName + ' ';
if (item.quantity) {
treatment += '数量:' + item.quantity + item.unitCode_dictText + ' ';
}
treatment += '频次:' + item.rateCode_dictText + ' ';
if (item.methodCode_dictText) {
treatment += '方式:' + item.methodCode_dictText + ' ';
}
treatment += ' ';
} else if (item.adviceType == 3) {
treatment += '[' + (index + 1) + ']' + ' ';
treatment += item.adviceName + ' ';
// 检查项目
auxiliaryExamination += '[' + (index + 1) + ']' + ' ';
auxiliaryExamination += item.adviceName + ' ';
auxiliaryExaminationIndex++;
}
}
@@ -2207,23 +2280,79 @@ function handleEmrTreatment() {
});
}
function handleClickOutside(row, index) {
nextTick(() => {
handleSaveSign(row, index);
});
}
function stockFormat(partPercent, unitList, quantity) {
let unitCode = unitList.find((item) => {
return item.type == 'unit';
})?.label;
let minUnitCode = unitList.find((item) => {
return item.type == 'minUnit';
})?.label;
function stockFormat(partPercent, unit, minUnit, quantity) {
let a = quantity % partPercent;
let b = Math.floor(quantity / partPercent);
console.log(partPercent, unit, minUnit, quantity);
if (a == 0) {
return b + ' ' + unit;
return b + ' ' + unitCode;
}
return b + ' ' + unit + ' ' + a + ' ' + minUnit;
return b + ' ' + unitCode + ' ' + a + ' ' + minUnitCode;
}
// 处理自动带出的诊疗或者耗材
function handleOrderBindInfo(bindIdInfo) {
const adviceDefinitionIds = bindIdInfo.map((row) => row.orderDefinitionId);
getAdviceBaseInfo({ adviceDefinitionIdParamList: adviceDefinitionIds.join(',') }).then((res) => {
const list = res.data.records.map((item) => {
const info = bindIdInfo.find((k) => k.orderDefinitionId == item.adviceDefinitionId);
return {
...item,
quantity: info.quantity,
unitCode: info.unitCode,
};
});
list?.forEach((item) => {
rowIndex.value = prescriptionList.value.length;
setValue(item);
// 创建新的处方项目
const newRow = {
...prescriptionList.value[rowIndex.value],
uniqueKey: nextId.value++,
patientId: props.patientInfo.patientId,
encounterId: props.patientInfo.encounterId,
accountId: accountId.value,
quantity: item.quantity,
methodCode: item.methodCode,
rateCode: item.rateCode,
dispensePerDuration: item.dispensePerDuration,
dose: item.dose,
doseQuantity: item.doseQuantity,
executeNum: 1,
unitCode: item.unitCode,
unitCode_dictText: item.unitCodeName || '',
statusEnum: 1,
dbOpType: prescriptionList.value[rowIndex.value].requestId ? '2' : '1',
conditionId: conditionId.value,
conditionDefinitionId: conditionDefinitionId.value,
encounterDiagnosisId: encounterDiagnosisId.value,
};
// 计算价格和总量
const unitInfo = unitCodeList.value.find((k) => k.value == item.unitCode);
if (unitInfo && unitInfo.type == 'minUnit') {
newRow.price = newRow.minUnitPrice;
newRow.totalPrice = (item.quantity * newRow.minUnitPrice).toFixed(6);
newRow.minUnitQuantity = item.quantity;
} else {
newRow.price = newRow.unitPrice;
newRow.totalPrice = (item.quantity * newRow.unitPrice).toFixed(6);
newRow.minUnitQuantity = item.quantity * item.partPercent;
}
newRow.contentJson = JSON.stringify(newRow);
prescriptionList.value[rowIndex.value] = newRow;
});
});
}
// 单行处方保存
function handleSaveSign(row, index, prescriptionId) {
// 如果传入了处方ID先切换到该处方
@@ -2272,6 +2401,29 @@ function handleSaveSign(row, index, prescriptionId) {
formRef.validate((valid) => {
if (valid) {
if (row.adviceType != 2) {
// 1:用法绑东西 2:诊疗绑东西
let typeCode = row.adviceType == 1 ? '1' : '2';
// 用法字典值/诊疗定义id
let itemNo = row.adviceType == 1 ? row.methodCode : row.adviceDefinitionId;
getBindDevice({ typeCode: typeCode, itemNo: itemNo }).then((res) => {
if (res.data.length == 0) {
return;
}
// 是否需要打开弹窗
let openBindDialog = localStorage.getItem('doctor' + userStore.id);
if (!JSON.parse(openBindDialog)) {
proxy.$refs['orderBindInfoRef'].open(res.data);
} else {
// 如果弹窗不提示带出的项目,自动带出
// 如果有未签发的项目,并且当前的项目没有带出过绑定项目,则自动带出
if (!bindMethod.value[itemNo]) {
handleOrderBindInfo(res.data);
bindMethod.value[itemNo] = true;
}
}
});
}
row.isEdit = false;
isAdding.value = false;
updateExpandOrder([]);
@@ -2453,23 +2605,17 @@ function handleSaveBatch(prescriptionId) {
function setValue(row) {
unitCodeList.value = [];
unitCodeList.value.push({ value: row.unitCode, label: row.unitCode_dictText, type: 'unit' });
if (row.doseUnitCode != row.minUnitCode) {
unitCodeList.value.push({
value: row.doseUnitCode,
label: row.doseUnitCode_dictText,
type: 'dose',
});
}
if (
(row.partAttributeEnum == 1 || row.partAttributeEnum == 3) &&
row.minUnitCode != row.unitCode
) {
unitCodeList.value.push({
value: row.minUnitCode,
label: row.minUnitCode_dictText,
type: 'minUnit',
});
}
unitCodeList.value.push({
value: row.doseUnitCode,
label: row.doseUnitCode_dictText,
type: 'dose',
});
unitCodeList.value.push({
value: row.minUnitCode,
label: row.minUnitCode_dictText,
type: 'minUnit',
});
if (row.adviceType == 2 && row.minUnitCode != row.unitCode) {
unitCodeList.value.push({
value: row.minUnitCode,
@@ -2527,10 +2673,9 @@ function setValue(row) {
return item.quantity > 0 && item.locationId == row.positionId;
})[0];
if (stock == {} || stock == undefined) {
proxy.$modal.msgWarning('该项目库存不足,请选择其它库房');
proxy.$modal.msgWarning(row.adviceName + '库存不足,请选择其它库房');
return;
}
// proxy.$modal.msgWarning('该项目库存不足,请选择其它库房');
// return;
}
prescriptionList.value[targetIndex].lotNumber = stock.lotNumber;
prescriptionList.value[targetIndex].inventoryId = stock.inventoryId;
@@ -2539,7 +2684,8 @@ function setValue(row) {
prescriptionList.value[targetIndex].positionName = stock.locationName;
prescriptionList.value[targetIndex].minUnitPrice = new Decimal(stock.price)
.div(row.partPercent)
.toFixed(2);
.toFixed(6);
prescriptionList.value[rowIndex.value].positionName = stock.locationName;
}
} else {
// 执行科室默认逻辑:优先使用诊疗项目维护的所属科室,如果没有则使用开单科室
@@ -2549,34 +2695,11 @@ function setValue(row) {
}
}
// 组套保存
// 选择组套
function handleSaveGroup(orderGroupList) {
// orderGroupList.map((item) => {
// item.patientId = props.patientInfo.patientId;
// item.encounterId = props.patientInfo.encounterId;
// item.accountId = accountId.value;
// item.dbOpType = item.requestId ? '2' : '1';
// item.minUnitQuantity = item.quantity * item.partPercent;
// item.conditionId = conditionId.value;
// item.conditionDefinitionId = conditionDefinitionId.value;
// item.encounterDiagnosisId = encounterDiagnosisId.value;
// item.contentJson = JSON.stringify(item);
// prescriptionList.value.push(item);
// });
// let paramList = orderGroupList.map((item) => {
// return item.adviceDefinitionId;
// });
// getAdviceBaseInfo({
// adviceDefinitionIdParamList: paramList.join(','),
// organizationId: props.patientInfo.orgId,
// }).then((res) => {
// getOrgList();
orderGroupList.forEach((item, index) => {
orderGroupList.forEach((item) => {
rowIndex.value = prescriptionList.value.length;
setValue(item.orderDetailInfos);
// let orderGroupValue = orderGroupList.find(
// (k) => k.adviceDefinitionId == item.adviceDefinitionId
// );
prescriptionList.value[targetIndex] = {
...prescriptionList.value[targetIndex],
@@ -2698,7 +2821,7 @@ function escKeyListener(e) {
}
prescriptionList.value.shift();
isAdding.value = false;
groupMarkers.value = getGroupMarkers(prescriptionList.value); // 删除行会出现组号混乱的情况,所以这里重新更新标记
getGroupMarkers(); // 删除行会出现组号混乱的情况,所以这里重新更新标记
}
}
}
@@ -2712,13 +2835,14 @@ function handleSingOut(prescriptionId) {
let requestIdList = prescriptionList.value
.filter((item) => {
return item.check && item.statusEnum == 2;
return item.statusEnum == 2;
})
.map((item) => {
return item.requestId;
});
if (requestIdList.length == 0) {
proxy.$modal.msgWarning('请选择已签发医嘱撤回');
return;
}
singOut(requestIdList).then((res) => {
if (res.code == 200) {
@@ -2726,12 +2850,11 @@ function handleSingOut(prescriptionId) {
getListInfo(false);
}
});
prescriptionRef.value.clearSelection();
}
function handleGroupId(paramList) {
updateGroupId(paramList).then(() => {
getListInfo(false);
});
updateGroupId(paramList);
}
// 组合
@@ -2747,31 +2870,22 @@ function combination(prescriptionId) {
proxy.$modal.msgWarning('至少选择两项');
return;
}
// 相同分组用法需要相同
let uniqueValues = new Set();
// 相同分组诊断需要相同
let uniqDiagnosis = new Set();
// 相同分组诊断需要相同
let uniqInjectFlag = new Set();
// 相同状态
let statusEnum = new Set();
let status = false;
let isSave = false;
groupIndexList.value.forEach((index) => {
if (prescriptionList.value[index].statusEnum == 2) {
selectRows.forEach((item) => {
if (item.statusEnum == 2) {
status = true;
}
if (prescriptionList.value[index].statusEnum == 1 && !prescriptionList.value[index].requestId) {
isSave = true;
}
uniqueValues.add(prescriptionList.value[index].methodCode);
uniqDiagnosis.add(prescriptionList.value[index].diagnosisName);
uniqInjectFlag.add(prescriptionList.value[index].injectFlag);
uniqueValues.add(item.methodCode);
uniqDiagnosis.add(item.diagnosisName);
statusEnum.add(item.statusEnumf);
});
// 校验是否有已签发的医嘱
if (isSave) {
proxy.$modal.msgWarning('请先保存当前医嘱后再进行分组');
return;
}
if (status) {
proxy.$modal.msgWarning('已签发医嘱不允许分组');
return;
@@ -2784,28 +2898,31 @@ function combination(prescriptionId) {
proxy.$modal.msgWarning('同一分组诊断必须相同');
return;
}
if (uniqInjectFlag.size != 1) {
proxy.$modal.msgWarning('同一分组必须全部为输液药品');
if (statusEnum.size != 1) {
proxy.$modal.msgWarning('不同状态医嘱无法组合');
return;
}
// 获取当前时间戳拼接组号做唯一组号
let timestamp = Date.now().toString();
let updateList = [];
groupIndexList.value.forEach((index) => {
selectRows.forEach((item) => {
// 直接更新表格数据中的groupId
const index = prescriptionList.value.findIndex((row) => row.uniqueKey === item.uniqueKey);
if (index !== -1) {
prescriptionList.value[index].groupId = timestamp + groupIndex.value;
}
updateList.push({
requestId: prescriptionList.value[index].requestId,
requestId: item.requestId,
groupId: timestamp + groupIndex.value,
});
// prescriptionList.value[index].groupId = JSON.parse(JSON.stringify(groupIndex.value));
prescriptionList.value[index].check = false;
});
// 更新组号
handleGroupId({ groupList: updateList });
// 根据组号排序
sortPrescriptionList();
groupMarkers.value = getGroupMarkers(prescriptionList.value); // 更新标记
groupIndex.value++;
groupIndexList.value = [];
if (selectRows[0].statusEnum == 1 && selectRows[0].requestId) {
// 更新组号
handleGroupId({ groupList: updateList });
}
prescriptionRef.value.clearSelection();
getGroupMarkers(); // 更新标记
}
// 拆组
@@ -2819,84 +2936,51 @@ function split(prescriptionId) {
proxy.$modal.msgWarning('至少选择一项');
return;
}
// 获取选中的所有行
const selectedRows = groupIndexList.value.map((index) => prescriptionList.value[index]);
// 校验是否包含已签发的医嘱
if (selectedRows.some((row) => row.statusEnum === 2)) {
if (selectRows.some((row) => row.statusEnum === 2)) {
proxy.$modal.msgWarning('已签发医嘱不允许拆组');
return;
}
// 提取出这些行涉及的所有 groupId
const selectedGroupIds = [...new Set(selectedRows.map((row) => row.groupId).filter(Boolean))];
if (selectedGroupIds.length === 0) {
if (selectRows.length === 0) {
proxy.$modal.msgWarning('请选择已分组的医嘱');
return;
}
// 构建最终要更新的列表
let updateList = [];
// 遍历每个 groupId
selectedGroupIds.forEach((groupId) => {
// 当前分组下所有的医嘱
const groupItems = prescriptionList.value.filter((item) => item.groupId === groupId);
// 当前分组中被选中的医嘱
const selectedInGroup = selectedRows.filter((row) => row.groupId === groupId);
// 如果选中数 = 总数 - 1 → 拆掉整个分组
if (selectedInGroup.length === groupItems.length - 1) {
updateList.push(
...groupItems.map((item) => ({
requestId: item.requestId,
groupId: '',
}))
);
} else {
// 否则只更新选中的
updateList.push(
...selectedInGroup.map((item) => ({
requestId: item.requestId,
groupId: '',
}))
);
selectRows.forEach((item) => {
// 直接更新表格数据中的groupId
const index = prescriptionList.value.findIndex((row) => row.uniqueKey === item.uniqueKey);
if (index !== -1) {
prescriptionList.value[index].groupId = undefined;
}
updateList.push({
requestId: item.requestId,
groupId: null,
});
});
// 清除本地数据中的 groupId
prescriptionList.value.forEach((item) => {
if (updateList.some((u) => u.requestId === item.requestId)) {
item.groupId = undefined;
item.check = false; // 取消勾选
}
});
// 更新分组号
handleGroupId({ groupList: updateList });
if (selectRows[0].statusEnum == 1 && selectRows[0].requestId) {
// 更新组号
handleGroupId({ groupList: updateList });
}
prescriptionRef.value.clearSelection();
// 更新分组标记
groupMarkers.value = getGroupMarkers(prescriptionList.value);
// 排序保持一致性
sortPrescriptionList();
// 清空选中索引
groupIndexList.value = [];
getGroupMarkers();
proxy.$modal.msgSuccess('拆组成功');
}
// 分组标记处理
function getGroupMarkers(prescriptionList) {
const groupMap = {};
const markers = [];
function getGroupMarkers() {
// 初始化所有行的 groupIcon 为 null
prescriptionList.value.forEach((item) => {
item.groupIcon = null;
});
// 遍历处方列表,记录每组的索引范围(忽略无 groupId 的项)
prescriptionList.forEach((item, index) => {
// 创建一个映射来存储每个 groupId 对应的行索引
const groupMap = {};
// 遍历处方列表,按 groupId 分组(忽略无 groupId 的项)
prescriptionList.value.forEach((item, index) => {
if (!item.groupId) {
markers[index] = null; // 没有组号的标记为 null
return;
}
@@ -2906,37 +2990,36 @@ function getGroupMarkers(prescriptionList) {
groupMap[item.groupId].push(index);
});
// 根据每组的索引范围设置标记
// 为每个组设置 groupIcon
Object.values(groupMap).forEach((indices) => {
if (indices.length === 1) {
// 单个组成员,显示上下括号
markers[indices[0]] = 'all';
} else {
// 只有当组内元素大于1个时才需要显示分组标记
if (indices.length > 1) {
indices.forEach((index, i) => {
if (i === 0) {
markers[index] = '┏';
// 第一行
prescriptionList.value[index].groupIcon = '┏';
} else if (i === indices.length - 1) {
markers[index] = '┗';
// 最后一行
prescriptionList.value[index].groupIcon = '┗';
} else {
markers[index] = '┃';
// 中间行
prescriptionList.value[index].groupIcon = '┃';
}
});
}
});
return markers;
}
const groupMarkers = ref([]);
// 计算总价
function calculateTotalPrice(row, index) {
nextTick(() => {
if (row.adviceType == 3) {
row.totalPrice = (row.unitPrice * row.quantity * 100) / 100;
row.totalPrice = (row.unitPrice * row.quantity).toFixed(6);
} else {
if (row.unitCode == row.minUnitCode) {
row.totalPrice = row.minUnitPrice * row.quantity;
row.totalPrice = (row.minUnitPrice * row.quantity).toFixed(6);
} else {
row.totalPrice = (row.unitPrice * row.quantity * 100) / 100;
row.totalPrice = (row.unitPrice * row.quantity).toFixed(6);
}
}
});
@@ -2945,7 +3028,7 @@ function calculateTotalPrice(row, index) {
// 单位切换时 自动计算对应单位的总量
function convertValues(row, index) {
nextTick(() => {
let code = unitCodeList.value.filter((item) => {
let code = row.unitCodeList.filter((item) => {
return item.value == row.doseUnitCode;
})[0];
@@ -2966,13 +3049,13 @@ function convertValues(row, index) {
break;
}
});
calculateTotalAmount(row, index);
// calculateTotalAmount(row, index);
}
// 单次剂量数量改变时自动计算总量
function convertDoseValues(row, index) {
nextTick(() => {
let code = unitCodeList.value.filter((item) => {
let code = row.unitCodeList.filter((item) => {
return item.value == row.doseUnitCode;
})[0];
@@ -2993,7 +3076,7 @@ function convertDoseValues(row, index) {
break;
}
});
calculateTotalAmount(row, index);
// calculateTotalAmount(row, index);
}
// 总量计算,仅适用只有两种单位的情况
@@ -3002,7 +3085,7 @@ function calculateTotalAmount(row, index) {
// 项目为西药或中成药时,根据用药天数和用药频次自动计算总量
if (row.adviceType == 1 || row.adviceType == 2) {
if (row.rateCode && row.dispensePerDuration) {
// 根据用药天数和用药频次计算数量
// 根据用药天数和用药频次计算数量,医生按顺序填的情况
let count = calculateQuantityByDays(row.rateCode, row.dispensePerDuration);
if (count) {
let quantity;
@@ -3038,6 +3121,13 @@ function calculateTotalAmount(row, index) {
}
}
}
} else if (row.quantity) {
// 如果医生开药先填总量 直接计算总价格
if (row.unitCode == row.minUnitCode) {
prescriptionList.value[index].totalPrice = (row.quantity * row.minUnitPrice).toFixed(6);
} else {
prescriptionList.value[index].totalPrice = (row.quantity * row.unitPrice).toFixed(6);
}
}
}
});
@@ -3577,11 +3667,12 @@ function getSignedPrescriptionInfo() {
defineExpose({ getListInfo, getDiagnosisInfo, getSignedPrescriptionInfo });
</script>
<style lang="scss" scoped>
:deep(.el-table__expand-icon) {
display: none !important;
}
.medicine-title {
font-size: 16px;
font-weight: 600;
@@ -3623,6 +3714,7 @@ defineExpose({ getListInfo, getDiagnosisInfo, getSignedPrescriptionInfo });
.el-input-number .el-input__inner {
text-align: center;
}
.el-table__cell .el-form-item--default {
margin-bottom: 0px;
}
@@ -3683,4 +3775,4 @@ defineExpose({ getListInfo, getDiagnosisInfo, getSignedPrescriptionInfo });
display: inline-block !important;
opacity: 1 !important;
}
</style>
</style>

View File

@@ -10,7 +10,9 @@
>
<div class="footer">
<div class="statistics">
<span> {{ total }} 个项目</span>
<span> </span>
<el-tag type="danger" style="font-size: 20px">{{ total }}</el-tag>
<span> 个项目 </span>
<!-- <span class="total">合计金额¥ {{ totalAmount.toFixed(2) }}</span> -->
</div>
</div>
@@ -38,6 +40,7 @@
v-loading="tableLoading"
border
height="600"
:span-method="tableSpanMethod"
>
<el-table-column
type="selection"
@@ -50,14 +53,15 @@
}
"
/>
<el-table-column label="支付单据号" align="center" prop="paymentId" width="180" />
<el-table-column label="处方号" align="center" prop="prescriptionNo" />
<el-table-column label="项目名" align="center" prop="itemName" />
<el-table-column label="项目名" align="center" prop="itemName" width="180" />
<el-table-column label="数量" align="center" prop="quantity" />
<el-table-column label="单位" align="center" prop="unitCode_dictText" />
<el-table-column label="收款金额" align="center" prop="totalPrice" />
<el-table-column label="发放状态" align="center">
<template #default="scope">
<el-tag v-if="scope.row.dispenseStatus != 0" type="default">
<el-tag v-if="scope.row.dispenseStatus != 0" type="danger">
{{ scope.row.dispenseStatus_enumText }}
</el-tag>
<el-tag v-else type="default">{{ scope.row.serviceStatus_enumText }}</el-tag>
@@ -110,7 +114,7 @@ const props = defineProps({
default: '',
},
});
const emit = defineEmits(['close']);
const emit = defineEmits(['close', 'refresh']);
const total = ref(0);
const tableLoading = ref(false);
const queryParams = ref({
@@ -126,7 +130,6 @@ const totalAmount = ref(0);
function openDialog() {
getList();
}
function getList() {
refundList.value = [];
tableLoading.value = true;
@@ -140,6 +143,40 @@ function getList() {
});
}
// 计算相同支付单据号的行合并信息(仅对相邻行生效)
const paymentIdRowSpans = computed(() => {
const data = refundList.value || [];
const spans = [];
let index = 0;
while (index < data.length) {
let next = index + 1;
while (next < data.length && data[next].paymentId === data[index].paymentId) {
next++;
}
const groupSize = next - index;
spans[index] = groupSize; // 首行显示合并行数
for (let i = index + 1; i < next; i++) {
spans[i] = 0; // 其余行隐藏
}
index = next;
}
return spans;
});
function tableSpanMethod({ row, column, rowIndex }) {
// 仅合并“支付单据号”列
if (column && column.property === 'paymentId') {
const rowspan = paymentIdRowSpans.value[rowIndex] ?? 1;
return { rowspan, colspan: rowspan > 0 ? 1 : 0 };
}
// 仅合并“处方号”列
if (column && column.property === 'prescriptionNo') {
const rowspan = paymentIdRowSpans.value[rowIndex] ?? 1;
return { rowspan, colspan: rowspan > 0 ? 1 : 0 };
}
return { rowspan: 1, colspan: 1 };
}
function submit() {
// 1. 获取当前选中行并提取去重的 paymentId 列表
const selectedRows = proxy.$refs['refundListRef'].getSelectionRows();
@@ -162,6 +199,7 @@ function submit() {
if (res.code === 200) {
proxy.$modal.msgSuccess('操作成功');
getList();
emit('refresh');
}
});

View File

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