版本更新

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

View File

@@ -0,0 +1,147 @@
<template>
<div @keyup="handleKeyDown" tabindex="0" ref="tableWrapper">
<el-table
ref="adviceBaseRef"
height="400"
:data="adviceBaseList"
highlight-current-row
@current-change="handleCurrentChange"
row-key="patientId"
@cell-click="clickRow"
>
<el-table-column label="名称" align="center" prop="adviceName" />
<el-table-column label="类型" align="center" prop="activityType_enumText" />
<el-table-column label="包装单位" align="center" prop="unitCode_dictText" />
<el-table-column label="最小单位" align="center" prop="minUnitCode_dictText" />
<el-table-column label="规格" align="center" prop="volume" />
<el-table-column label="用法" align="center" prop="methodCode_dictText" />
<el-table-column label="频次" align="center" prop="rateCode_dictText" />
<el-table-column label="单次剂量" align="center" prop="dose" />
<el-table-column label="剂量单位" align="center" prop="doseUnitCode_dictText" />
<el-table-column label="注射药品" align="center" prop="injectFlag_enumText" />
<el-table-column label="皮试" align="center" prop="skinTestFlag_enumText" />
</el-table>
</div>
</template>
<script setup>
import { nextTick } from 'vue';
import { getAdviceBaseInfo } from './api';
import { throttle } from 'lodash-es';
const props = defineProps({
adviceQueryParams: {
type: Object,
default: '',
},
patientInfo: {
type: Object,
required: true,
},
});
const emit = defineEmits(['selectAdviceBase']);
const total = ref(0);
const adviceBaseRef = ref();
const tableWrapper = ref();
const currentIndex = ref(0); // 当前选中行索引
const currentSelectRow = ref({});
const queryParams = ref({
pageSize: 100,
pageNum: 1,
});
const adviceBaseList = ref([]);
// 节流函数
const throttledGetList = throttle(
() => {
getList();
},
300,
{ leading: true, trailing: true }
);
watch(
() => props.adviceQueryParams,
(newValue) => {
queryParams.value.searchKey = newValue.searchKey;
queryParams.value.adviceType = newValue.adviceType;
throttledGetList();
},
{ deep: true }
);
getList();
function getList() {
queryParams.value.organizationId = props.patientInfo.orgId;
getAdviceBaseInfo(queryParams.value).then((res) => {
adviceBaseList.value = res.data.records;
total.value = res.data.total;
nextTick(() => {
currentIndex.value = 0;
if (adviceBaseList.value.length > 0) {
adviceBaseRef.value.setCurrentRow(adviceBaseList.value[0]);
}
});
});
}
// 处理键盘事件
const handleKeyDown = (event) => {
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': // 回车键
// const currentRow = adviceBaseRef.value.getSelectionRows();
event.preventDefault();
if (currentSelectRow.value) {
// 这里可以触发自定义逻辑,如弹窗、跳转等
emit('selectAdviceBase', currentSelectRow.value);
}
break;
}
};
// 设置选中行(带滚动)
const setCurrentRow = (row) => {
adviceBaseRef.value.setCurrentRow(row);
// 滚动到选中行
const tableBody = adviceBaseRef.value.$el.querySelector('.el-table__body-wrapper');
const currentRowEl = adviceBaseRef.value.$el.querySelector('.current-row');
if (tableBody && currentRowEl) {
currentRowEl.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}
};
// 当前行变化时更新索引
const handleCurrentChange = (currentRow) => {
currentIndex.value = adviceBaseList.value.findIndex((item) => item === currentRow);
currentSelectRow.value = currentRow;
};
function clickRow(row) {
emit('selectAdviceBase', row);
}
defineExpose({
handleKeyDown,
});
</script>
<style scoped>
.popover-table-wrapper:focus {
outline: 2px solid #409eff; /* 聚焦时的高亮效果 */
}
</style>

View File

@@ -0,0 +1,202 @@
import request from '@/utils/request'
/**
* 获取患者列表
*/
export function getList(queryParams) {
return request({
url: '/charge-manage/pricing/patient-info',
method: 'get',
params: queryParams
})
}
// 处方相关接口
/**
* 获取药品列表
*/
export function getAdviceBaseInfo(queryParams) {
return request({
url: '/charge-manage/pricing/advice-base-info',
method: 'get',
params: queryParams
})
}
/**
* 保存处方(单条)
*/
export function savePrescription(data) {
return request({
url: '/doctor-station/advice/save-advice',
method: 'post',
data: data
})
}
/**
* 签发处方
*/
export function savePrescriptionSign(data) {
return request({
url: '/doctor-station/advice/sign-advice',
method: 'post',
data: data
})
}
/**
* 处方签退
*/
export function singOut(data) {
return request({
url: '/doctor-station/advice/sign-off',
method: 'post',
data: data
})
}
/**
* 获取患者本次就诊处方
*/
export function getPrescriptionList(encounterId) {
return request({
url: '/doctor-station/advice/request-base-info?encounterId=' + encounterId,
method: 'get',
})
}
/**
* 获取科室列表
*/
export function getOrgTree() {
return request({
url: '/base-data-manage/organization/organization',
method: 'get',
})
}
/**
* 获取退费账单
*/
export function getEncounterPatientPayment(encounterId) {
return request({
url: '/charge-manage/refund/patient-payment?encounterId=' + encounterId,
method: 'get',
})
}
/**
* 申请退费
*/
export function refundPayment(data) {
return request({
url: '/charge-manage/refund/refund-payment',
method: 'post',
data: data
})
}
// 电子处方相关接口
/**
* 电子处方查询
*/
export function getVeriPrescriptionInfo(queryParams) {
return request({
url: '/ybelep-request/get-PrescriptionInfo',
method: 'get',
params: queryParams
})
}
// 处方开立相关接口
/**
* 获取全部药品信息
*/
export function getAllMedicationInfo(queryParams) {
return request({
url: '/doctor-station/elep/get-allMedicationInfo',
method: 'get',
params: queryParams
})
}
/**
* 电子处方下拉框
*/
export function elepPrescriptionInit() {
return request({
url: '/doctor-station/elep/init',
method: 'get'
})
}
/**
* 获取处方信息
*/
export function getPrescriptionInfo(queryParams) {
return request({
url: '/doctor-station/elep/get-prescriptionInfo',
method: 'get',
params: queryParams
})
}
/**
* 获取药品信息
*/
export function getMedicationInfo(queryParams) {
return request({
url: '/doctor-station/elep/get-medicationInfo',
method: 'get',
params: queryParams
})
}
/**
* 获取单据号
*/
export function prescriptionNoInit() {
return request({
url: '/doctor-station/elep/prescriptionNoInit',
method: 'get'
})
}
/**
* 新增处方
*/
export function savePrescriptionInfo(data) {
return request({
url: '/doctor-station/elep/save-prescriptionInfo',
method: 'post',
data: data
})
}
/**
* 修改处方
*/
export function updatePrescriptionInfo(data) {
return request({
url: '/doctor-station/elep/update-prescriptionInfo',
method: 'post',
data: data
})
}
/**
* 删除处方
*/
export function deletePrescriptionInfo(data) {
return request({
url: '/doctor-station/elep/delete-prescriptionInfo',
method: 'post',
data: data
})
}
/**
* 签发处方
*/
export function issuancePrescription(prescriptionNoList) {
return request({
url: '/doctor-station/elep/issuance-prescription',
method: 'post',
data: prescriptionNoList
})
}

View File

@@ -0,0 +1,797 @@
<template>
<div style="width: 100%">
<div style="margin-bottom: 5px">
<el-button type="primary" @click="handleAddPrescription()" :disabled="false">
新增
</el-button>
<el-button type="primary" @click="handleSave()" :disabled="handleSaveDisabled"> 签发 </el-button>
<el-button type="warning" plain @click="handleSingOut()" :disabled="handleSingOutDisabled"> 签退 </el-button>
<!-- <el-button type="primary" plain @click="open()" :disabled="false"> 组套 </el-button> -->
<el-button type="danger" plain @click="handleDelete()" :disabled="false"> 删除 </el-button>
</div>
<el-table
max-height="650"
ref="prescriptionRef"
:data="prescriptionList"
row-key="uniqueKey"
border
@row-dblclick="clickRowDb"
:expand-row-keys="expandOrder"
>
<el-table-column type="expand" width="1" style="width: 0">
<template #default="scope">
<el-form :model="scope.row" :rules="rowRules" :ref="'formRef' + scope.$index">
<div style="padding: 16px; background: #f8f9fa; border-radius: 8px">
<template v-if="scope.row.adviceType == 2">
<div style="display: flex; align-items: center; margin-bottom: 16px; gap: 16px">
<span style="font-size: 16px; font-weight: 600">
{{
scope.row.adviceName +
' ' +
scope.row.volume +
' ' +
scope.row.unitPrice +
' 元/' +
scope.row.unitCode_dictText
}}
</span>
<div class="form-group">
<el-select
v-model="scope.row.lotNumber"
style="width: 180px; margin-right: 20px"
placeholder="药房"
>
<el-option
v-for="item in scope.row.stockList"
:key="item.lotNumber"
:value="item.lotNumber"
:label="
item.locationName +
' ' +
'批次号: ' +
item.lotNumber +
' ' +
' 库存:' +
item.quantity / scope.row.partPercent +
item.unitCode_dictText +
' 单价:' +
item.price.toFixed(2) +
'/' +
item.unitCode_dictText
"
@click="handleNumberClick(item, scope.$index)"
/>
</el-select>
<el-form-item
label="数量:"
prop="quantity"
class="required-field"
data-prop="quantity"
>
<el-input-number
placeholder="数量"
v-model="scope.row.quantity"
style="width: 70px"
controls-position="right"
:controls="false"
@keyup.enter.prevent="handleEnter('quantity', scope.row, scope.$index)"
@input="calculateTotalPrice(scope.row, scope.$index)"
/>
</el-form-item>
<el-select
v-model="scope.row.unitCode"
style="width: 70px; margin-right: 20px"
placeholder=" "
@change="calculateTotalAmount(scope.row, scope.$index)"
>
<template v-for="item in scope.row.unitCodeList" :key="item.value">
<el-option
v-if="item.type != unitMap['dose']"
:value="item.value"
:label="item.label"
/>
</template>
</el-select>
<span class="total-amount">
总金额{{ scope.row.totalPrice ? scope.row.totalPrice + ' 元' : '0.00 元' }}
</span>
</div>
<el-button type="primary" @click="handleSaveSign(scope.row, scope.$index)">
保存
</el-button>
</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">
{{
scope.row.adviceName + ' ' + scope.row.unitPrice
? Number(scope.row.unitPrice).toFixed(2)
: '-' + '元'
}}
</span>
<div class="form-group">
<el-form-item
label="执行次数:"
prop="quantity"
class="required-field"
data-prop="quantity"
>
<el-input-number
placeholder="执行次数"
style="width: 100px; margin: 0 20px"
v-model="scope.row.quantity"
controls-position="right"
:controls="false"
@keyup.enter.prevent="handleEnter('quantity', scope.row, scope.$index)"
@input="calculateTotalPrice(scope.row, scope.$index)"
/>
</el-form-item>
<el-tree-select
clearable
v-model="scope.row.orgId"
:data="organization"
:props="{ value: 'id', label: 'name', children: 'children' }"
value-key="id"
check-strictly
placeholder="请选择执行科室"
/>
<span class="total-amount">
总金额{{ scope.row.totalPrice ? scope.row.totalPrice + ' 元' : '0.00 元' }}
</span>
<span style="font-size: 16px; font-weight: 600">
<!-- 金额: {{ scope.row.priceList[0].price }} -->
</span>
</div>
<el-button type="primary" @click="handleSaveSign(scope.row, scope.$index)">
保存
</el-button>
</div>
</template>
</div>
</el-form>
</template>
</el-table-column>
<el-table-column label="" align="center" prop="groupId" width="60">
<template #default="scope">
<el-checkbox
:disabled = "scope.row.bizRequestFlag==0"
v-model="scope.row.check"
placeholder=""
@click.stop=""
@change="changeCheck(scope.row.check,scope.$index,scope.row)"
/>
</template>
<!-- (value) => {
if (value) {
groupIndexList.push(scope.$index);
} else {
groupIndexList.splice(groupIndexList.indexOf(scope.$index), 1);
}
} -->
</el-table-column>
<el-table-column label="项目" align="center" prop="productName" width="400">
<template #default="scope">
<template v-if="getRowDisabled(scope.row)">
<el-select
style="width: 35%; margin-right: 20px"
v-model="scope.row.adviceType"
:ref="'adviceTypeRef' + scope.$index"
@change="
(value) => {
expandOrder = [];
prescriptionList[scope.$index].adviceName = undefined;
adviceQueryParams.adviceType = value;
}
"
>
<el-option
v-for="item in adviceTypeList"
:key="item.value"
:label="item.label"
:value="item.value"
@click="
() => {
prescriptionList[scope.$index].adviceType = item.value;
prescriptionList[scope.$index].adviceType_dictText = item.label;
}
"
/>
</el-select>
<el-popover
:popper-style="{ padding: '0' }"
placement="bottom-start"
:visible="scope.row.showPopover"
:width="1200"
>
<adviceBaseList
ref="adviceTableRef"
:popoverVisible="scope.row.showPopover"
:adviceQueryParams="adviceQueryParams"
:patientInfo="props.patientInfo"
@selectAdviceBase="(row) => selectAdviceBase(scope.row.uniqueKey, row)"
/>
<template #reference>
<el-input
:ref="'adviceRef' + scope.$index"
style="width: 50%"
v-model="scope.row.adviceName"
placeholder="请选择项目"
@input="handleChange"
@click="handleFocus(scope.row, scope.$index)"
@keyup.enter.stop="handleFocus(scope.row, scope.$index)"
@keydown="
(e) => {
if (!scope.row.showPopover) return;
// 拦截上下键和回车事件
if (['ArrowUp', 'ArrowDown', 'Enter'].includes(e.key)) {
e.preventDefault();
// 传递事件到弹窗容器
adviceTableRef.handleKeyDown(e);
}
}
"
@blur="handleBlur(scope.row)"
/>
</template>
</el-popover>
</template>
<span v-else>{{ scope.row.adviceName }}</span>
</template>
</el-table-column>
<el-table-column label="状态" align="center" prop="" width="90">
<template #default="scope">
<el-tag v-if="scope.row.statusEnum == 2" type="success">已签发</el-tag>
<el-tag v-else-if="scope.row.statusEnum == 1" type="">待签发</el-tag>
</template>
</el-table-column>
<el-table-column label="总量" align="center" prop="">
<template #default="scope">
<span v-if="!scope.row.isEdit">
{{ scope.row.quantity ? scope.row.quantity + ' ' + scope.row.unitCode_dictText : '' }}
</span>
</template>
</el-table-column>
<el-table-column label="总金额" align="right" prop="" header-align="center">
<template #default="scope">
<span v-if="!scope.row.isEdit" style="text-align: right">
{{ scope.row.totalPrice ? Number(scope.row.totalPrice).toFixed(2) + ' ' : '-' }}
</span>
</template>
</el-table-column>
<el-table-column label="药房/科室" align="center" prop="" width="240">
<template #default="scope">
<span v-if="!scope.row.isEdit">
{{ scope.row.positionName }}
</span>
</template>
</el-table-column>
<el-table-column label="签发人" align="center" prop="" width="240">
<template #default="scope">
<span v-if="!scope.row.isEdit">
{{ scope.row.requesterId_dictText }}
</span>
</template>
</el-table-column>
<el-table-column label="签发时间" align="center" prop="" width="240">
<template #default="scope">
<span v-if="!scope.row.isEdit">
{{ scope.row.requestTime }}
</span>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script setup>
import {
savePrescription,
getPrescriptionList,
getOrgTree,
savePrescriptionSign,
singOut,
} from './api';
import adviceBaseList from './adviceBaseList';
import { getCurrentInstance, nextTick, ref, watch } from 'vue';
const emit = defineEmits(['selectDiagnosis']);
const prescriptionList = ref([]);
const form = ref({
prescriptionList: prescriptionList.value,
});
const adviceQueryParams = ref({});
const rowIndex = ref(-1);
const groupIndexList = ref([]);
const nextId = ref(1);
const unitCodeList = ref([]);
const adviceTableRef = ref([]);
const organization = ref([]);
const rowRules = ref({
conditionDefinitionId: [{ required: true, message: '请选择诊断', trigger: 'change' }],
dose: [{ required: true, message: '请输入单次剂量', trigger: 'change' }],
doseQuantity: [{ required: true, message: '请输入单次剂量', trigger: 'change' }],
quantity: [{ required: true, message: '请输入数量', trigger: 'change' }],
dispensePerDuration: [{ required: true, message: '请输入用药天数', trigger: 'change' }],
});
const unitMap = ref({
dose: 'dose',
minUnit: 'minUnit',
unit: 'unit',
});
const props = defineProps({
patientInfo: {
type: Object,
required: true,
},
activeTab: {
type: String,
},
});
const isAdding = ref(false);
const prescriptionRef = ref();
const expandOrder = ref([]); //目前的展开行
const stockList = ref([]);
const groupList = ref([])
const { proxy } = getCurrentInstance();
const inputRefs = ref({}); // 存储输入框实例
const requiredProps = ref([]); // 存储必填项 prop 顺序
const { method_code, unit_code, rate_code, distribution_category_code } = proxy.useDict(
'method_code',
'unit_code',
'rate_code',
'distribution_category_code'
);
const handleSaveDisabled = ref(false) //签发状态
const handleSingOutDisabled = ref(false) //签退状态
const adviceTypeList = ref([
{
label: '耗材',
value: 2,
},
{
label: '诊疗',
value: 3,
},
{
label: '全部',
value: undefined,
},
]);
watch(
() => expandOrder.value,
(newValue) => {
console.log(newValue,"监听·")
if (newValue.length > 0) {
nextTick(() => {
const index = prescriptionList.value.findIndex((row) => row.uniqueKey === newValue[0]);
const items = proxy.$refs['formRef' + index]?.$el?.querySelectorAll('[data-prop]');
requiredProps.value = Array.from(items).map((item) => item.dataset.prop);
});
} else {
requiredProps.value = {};
}
}
);
watch(
() => prescriptionList.value,
(newValue) => {
console.log(prescriptionList.value,"prescriptionList.value")
if(newValue&&newValue.length>0){
let saveList = prescriptionList.value.filter((item) => {
return item.statusEnum == 1&&(Number(item.bizRequestFlag)==1||!item.bizRequestFlag)
})
prescriptionList.value.map(k=>{
k.check = false
})
console.log(saveList,"prescriptionList.value")
if (saveList.length == 0) {
handleSaveDisabled.value = true
}else{
handleSaveDisabled.value = false
}
}
},
{ immediate: true }
);
function getListInfo(addNewRow) {
isAdding.value = false;
getPrescriptionList(props.patientInfo.encounterId).then((res) => {
prescriptionList.value = res.data;
if (props.activeTab == 'prescription' && addNewRow) {
handleAddPrescription();
}
});
}
function getRowDisabled(row) {
return row.isEdit;
}
// 新增医嘱
function handleAddPrescription() {
if (isAdding.value) {
proxy.$modal.msgWarning('请先保存当前医嘱');
return;
}
isAdding.value = true;
// 在数组最前方添加一行,让新增行显示在最上边
prescriptionList.value.unshift({
uniqueKey: nextId.value++,
showPopover: false,
check: false,
isEdit: true,
statusEnum: 1,
});
nextTick(() => {
proxy.$refs['adviceRef0'].focus();
});
}
// 行双击打开编辑块,仅待发送的可编辑
function clickRowDb(row) {
if (row.statusEnum == 1) {
row = { ...row, ...JSON.parse(row.contentJson) };
row.isEdit = true;
const index = prescriptionList.value.findIndex((item) => item.uniqueKey === row.uniqueKey);
prescriptionList.value[index] = row;
console.log(prescriptionList.value,"prescriptionList.value")
expandOrder.value = [row.uniqueKey];
}
}
function handleDiagnosisChange(item, row) {
row.diagnosisName = item.name;
row.conditionId = item.conditionId;
}
function handleFocus(row, index) {
rowIndex.value = index;
row.showPopover = true;
}
function handleBlur(row) {
row.showPopover = false;
}
function handleChange(value) {
adviceQueryParams.value.searchKey = value;
}
/**
* 选择药品回调
*/
function selectAdviceBase(key, row) {
getOrgList();
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',
});
}
prescriptionList.value[rowIndex.value] = {
...prescriptionList.value[rowIndex.value],
...JSON.parse(JSON.stringify(row)),
};
prescriptionList.value[rowIndex.value].orgId = undefined;
prescriptionList.value[rowIndex.value].dose = undefined;
prescriptionList.value[rowIndex.value].unitCodeList = unitCodeList.value;
prescriptionList.value[rowIndex.value].doseUnitCode =
row.minUnitCode != row.unitCode ? row.minUnitCode : row.unitCode;
prescriptionList.value[rowIndex.value].minUnitCode = JSON.parse(JSON.stringify(row.doseUnitCode));
prescriptionList.value[rowIndex.value].unitCode =
row.partAttributeEnum == 1 ? row.minUnitCode : row.unitCode;
// prescriptionList.value[rowIndex.value].doseUnitCode_dictText = row.minUnitCode_dictText;
prescriptionList.value[rowIndex.value].definitionId = JSON.parse(
JSON.stringify(row)
).chargeItemDefinitionId;
// 库存列表 + 价格列表拼成批次号的下拉框
if (row.adviceType != 3) {
if (row.inventoryList && row.inventoryList.length == 0) {
expandOrder.value = [];
proxy.$modal.msgWarning('该项目无库存');
return;
}
stockList.value = row.inventoryList.map((item, index) => {
return { ...item, ...row.priceList[index] };
});
prescriptionList.value[rowIndex.value].stockList = stockList.value;
// 获取默认批次号的库存,如果没有让医生重新选
let stock = stockList.value.filter((item) => {
return item.lotNumber == row.defaultLotNumber;
})[0];
if (stock != {} && stock != undefined) {
if (stock.quantity <= 0) {
proxy.$modal.msgWarning('该项目库存不足,请选择其它库房');
// return;
}
prescriptionList.value[rowIndex.value].lotNumber = stock.lotNumber;
prescriptionList.value[rowIndex.value].inventoryId = stock.inventoryId;
prescriptionList.value[rowIndex.value].locationId = stock.locationId;
prescriptionList.value[rowIndex.value].unitPrice = stock.price;
prescriptionList.value[rowIndex.value].positionName = stock.locationName;
}
} else {
prescriptionList.value[rowIndex.value].orgId = JSON.parse(JSON.stringify(row)).positionId;
prescriptionList.value[rowIndex.value].unitPrice = row.priceList[0].price;
}
expandOrder.value = [key];
nextTick(() => {
if (row.adviceType == 1) {
if (row.injectFlag == 1) {
inputRefs.value['executeNum']?.focus();
} else {
inputRefs.value['dose']?.focus();
}
} else {
inputRefs.value['quantity']?.focus();
}
});
}
function getOrgList() {
getOrgTree().then((res) => {
organization.value = res.data.records;
console.log(organization.value,"organization.value")
});
}
function handleDelete() {
let deleteList = prescriptionList.value
.filter((item) => {
return item.check && item.statusEnum == 1;
})
.map((item) => {
return {
requestId: item.requestId,
dbOpType: '3',
adviceType: item.adviceType,
};
});
if (deleteList.length == 0) {
proxy.$modal.msgWarning('请选择要删除的项目');
return;
}
if (!deleteList[0].requestId) {
prescriptionList.value.shift();
} else {
savePrescription({ adviceSaveList: deleteList }).then((res) => {
if (res.code == 200) {
proxy.$modal.msgSuccess('操作成功');
getListInfo(false);
}
});
}
// groupIndexList.value
// .sort((a, b) => b - a)
// .forEach((item) => {
// prescriptionList.value.splice(item, 1);
// });
// groupIndexList.value = [];
expandOrder.value = [];
isAdding.value = false;
adviceQueryParams.value.adviceType = undefined;
// prescriptionList.value.splice(index, 1);
}
function handleNumberClick(item, index) {
prescriptionList.value[index].unitPrice = item.price;
// prescriptionList.value[index].lotNumber = item.lotNumber;
prescriptionList.value[index].locationId = item.locationId;
prescriptionList.value[index].positionId = item.locationId;
prescriptionList.value[index].positionName = item.locationName;
}
function changeCheck(value,index,row){
if (value) {
groupIndexList.value.push(index)
groupList.value.push(row)
} else {
groupIndexList.value.splice(groupIndexList.value.indexOf(index), 1)
groupList.value.splice(groupList.value.indexOf(index), 1)
}
groupList.value.map(k=>{
if(k.check){
if(k.statusEnum == 1){//待签发
if(Number(k.bizRequestFlag)==1||!k.bizRequestFlag){
if(handleSaveDisabled.value&&!handleSingOutDisabled.value&&groupList.value.length>1){
proxy.$modal.msgWarning('请选择相同的状态的项目进行操作')
return
}else{
handleSaveDisabled.value = false
handleSingOutDisabled.value = true
}
}else{
handleSaveDisabled.value = true
handleSingOutDisabled.value = true
return
}
}
if(k.statusEnum == 2){ //已签发
if(Number(k.bizRequestFlag)==1||!k.bizRequestFlag){
if(!handleSaveDisabled.value&&handleSingOutDisabled.value&&groupList.value.length>1){
proxy.$modal.msgWarning('请选择相同的状态的项目进行操作')
return
}else{
handleSaveDisabled.value = true
handleSingOutDisabled.value = false
}
}else{
handleSaveDisabled.value = true
handleSingOutDisabled.value = true
return
}
}
}
})
console.log(groupIndexList.value,"!21")
}
/**
* 保存处方
*/
function handleSave() {
if (expandOrder.value.length > 0) {
proxy.$modal.msgWarning('请先保存当前医嘱');
return;
}
let saveList = prescriptionList.value.filter((item) => {
return item.statusEnum == 1&&(Number(item.bizRequestFlag)==1||!item.bizRequestFlag)
});
// let saveList = prescriptionList.value
// .filter((item) => {
// return item.check;
// }).filter((item) => {
// return item.statusEnum == 1&&item.bizRequestFlag==1
// })
// if (saveList.length == 0) {
// proxy.$modal.msgWarning('当前无可签发处方');
// return;
// }
// 此处签发处方和单行保存处方传参相同后台已经将传参存为JSON字符串此处直接转换为JSON即可
let list = saveList.map((item) => {
return {
...JSON.parse(item.contentJson),
requestId: item.requestId,
dbOpType: '1',
groupId: item.groupId,
};
});
savePrescriptionSign({
organizationId: props.patientInfo.orgId,
adviceSaveList: list,
}).then((res) => {
if (res.code === 200) {
proxy.$modal.msgSuccess('保存成功');
getListInfo(false);
prescriptionList.value.map(k=>{
k.check = false
})
groupIndexList.value = []
groupList.value = []
nextId.value == 1;
}
});
}
// 单行处方保存
function handleSaveSign(row, index) {
proxy.$refs['formRef' + index].validate((valid) => {
if (valid) {
row.isEdit = false;
isAdding.value = false;
expandOrder.value = [];
row.patientId = props.patientInfo.patientId;
row.encounterId = props.patientInfo.encounterId;
row.accountId = props.patientInfo.accountId;
row.contentJson = JSON.stringify(row);
row.dbOpType = row.requestId ? '2' : '1';
row.minUnitQuantity = row.quantity * row.partPercent;
savePrescription({ adviceSaveList: [row] }).then((res) => {
if (res.code === 200) {
proxy.$modal.msgSuccess('保存成功');
// getListInfo(true);
nextId.value == 1;
}
});
}
});
}
// 签退
function handleSingOut() {
let requestIdList = prescriptionList.value
.filter((item) => {
return item.check;
})
.filter((item) => {
return item.statusEnum == 2&&(Number(item.bizRequestFlag)==1||!item.bizRequestFlag)
})
.map((item) => {
return item.requestId;
});
console.log(requestIdList,"签退")
if (requestIdList.length == 0) {
proxy.$modal.msgWarning('未选择可签退的医嘱');
return
}
singOut(requestIdList).then((res) => {
if (res.code == 200) {
proxy.$modal.msgSuccess('操作成功');
getListInfo(false);
console.log( prescriptionList.value," groupIndexList.value")
prescriptionList.value.map(k=>{
k.check = false
})
groupIndexList.value = []
groupList.value = []
}
});
}
defineExpose({ getListInfo });
</script>
<style lang="scss" scoped>
:deep(.el-table__expand-icon) {
display: none !important;
}
.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);
}
/* 调整element组件默认间距 */
// .el-select,
// .el-input-number {
// margin-right: 0 !important;
// }
.el-input-number .el-input__inner {
text-align: center;
}
.el-table__cell .el-form-item--default {
margin-bottom: 0px;
}
</style>

View File

@@ -0,0 +1,327 @@
<template>
<div style="display: flex; justify-content: space-between; height: 90vh">
<div style="width: 15%; height: 100%; border: 1px solid #eee; border-right: 0">
<div style="padding: 10px; border: 1px solid #eee; height: 50px; border-right: 0">
<span>现诊患者</span>
</div>
<div style="width: 100%; padding: 10px">
<el-input
v-model="queryParams.searchKey"
placeholder="请输入患者名"
clearable
style="width: 100%; margin-bottom: 10px"
@keyup.enter="getPatientList"
>
<template #append>
<el-button icon="Search" @click="getPatientList" />
</template>
</el-input>
<el-scrollbar height="700px">
<div
v-for="(item, index) in patientList"
:class="item.active ? 'patient-card actived' : 'patient-card'"
:key="item.id"
@click="handleCardClick(item, index)"
>
<div class="main-info-container">
<div class="bed-container">
<div class="bed">
<el-text truncated :tclass="bedfont" width="auto">初诊</el-text>
</div>
<div class="bed_new" />
</div>
</div>
<div class="doctor-parent-line" />
<div class="personal-info-container">
<div class="name-container">
<!-- 患者姓名 -->
<div class="name" style="max-width: 70px">
<el-text tclass="name" width="auto">{{ item.patientName || '未知' }}</el-text>
</div>
<!-- 患者性别/年龄 -->
<div class="age">
{{ item.genderEnum_enumText }}/{{ item.age }}/{{ item.typeCode_dictText }}
</div>
</div>
</div>
</div>
</el-scrollbar>
</div>
</div>
<div style="width: 85%; border: 1px solid #eee; position: relative">
<div style="padding: 10px; border: 1px solid #eee; height: 50px; border-left: 0">
<el-descriptions :column="4">
<el-descriptions-item label="患者信息:" width="150">
{{
Object.keys(patientInfo).length !== 0
? patientInfo.patientName +
' / ' +
patientInfo.age +
' / ' +
patientInfo.genderEnum_enumText +
' / ' +
patientInfo.typeCode_dictText
: '-'
}}
</el-descriptions-item>
<el-descriptions-item label="挂号时间" width="150">
{{ Object.keys(patientInfo).length !== 0 ? formatDate(patientInfo.registerTime) : '-' }}
</el-descriptions-item>
<el-descriptions-item label="医生" width="150">{{ userStore.name }}</el-descriptions-item>
<el-descriptions-item label="" width="150">
<!-- {{ '' }} -->
</el-descriptions-item>
</el-descriptions>
</div>
<div style="padding: 10px">
<prescriptionlist :patientInfo="patientInfo" ref="prescriptionRef" />
<div class="overlay" v-if="disabled"></div>
</div>
</div>
</div>
</template>
<script setup>
import { getList } from './component/api.js';
import { formatDate } from '@/utils/index';
import useUserStore from '@/store/modules/user';
import { nextTick } from 'vue';
import Prescriptionlist from './component/prescriptionlist.vue';
import { onBeforeRouteLeave } from 'vue-router';
// // 监听路由离开事件
// onBeforeRouteLeave((to, from, next) => {
// // 弹出确认框
// const confirmLeave = window.confirm('确定要离开吗?未保存的数据可能丢失!');
// if (confirmLeave) {
// next(); // 允许离开
// } else {
// next(false); // 取消离开
// }
// });
defineOptions({
name: 'PatientParentCard',
});
const userStore = useUserStore();
const bedfont = 'bed-font';
const queryParams = ref({});
const currentEncounterId = ref('');
const emits = defineEmits(['click']);
const patientList = ref([]);
const patientInfo = ref({});
const prescriptionRef = ref();
const waitCount = ref(0);
const { proxy } = getCurrentInstance();
const disabled = computed(() => {
return Object.keys(patientInfo.value).length === 0;
});
getPatientList();
// 获取现诊患者列表
function getPatientList() {
getList(queryParams.value).then((res) => {
patientList.value = res.data.records.map((item) => {
return {
...item,
active: currentEncounterId.value ? item.encounterId == currentEncounterId.value : false,
};
});
});
}
function handleQuery() {}
function handleCardClick(item, index) {
currentEncounterId.value = '';
// if (item.active) {
// patientList.value[index].active = false;
// return;
// }
patientList.value.forEach((patient) => {
patient.active = patient.encounterId === item.encounterId;
});
patientInfo.value = item;
nextTick(() => {
prescriptionRef.value.getListInfo();
});
}
</script>
<style lang="scss" scoped>
.patient-card {
width: 100%;
overflow: hidden;
background-color: #fff;
border: 1px solid;
border-color: #eee;
border-radius: 4px;
box-shadow: 0 2px 2px 0 rgba(57.55, 69.04, 86.28, 20%);
margin-bottom: 10px;
cursor: pointer;
&.actived {
background-color: rgb(7, 155, 140, 5%);
border-color: var(--el-color-primary);
}
.cross-dept {
height: 24px;
padding: 0 16px;
color: #fff;
font-size: 14px;
line-height: 24px;
background-color: #256d95;
}
.main-info-container {
display: flex;
align-items: center;
justify-content: space-between;
height: 24px;
margin: 7px 0;
padding: 0 16px;
.bed-container {
display: flex;
flex: 1;
align-items: center;
min-width: 0;
.bed {
flex-grow: 0;
flex-shrink: 1;
min-width: 0;
:deep(.bed-font) {
color: #333;
font-weight: 600;
font-size: 16px;
}
}
.bed_new {
flex-shrink: 0;
width: 10px;
height: 10px;
margin-left: 4px;
background: #29af6f;
border-radius: 50%;
}
}
.indepatient-code-container {
display: flex;
flex-shrink: 0;
align-items: center;
padding-left: 6px;
color: #666;
font-size: 14px;
.sign {
width: 24px;
height: 24px;
color: white;
line-height: 24px;
text-align: center;
border-radius: 50%;
user-select: none;
}
}
}
.doctor-parent-line {
margin: 0 16px;
border-bottom: 1px dashed #ddd;
}
.personal-info-container {
display: flex;
align-items: center;
justify-content: space-between;
margin: 10px 0;
padding: 0 16px;
.name-container {
display: flex;
align-items: center;
height: 24px;
.name {
color: #333;
font-size: 16px;
}
.age {
margin-left: 10px;
color: #666;
font-size: 14px;
}
}
.change-department {
width: 58px;
height: 24px;
color: #5585e3;
font-size: 14px;
line-height: 24px;
text-align: center;
background: #e6edfb;
border-radius: 4px;
}
}
.dept {
margin-bottom: 4px;
padding: 0 16px;
display: flex;
justify-content: space-between;
align-items: center;
.doctor {
display: flex;
align-items: center;
height: 32px;
line-height: 32px;
.doctor_name {
display: flex;
align-items: center;
margin-left: 4px;
color: #333;
}
}
.deptNurseName {
display: flex;
align-items: center;
height: 32px;
color: #256d95;
line-height: 32px;
}
}
}
::v-deep .el-tabs__header {
padding: 0;
position: relative;
margin: 0 0 5px !important;
}
::v-deep .el-drawer__header {
margin-bottom: 15px !important;
}
::v-deep .el-drawer__body {
padding: 10px !important;
}
.el-badge {
--el-badge-padding: 6px;
}
.disabled-wrapper .overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 999; /* 确保覆盖在内容上方 */
cursor: not-allowed;
}
</style>