2 Commits

Author SHA1 Message Date
c5528ce1b7 fix(ui): 修复多个功能模块的验证和数据处理问题
- 在医生工作站退费功能中添加患者选择验证
- 统一药品管理中的仓库类型选择逻辑,移除重复代码
- 修复统计管理页面清空按钮的数据重置问题
- 修正西药管理页面处方打印按钮的功能绑定
- 完善库存报表查询的SQL过滤条件实现
- 更新多个控制器接口参数类型以支持业务流程
- 优化退费列表对话框的数据加载和错误处理
2026-03-02 23:27:22 +08:00
9116ea4a84 fix(ui): 修复多个功能模块的验证和数据处理问题
- 在医生工作站退费功能中添加患者选择验证
- 统一药品管理中的仓库类型选择逻辑,移除重复代码
- 修复统计管理页面清空按钮的数据重置问题
- 修正西药管理页面处方打印按钮的功能绑定
- 完善库存报表查询的SQL过滤条件实现
- 更新多个控制器接口参数类型以支持业务流程
- 优化退费列表对话框的数据加载和错误处理
2026-03-02 23:27:11 +08:00
23 changed files with 448 additions and 156 deletions

View File

@@ -108,9 +108,9 @@ public class ProductDetailAppServiceImpl extends ServiceImpl<InventoryItemMapper
if (devCategoryCodes != null && !devCategoryCodes.isEmpty()) { if (devCategoryCodes != null && !devCategoryCodes.isEmpty()) {
queryWrapper.in(CommonConstants.FieldName.DevCategoryCode, devCategoryCodes); queryWrapper.in(CommonConstants.FieldName.DevCategoryCode, devCategoryCodes);
} }
// 库存是否为零 // 库存是否为零 (zeroFlag: 1=库存为零, 0=库存大于零)
if (zeroFlag != null) { if (zeroFlag != null) {
if (Whether.YES.getValue().equals(zeroFlag)) { if (Integer.valueOf(1).equals(zeroFlag)) {
queryWrapper.eq(CommonConstants.FieldName.Quantity, BigDecimal.ZERO); queryWrapper.eq(CommonConstants.FieldName.Quantity, BigDecimal.ZERO);
} else { } else {
queryWrapper.gt(CommonConstants.FieldName.Quantity, BigDecimal.ZERO); queryWrapper.gt(CommonConstants.FieldName.Quantity, BigDecimal.ZERO);
@@ -259,9 +259,9 @@ public class ProductDetailAppServiceImpl extends ServiceImpl<InventoryItemMapper
if (devCategoryCodes != null && !devCategoryCodes.isEmpty()) { if (devCategoryCodes != null && !devCategoryCodes.isEmpty()) {
queryWrapper.in(CommonConstants.FieldName.DevCategoryCode, devCategoryCodes); queryWrapper.in(CommonConstants.FieldName.DevCategoryCode, devCategoryCodes);
} }
// 库存是否为零 // 库存是否为零 (zeroFlag: 1=库存为零, 0=库存大于零)
if (zeroFlag != null) { if (zeroFlag != null) {
if (Whether.YES.getValue().equals(zeroFlag)) { if (Integer.valueOf(1).equals(zeroFlag)) {
queryWrapper.eq(CommonConstants.FieldName.Quantity, BigDecimal.ZERO); queryWrapper.eq(CommonConstants.FieldName.Quantity, BigDecimal.ZERO);
} else { } else {
queryWrapper.gt(CommonConstants.FieldName.Quantity, BigDecimal.ZERO); queryWrapper.gt(CommonConstants.FieldName.Quantity, BigDecimal.ZERO);
@@ -507,9 +507,9 @@ public class ProductDetailAppServiceImpl extends ServiceImpl<InventoryItemMapper
if (devCategoryCodes != null && !devCategoryCodes.isEmpty()) { if (devCategoryCodes != null && !devCategoryCodes.isEmpty()) {
queryWrapper.in(CommonConstants.FieldName.DevCategoryCode, devCategoryCodes); queryWrapper.in(CommonConstants.FieldName.DevCategoryCode, devCategoryCodes);
} }
// 库存是否为零 // 库存是否为零 (zeroFlag: 1=库存为零, 0=库存大于零)
if (zeroFlag != null) { if (zeroFlag != null) {
if (Whether.YES.getValue().equals(zeroFlag)) { if (Integer.valueOf(1).equals(zeroFlag)) {
queryWrapper.eq(CommonConstants.FieldName.Quantity, BigDecimal.ZERO); queryWrapper.eq(CommonConstants.FieldName.Quantity, BigDecimal.ZERO);
} else { } else {
queryWrapper.gt(CommonConstants.FieldName.Quantity, BigDecimal.ZERO); queryWrapper.gt(CommonConstants.FieldName.Quantity, BigDecimal.ZERO);

View File

@@ -213,10 +213,24 @@ public class PaymentRecServiceImpl implements IPaymentRecService {
return R.fail("收费项的就诊类型未统一"); return R.fail("收费项的就诊类型未统一");
} }
// 获取所有的账户id // 获取所有的账户id过滤掉null值防止groupingBy时空指针异常
List<Long> accountIdList = chargeItemList.stream().map(ChargeItem::getAccountId).collect(Collectors.toList()); List<Long> accountIdList = chargeItemList.stream()
.map(ChargeItem::getAccountId)
.filter(Objects::nonNull)
.collect(Collectors.toList());
// account去重 // account去重
List<Long> distinctAccountIdList = accountIdList.stream().distinct().collect(Collectors.toList()); List<Long> distinctAccountIdList = accountIdList.stream().distinct().collect(Collectors.toList());
// 检查是否存在accountId为null的收费项
long nullAccountIdCount = chargeItemList.stream()
.map(ChargeItem::getAccountId)
.filter(Objects::isNull)
.count();
if (nullAccountIdCount > 0) {
throw new ServiceException("部分收费项缺少账户信息,请检查收费项数据");
}
if (distinctAccountIdList.isEmpty()) {
throw new ServiceException("未找到有效的账户信息");
}
List<Account> accountList = iAccountService.list(new LambdaQueryWrapper<Account>() List<Account> accountList = iAccountService.list(new LambdaQueryWrapper<Account>()
.in(Account::getId, distinctAccountIdList).eq(Account::getEncounterId, prePaymentDto.getEncounterId())); .in(Account::getId, distinctAccountIdList).eq(Account::getEncounterId, prePaymentDto.getEncounterId()));
if (accountList.size() != distinctAccountIdList.size()) { if (accountList.size() != distinctAccountIdList.size()) {
@@ -503,9 +517,15 @@ public class PaymentRecServiceImpl implements IPaymentRecService {
// } // }
// } // }
// 收费详情按照收费批次进行分组 // 收费详情按照收费批次进行分组过滤掉payTransNo为null的记录
Map<String, List<PaymentRecDetail>> payTransNoMap Map<String, List<PaymentRecDetail>> payTransNoMap
= paymentRecDetails.stream().collect(Collectors.groupingBy(PaymentRecDetail::getPayTransNo)); = paymentRecDetails.stream()
.filter(detail -> detail.getPayTransNo() != null)
.collect(Collectors.groupingBy(PaymentRecDetail::getPayTransNo));
if (payTransNoMap.isEmpty()) {
throw new ServiceException("收费详情缺少批次号信息");
}
com.openhis.financial.model.PaymentResult paymentResult; com.openhis.financial.model.PaymentResult paymentResult;
List<com.openhis.financial.model.PaymentResult> paymentResultList = new ArrayList<>(); List<com.openhis.financial.model.PaymentResult> paymentResultList = new ArrayList<>();

View File

@@ -48,10 +48,11 @@ public class PendingMedicationDetailsAppServiceImpl implements IPendingMedicatio
QueryWrapper<PendingMedicationSearchParam> queryWrapper = HisQueryUtils.buildQueryWrapper( QueryWrapper<PendingMedicationSearchParam> queryWrapper = HisQueryUtils.buildQueryWrapper(
pendingMedicationSearchParam, searchKey, new HashSet<>(Arrays.asList("medicine_name", "medicine_no", "py_str")), request); pendingMedicationSearchParam, searchKey, new HashSet<>(Arrays.asList("medicine_name", "medicine_no", "py_str")), request);
// 查询待发药明细列表 // 查询待发药明细列表(包含待配药、待发药、已配药三种状态,与门诊发药界面一致)
Page<PendingMedicationPageDto> pendingMedicationPage = pendingMedicationDetailsMapper Page<PendingMedicationPageDto> pendingMedicationPage = pendingMedicationDetailsMapper
.selectPendingMedicationDetailsPage(new Page<>(pageNo, pageSize), queryWrapper, .selectPendingMedicationDetailsPage(new Page<>(pageNo, pageSize), queryWrapper,
DispenseStatus.IN_PROGRESS.getValue(), EncounterClass.AMB.getValue(), EncounterClass.IMP.getValue()); DispenseStatus.IN_PROGRESS.getValue(), DispenseStatus.PREPARATION.getValue(),
DispenseStatus.PREPARED.getValue(), EncounterClass.AMB.getValue(), EncounterClass.IMP.getValue());
pendingMedicationPage.getRecords().forEach(e -> { pendingMedicationPage.getRecords().forEach(e -> {
// 发药类型 // 发药类型

View File

@@ -20,11 +20,19 @@ public interface PendingMedicationDetailsMapper {
* @param page 分页 * @param page 分页
* @param queryWrapper 查询条件 * @param queryWrapper 查询条件
* @param inProgress 发药类型:待发药 * @param inProgress 发药类型:待发药
* @param preparation 发药类型:待配药
* @param prepared 发药类型:已配药
* @param amb 门诊类型
* @param imp 住院类型
* @return 待发药明细 * @return 待发药明细
*/ */
Page<PendingMedicationPageDto> selectPendingMedicationDetailsPage( Page<PendingMedicationPageDto> selectPendingMedicationDetailsPage(
@Param("page") Page<PendingMedicationPageDto> page, @Param("page") Page<PendingMedicationPageDto> page,
@Param(Constants.WRAPPER) QueryWrapper<PendingMedicationSearchParam> queryWrapper, @Param(Constants.WRAPPER) QueryWrapper<PendingMedicationSearchParam> queryWrapper,
@Param("inProgress") Integer inProgress, @Param("amb") Integer amb, @Param("imp") Integer imp); @Param("inProgress") Integer inProgress,
@Param("preparation") Integer preparation,
@Param("prepared") Integer prepared,
@Param("amb") Integer amb,
@Param("imp") Integer imp);
} }

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.openhis.web.pharmacymanage.mapper.PendingMedicationDetailsMapper"> <mapper namespace="com.openhis.web.pharmacymanage.mapper.PendingMedicationDetailsMapper">
<select id="selectPendingMedicationDetailsPage" <select id="selectPendingMedicationDetailsPage"
resultType="com.openhis.web.pharmacymanage.dto.PendingMedicationPageDto"> resultType="com.openhis.web.pharmacymanage.dto.PendingMedicationPageDto">
SELECT T7.medicine_no, --药品编码 SELECT T7.medicine_no, --药品编码
T7.medicine_name, --药品名称 T7.medicine_name, --药品名称
@@ -16,44 +16,44 @@
T7.create_time, --开单时间 T7.create_time, --开单时间
T7.tenant_id --租户ID T7.tenant_id --租户ID
FROM ( FROM (
SELECT T1.bus_no AS medicine_no, --药品编码 SELECT T1.bus_no AS medicine_no, --药品编码
T6."name" AS medicine_name, --药品名称 T6."name" AS medicine_name, --药品名称
T6.py_str, --药品拼音 T6.py_str, --药品拼音
T1.quantity AS dispense_quantity, --待发药数量 T1.quantity AS dispense_quantity, --待发药数量
T1.unit_code, --请求单位 T1.unit_code, --请求单位
T1.dispense_enum, --发药类型 T1.dispense_enum, --发药类型
T3."name" AS patient_name, --患者姓名 T3."name" AS patient_name, --患者姓名
T4.prescription_no, --处方号 T4.prescription_no, --处方号
CASE CASE
WHEN T2.class_enum = #{amb} WHEN T2.class_enum = #{amb}
THEN T2.bus_no THEN T2.bus_no
ELSE '' END AS outpatient_no, --门诊号 ELSE '' END AS outpatient_no, --门诊号
CASE CASE
WHEN T2.class_enum = #{imp} WHEN T2.class_enum = #{imp}
THEN T2.bus_no THEN T2.bus_no
ELSE '' END AS admission_no, --住院号 ELSE '' END AS admission_no, --住院号
T1.create_time, --开单时间 T1.create_time, --开单时间
T1.tenant_id --租户ID T1.tenant_id --租户ID
FROM med_medication_dispense AS T1 FROM med_medication_dispense AS T1
LEFT JOIN adm_encounter AS T2 LEFT JOIN adm_encounter AS T2
ON T1.encounter_id = T2.id ON T1.encounter_id = T2.id
AND T2.delete_flag = '0' AND T2.delete_flag = '0'
LEFT JOIN adm_patient AS T3 LEFT JOIN adm_patient AS T3
ON T1.patient_id = T3.id ON T1.patient_id = T3.id
AND T3.delete_flag = '0' AND T3.delete_flag = '0'
INNER JOIN med_medication_request AS T4 INNER JOIN med_medication_request AS T4
ON T1.med_req_id = T4.id ON T1.med_req_id = T4.id
AND T4.delete_flag = '0' AND T4.delete_flag = '0'
LEFT JOIN med_medication_definition AS T6 LEFT JOIN med_medication_definition AS T6
ON T1.medication_id = T6.id ON T1.medication_id = T6.id
AND T6.delete_flag = '0' AND T6.delete_flag = '0'
LEFT JOIN med_medication AS T5 LEFT JOIN med_medication AS T5
ON T5.medication_def_id = T6.id ON T5.medication_def_id = T6.id
AND T5.delete_flag = '0' AND T5.delete_flag = '0'
WHERE T1.delete_flag = '0' WHERE T1.delete_flag = '0'
AND T1.status_enum = #{inProgress} AND T1.status_enum IN (#{inProgress}, #{preparation}, #{prepared})
ORDER BY T1.create_time DESC ORDER BY T1.create_time DESC
) AS T7 ) AS T7
${ew.customSqlSegment} ${ew.customSqlSegment}
</select> </select>
</mapper> </mapper>

View File

@@ -107,15 +107,32 @@ service.interceptors.request.use(config => {
if (code === 401) { if (code === 401) {
if (!isRelogin.show) { if (!isRelogin.show) {
isRelogin.show = true; isRelogin.show = true;
ElMessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => { // 判断是否在登录页面
isRelogin.show = false; const isLoginPage = window.location.pathname === '/login' || window.location.pathname === '/';
if (isLoginPage) {
// 登录页面直接清理token不弹窗
useUserStore().logOut().then(() => { useUserStore().logOut().then(() => {
location.href = '/index'; isRelogin.show = false;
}) }).catch(() => {
}).catch(() => { isRelogin.show = false;
isRelogin.show = false; });
}); return Promise.reject('登录已过期,请重新登录。')
} }
// 其他页面:显示提示后自动跳转
ElMessage.warning('登录已过期,正在跳转到登录页面...');
useUserStore().logOut().then(() => {
isRelogin.show = false;
// 跳转到登录页保留当前路径作为redirect参数
const currentPath = window.location.pathname;
const redirectUrl = currentPath !== '/login' ? `/login?redirect=${encodeURIComponent(currentPath)}` : '/login';
location.href = redirectUrl;
}).catch(() => {
isRelogin.show = false;
location.href = '/login';
});
}
return Promise.reject('无效的会话,或者会话已过期,请重新登录。') return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
} else if (code === 500) { } else if (code === 500) {
// 检查是否需要跳过错误提示 // 检查是否需要跳过错误提示

View File

@@ -342,7 +342,7 @@ async function getList() {
if (res.data && res.data.records) { if (res.data && res.data.records) {
const result = res.data.records.map((item) => ({ const result = res.data.records.map((item) => ({
adviceName: item.name || item.busNo, adviceName: item.name || item.busNo,
adviceType: 2, adviceType: 4, // 🔧 Bug #147 修复前端耗材类型值为4保存时会转换为后端类型值2
unitCode: item.unitCode || '', unitCode: item.unitCode || '',
unitCode_dictText: item.unitCode_dictText || '', unitCode_dictText: item.unitCode_dictText || '',
minUnitCode: item.minUnitCode || item.unitCode || '', minUnitCode: item.minUnitCode || item.unitCode || '',

View File

@@ -714,11 +714,11 @@ function handleNodeClick(data) {
? Math.max(...form.value.diagnosisList.map(item => item.diagSrtNo || 0)) ? Math.max(...form.value.diagnosisList.map(item => item.diagSrtNo || 0))
: 0; : 0;
form.value.diagnosisList.push({ form.value.diagnosisList.push({
ybNo: data.ybNo, ybNo: data.ybNo,
name: data.name, name: data.name,
verificationStatusEnum: 4, verificationStatusEnum: 4,
medTypeCode: '11', medTypeCode: '初诊诊断',
diagSrtNo: maxSortNo + 1, diagSrtNo: maxSortNo + 1,
definitionId: data.definitionId, definitionId: data.definitionId,
classification: '西医', // 默认为西医 classification: '西医', // 默认为西医

View File

@@ -230,6 +230,67 @@
</el-button> </el-button>
</div> </div>
</template> </template>
<!-- 🔧 Bug #147 修复:耗材类型(adviceType=4)的编辑模板 -->
<template v-else-if="scope.row.adviceType == 4">
<div style="
display: flex;
align-items: center;
margin-bottom: 16px;
gap: 16px;
">
<span class="medicine-title">
{{
scope.row.adviceName +
" " +
(scope.row.volume || '') +
" [" +
(scope.row.unitPrice !== undefined && scope.row.unitPrice !== null && !isNaN(scope.row.unitPrice) &&
isFinite(scope.row.unitPrice) ? Number(scope.row.unitPrice).toFixed(2) : '-') +
" " +
"/" +
(scope.row.unitCode_dictText || '个') +
"]"
}}
</span>
<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" :ref="(el) => (inputRefs.quantity = el)"
@keyup.enter.prevent="handleEnter('quantity', scope.row, scope.$index)"
@input="calculateTotalAmount(scope.row, scope.$index)" />
</el-form-item>
<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" @click="
() => {
scope.row.unitCode_dictText = item.label;
}
" @keyup.enter.prevent="
handleEnter(
'executeNum',
scope.row,
scope.$index,
prescription.id
)
" style="width: 70px; margin-right: 20px" />
</template>
</el-select>
</el-form-item>
<span class="total-amount">
总金额:{{
(scope.row.totalPrice !== undefined && scope.row.totalPrice !== null && !isNaN(scope.row.totalPrice)
&&
isFinite(scope.row.totalPrice))
? Number(scope.row.totalPrice).toFixed(2) + ' 元'
: '0.00 元'
}}
</span>
</div>
<el-button type="primary" @click="handleSaveSign(scope.row, scope.$index)">
确定
</el-button>
</template>
<template v-else-if="scope.row.adviceType == 2"> <template v-else-if="scope.row.adviceType == 2">
<div style=" <div style="
display: flex; display: flex;
@@ -2390,7 +2451,9 @@ function setValue(row) {
prescriptionList.value[rowIndex.value].executeNum = 1; prescriptionList.value[rowIndex.value].executeNum = 1;
// 库存列表 + 价格列表拼成批次号的下拉框 // 库存列表 + 价格列表拼成批次号的下拉框
if (row.adviceType != 3) { // 🔧 Bug #147 修复:耗材(adviceType=4)和诊疗(adviceType=3, adviceType=5)不检查库存
// 耗材从getDeviceList接口获取inventoryList为空但需要设置价格
if (row.adviceType != 3 && row.adviceType != 4 && row.adviceType != 5) {
if (row.inventoryList && row.inventoryList.length == 0) { if (row.inventoryList && row.inventoryList.length == 0) {
expandOrder.value = []; expandOrder.value = [];
proxy.$modal.msgWarning(row.adviceName + '无库存'); proxy.$modal.msgWarning(row.adviceName + '无库存');
@@ -2431,6 +2494,18 @@ function setValue(row) {
.toFixed(6); .toFixed(6);
prescriptionList.value[rowIndex.value].positionName = stock.locationName; prescriptionList.value[rowIndex.value].positionName = stock.locationName;
} }
} else if (row.adviceType == 4) {
// 🔧 Bug #147 修复:耗材类型(adviceType=4)的专门处理
// 耗材从getDeviceList接口获取使用priceList中的价格
if (row.priceList && row.priceList.length > 0) {
prescriptionList.value[rowIndex.value].unitPrice = row.priceList[0].price;
prescriptionList.value[rowIndex.value].unitTempPrice = row.priceList[0].price;
prescriptionList.value[rowIndex.value].minUnitPrice = row.priceList[0].price;
prescriptionList.value[rowIndex.value].quantity = 1;
prescriptionList.value[rowIndex.value].totalPrice = row.priceList[0].price;
prescriptionList.value[rowIndex.value].positionName = row.positionName || '';
prescriptionList.value[rowIndex.value].locationId = row.positionId;
}
} else { } else {
getOrgList(); getOrgList();
// 会诊类型adviceType == 5和诊疗类型adviceType == 3的处理 // 会诊类型adviceType == 5和诊疗类型adviceType == 3的处理

View File

@@ -758,10 +758,10 @@ function handleEdit(row) {
loadDoctorList() loadDoctorList()
} }
getSurgeryDetail(row.surgeryNo).then(res => { getSurgeryDetail(row.id).then(res => {
if (res.code === 200) { if (res.code === 200) {
console.log('【编辑手术】完整返回数据:', res.data) console.log('【编辑手术】完整返回数据:', res.data)
console.log('【编辑手术】手术指征字段值:', res.data.surgeryIndication) console.log('【编辑手术】手术指征字段值:', res.data.surgeryIndication)
Object.assign(form.value, res.data) Object.assign(form.value, res.data)
@@ -796,7 +796,7 @@ function handleEdit(row) {
// 查看 // 查看
function handleView(row) { function handleView(row) {
viewOpen.value = true viewOpen.value = true
getSurgeryDetail(row.surgeryNo).then(res => { getSurgeryDetail(row.id).then(res => {
if (res.code === 200) { if (res.code === 200) {
console.log('【手术详情】完整返回数据:', res.data) console.log('【手术详情】完整返回数据:', res.data)
console.log('【手术详情】手术指征字段值:', res.data.surgeryIndication) console.log('【手术详情】手术指征字段值:', res.data.surgeryIndication)
@@ -822,7 +822,7 @@ function handleDelete(row) {
if (row.statusEnum === 0) { if (row.statusEnum === 0) {
// 新开状态 - 直接删除 // 新开状态 - 直接删除
proxy.$modal.confirm('是否确认删除手术"' + row.surgeryName + '"?').then(() => { proxy.$modal.confirm('是否确认删除手术"' + row.surgeryName + '"?').then(() => {
return deleteSurgery(row.surgeryNo) return deleteSurgery(row.id)
}).then(() => { }).then(() => {
getList() getList()
proxy.$modal.msgSuccess('删除成功') proxy.$modal.msgSuccess('删除成功')
@@ -833,7 +833,7 @@ function handleDelete(row) {
} else if (row.statusEnum === 1) { } else if (row.statusEnum === 1) {
// 已安排状态 - 更新为已取消 // 已安排状态 - 更新为已取消
proxy.$modal.confirm('是否确认取消手术"' + row.surgeryName + '"?').then(() => { proxy.$modal.confirm('是否确认取消手术"' + row.surgeryName + '"?').then(() => {
return updateSurgeryStatus(row.surgeryNo, 4) // 4 = 已取消 return updateSurgeryStatus(row.id, 4) // 4 = 已取消
}).then(() => { }).then(() => {
getList() getList()
proxy.$modal.msgSuccess('手术已取消') proxy.$modal.msgSuccess('手术已取消')

View File

@@ -109,7 +109,8 @@
<el-button type="primary" plain @click.stop="handleLeave(patientInfo.encounterId)"> <el-button type="primary" plain @click.stop="handleLeave(patientInfo.encounterId)">
暂离 暂离
</el-button> </el-button>
<el-button type="primary" plain @click.stop="handleRefund(patientInfo.encounterId)"> <el-button type="primary" plain :disabled="isRefundButtonDisabled"
@click.stop="handleRefund(patientInfo.encounterId)">
退费 退费
</el-button> </el-button>
<el-button type="primary" plain class="top-layer-btn" <el-button type="primary" plain class="top-layer-btn"
@@ -289,6 +290,16 @@ const isHospitalizationButtonDisabled = computed(() => {
patientInfo.value.encounterId === undefined; patientInfo.value.encounterId === undefined;
}); });
// 计算属性:确定退费按钮是否应被禁用(与住院按钮使用相同的逻辑)
const isRefundButtonDisabled = computed(() => {
return !patientInfo.value ||
typeof patientInfo.value !== 'object' ||
!patientInfo.value.encounterId ||
patientInfo.value.encounterId === '' ||
patientInfo.value.encounterId === null ||
patientInfo.value.encounterId === undefined;
});
const prescriptionInfo = ref([]); const prescriptionInfo = ref([]);
const registerTime = ref(formatDate(new Date())); const registerTime = ref(formatDate(new Date()));
const patientDrawerRef = ref(); const patientDrawerRef = ref();

View File

@@ -696,7 +696,9 @@ import {
delProductStocktaking, delProductStocktaking,
getCount, getCount,
getDetailInit, getDetailInit,
getDispensaryList,
getInit, getInit,
getPharmacyList,
getstocktakingDetail, getstocktakingDetail,
getStocktakingReceiptBatch, getStocktakingReceiptBatch,
productStocktakingApproved, productStocktakingApproved,
@@ -2295,7 +2297,7 @@ function handleChangePurposeTypeEnum(value, type) {
} }
// getinitValue() // getinitValue()
}); });
} else if (numValue === 17) { } else if (value === 17) {
// 处理耗材库类型 // 处理耗材库类型
// 参考采购订单模块的实现,硬编码设置中心耗材库信息 // 参考采购订单模块的实现,硬编码设置中心耗材库信息
purposeTypeListOptions.value = [ purposeTypeListOptions.value = [

View File

@@ -1174,44 +1174,40 @@ function handleChangePurposeTypeEnum(value, type) {
receiptHeaderForm.purposeLocationId = ''; receiptHeaderForm.purposeLocationId = '';
} }
}); });
} else if (value === 17) {
// 处理耗材库类型
// 参考采购订单模块的实现,硬编码设置中心耗材库信息
purposeTypeListOptions.value = [
{
id: "1",
name: "中心耗材库",
formEnum: 17,
children: []
}
];
// 设置默认仓库和货位
getinitValue();
} else {
console.log('未知的仓库类型值:', value);
purposeTypeListOptions.value = [];
freightListOptions.value = [];
} }
}
if (numValue === 16 || numValue === 11) { // 获取默认值
console.log('Calling getpharmacyCabinetList for warehouse type:', numValue); function getinitValue() {
// 使用统一接口获取药房或药库列表 if (purposeTypeListOptions.value.length > 0) {
getpharmacyCabinetList().then((res) => { // 判断是否有盘点仓库
console.log('getPharmacyCabinetList response:', res); receiptHeaderForm.purposeLocationId = purposeTypeListOptions.value[0].id; // 盘点仓库默认值
// 过滤出符合当前类型的仓库列表 if (
const filteredList = res.data.filter(item => item.formEnum === numValue); purposeTypeListOptions.value[0].children &&
purposeTypeListOptions.value = filteredList; purposeTypeListOptions.value[0].children.length > 0
console.log('purposeTypeListOptions set to filtered list:', purposeTypeListOptions.value); ) {
// 设置默认仓库和货位 // 判断盘点仓库内是否有货位
getinitValue(); freightListOptions.value = purposeTypeListOptions.value[0].children;
}).catch((error) => { receiptHeaderForm.purposeLocation = purposeTypeListOptions.value[0].children[0].name;
console.error('getPharmacyCabinetList error:', error);
purposeTypeListOptions.value = [];
freightListOptions.value = [];
});
} else if (numValue === 17) {
console.log('Setting hardcoded consumable warehouse');
// 处理耗材库类型
// 参考采购订单模块的实现,硬编码设置中心耗材库信息
purposeTypeListOptions.value = [
{
id: "1",
name: "中心耗材库",
formEnum: 17,
children: []
}
];
console.log('purposeTypeListOptions set to:', purposeTypeListOptions.value);
// 设置默认仓库和货位
getinitValue();
} else {
console.log('Unknown value:', value);
purposeTypeListOptions.value = [];
freightListOptions.value = [];
} }
}
} }
// 切换仓库获取货位列表 -20250414 // 切换仓库获取货位列表 -20250414

View File

@@ -114,6 +114,14 @@ export function getDispensaryList() {
}) })
} }
// 获取耗材库列表
export function getWarehouseList() {
return request({
url: '/app-common/warehouse-list',
method: 'get',
})
}
/** /**
* 审批驳回 * 审批驳回
*/ */

View File

@@ -536,6 +536,7 @@ import {
getMedicineList, getMedicineList,
getPharmacyCabinetList, getPharmacyCabinetList,
getPharmacyList, getPharmacyList,
getWarehouseList,
getTransferProductDetail, getTransferProductDetail,
lossReportApproved, lossReportApproved,
reject, reject,
@@ -857,10 +858,26 @@ function handleBlur(row, index) {
row.applicantId = userStore.id; row.applicantId = userStore.id;
} }
function handleChangeSourceTypeEnum(value) { function handleChangeSourceTypeEnum(value) {
// 无论选择哪种仓库类型,都显示药房、药库、耗材库的选项 // 根据仓库类型获取对应的仓库列表
getPharmacyCabinetList().then((res) => { // 16: 药房, 11: 药库, 17: 耗材库
sourceTypeListOptions.value = res.data; if (value == 16) {
}); // 药房
getPharmacyList().then((res) => {
sourceTypeListOptions.value = res.data;
});
} else if (value == 11) {
// 药库
getDispensaryList().then((res) => {
sourceTypeListOptions.value = res.data;
});
} else if (value == 17) {
// 耗材库
getWarehouseList().then((res) => {
sourceTypeListOptions.value = res.data;
});
} else {
sourceTypeListOptions.value = [];
}
} }
// 获取详情 // 获取详情
function getTransferProductDetails() { function getTransferProductDetails() {
@@ -1242,13 +1259,39 @@ function handleChangePurposeTypeEnum(value) {
} }
// 源仓库切换 // 源仓库切换
function handleChangelossTypeEnum(value) { function handleChangelossTypeEnum(value) {
// 无论选择哪种仓库类型,都显示药房、药库、耗材库的选项 // 根据仓库类型获取对应的仓库列表
getPharmacyCabinetList().then((res) => { // 16: 药房, 11: 药库, 17: 耗材库
sourceTypeListOptions.value = res.data; if (value == 16) {
// 药房
getPharmacyList().then((res) => {
sourceTypeListOptions.value = res.data;
if (!route.query.supplyBusNo) {
receiptHeaderForm.lossLocationId = '';
}
});
} else if (value == 11) {
// 药库
getDispensaryList().then((res) => {
sourceTypeListOptions.value = res.data;
if (!route.query.supplyBusNo) {
receiptHeaderForm.lossLocationId = '';
}
});
} else if (value == 17) {
// 耗材库
getWarehouseList().then((res) => {
sourceTypeListOptions.value = res.data;
if (!route.query.supplyBusNo) {
receiptHeaderForm.lossLocationId = '';
}
});
} else {
// 其他情况清空列表
sourceTypeListOptions.value = [];
if (!route.query.supplyBusNo) { if (!route.query.supplyBusNo) {
receiptHeaderForm.lossLocationId = ''; receiptHeaderForm.lossLocationId = '';
} }
}); }
} }
// 单位处理 // 单位处理
function handleUnitCodeChange(row, index, value) { function handleUnitCodeChange(row, index, value) {

View File

@@ -57,7 +57,7 @@ export function submitApproval(busNo) {
return request({ return request({
url: '/inventory-manage/purchase/submit-approval', url: '/inventory-manage/purchase/submit-approval',
method: 'put', method: 'put',
data: busNo data: { busNo }
}) })
} }
@@ -66,7 +66,7 @@ export function withdrawApproval(busNo) {
return request({ return request({
url: '/inventory-manage/purchase/withdraw-approval', url: '/inventory-manage/purchase/withdraw-approval',
method: 'put', method: 'put',
data: busNo data: { busNo }
}) })
} }

View File

@@ -58,7 +58,7 @@ export function submitApproval(busNo) {
url: '/issue-manage/requisition/submit-approval', url: '/issue-manage/requisition/submit-approval',
// '/inventory-manage/purchase/submit-approval', // '/inventory-manage/purchase/submit-approval',
method: 'put', method: 'put',
data: busNo data: { busNo }
}) })
} }
@@ -68,7 +68,7 @@ export function withdrawApproval(busNo) {
url: '/issue-manage/requisition/withdraw-approval', url: '/issue-manage/requisition/withdraw-approval',
// '/inventory-manage/purchase/withdraw-approval', // '/inventory-manage/purchase/withdraw-approval',
method: 'put', method: 'put',
data: busNo data: { busNo }
}) })
} }
@@ -173,7 +173,7 @@ export function submitTHApproval(busNo) {
url: '/issue-manage/return/submit-approval', url: '/issue-manage/return/submit-approval',
// '/inventory-manage/purchase/submit-approval', // '/inventory-manage/purchase/submit-approval',
method: 'put', method: 'put',
data: busNo data: { busNo }
}) })
} }
@@ -183,7 +183,7 @@ export function withdrawTHApproval(busNo) {
url: '/issue-manage/return/withdraw-approval', url: '/issue-manage/return/withdraw-approval',
// '/inventory-manage/purchase/withdraw-approval', // '/inventory-manage/purchase/withdraw-approval',
method: 'put', method: 'put',
data: busNo data: { busNo }
}) })
} }
/** /**

View File

@@ -61,10 +61,10 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="停供状态" prop="categoryCode"> <el-form-item label="停供状态" prop="inventoryStatusEnum">
<el-select <el-select
v-model="queryParams.inventoryStatusEnum" v-model="queryParams.inventoryStatusEnum"
placeholder="请选择药品类别" placeholder="请选择停供状态"
clearable clearable
style="width: 150px" style="width: 150px"
@change="handleQuery" @change="handleQuery"
@@ -525,6 +525,7 @@ const data = reactive({
medCategoryCodes: [], medCategoryCodes: [],
devCategoryCodes: [], devCategoryCodes: [],
backUpDate: undefined, backUpDate: undefined,
inventoryStatusEnum: undefined,
}, },
rules: {}, rules: {},
}); });
@@ -737,8 +738,6 @@ function handleClear() {
// 清空不在 queryParams 中的字段 // 清空不在 queryParams 中的字段
locationId.value = []; locationId.value = [];
supplierId.value = []; supplierId.value = [];
// 清空 prop 与 v-model 不匹配的字段
queryParams.value.inventoryStatusEnum = undefined;
getList(); getList();
} }

View File

@@ -1080,27 +1080,70 @@ const handleSave = async () => {
if (localIsAddOrEditOrder.value.isAddOrder) { if (localIsAddOrEditOrder.value.isAddOrder) {
addOrEditOrder(editData).then((res) => { addOrEditOrder(editData).then((res) => {
if (res.code === 200) { if (res.code === 200) {
proxy.$message.success('新增成功'); proxy.$message.success('新增成功,可以进行审核');
// 更新本地表单数据
localForm.value.busNo = editData[0].busNo;
// 设置订单状态为已编辑
localIsAddOrEditOrder.value = {
isAddOrder: false,
isEditOrder: false,
};
// 设置表格为查看状态
localTableData.value.forEach((item) => {
item.isEditing = false;
item.isViewing = true;
item.busNo = editData[0].busNo;
});
// 更新按钮状态,启用审核按钮
emit('updateButtonState', {
isAuditDisabled: false, // 启用审核按钮
isCancelDisabled: true, // 禁用取消按钮
isDeleteDisabled: true, // 禁用删除按钮
isAddDisabled: true, // 禁用新增按钮
isEditDisabled: true, // 禁用编辑按钮
isAddShow: false, // 隐藏添加行按钮
isDeleteShow: false, // 隐藏删除行按钮
isSaveShow: false, // 隐藏保存按钮
isEditShow: false, // 隐藏编辑按钮
isAlertShow: false, // 隐藏警戒订货按钮
});
// 调用父组件的 getList 方法 // 调用父组件的 getList 方法
emit('getList'); emit('getList');
// 清空表单
// resetAllData();
// 清空 父组件 tableFormRef 表单数据
emit('clearForm');
// 关闭加载 // 关闭加载
loading.value = false; loading.value = false;
} else {
loading.value = false;
} }
}); });
} else if (localIsAddOrEditOrder.value.isEditOrder) { } else if (localIsAddOrEditOrder.value.isEditOrder) {
addOrEditOrder(editData).then((res) => { addOrEditOrder(editData).then((res) => {
if (res.code === 200) { if (res.code === 200) {
proxy.$message.success('保存成功'); proxy.$message.success('保存成功,可以进行审核');
// 设置订单状态为已编辑
localIsAddOrEditOrder.value = {
isAddOrder: false,
isEditOrder: false,
};
// 设置表格为查看状态
localTableData.value.forEach((item) => {
item.isEditing = false;
item.isViewing = true;
});
// 更新按钮状态,启用审核按钮
emit('updateButtonState', {
isAuditDisabled: false, // 启用审核按钮
isCancelDisabled: true, // 禁用取消按钮
isDeleteDisabled: true, // 禁用删除按钮
isAddDisabled: true, // 禁用新增按钮
isEditDisabled: true, // 禁用编辑按钮
isAddShow: false, // 隐藏添加行按钮
isDeleteShow: false, // 隐藏删除行按钮
isSaveShow: false, // 隐藏保存按钮
isEditShow: false, // 隐藏编辑按钮
isAlertShow: false, // 隐藏警戒订货按钮
});
// 调用父组件的 getList 方法 // 调用父组件的 getList 方法
emit('getList'); emit('getList');
// 清空表单
// resetAllData();
// 清空 父组件 tableFormRef 表单数据
emit('clearForm');
} else { } else {
proxy.$message.error('保存失败'); proxy.$message.error('保存失败');
} }

View File

@@ -275,6 +275,7 @@ const buttonShow = ref({
isDeleteShow: false, isDeleteShow: false,
isSaveShow: false, isSaveShow: false,
isEditShow: false, isEditShow: false,
isAlertShow: false,
}); });
const rules = ref({ const rules = ref({
locationId: [{ required: true, message: '请选择库房', trigger: 'blur' }], locationId: [{ required: true, message: '请选择库房', trigger: 'blur' }],
@@ -790,7 +791,7 @@ const handleUpdateButtonState = (buttonState) => {
// 编辑行 按钮显示 // 编辑行 按钮显示
buttonShow.value.isEditShow = buttonState.isEditShow; buttonShow.value.isEditShow = buttonState.isEditShow;
// 警戒订货 按钮显示 // 警戒订货 按钮显示
buttonShow.value.isAlertShow = buttonState.isAlertShow; buttonShow.value.isAlertShow = buttonState.isAlertShow || false;
}; };
// 监听路由变化 // 监听路由变化
watch( watch(

View File

@@ -1074,27 +1074,70 @@ const handleSave = async () => {
if (localIsAddOrEditOrder.value.isAddOrder) { if (localIsAddOrEditOrder.value.isAddOrder) {
addOrEditOrder(editData).then((res) => { addOrEditOrder(editData).then((res) => {
if (res.code === 200) { if (res.code === 200) {
proxy.$message.success('新增成功'); proxy.$message.success('新增成功,可以进行审核');
// 更新本地表单数据
localForm.value.busNo = editData[0].busNo;
// 设置订单状态为已编辑
localIsAddOrEditOrder.value = {
isAddOrder: false,
isEditOrder: false,
};
// 设置表格为查看状态
localTableData.value.forEach((item) => {
item.isEditing = false;
item.isViewing = true;
item.busNo = editData[0].busNo;
});
// 更新按钮状态,启用审核按钮
emit('updateButtonState', {
isAuditDisabled: false, // 启用审核按钮
isCancelDisabled: true, // 禁用取消按钮
isDeleteDisabled: true, // 禁用删除按钮
isAddDisabled: true, // 禁用新增按钮
isEditDisabled: true, // 禁用编辑按钮
isAddShow: false, // 隐藏添加行按钮
isDeleteShow: false, // 隐藏删除行按钮
isSaveShow: false, // 隐藏保存按钮
isEditShow: false, // 隐藏编辑按钮
isAlertShow: false, // 隐藏警戒订货按钮
});
// 调用父组件的 getList 方法 // 调用父组件的 getList 方法
emit('getList'); emit('getList');
// 清空表单
// resetAllData();
// 清空 父组件 tableFormRef 表单数据
emit('clearForm');
// 关闭加载 // 关闭加载
loading.value = false; loading.value = false;
} else {
loading.value = false;
} }
}); });
} else if (localIsAddOrEditOrder.value.isEditOrder) { } else if (localIsAddOrEditOrder.value.isEditOrder) {
addOrEditOrder(editData).then((res) => { addOrEditOrder(editData).then((res) => {
if (res.code === 200) { if (res.code === 200) {
proxy.$message.success('保存成功'); proxy.$message.success('保存成功,可以进行审核');
// 设置订单状态为已编辑
localIsAddOrEditOrder.value = {
isAddOrder: false,
isEditOrder: false,
};
// 设置表格为查看状态
localTableData.value.forEach((item) => {
item.isEditing = false;
item.isViewing = true;
});
// 更新按钮状态,启用审核按钮
emit('updateButtonState', {
isAuditDisabled: false, // 启用审核按钮
isCancelDisabled: true, // 禁用取消按钮
isDeleteDisabled: true, // 禁用删除按钮
isAddDisabled: true, // 禁用新增按钮
isEditDisabled: true, // 禁用编辑按钮
isAddShow: false, // 隐藏添加行按钮
isDeleteShow: false, // 隐藏删除行按钮
isSaveShow: false, // 隐藏保存按钮
isEditShow: false, // 隐藏编辑按钮
isAlertShow: false, // 隐藏警戒订货按钮
});
// 调用父组件的 getList 方法 // 调用父组件的 getList 方法
emit('getList'); emit('getList');
// 清空表单
// resetAllData();
// 清空 父组件 tableFormRef 表单数据
emit('clearForm');
} else { } else {
proxy.$message.error('保存失败'); proxy.$message.error('保存失败');
} }

View File

@@ -275,6 +275,7 @@ const buttonShow = ref({
isDeleteShow: false, isDeleteShow: false,
isSaveShow: false, isSaveShow: false,
isEditShow: false, isEditShow: false,
isAlertShow: false,
}); });
const rules = ref({ const rules = ref({
locationId: [{ required: true, message: '请选择库房', trigger: 'blur' }], locationId: [{ required: true, message: '请选择库房', trigger: 'blur' }],
@@ -790,7 +791,7 @@ const handleUpdateButtonState = (buttonState) => {
// 编辑行 按钮显示 // 编辑行 按钮显示
buttonShow.value.isEditShow = buttonState.isEditShow; buttonShow.value.isEditShow = buttonState.isEditShow;
// 警戒订货 按钮显示 // 警戒订货 按钮显示
buttonShow.value.isAlertShow = buttonState.isAlertShow; buttonShow.value.isAlertShow = buttonState.isAlertShow || false;
}; };
// 监听路由变化 // 监听路由变化
watch( watch(

View File

@@ -608,14 +608,29 @@ function getList() {
} }
async function printPrescription() { async function printPrescription() {
// 空值检查 - 防止 tableRef 为空时报错
if (!tableRef.value) {
proxy.$modal.msgWarning("表格组件未初始化,请刷新页面重试");
return;
}
const selectedRows = tableRef.value.getSelectionRows(); const selectedRows = tableRef.value.getSelectionRows();
if (selectedRows.length === 0) { if (!selectedRows || selectedRows.length === 0) {
proxy.$modal.msgWarning("未选择要打印的项目,请重新选择,打印失败"); proxy.$modal.msgWarning("未选择要打印的项目,请重新选择,打印失败");
return; return;
} }
let requestIds = selectedRows.map((item) => item.requestId).join(",");
const result = []; try {
advicePrint({requestIds: requestIds, isPrescription: "1"}).then(async (res) => { let requestIds = selectedRows.map((item) => item.requestId).join(",");
const result = [];
const res = await advicePrint({requestIds: requestIds, isPrescription: "1"});
if (!res || !res.data || !res.data.adviceItemList) {
proxy.$modal.msgWarning("获取打印数据失败,请稍后重试");
return;
}
const groupedRows = {}; const groupedRows = {};
res.data.adviceItemList.forEach((row) => { res.data.adviceItemList.forEach((row) => {
const prescriptionNo = row.prescriptionNo; const prescriptionNo = row.prescriptionNo;
@@ -633,8 +648,13 @@ async function printPrescription() {
// 获取所有选择数据医生的签名信息 // 获取所有选择数据医生的签名信息
const doctorSignatures = {}; const doctorSignatures = {};
for (const doctorId of uniqueDoctorIds) { for (const doctorId of uniqueDoctorIds) {
const signatureResult = await getDoctorSignature({practitionerId: doctorId}); try {
doctorSignatures[doctorId] = signatureResult?.data || ''; const signatureResult = await getDoctorSignature({practitionerId: doctorId});
doctorSignatures[doctorId] = signatureResult?.data || '';
} catch (e) {
console.warn('获取医生签名失败:', doctorId, e);
doctorSignatures[doctorId] = '';
}
} }
// 将adviceItemList中的chineseHerbsDoseQuantity字段合并到selectedRows中 // 将adviceItemList中的chineseHerbsDoseQuantity字段合并到selectedRows中
@@ -712,8 +732,12 @@ async function printPrescription() {
// 发送任务到打印机失败 // 发送任务到打印机失败
hiprintTemplate.on('printError', function (e) { hiprintTemplate.on('printError', function (e) {
console.log('打印失败'); console.log('打印失败');
proxy.$modal.msgError('打印失败,请检查打印机连接');
}); });
}); } catch (error) {
console.error('处方打印失败:', error);
proxy.$modal.msgError('处方打印失败: ' + (error.message || '未知错误'));
}
} }
// 取消打印机选择 // 取消打印机选择