Merge remote-tracking branch 'origin/develop' into develop

This commit is contained in:
wangjian963
2026-05-20 18:13:22 +08:00
5 changed files with 128 additions and 42 deletions

View File

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.enums.DelFlag;
import com.core.common.exception.ServiceException;
import com.core.common.utils.AssignSeqUtil;
import com.core.common.utils.MessageUtils;
@@ -17,6 +18,8 @@ import com.openhis.common.constant.PromptMsgConstant;
import com.openhis.common.enums.*;
import com.openhis.document.domain.RequestForm;
import com.openhis.document.service.IRequestFormService;
import com.openhis.lab.domain.Specimen;
import com.openhis.lab.service.ISpecimenService;
import com.openhis.web.doctorstation.dto.ActivityChildrenJsonParams;
import com.openhis.web.doctorstation.utils.AdviceUtils;
import com.openhis.web.regdoctorstation.appservice.IRequestFormManageAppService;
@@ -67,6 +70,39 @@ public class RequestFormManageAppServiceImpl implements IRequestFormManageAppSer
@Resource
IActivityDefinitionService iActivityDefinitionService;
@Resource
ISpecimenService iSpecimenService;
/**
* 校验当前用户是否有权操作该申请单(申请者本人或管理员)
*/
private R<?> validateRequestFormPermission(RequestForm requestForm) {
if (SecurityUtils.isAdmin(SecurityUtils.getUserId())) {
return null;
}
Long currentPractitionerId = SecurityUtils.getLoginUser().getPractitionerId();
Long requesterId = requestForm.getRequesterId();
if (currentPractitionerId == null || requesterId == null
|| !currentPractitionerId.equals(requesterId)) {
return R.fail("无操作权限,仅申请开立者或管理员可操作");
}
return null;
}
/**
* 校验关联医嘱是否已采证(存在已采集/已接收标本则不可撤回)
*/
private boolean hasCollectedSpecimen(List<Long> serviceRequestIds) {
if (serviceRequestIds == null || serviceRequestIds.isEmpty()) {
return false;
}
long count = iSpecimenService.count(
new LambdaQueryWrapper<Specimen>()
.in(Specimen::getServiceId, serviceRequestIds)
.ge(Specimen::getCollectionStatusEnum, SpecCollectStatus.COLLECTED.getValue()));
return count > 0;
}
/**
* 保存申请单
*
@@ -528,12 +564,17 @@ public class RequestFormManageAppServiceImpl implements IRequestFormManageAppSer
if (requestForm == null) {
return R.fail("申请单不存在");
}
R<?> permissionResult = validateRequestFormPermission(requestForm);
if (permissionResult != null) {
return permissionResult;
}
String prescriptionNo = requestForm.getPrescriptionNo();
// 查询该申请单下所有 ServiceRequest含子项
List<ServiceRequest> serviceRequests = iServiceRequestService.list(
new LambdaQueryWrapper<ServiceRequest>()
.eq(ServiceRequest::getPrescriptionNo, prescriptionNo));
.eq(ServiceRequest::getPrescriptionNo, prescriptionNo)
.eq(ServiceRequest::getDeleteFlag, DelFlag.NO.getCode()));
if (serviceRequests == null || serviceRequests.isEmpty()) {
return R.fail("未找到关联的诊疗医嘱");
}
@@ -563,7 +604,7 @@ public class RequestFormManageAppServiceImpl implements IRequestFormManageAppSer
// 4. 删除申请单
iRequestFormService.removeById(requestFormId);
log.info("申请单删除成功requestFormId={}, prescriptionNo={}", requestFormId, prescriptionNo);
log.info("申请单删除成功requestFormId={}, prescriptionNo={}", requestFormId, prescriptionNo);
return R.ok("删除成功");
}
@@ -576,32 +617,43 @@ public class RequestFormManageAppServiceImpl implements IRequestFormManageAppSer
if (requestForm == null) {
return R.fail("申请单不存在");
}
R<?> permissionResult = validateRequestFormPermission(requestForm);
if (permissionResult != null) {
return permissionResult;
}
String prescriptionNo = requestForm.getPrescriptionNo();
// 查询该申请单下所有 ServiceRequest
List<ServiceRequest> serviceRequests = iServiceRequestService.list(
new LambdaQueryWrapper<ServiceRequest>()
.eq(ServiceRequest::getPrescriptionNo, prescriptionNo));
.eq(ServiceRequest::getPrescriptionNo, prescriptionNo)
.eq(ServiceRequest::getDeleteFlag, DelFlag.NO.getCode()));
if (serviceRequests == null || serviceRequests.isEmpty()) {
return R.fail("未找到关联的诊疗医嘱");
}
List<Long> serviceRequestIds = serviceRequests.stream()
.map(ServiceRequest::getId).collect(Collectors.toList());
// 校验:标本已采集则不可撤回
if (hasCollectedSpecimen(serviceRequestIds)) {
return R.fail("标本已采集,无法撤回");
}
// 校验:只有已签发(status=2)的申请单可撤回
boolean allActive = serviceRequests.stream()
.allMatch(sr -> RequestStatus.ACTIVE.getValue().equals(sr.getStatusEnum()));
if (!allActive) {
return R.fail("只有已签发状态的申请单可撤回");
return R.fail("只有已签发且未采证的申请单可撤回");
}
// 将所有 ServiceRequest 状态改回待签发(DRAFT=0)
List<Long> serviceRequestIds = serviceRequests.stream()
.map(ServiceRequest::getId).collect(Collectors.toList());
// 将所有 ServiceRequest 状态改回待签发,与申请单展示状态同步
iServiceRequestService.update(
new ServiceRequest().setStatusEnum(RequestStatus.DRAFT.getValue()),
new LambdaUpdateWrapper<ServiceRequest>()
.in(ServiceRequest::getId, serviceRequestIds));
log.info("申请单撤回成功requestFormId={}, prescriptionNo={}", requestFormId, prescriptionNo);
log.info("申请单撤回成功requestFormId={}, prescriptionNo={}", requestFormId, prescriptionNo);
return R.ok("撤回成功");
}

View File

@@ -35,21 +35,27 @@
WHERE ws.prescription_no = drf.prescription_no AND ws.delete_flag = '0'
AND ws.status_enum = 8
) THEN 6
WHEN EXISTS (
SELECT 1 FROM wor_service_request ws
WHERE ws.prescription_no = drf.prescription_no AND ws.delete_flag = '0'
AND ws.status_enum = 5
) THEN 7
WHEN EXISTS (
SELECT 1 FROM wor_service_request ws
WHERE ws.prescription_no = drf.prescription_no AND ws.delete_flag = '0'
AND ws.status_enum = 3
) THEN 5
WHEN EXISTS (
SELECT 1 FROM wor_service_request ws
INNER JOIN lab_specimen ls ON ls.service_id = ws.id
WHERE ws.prescription_no = drf.prescription_no AND ws.delete_flag = '0'
AND ls.collection_status_enum >= 1
) THEN 4
WHEN EXISTS (
SELECT 1 FROM wor_service_request ws
WHERE ws.prescription_no = drf.prescription_no AND ws.delete_flag = '0'
AND ws.status_enum = 2
) THEN 1
WHEN EXISTS (
SELECT 1 FROM wor_service_request ws
WHERE ws.prescription_no = drf.prescription_no AND ws.delete_flag = '0'
AND ws.status_enum = 5
) THEN 7
ELSE 0
END AS computed_status
FROM doc_request_form AS drf

View File

@@ -749,22 +749,26 @@ function handleInfectiousDiseaseReport() {
'手足口病': '0311',
};
// 获取所有诊断名称对应的报卡编码,但跳过已有已提交报卡的诊断
const allSelectedDiseases = form.value.diagnosisList
.filter(d => d.name && d.hasInfectiousReport !== 1)
.map(d => diseaseNameToCode[d.name] || null)
.filter(code => code);
// 获取所有命中传染病映射的诊断,但跳过已有已提交报卡的诊断
const infectiousDiagnoses = form.value.diagnosisList
.map(d => ({
diagnosis: d,
diseaseCode: d.name && d.hasInfectiousReport !== 1 ? diseaseNameToCode[d.name] : null
}))
.filter(item => item.diseaseCode);
const allSelectedDiseases = infectiousDiagnoses.map(item => item.diseaseCode);
if (allSelectedDiseases.length === 0) {
return;
}
// 优先使用主诊断(同样跳过已有报卡的)
const mainDiagnosis = form.value.diagnosisList.find(d => d.maindiseFlag === 1 && d.hasInfectiousReport !== 1);
const firstDiagnosis = form.value.diagnosisList.find(d => d.hasInfectiousReport !== 1) || form.value.diagnosisList[0];
// 优先使用命中传染病映射的主诊断,否则使用第一条命中的传染病诊断
const mainInfectiousDiagnosis = infectiousDiagnoses.find(item => item.diagnosis.maindiseFlag === 1)?.diagnosis;
const firstInfectiousDiagnosis = infectiousDiagnoses[0].diagnosis;
const diagnosisToShow = {
...(mainDiagnosis || firstDiagnosis),
...(mainInfectiousDiagnosis || firstInfectiousDiagnosis),
selectedDiseases: allSelectedDiseases
};

View File

@@ -1442,7 +1442,7 @@ async function buildSubmitData() {
const submitData = {
cardNo: formData.cardNo,
visitId: props.patientInfo?.encounterId || formData.encounterId || null,
diagId: formData.diagnosisId ? Number(formData.diagnosisId) : null,
diagId: formData.diagnosisId || null,
patId: formData.patientId || null,
idType: 1, // 默认身份证
idNo: formData.idNo,

View File

@@ -115,20 +115,20 @@
</template>
</el-table-column>
<el-table-column prop="requesterId_dictText" label="申请者" width="120" />
<el-table-column label="操作" align="center" fixed="right" width="220">
<el-table-column label="操作" align="center" fixed="right" width="280">
<template #default="scope">
<!-- 待签发可修改删除 -->
<template v-if="isPendingStatus(scope.row)">
<el-button link type="primary" @click="handleEdit(scope.row)">修改</el-button>
<el-button link type="danger" @click="handleDelete(scope.row)">删除</el-button>
<el-button link type="primary" @click="handleViewDetail(scope.row)">详情</el-button>
<template v-if="canManageRow(scope.row)">
<template v-if="isPendingStatus(scope.row)">
<el-button link type="primary" @click="handleEdit(scope.row)">修改</el-button>
<el-button link type="danger" @click="handleDelete(scope.row)">删除</el-button>
</template>
<template v-else-if="isWithdrawableStatus(scope.row)">
<el-button link type="warning" @click="handleWithdraw(scope.row)">撤回</el-button>
</template>
</template>
<!-- 已签发可撤回 -->
<template v-else-if="isIssuedStatus(scope.row)">
<el-button link type="warning" @click="handleWithdraw(scope.row)">撤回</el-button>
</template>
<!-- 已采证已送检报告已出已作废仅查看详情 -->
<template v-else>
<el-button link type="primary" @click="handleViewDetail(scope.row)">详情</el-button>
<template v-if="isReportStatus(scope.row)">
<el-button link type="success" @click="handleViewReport(scope.row)">查看报告</el-button>
</template>
</template>
</el-table-column>
@@ -228,7 +228,10 @@ import {patientInfo} from '../../store/patient.js';
import {getInspection, deleteRequestForm, withdrawRequestForm, getProofResult} from './api';
import {getDepartmentList} from '@/api/public.js';
import LaboratoryTests from '../order/applicationForm/laboratoryTests.vue';
import {saveInspection} from '../order/applicationForm/api.js';
import useUserStore from '@/store/modules/user';
import auth from '@/plugins/auth';
const userStore = useUserStore();
const { proxy } = getCurrentInstance();
@@ -378,10 +381,25 @@ const isPendingStatus = (row) => {
return status === undefined || status === null || status === '' || String(status) === '0';
};
const isIssuedStatus = (row) => String(getBillStatus(row)) === '1';
const isWithdrawableStatus = (row) => String(getBillStatus(row)) === '1';
const isReportStatus = (row) => ['6', '8'].includes(String(getBillStatus(row)));
/**
* 是否可管理该申请单:申请者本人或管理员
*/
const canManageRow = (row) => {
if (auth.hasRole('admin')) {
return true;
}
const currentPractitionerId = userStore.practitionerId;
const requesterId = row?.requesterId;
if (!currentPractitionerId || !requesterId) {
return false;
}
return String(currentPractitionerId) === String(requesterId);
};
const sortByCreateTimeDesc = (a, b) => {
const aTime = a?.createTime ? new Date(a.createTime).getTime() : 0;
const bTime = b?.createTime ? new Date(b.createTime).getTime() : 0;
@@ -586,9 +604,9 @@ const submitEditForm = () => {
*/
const handleDelete = async (row) => {
try {
await proxy.$modal?.confirm?.(`确定要删除申请单 "${row.prescriptionNo}" 吗?此操作不可恢复。`);
await proxy.$modal?.confirm?.('确认作废该申请单吗?作废后不可撤销');
} catch {
return; // 用户取消
return;
}
try {
@@ -605,13 +623,15 @@ const handleDelete = async (row) => {
};
/**
* 撤回检验申请单(已签发状态撤回至待签发
* 撤回检验申请单(已签发且未采证状态撤回)
*/
const handleWithdraw = async (row) => {
try {
await proxy.$modal?.confirm?.(`确定要撤回申请单 "${row.prescriptionNo}" 吗?撤回后将恢复为待签发状态。`);
await proxy.$modal?.confirm?.(
'确认撤回该申请单吗?撤回后申请单及关联医嘱将恢复为待签发状态,护士站将同步更新。'
);
} catch {
return; // 用户取消
return;
}
try {
@@ -740,6 +760,10 @@ defineExpose({
.report-status-tag {
cursor: pointer;
background-color: #f0f9eb !important;
border-color: #67c23a !important;
color: #529b2e !important;
font-weight: 600;
}
@keyframes rotating {