Merge branch 'develop' of http://192.168.110.253:3000/wangyizhe/his into develop

This commit is contained in:
2026-04-14 21:36:16 +08:00
20 changed files with 838 additions and 507 deletions

View File

@@ -1 +1,2 @@
陈琳Git提交测试 - 2026-04-14 16:57:08 陈琳Git提交测试 - 2026-04-14 16:57:08
陈琳二次测试 - 2026-04-14 21:35:12

1
TEST.md Normal file
View File

@@ -0,0 +1 @@
# 张飞测试记录

1
git_test3.md Normal file
View File

@@ -0,0 +1 @@
# Git 代理禁用后测试 - 关羽 2026-04-14 17:11:41

1
git_test4.md Normal file
View File

@@ -0,0 +1 @@
# Git 晚间测试 - 关羽 2026-04-14 21:35:44

View File

@@ -12,6 +12,8 @@ import com.core.common.utils.SecurityUtils;
import com.core.common.core.domain.model.LoginUser; import com.core.common.core.domain.model.LoginUser;
import com.openhis.infectious.domain.InfectiousAudit; import com.openhis.infectious.domain.InfectiousAudit;
import com.openhis.infectious.domain.InfectiousCard; import com.openhis.infectious.domain.InfectiousCard;
import com.openhis.administration.domain.Practitioner;
import com.openhis.administration.service.IPractitionerService;
import com.openhis.web.cardmanagement.appservice.ICardManageAppService; import com.openhis.web.cardmanagement.appservice.ICardManageAppService;
import com.openhis.web.cardmanagement.dto.*; import com.openhis.web.cardmanagement.dto.*;
import com.openhis.web.cardmanagement.mapper.InfectiousAuditMapper; import com.openhis.web.cardmanagement.mapper.InfectiousAuditMapper;
@@ -52,6 +54,7 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
private final InfectiousCardMapper infectiousCardMapper; private final InfectiousCardMapper infectiousCardMapper;
private final InfectiousAuditMapper infectiousAuditMapper; private final InfectiousAuditMapper infectiousAuditMapper;
private final IPractitionerService iPractitionerService;
@Override @Override
public CardStatisticsDto getStatistics() { public CardStatisticsDto getStatistics() {
@@ -74,7 +77,7 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
} }
// 状态 // 状态
if (StringUtils.hasText(queryParams.getStatus())) { if (queryParams.getStatus() != null) {
wrapper.eq(InfectiousCard::getStatus, queryParams.getStatus()); wrapper.eq(InfectiousCard::getStatus, queryParams.getStatus());
} }
@@ -127,7 +130,7 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
if (card == null) { if (card == null) {
return new ArrayList<>(); return new ArrayList<>();
} }
List<InfectiousAudit> records = infectiousAuditMapper.selectByCardId(card.getId()); List<InfectiousAudit> records = infectiousAuditMapper.selectByCardId(card.getCardNo());
return records.stream().map(this::convertAuditToDto).collect(Collectors.toList()); return records.stream().map(this::convertAuditToDto).collect(Collectors.toList());
} }
@@ -145,16 +148,16 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
for (String cardNo : batchAuditDto.getCardNos()) { for (String cardNo : batchAuditDto.getCardNos()) {
InfectiousCard card = infectiousCardMapper.selectByCardNo(cardNo); InfectiousCard card = infectiousCardMapper.selectByCardNo(cardNo);
if (card == null) continue; if (card == null) continue;
if ("2".equals(card.getStatus()) || "3".equals(card.getStatus())) continue; if (Integer.valueOf(2).equals(card.getStatus()) || Integer.valueOf(3).equals(card.getStatus())) continue;
// 更新状态为已审核 // 更新状态为已审核
String oldStatus = card.getStatus(); Integer oldStatus = card.getStatus();
card.setStatus("2"); card.setStatus(2);
card.setUpdateTime(new Date()); card.setUpdateTime(new Date());
infectiousCardMapper.updateById(card); infectiousCardMapper.updateById(card);
// 创建审核记录 // 创建审核记录
createAuditRecord(card.getId(), oldStatus, "2", "1", batchAuditDto.getAuditOpinion(), createAuditRecord(card.getCardNo(), oldStatus, 2, 1, batchAuditDto.getAuditOpinion(),
null, auditorId, auditorName, true, batchAuditDto.getCardNos().size()); null, auditorId, auditorName, true, batchAuditDto.getCardNos().size());
successCount++; successCount++;
} }
@@ -176,17 +179,17 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
for (String cardNo : batchReturnDto.getCardNos()) { for (String cardNo : batchReturnDto.getCardNos()) {
InfectiousCard card = infectiousCardMapper.selectByCardNo(cardNo); InfectiousCard card = infectiousCardMapper.selectByCardNo(cardNo);
if (card == null) continue; if (card == null) continue;
if ("2".equals(card.getStatus()) || "3".equals(card.getStatus())) continue; if (Integer.valueOf(2).equals(card.getStatus()) || Integer.valueOf(3).equals(card.getStatus())) continue;
// 更新状态为退回 (审核失败) // 更新状态为退回 (审核失败)
String oldStatus = card.getStatus(); Integer oldStatus = card.getStatus();
card.setStatus("5"); card.setStatus(5);
card.setReturnReason(batchReturnDto.getReturnReason()); card.setReturnReason(batchReturnDto.getReturnReason());
card.setUpdateTime(new Date()); card.setUpdateTime(new Date());
infectiousCardMapper.updateById(card); infectiousCardMapper.updateById(card);
// 创建审核记录 // 创建审核记录
createAuditRecord(card.getId(), oldStatus, "5", "3", null, createAuditRecord(card.getCardNo(), oldStatus, 5, 3, null,
batchReturnDto.getReturnReason(), auditorId, auditorName, true, batchReturnDto.getCardNos().size()); batchReturnDto.getReturnReason(), auditorId, auditorName, true, batchReturnDto.getCardNos().size());
successCount++; successCount++;
} }
@@ -206,13 +209,13 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
String auditorName = SecurityUtils.getUsername(); String auditorName = SecurityUtils.getUsername();
// 更新状态 // 更新状态
String oldStatus = card.getStatus(); Integer oldStatus = card.getStatus();
card.setStatus("2"); card.setStatus(2);
card.setUpdateTime(new Date()); card.setUpdateTime(new Date());
infectiousCardMapper.updateById(card); infectiousCardMapper.updateById(card);
// 创建审核记录 // 创建审核记录
createAuditRecord(card.getId(), oldStatus, "2", "2", auditDto.getAuditOpinion(), createAuditRecord(card.getCardNo(), oldStatus, 2, 2, auditDto.getAuditOpinion(),
null, auditorId, auditorName, false, 1); null, auditorId, auditorName, false, 1);
return R.ok("审核通过"); return R.ok("审核通过");
@@ -230,14 +233,14 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
String auditorName = SecurityUtils.getUsername(); String auditorName = SecurityUtils.getUsername();
// 更新状态 // 更新状态
String oldStatus = card.getStatus(); Integer oldStatus = card.getStatus();
card.setStatus("5"); card.setStatus(5);
card.setReturnReason(returnDto.getReturnReason()); card.setReturnReason(returnDto.getReturnReason());
card.setUpdateTime(new Date()); card.setUpdateTime(new Date());
infectiousCardMapper.updateById(card); infectiousCardMapper.updateById(card);
// 创建审核记录 // 创建审核记录
createAuditRecord(card.getId(), oldStatus, "5", "4", null, createAuditRecord(card.getCardNo(), oldStatus, 5, 4, null,
returnDto.getReturnReason(), auditorId, auditorName, false, 1); returnDto.getReturnReason(), auditorId, auditorName, false, 1);
return R.ok("已退回"); return R.ok("已退回");
@@ -251,7 +254,7 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
if (queryParams.getRegistrationSource() != null) { if (queryParams.getRegistrationSource() != null) {
wrapper.eq(InfectiousCard::getRegistrationSource, queryParams.getRegistrationSource()); wrapper.eq(InfectiousCard::getRegistrationSource, queryParams.getRegistrationSource());
} }
if (StringUtils.hasText(queryParams.getStatus())) { if (queryParams.getStatus() != null) {
wrapper.eq(InfectiousCard::getStatus, queryParams.getStatus()); wrapper.eq(InfectiousCard::getStatus, queryParams.getStatus());
} }
if (StringUtils.hasText(queryParams.getPatientName())) { if (StringUtils.hasText(queryParams.getPatientName())) {
@@ -292,7 +295,7 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
row.createCell(1).setCellValue(card.getPatName()); row.createCell(1).setCellValue(card.getPatName());
row.createCell(2).setCellValue("1".equals(card.getSex()) ? "" : "2".equals(card.getSex()) ? "" : "未知"); row.createCell(2).setCellValue("1".equals(card.getSex()) ? "" : "2".equals(card.getSex()) ? "" : "未知");
row.createCell(3).setCellValue(card.getAge() != null ? card.getAge() + "" : ""); row.createCell(3).setCellValue(card.getAge() != null ? card.getAge() + "" : "");
row.createCell(4).setCellValue(card.getDiseaseName()); row.createCell(4).setCellValue(card.getDiseaseCode());
row.createCell(5).setCellValue(card.getDeptName()); row.createCell(5).setCellValue(card.getDeptName());
row.createCell(6).setCellValue(card.getCreateTime() != null ? dateFormat.format(card.getCreateTime()) : ""); row.createCell(6).setCellValue(card.getCreateTime() != null ? dateFormat.format(card.getCreateTime()) : "");
row.createCell(7).setCellValue(getStatusText(card.getStatus())); row.createCell(7).setCellValue(getStatusText(card.getStatus()));
@@ -316,7 +319,19 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
@Override @Override
public DoctorCardStatisticsDto getDoctorCardStatistics() { public DoctorCardStatisticsDto getDoctorCardStatistics() {
Long doctorId = SecurityUtils.getUserId(); Long userId = SecurityUtils.getUserId();
// 通过 sys_user 表的 user_id 查询医生表 (adm_practitioner) 获取医生 ID
Practitioner practitioner = iPractitionerService.getPractitionerByUserId(userId);
if (practitioner == null) {
DoctorCardStatisticsDto dto = new DoctorCardStatisticsDto();
dto.setTotalCount(0);
dto.setPendingFailedCount(0);
dto.setReportedCount(0);
return dto;
}
Long doctorId = practitioner.getId();
DoctorCardStatisticsDto dto = new DoctorCardStatisticsDto(); DoctorCardStatisticsDto dto = new DoctorCardStatisticsDto();
Integer totalCount = infectiousCardMapper.countByDoctorId(doctorId); Integer totalCount = infectiousCardMapper.countByDoctorId(doctorId);
@@ -331,7 +346,18 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
@Override @Override
public R<?> getDoctorCardPage(DoctorCardQueryDto queryParams) { public R<?> getDoctorCardPage(DoctorCardQueryDto queryParams) {
Long doctorId = SecurityUtils.getUserId(); Long userId = SecurityUtils.getUserId();
// 通过 sys_user 表的 user_id 查询医生表 (adm_practitioner) 获取医生 ID
Practitioner practitioner = iPractitionerService.getPractitionerByUserId(userId);
if (practitioner == null) {
Map<String, Object> emptyResult = new HashMap<>();
emptyResult.put("list", new ArrayList<>());
emptyResult.put("total", 0L);
return R.ok(emptyResult);
}
Long doctorId = practitioner.getId();
Page<InfectiousCard> page = new Page<>(queryParams.getPageNo(), queryParams.getPageSize()); Page<InfectiousCard> page = new Page<>(queryParams.getPageNo(), queryParams.getPageSize());
LambdaQueryWrapper<InfectiousCard> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<InfectiousCard> wrapper = new LambdaQueryWrapper<>();
@@ -340,7 +366,7 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
wrapper.eq(InfectiousCard::getDoctorId, doctorId); wrapper.eq(InfectiousCard::getDoctorId, doctorId);
// 状态筛选 // 状态筛选
if (StringUtils.hasText(queryParams.getStatus())) { if (queryParams.getStatus() != null) {
wrapper.eq(InfectiousCard::getStatus, queryParams.getStatus()); wrapper.eq(InfectiousCard::getStatus, queryParams.getStatus());
} }
@@ -354,13 +380,24 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
wrapper.le(InfectiousCard::getCreateTime, endDateTime); wrapper.le(InfectiousCard::getCreateTime, endDateTime);
} }
// 关键词搜索(患者姓名报卡名称) // 关键词搜索(患者姓名、疾病编码、报卡名称)
if (StringUtils.hasText(queryParams.getKeyword())) { if (StringUtils.hasText(queryParams.getKeyword())) {
wrapper.and(w -> w String kw = queryParams.getKeyword();
.like(InfectiousCard::getPatName, queryParams.getKeyword()) // 将关键词匹配报卡名称,找出对应的 cardNameCode 列表
.or() List<Integer> matchedCodes = getMatchedCardNameCodes(kw);
.like(InfectiousCard::getDiseaseName, queryParams.getKeyword()) // cardNameCode为null的记录默认也属于"中华人民共和国传染病报告卡"匹配到code=1时需包含Null记录
); boolean includeNull = matchedCodes.contains(1);
wrapper.and(w -> {
w.like(InfectiousCard::getPatName, kw)
.or()
.like(InfectiousCard::getDiseaseCode, kw);
if (!matchedCodes.isEmpty()) {
w.or().in(InfectiousCard::getCardNameCode, matchedCodes);
}
if (includeNull) {
w.or().isNull(InfectiousCard::getCardNameCode);
}
});
} }
// 按创建时间倒序 // 按创建时间倒序
@@ -388,17 +425,19 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
} }
// 验证权限:只能提交自己的报卡 // 验证权限:只能提交自己的报卡
if (!card.getDoctorId().equals(SecurityUtils.getUserId())) { Long userId = SecurityUtils.getUserId();
Practitioner practitioner = iPractitionerService.getPractitionerByUserId(userId);
if (practitioner == null || !practitioner.getId().equals(card.getDoctorId())) {
return R.fail("无权操作此报卡"); return R.fail("无权操作此报卡");
} }
// 证状态:只有暂存状态可以提交 // 证状态:只有暂存状态可以提交
if (!"0".equals(card.getStatus())) { if (!Integer.valueOf(0).equals(card.getStatus())) {
return R.fail("只能提交暂存状态的报卡"); return R.fail("只能提交暂存状态的报卡");
} }
// 更新状态为已提交 // 更新状态为已提交
card.setStatus("1"); card.setStatus(1);
card.setUpdateTime(new Date()); card.setUpdateTime(new Date());
infectiousCardMapper.updateById(card); infectiousCardMapper.updateById(card);
@@ -414,17 +453,19 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
} }
// 验证权限:只能撤回自己的报卡 // 验证权限:只能撤回自己的报卡
if (!card.getDoctorId().equals(SecurityUtils.getUserId())) { Long userId = SecurityUtils.getUserId();
Practitioner practitioner = iPractitionerService.getPractitionerByUserId(userId);
if (practitioner == null || !practitioner.getId().equals(card.getDoctorId())) {
return R.fail("无权操作此报卡"); return R.fail("无权操作此报卡");
} }
// 证状态:只有已提交状态可以撤回 // 证状态:只有已提交状态可以撤回
if (!"1".equals(card.getStatus())) { if (!Integer.valueOf(1).equals(card.getStatus())) {
return R.fail("只能撤回已提交状态的报卡"); return R.fail("只能撤回已提交状态的报卡");
} }
// 更新状态为暂存 // 更新状态为暂存
card.setStatus("0"); card.setStatus(0);
card.setUpdateTime(new Date()); card.setUpdateTime(new Date());
infectiousCardMapper.updateById(card); infectiousCardMapper.updateById(card);
@@ -440,17 +481,19 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
} }
// 验证权限:只能删除自己的报卡 // 验证权限:只能删除自己的报卡
if (!card.getDoctorId().equals(SecurityUtils.getUserId())) { Long userId = SecurityUtils.getUserId();
Practitioner practitioner = iPractitionerService.getPractitionerByUserId(userId);
if (practitioner == null || !practitioner.getId().equals(card.getDoctorId())) {
return R.fail("无权操作此报卡"); return R.fail("无权操作此报卡");
} }
// 证状态:只有暂存状态可以删除 // 证状态:只有暂存状态可以删除
if (!"0".equals(card.getStatus())) { if (!Integer.valueOf(0).equals(card.getStatus())) {
return R.fail("只能删除暂存状态的报卡"); return R.fail("只能删除暂存状态的报卡");
} }
// 更新状态为作废 // 更新状态为作废
card.setStatus("6"); card.setStatus(6);
card.setUpdateTime(new Date()); card.setUpdateTime(new Date());
infectiousCardMapper.updateById(card); infectiousCardMapper.updateById(card);
@@ -464,7 +507,12 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
return R.fail("请选择要提交的报卡"); return R.fail("请选择要提交的报卡");
} }
Long doctorId = SecurityUtils.getUserId(); Long userId = SecurityUtils.getUserId();
Practitioner practitioner = iPractitionerService.getPractitionerByUserId(userId);
if (practitioner == null) {
return R.fail("当前用户未关联医生信息");
}
Long doctorId = practitioner.getId();
int successCount = 0; int successCount = 0;
for (String cardNo : cardNos) { for (String cardNo : cardNos) {
@@ -472,13 +520,13 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
if (card == null) continue; if (card == null) continue;
// 验证权限:只能提交自己的报卡 // 验证权限:只能提交自己的报卡
if (!card.getDoctorId().equals(doctorId)) continue; if (!doctorId.equals(card.getDoctorId())) continue;
// 证状态:只有暂存状态可以提交 // 证状态:只有暂存状态可以提交
if (!"0".equals(card.getStatus())) continue; if (!Integer.valueOf(0).equals(card.getStatus())) continue;
// 更新状态为已提交 // 更新状态为已提交
card.setStatus("1"); card.setStatus(1);
card.setUpdateTime(new Date()); card.setUpdateTime(new Date());
infectiousCardMapper.updateById(card); infectiousCardMapper.updateById(card);
successCount++; successCount++;
@@ -498,7 +546,12 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
return R.fail("请选择要删除的报卡"); return R.fail("请选择要删除的报卡");
} }
Long doctorId = SecurityUtils.getUserId(); Long userId = SecurityUtils.getUserId();
Practitioner practitioner = iPractitionerService.getPractitionerByUserId(userId);
if (practitioner == null) {
return R.fail("当前用户未关联医生信息");
}
Long doctorId = practitioner.getId();
int successCount = 0; int successCount = 0;
for (String cardNo : cardNos) { for (String cardNo : cardNos) {
@@ -506,13 +559,13 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
if (card == null) continue; if (card == null) continue;
// 验证权限:只能删除自己的报卡 // 验证权限:只能删除自己的报卡
if (!card.getDoctorId().equals(doctorId)) continue; if (!doctorId.equals(card.getDoctorId())) continue;
// 证状态:只有暂存状态可以删除 // 证状态:只有暂存状态可以删除
if (!"0".equals(card.getStatus())) continue; if (!Integer.valueOf(0).equals(card.getStatus())) continue;
// 更新状态为作废 // 更新状态为作废
card.setStatus("6"); card.setStatus(6);
card.setUpdateTime(new Date()); card.setUpdateTime(new Date());
infectiousCardMapper.updateById(card); infectiousCardMapper.updateById(card);
successCount++; successCount++;
@@ -531,6 +584,13 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
LoginUser loginUser = SecurityUtils.getLoginUser(); LoginUser loginUser = SecurityUtils.getLoginUser();
Long currentUserId = loginUser.getUserId(); Long currentUserId = loginUser.getUserId();
// 通过 sys_user 表的 user_id 查询医生表 (adm_practitioner) 获取医生 ID
Practitioner practitioner = iPractitionerService.getPractitionerByUserId(currentUserId);
if (practitioner == null) {
return R.fail("当前用户未关联医生信息");
}
Long doctorId = practitioner.getId();
// 查询报卡 // 查询报卡
InfectiousCard card = infectiousCardMapper.selectByCardNo(updateDto.getCardNo()); InfectiousCard card = infectiousCardMapper.selectByCardNo(updateDto.getCardNo());
if (card == null) { if (card == null) {
@@ -538,12 +598,12 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
} }
// 验证是否当前医生的报卡 - 根据 doctorId 字段验证 // 验证是否当前医生的报卡 - 根据 doctorId 字段验证
if (!currentUserId.equals(card.getDoctorId())) { if (!doctorId.equals(card.getDoctorId())) {
return R.fail("只能修改自己的报卡"); return R.fail("只能修改自己的报卡");
} }
// 证状态是否允许修改(只能修改暂存状态的报卡) // 证状态是否允许修改(只能修改暂存状态的报卡)
if (!"0".equals(card.getStatus())) { if (!Integer.valueOf(0).equals(card.getStatus())) {
return R.fail("只能修改暂存状态的报卡"); return R.fail("只能修改暂存状态的报卡");
} }
@@ -559,15 +619,6 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
card.setUpdateTime(new Date()); card.setUpdateTime(new Date());
card.setUpdateBy(loginUser.getUsername()); // 使用username作为更新者 card.setUpdateBy(loginUser.getUsername()); // 使用username作为更新者
card.setUpdateTime(new Date());
card.setUpdateBy(loginUser.getUsername()); // 使用 username 作为更新者
card.setUpdateTime(new Date());
card.setUpdateBy(loginUser.getUsername()); // 使用 username 作为更新者
card.setUpdateTime(new Date());
card.setUpdateBy(loginUser.getUsername()); // 使用 username 作为更新者
int rows = infectiousCardMapper.updateById(card); int rows = infectiousCardMapper.updateById(card);
if (rows > 0) { if (rows > 0) {
return R.ok("更新成功"); return R.ok("更新成功");
@@ -583,12 +634,14 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
} }
// 验证权限:只能导出自己的报卡 // 验证权限:只能导出自己的报卡
if (!card.getDoctorId().equals(SecurityUtils.getUserId())) { Long userId = SecurityUtils.getUserId();
Practitioner practitioner = iPractitionerService.getPractitionerByUserId(userId);
if (practitioner == null || !practitioner.getId().equals(card.getDoctorId())) {
return; return;
} }
// 证状态:只有已上报状态可以导出 // 证状态:只有已上报状态可以导出
if (!"3".equals(card.getStatus())) { if (!Integer.valueOf(3).equals(card.getStatus())) {
return; return;
} }
@@ -612,6 +665,8 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
private DoctorCardListDto convertToDoctorCardListDto(InfectiousCard card) { private DoctorCardListDto convertToDoctorCardListDto(InfectiousCard card) {
DoctorCardListDto dto = new DoctorCardListDto(); DoctorCardListDto dto = new DoctorCardListDto();
BeanUtils.copyProperties(card, dto); BeanUtils.copyProperties(card, dto);
// 由于数据库中没有 disease_name 字段,使用 disease_code 作为疾病名称展示
dto.setDiseaseName(card.getDiseaseCode());
dto.setCardName(getCardName(card.getCardNameCode())); dto.setCardName(getCardName(card.getCardNameCode()));
dto.setSubmitTime(card.getCreateTime() != null ? dto.setSubmitTime(card.getCreateTime() != null ?
new SimpleDateFormat("yyyy-MM-dd HH:mm").format(card.getCreateTime()) : null); new SimpleDateFormat("yyyy-MM-dd HH:mm").format(card.getCreateTime()) : null);
@@ -632,13 +687,35 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
} }
} }
/**
* 根据关键词匹配报卡名称,返回匹配的 cardNameCode 列表
*/
private List<Integer> getMatchedCardNameCodes(String keyword) {
// 报卡名称映射表 code -> name
java.util.Map<Integer, String> cardNameMap = new java.util.LinkedHashMap<>();
cardNameMap.put(1, "中华人民共和国传染病报告卡");
cardNameMap.put(2, "甲类传染病报告卡");
cardNameMap.put(3, "乙类传染病报告卡");
cardNameMap.put(4, "丙类传染病报告卡");
List<Integer> matchedCodes = new ArrayList<>();
for (java.util.Map.Entry<Integer, String> entry : cardNameMap.entrySet()) {
if (entry.getValue().contains(keyword)) {
matchedCodes.add(entry.getKey());
}
}
// cardNameCode 为 null 的数据默认也是「中华人民共和国传染病报告卡」
// 如果关键词匹配 code=1则同时要包含 null 的记录
return matchedCodes;
}
/** /**
* 转换审核记录为 DTO * 转换审核记录为 DTO
*/ */
private AuditRecordDto convertAuditToDto(InfectiousAudit audit) { private AuditRecordDto convertAuditToDto(InfectiousAudit audit) {
AuditRecordDto dto = new AuditRecordDto(); AuditRecordDto dto = new AuditRecordDto();
BeanUtils.copyProperties(audit, dto); BeanUtils.copyProperties(audit, dto);
dto.setCardId(audit.getCardId() != null ? audit.getCardId().toString() : null); dto.setCardId(audit.getCardId());
return dto; return dto;
} }
@@ -648,6 +725,8 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
private InfectiousCardDto convertToDto(InfectiousCard card) { private InfectiousCardDto convertToDto(InfectiousCard card) {
InfectiousCardDto dto = new InfectiousCardDto(); InfectiousCardDto dto = new InfectiousCardDto();
BeanUtils.copyProperties(card, dto); BeanUtils.copyProperties(card, dto);
// 由于数据库中没有 disease_name 字段,使用 disease_code 作为疾病名称展示
dto.setDiseaseName(card.getDiseaseCode());
dto.setStatusText(getStatusText(card.getStatus())); dto.setStatusText(getStatusText(card.getStatus()));
return dto; return dto;
} }
@@ -655,15 +734,15 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
/** /**
* 创建审核记录 * 创建审核记录
*/ */
private void createAuditRecord(Long cardId, String statusFrom, String statusTo, String auditType, private void createAuditRecord(String cardId, Integer statusFrom, Integer statusTo, Integer auditType,
String auditOpinion, String returnReason, String auditorId, String auditorName, String auditOpinion, String returnReason, String auditorId, String auditorName,
Boolean isBatch, Integer batchSize) { Boolean isBatch, Integer batchSize) {
InfectiousAudit audit = new InfectiousAudit(); InfectiousAudit audit = new InfectiousAudit();
audit.setCardId(cardId); audit.setCardId(cardId);
audit.setAuditSeq(infectiousAuditMapper.getNextAuditSeq(cardId)); audit.setAuditSeq(infectiousAuditMapper.getNextAuditSeq(cardId));
audit.setAuditType(auditType); audit.setAuditType(String.valueOf(auditType));
audit.setAuditStatusFrom(statusFrom); audit.setAuditStatusFrom(statusFrom != null ? String.valueOf(statusFrom) : null);
audit.setAuditStatusTo(statusTo); audit.setAuditStatusTo(statusTo != null ? String.valueOf(statusTo) : null);
audit.setAuditTime(LocalDateTime.now()); audit.setAuditTime(LocalDateTime.now());
audit.setAuditorId(auditorId); audit.setAuditorId(auditorId);
audit.setAuditorName(auditorName); audit.setAuditorName(auditorName);
@@ -677,15 +756,16 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
/** /**
* 获取状态文本 * 获取状态文本
*/ */
private String getStatusText(String status) { private String getStatusText(Integer status) {
if (status == null) return "未知";
switch (status) { switch (status) {
case "0": return "暂存"; case 0: return "暂存";
case "1": return "已提交"; case 1: return "已提交";
case "2": return "审核通过"; case 2: return "审核通过";
case "3": return "已上报"; case 3: return "已上报";
case "4": return "失败"; case 4: return "失败";
case "5": return "审核失败"; case 5: return "审核失败";
case "6": return "作废"; case 6: return "作废";
default: return "未知"; default: return "未知";
} }
} }

View File

@@ -29,8 +29,8 @@ public class CardQueryDto {
/** 患者姓名 */ /** 患者姓名 */
private String patientName; private String patientName;
/** 审核状态 */ /** 审核状态(0暂存/1已提交/2已审核/3已上报/4失败/5退回/6作废) */
private String status; private Integer status;
/** 科室ID */ /** 科室ID */
private Long deptId; private Long deptId;

View File

@@ -7,6 +7,9 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data; import lombok.Data;
import java.time.LocalDate;
import java.time.LocalDateTime;
/** /**
* 医生个人报卡列表DTO * 医生个人报卡列表DTO
* *
@@ -41,6 +44,51 @@ public class DoctorCardListDto {
/** 提交时间 */ /** 提交时间 */
private String submitTime; private String submitTime;
/** 状态 */ /** 状态(0暂存/1已提交/2已审核/3已上报/4失败/5退回/6作废) */
private String status; private Integer status;
/** 疾病名称 */
private String diseaseName;
/** 发病日期 */
private LocalDate onsetDate;
/** 诊断日期 */
private LocalDateTime diagDate;
/** 报告单位 */
private String reportOrg;
/** 报告医生 */
private String reportDoc;
/** 传染病类别 */
private String diseaseType;
/** 性别 (1男/2女/0未知) */
private String sex;
/** 年龄 */
private Integer age;
/** 年龄单位 (1岁/2月/3天) */
private String ageUnit;
/** 现住址省 */
private String addressProv;
/** 现住址市 */
private String addressCity;
/** 现住址县 */
private String addressCounty;
/** 现住址街道 */
private String addressTown;
/** 现住址村/居委 */
private String addressVillage;
/** 现住址门牌号 */
private String addressHouse;
} }

View File

@@ -26,8 +26,8 @@ public class DoctorCardQueryDto {
/** 结束日期 */ /** 结束日期 */
private String endDate; private String endDate;
/** 状态(0暂存/1已提交/2已审核/3已上报/4失败/5退回) */ /** 状态(0暂存/1已提交/2已审核/3已上报/4失败/5退回/6作废) */
private String status; private Integer status;
/** 患者姓名或报卡名称 */ /** 患者姓名或报卡名称 */
private String keyword; private String keyword;

View File

@@ -1,18 +1,44 @@
package com.openhis.web.cardmanagement.dto; package com.openhis.web.cardmanagement.dto;
import lombok.Data; import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@Data @Data
public class DoctorCardUpdateDto { public class DoctorCardUpdateDto {
@NotBlank(message = "卡片编号不能为空")
private String cardNo; private String cardNo;
private String phone; private String phone;
private String contactPhone; // 紧急联系人电话
private LocalDate onsetDate; private LocalDate onsetDate;
private LocalDateTime diagDate; private LocalDateTime diagDate;
private String diseaseType; // 修改为diseaseType对应InfectiousCard中的diseaseType字段
private String addressProv; private String diseaseType; // 病例分类对应InfectiousCard中的diseaseType字段
private String addressCity; private String diseaseCode; // 疾病编码
private String addressCounty;
private String addressHouse; @NotNull(message = "病例类别不能为空")
private Integer caseClass; // 病例类别(1疑似病例/2临床诊断病例/3实验室确诊病例/4病原携带者/5阳性检测结果)
private String occupation; // 职业
@NotNull(message = "病人属于不能为空")
private Integer patientBelong; // 病人属于(1本县区/2本市其他县区/3本省其他地市/4外省/5港澳台/6外籍)
private String addressProv; // 现住址省
private String addressCity; // 现住址市
private String addressCounty; // 现住址县
private String addressTown; // 现住址街道
private String addressVillage; // 现住址村/居委
private String addressHouse; // 现住址门牌号
private String parentName; // 家长姓名
private String workplace; // 工作单位
private String correctName; // 订正病名
private LocalDate deathDate; // 死亡日期
private String withdrawReason; // 退卡原因
private String otherDisease; // 其他传染病名称
} }

View File

@@ -65,8 +65,8 @@ public class InfectiousCardDto {
/** 现住址门牌号 */ /** 现住址门牌号 */
private String addressHouse; private String addressHouse;
/** 病人属于 */ /** 病人属于(1本县区/2本市其他县区/3本省其他地市/4外省/5港澳台/6外籍) */
private String patientbelong; private Integer patientBelong;
/** 职业 */ /** 职业 */
private String occupation; private String occupation;
@@ -110,8 +110,8 @@ public class InfectiousCardDto {
/** 填卡日期 */ /** 填卡日期 */
private LocalDate reportDate; private LocalDate reportDate;
/** 状态 */ /** 状态(0暂存/1已提交/2已审核/3已上报/4失败/5退回/6作废) */
private String status; private Integer status;
/** 状态文本 */ /** 状态文本 */
private String statusText; private String statusText;

View File

@@ -18,14 +18,14 @@ import java.util.List;
public interface InfectiousAuditMapper extends BaseMapper<InfectiousAudit> { public interface InfectiousAuditMapper extends BaseMapper<InfectiousAudit> {
/** /**
* 根据报卡ID查询审核记录 * 根据报卡编号查询审核记录
*/ */
@Select("SELECT * FROM infectious_audit WHERE card_id = #{cardId} ORDER BY audit_time DESC") @Select("SELECT * FROM infectious_audit WHERE card_id = #{cardId} ORDER BY audit_time DESC")
List<InfectiousAudit> selectByCardId(@Param("cardId") Long cardId); List<InfectiousAudit> selectByCardId(@Param("cardId") String cardId);
/** /**
* 获取下一个审核序号 * 获取下一个审核序号
*/ */
@Select("SELECT COALESCE(MAX(audit_seq), 0) + 1 FROM infectious_audit WHERE card_id = #{cardId}") @Select("SELECT COALESCE(MAX(audit_seq), 0) + 1 FROM infectious_audit WHERE card_id = #{cardId}")
Integer getNextAuditSeq(@Param("cardId") Long cardId); Integer getNextAuditSeq(@Param("cardId") String cardId);
} }

View File

@@ -21,25 +21,25 @@ public interface InfectiousCardMapper extends BaseMapper<InfectiousCard> {
/** /**
* 统计今日待审核数量 * 统计今日待审核数量
*/ */
@Select("SELECT COUNT(*) FROM infectious_card WHERE DATE(create_time) = CURRENT_DATE AND status = '1'") @Select("SELECT COUNT(*) FROM infectious_card WHERE DATE(create_time) = CURRENT_DATE AND status = 1")
Integer countTodayPending(); Integer countTodayPending();
/** /**
* 统计本月审核失败数量 * 统计本月审核失败数量
*/ */
@Select("SELECT COUNT(*) FROM infectious_card WHERE DATE_TRUNC('month', create_time) = DATE_TRUNC('month', CURRENT_DATE) AND status = '5'") @Select("SELECT COUNT(*) FROM infectious_card WHERE DATE_TRUNC('month', create_time) = DATE_TRUNC('month', CURRENT_DATE) AND status = 5")
Integer countMonthFailed(); Integer countMonthFailed();
/** /**
* 统计本月审核成功数量 * 统计本月审核成功数量
*/ */
@Select("SELECT COUNT(*) FROM infectious_card WHERE DATE_TRUNC('month', create_time) = DATE_TRUNC('month', CURRENT_DATE) AND status = '2'") @Select("SELECT COUNT(*) FROM infectious_card WHERE DATE_TRUNC('month', create_time) = DATE_TRUNC('month', CURRENT_DATE) AND status = 2")
Integer countMonthSuccess(); Integer countMonthSuccess();
/** /**
* 统计本月已上报数量 * 统计本月已上报数量
*/ */
@Select("SELECT COUNT(*) FROM infectious_card WHERE DATE_TRUNC('month', create_time) = DATE_TRUNC('month', CURRENT_DATE) AND status = '3'") @Select("SELECT COUNT(*) FROM infectious_card WHERE DATE_TRUNC('month', create_time) = DATE_TRUNC('month', CURRENT_DATE) AND status = 3")
Integer countMonthReported(); Integer countMonthReported();
/** /**
@@ -55,14 +55,14 @@ public interface InfectiousCardMapper extends BaseMapper<InfectiousCard> {
Integer countByDoctorId(@Param("doctorId") Long doctorId); Integer countByDoctorId(@Param("doctorId") Long doctorId);
/** /**
* 统计医生待处理失败状态为0暂存或4失败 * 统计医生待提交状态为0暂存待提交
*/ */
@Select("SELECT COUNT(*) FROM infectious_card WHERE doctor_id = #{doctorId} AND status IN ('0', '4')") @Select("SELECT COUNT(*) FROM infectious_card WHERE doctor_id = #{doctorId} AND status = 0")
Integer countPendingFailedByDoctorId(@Param("doctorId") Long doctorId); Integer countPendingFailedByDoctorId(@Param("doctorId") Long doctorId);
/** /**
* 统计医生已成功上报数状态为3已上报 * 统计医生已成功上报数状态为3已上报
*/ */
@Select("SELECT COUNT(*) FROM infectious_card WHERE doctor_id = #{doctorId} AND status = '3'") @Select("SELECT COUNT(*) FROM infectious_card WHERE doctor_id = #{doctorId} AND status = 3")
Integer countReportedByDoctorId(@Param("doctorId") Long doctorId); Integer countReportedByDoctorId(@Param("doctorId") Long doctorId);
} }

View File

@@ -127,14 +127,11 @@ public class InfectiousCardDto {
/** 审核意见 */ /** 审核意见 */
private String auditOpinion; private String auditOpinion;
/** 退原因 */ /** 退原因 */
private String returnReason; private String returnReason;
/** 订正病名 */ /** 订正病名 */
private String correctName; private String revisedDiseaseName;
/** 退卡原因 */
private String withdrawReason;
/** 其他传染病 */ /** 其他传染病 */
private String otherDisease; private String otherDisease;

View File

@@ -29,9 +29,8 @@ public class InfectiousAudit extends HisBaseEntity {
@JsonSerialize(using = ToStringSerializer.class) @JsonSerialize(using = ToStringSerializer.class)
private Long auditId; private Long auditId;
/** 报卡ID */ /** 报卡编号(关联 infectious_card.card_no */
@JsonSerialize(using = ToStringSerializer.class) private String cardId;
private Long cardId;
/** 审核序号 */ /** 审核序号 */
private Integer auditSeq; private Integer auditSeq;

View File

@@ -1,6 +1,7 @@
package com.openhis.infectious.domain; package com.openhis.infectious.domain;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import com.core.common.core.domain.HisBaseEntity; import com.core.common.core.domain.HisBaseEntity;
@@ -26,12 +27,8 @@ import java.time.LocalDateTime;
@EqualsAndHashCode(callSuper = false) @EqualsAndHashCode(callSuper = false)
public class InfectiousCard extends HisBaseEntity { public class InfectiousCard extends HisBaseEntity {
/** 卡片编号 */ /** 卡片编号(业务编号,主键) */
@TableId(type = IdType.ASSIGN_ID) @TableId(type = IdType.INPUT)
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
/** 卡片编号(业务编号) */
private String cardNo; private String cardNo;
/** 本次就诊ID */ /** 本次就诊ID */
@@ -97,8 +94,9 @@ public class InfectiousCard extends HisBaseEntity {
/** 现住址门牌号 */ /** 现住址门牌号 */
private String addressHouse; private String addressHouse;
/** 病人属于 */ /** 病人属于(1本县区/2本市其他县区/3本省其他地市/4外省/5港澳台/6外籍) */
private String patientbelong; @TableField("patient_belong")
private Integer patientBelong;
/** 职业 */ /** 职业 */
private String occupation; private String occupation;
@@ -106,18 +104,15 @@ public class InfectiousCard extends HisBaseEntity {
/** 疾病编码 */ /** 疾病编码 */
private String diseaseCode; private String diseaseCode;
/** 疾病名称 */
private String diseaseName;
/** 分型 */
private String diseaseSubtype;
/** 其他传染病 */
private String otherDisease;
/** 病例分类 */ /** 病例分类 */
private String diseaseType; private String diseaseType;
/** 其他传染病名称 */
private String otherDisease;
/** 病例类别(1疑似病例/2临床诊断病例/3实验室确诊病例/4病原携带者/5阳性检测结果) */
private Integer caseClass;
/** 发病日期 */ /** 发病日期 */
private LocalDate onsetDate; private LocalDate onsetDate;
@@ -146,7 +141,7 @@ public class InfectiousCard extends HisBaseEntity {
private LocalDate reportDate; private LocalDate reportDate;
/** 状态(0暂存/1已提交/2已审核/3已上报/4失败/5退回) */ /** 状态(0暂存/1已提交/2已审核/3已上报/4失败/5退回) */
private String status; private Integer status;
/** 失败原因 */ /** 失败原因 */
private String failMsg; private String failMsg;
@@ -165,6 +160,7 @@ public class InfectiousCard extends HisBaseEntity {
private Long deptId; private Long deptId;
/** 科室名称 */ /** 科室名称 */
@TableField(exist = false)
private String deptName; private String deptName;
/** 医生ID */ /** 医生ID */

View File

@@ -334,12 +334,12 @@
<el-col :span="12"> <el-col :span="12">
<el-form-item label="病人属于"> <el-form-item label="病人属于">
<el-select v-model="currentCard.patientBelong" :disabled="drawerMode !== 'edit'" style="width: 100%"> <el-select v-model="currentCard.patientBelong" :disabled="drawerMode !== 'edit'" style="width: 100%">
<el-option label="本县区" value="1" /> <el-option label="本县区" :value="1" />
<el-option label="本市其他县区" value="2" /> <el-option label="本市其他县区" :value="2" />
<el-option label="本省其他地市" value="3" /> <el-option label="本省其他地市" :value="3" />
<el-option label="外省" value="4" /> <el-option label="外省" :value="4" />
<el-option label="港澳台" value="5" /> <el-option label="港澳台" :value="5" />
<el-option label="外籍" value="6" /> <el-option label="外籍" :value="6" />
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>

View File

@@ -130,12 +130,12 @@
<el-col :span="24" class="form-item full-width"> <el-col :span="24" class="form-item full-width">
<span class="form-label required">病人属于</span> <span class="form-label required">病人属于</span>
<el-radio-group v-model="form.patientBelong"> <el-radio-group v-model="form.patientBelong">
<el-radio label="1">本县区</el-radio> <el-radio :label="1">本县区</el-radio>
<el-radio label="2">本市其他县区</el-radio> <el-radio :label="2">本市其他县区</el-radio>
<el-radio label="3">本省其他地市</el-radio> <el-radio :label="3">本省其他地市</el-radio>
<el-radio label="4">外省</el-radio> <el-radio :label="4">外省</el-radio>
<el-radio label="5">港澳台</el-radio> <el-radio :label="5">港澳台</el-radio>
<el-radio label="6">外籍</el-radio> <el-radio :label="6">外籍</el-radio>
</el-radio-group> </el-radio-group>
</el-col> </el-col>
</el-row> </el-row>
@@ -732,7 +732,7 @@ const form = ref({
addressTown: '', addressTown: '',
addressVillage: '', addressVillage: '',
addressHouse: '', addressHouse: '',
patientBelong: '1', patientBelong: 1,
occupation: '', occupation: '',
caseClass: '', caseClass: '',
onsetDate: '', onsetDate: '',
@@ -1186,7 +1186,7 @@ function show(diagnosisData) {
addressHouse: diagnosisData?.addressHouse || '', // 门牌号 addressHouse: diagnosisData?.addressHouse || '', // 门牌号
// 患者类型和职业 // 患者类型和职业
patientBelong: '1', // 患者属于(本县区/本市其他县区/本省其他地市/外省/港澳台/外籍) patientBelong: 1, // 患者属于(本县区/本市其他县区/本省其他地市/外省/港澳台/外籍)
occupation: '', // 职业 occupation: '', // 职业
caseClass: '', // 病例分类(疑似病例/临床诊断病例/确诊病例/病原携带者/阳性检测) caseClass: '', // 病例分类(疑似病例/临床诊断病例/确诊病例/病原携带者/阳性检测)
@@ -1297,7 +1297,7 @@ async function buildSubmitData() {
addressTown: formData.addressTown || '', addressTown: formData.addressTown || '',
addressVillage: formData.addressVillage || '', addressVillage: formData.addressVillage || '',
addressHouse: formData.addressHouse || '', addressHouse: formData.addressHouse || '',
patientBelong: patientBelongMap[formData.patientBelong] || 1, patientBelong: formData.patientBelong || 1,
occupation: formData.occupation || null, occupation: formData.occupation || null,
diseaseCode: diseaseCode || null, diseaseCode: diseaseCode || null,
diseaseType: diseaseType || null, diseaseType: diseaseType || null,

View File

@@ -31,12 +31,12 @@
</el-col> </el-col>
<el-col :span="8"> <el-col :span="8">
<el-form-item :label="'家长姓名' + (isChildPatient ? '' : '')" :prop="isChildPatient ? 'parentName' : ''" :required="isChildPatient"> <el-form-item :label="'家长姓名' + (isChildPatient ? '' : '')" :prop="isChildPatient ? 'parentName' : ''" :required="isChildPatient">
<el-input v-model="form.parentName" placeholder="≤14岁必填" /> <el-input v-model="form.parentName" placeholder="≤14岁必填" :disabled="isReadOnly" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8"> <el-col :span="8">
<el-form-item label="身份证号" prop="idNo" required> <el-form-item label="身份证号" prop="idNo" required>
<el-input v-model="form.idNo" placeholder="请输入身份证号" maxlength="18" @change="handleIdCardChange" /> <el-input v-model="form.idNo" placeholder="请输入身份证号" maxlength="18" :disabled="isReadOnly" @change="isReadOnly ? null : handleIdCardChange($event)" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -45,7 +45,7 @@
<el-row :gutter="16" class="form-row"> <el-row :gutter="16" class="form-row">
<el-col :span="6"> <el-col :span="6">
<el-form-item label="性别" prop="sex" required> <el-form-item label="性别" prop="sex" required>
<el-radio-group v-model="form.sex"> <el-radio-group v-model="form.sex" :disabled="isReadOnly">
<el-radio label="男"></el-radio> <el-radio label="男"></el-radio>
<el-radio label="女"></el-radio> <el-radio label="女"></el-radio>
<el-radio label="未知">未知</el-radio> <el-radio label="未知">未知</el-radio>
@@ -55,11 +55,11 @@
<el-col :span="10"> <el-col :span="10">
<el-form-item label="出生日期" required> <el-form-item label="出生日期" required>
<div class="date-inputs"> <div class="date-inputs">
<el-input v-model="form.birthYear" placeholder="年" maxlength="4" @change="calculateAge" style="width: 80px" /> <el-input v-model="form.birthYear" placeholder="年" maxlength="4" :disabled="isReadOnly" @change="isReadOnly ? null : calculateAge()" style="width: 80px" />
<span></span> <span></span>
<el-input v-model="form.birthMonth" placeholder="月" maxlength="2" @change="calculateAge" style="width: 60px" /> <el-input v-model="form.birthMonth" placeholder="月" maxlength="2" :disabled="isReadOnly" @change="isReadOnly ? null : calculateAge()" style="width: 60px" />
<span></span> <span></span>
<el-input v-model="form.birthDay" placeholder="日" maxlength="2" @change="calculateAge" style="width: 60px" /> <el-input v-model="form.birthDay" placeholder="日" maxlength="2" :disabled="isReadOnly" @change="isReadOnly ? null : calculateAge()" style="width: 60px" />
<span></span> <span></span>
</div> </div>
</el-form-item> </el-form-item>
@@ -67,8 +67,8 @@
<el-col :span="8"> <el-col :span="8">
<el-form-item label="或 实足年龄"> <el-form-item label="或 实足年龄">
<div class="age-inputs"> <div class="age-inputs">
<el-input v-model="form.age" placeholder="年龄" style="width: 100px" /> <el-input v-model="form.age" placeholder="年龄" style="width: 100px" :disabled="isReadOnly" />
<el-select v-model="form.ageUnit" style="width: 80px"> <el-select v-model="form.ageUnit" style="width: 80px" :disabled="isReadOnly">
<el-option label="岁" value="岁" /> <el-option label="岁" value="岁" />
<el-option label="月" value="月" /> <el-option label="月" value="月" />
<el-option label="天" value="天" /> <el-option label="天" value="天" />
@@ -82,7 +82,7 @@
<el-row :gutter="16" class="form-row"> <el-row :gutter="16" class="form-row">
<el-col :span="24"> <el-col :span="24">
<el-form-item label="工作单位(学校)"> <el-form-item label="工作单位(学校)">
<el-input v-model="form.workplace" placeholder="请输入工作单位" /> <el-input v-model="form.workplace" placeholder="请输入工作单位" :disabled="isReadOnly" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -91,12 +91,12 @@
<el-row :gutter="16" class="form-row"> <el-row :gutter="16" class="form-row">
<el-col :span="12"> <el-col :span="12">
<el-form-item label="联系电话" prop="phone" required> <el-form-item label="联系电话" prop="phone" required>
<el-input v-model="form.phone" placeholder="请输入联系电话" maxlength="11" /> <el-input v-model="form.phone" placeholder="请输入联系电话" maxlength="11" :disabled="isReadOnly" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="紧急联系人电话" prop="contactPhone" required> <el-form-item label="紧急联系人电话" prop="contactPhone" required>
<el-input v-model="form.contactPhone" placeholder="请输入紧急联系人电话" maxlength="11" /> <el-input v-model="form.contactPhone" placeholder="请输入紧急联系人电话" maxlength="11" :disabled="isReadOnly" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -112,6 +112,7 @@
placeholder="请选择省/市/区县/街道" placeholder="请选择省/市/区县/街道"
clearable clearable
style="width: 100%" style="width: 100%"
:disabled="isReadOnly"
@change="handleAddressChange" @change="handleAddressChange"
/> />
</el-form-item> </el-form-item>
@@ -119,10 +120,10 @@
</el-row> </el-row>
<el-row :gutter="16" class="form-row"> <el-row :gutter="16" class="form-row">
<el-col :span="12"> <el-col :span="12">
<el-input v-model="form.addressVillage" placeholder="村(居)" /> <el-input v-model="form.addressVillage" placeholder="村(居)" :disabled="isReadOnly" />
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-input v-model="form.addressHouse" placeholder="门牌号" /> <el-input v-model="form.addressHouse" placeholder="门牌号" :disabled="isReadOnly" />
</el-col> </el-col>
</el-row> </el-row>
@@ -130,13 +131,13 @@
<el-row :gutter="16" class="form-row"> <el-row :gutter="16" class="form-row">
<el-col :span="24"> <el-col :span="24">
<el-form-item label="病人属于" prop="patientBelong" required> <el-form-item label="病人属于" prop="patientBelong" required>
<el-radio-group v-model="form.patientBelong"> <el-radio-group v-model="form.patientBelong" :disabled="isReadOnly">
<el-radio label="1">本县区</el-radio> <el-radio :label="1">本县区</el-radio>
<el-radio label="2">本市其他县区</el-radio> <el-radio :label="2">本市其他县区</el-radio>
<el-radio label="3">本省其他地市</el-radio> <el-radio :label="3">本省其他地市</el-radio>
<el-radio label="4">外省</el-radio> <el-radio :label="4">外省</el-radio>
<el-radio label="5">港澳台</el-radio> <el-radio :label="5">港澳台</el-radio>
<el-radio label="6">外籍</el-radio> <el-radio :label="6">外籍</el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
</el-col> </el-col>
@@ -146,14 +147,14 @@
<el-row :gutter="16" class="form-row"> <el-row :gutter="16" class="form-row">
<el-col :span="12"> <el-col :span="12">
<el-form-item label="职业" prop="occupation" required> <el-form-item label="职业" prop="occupation" required>
<el-select v-model="form.occupation" placeholder="请选择职业" style="width: 100%"> <el-select v-model="form.occupation" placeholder="请选择职业" style="width: 100%" :disabled="isReadOnly">
<el-option v-for="item in occupationList" :key="item.value" :label="item.label" :value="item.value" /> <el-option v-for="item in occupationList" :key="item.value" :label="item.label" :value="item.value" />
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="病例分类" prop="caseClass" required> <el-form-item label="病例分类" prop="caseClass" required>
<el-radio-group v-model="form.caseClass"> <el-radio-group v-model="form.caseClass" :disabled="isReadOnly">
<el-radio label="1">疑似病例</el-radio> <el-radio label="1">疑似病例</el-radio>
<el-radio label="2">临床诊断病例</el-radio> <el-radio label="2">临床诊断病例</el-radio>
<el-radio label="3">确诊病例</el-radio> <el-radio label="3">确诊病例</el-radio>
@@ -175,6 +176,7 @@
style="width: 100%" style="width: 100%"
value-format="YYYY-MM-DD" value-format="YYYY-MM-DD"
format="YYYY-MM-DD" format="YYYY-MM-DD"
:disabled="isReadOnly"
/> />
</el-form-item> </el-form-item>
</el-col> </el-col>
@@ -187,6 +189,7 @@
style="width: 100%" style="width: 100%"
value-format="YYYY-MM-DD" value-format="YYYY-MM-DD"
format="YYYY-MM-DD" format="YYYY-MM-DD"
:disabled="isReadOnly"
/> />
</el-form-item> </el-form-item>
</el-col> </el-col>
@@ -199,6 +202,7 @@
style="width: 100%" style="width: 100%"
value-format="YYYY-MM-DD" value-format="YYYY-MM-DD"
format="YYYY-MM-DD" format="YYYY-MM-DD"
:disabled="isReadOnly"
/> />
</el-form-item> </el-form-item>
</el-col> </el-col>
@@ -215,11 +219,13 @@
<div class="disease-list"> <div class="disease-list">
<el-checkbox <el-checkbox
:model-value="form.selectedClassA === '0101'" :model-value="form.selectedClassA === '0101'"
@update:model-value="(checked) => handleClassACheckbox('0101', checked)" :disabled="isReadOnly"
@update:model-value="(checked) => isReadOnly ? null : handleClassACheckbox('0101', checked)"
>鼠疫</el-checkbox> >鼠疫</el-checkbox>
<el-checkbox <el-checkbox
:model-value="form.selectedClassA === '0102'" :model-value="form.selectedClassA === '0102'"
@update:model-value="(checked) => handleClassACheckbox('0102', checked)" :disabled="isReadOnly"
@update:model-value="(checked) => isReadOnly ? null : handleClassACheckbox('0102', checked)"
>霍乱</el-checkbox> >霍乱</el-checkbox>
</div> </div>
</div> </div>
@@ -232,7 +238,8 @@
v-for="disease in classBDiseases" v-for="disease in classBDiseases"
:key="disease.code" :key="disease.code"
:model-value="form.selectedClassB === disease.code" :model-value="form.selectedClassB === disease.code"
@update:model-value="(checked) => handleClassBCheckbox(disease.code, checked)" :disabled="isReadOnly"
@update:model-value="(checked) => isReadOnly ? null : handleClassBCheckbox(disease.code, checked)"
>{{ disease.name }}</el-checkbox> >{{ disease.name }}</el-checkbox>
</div> </div>
</div> </div>
@@ -245,7 +252,8 @@
v-for="disease in classCDiseases" v-for="disease in classCDiseases"
:key="disease.code" :key="disease.code"
:model-value="form.selectedClassC === disease.code" :model-value="form.selectedClassC === disease.code"
@update:model-value="(checked) => handleClassCCheckbox(disease.code, checked)" :disabled="isReadOnly"
@update:model-value="(checked) => isReadOnly ? null : handleClassCCheckbox(disease.code, checked)"
>{{ disease.name }}</el-checkbox> >{{ disease.name }}</el-checkbox>
</div> </div>
</div> </div>
@@ -254,12 +262,12 @@
<el-row :gutter="16" class="form-row"> <el-row :gutter="16" class="form-row">
<el-col :span="showSubtypeSelect ? 16 : 24"> <el-col :span="showSubtypeSelect ? 16 : 24">
<el-form-item label="其他法定管理以及重点监测传染病"> <el-form-item label="其他法定管理以及重点监测传染病">
<el-input v-model="form.otherDisease" placeholder="手动输入非列表疾病" /> <el-input v-model="form.otherDisease" placeholder="手动输入非列表疾病" :disabled="isReadOnly" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col v-if="showSubtypeSelect" :span="8"> <el-col v-if="showSubtypeSelect" :span="8">
<el-form-item label="分型" prop="diseaseType" :required="showSubtypeSelect"> <el-form-item label="分型" prop="diseaseType" :required="showSubtypeSelect">
<el-select v-model="form.diseaseType" placeholder="请选择分型" style="width: 100%"> <el-select v-model="form.diseaseType" placeholder="请选择分型" style="width: 100%" :disabled="isReadOnly">
<el-option <el-option
v-for="option in currentSubtypeOptions" v-for="option in currentSubtypeOptions"
:key="option.value" :key="option.value"
@@ -284,7 +292,7 @@
</el-col> </el-col>
<el-col :span="8"> <el-col :span="8">
<el-form-item label="联系电话"> <el-form-item label="联系电话">
<el-input v-model="form.reportOrgPhone" placeholder="请输入联系电话" /> <el-input v-model="form.reportOrgPhone" placeholder="请输入联系电话" :disabled="isReadOnly" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8"> <el-col :span="8">
@@ -304,17 +312,18 @@
style="width: 100%" style="width: 100%"
value-format="YYYY-MM-DD" value-format="YYYY-MM-DD"
format="YYYY-MM-DD" format="YYYY-MM-DD"
:disabled="isReadOnly"
/> />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8"> <el-col :span="8">
<el-form-item label="订正病名"> <el-form-item label="订正病名">
<el-input v-model="form.correctName" placeholder="请输入订正病名" /> <el-input v-model="form.correctName" placeholder="请输入订正病名" :disabled="isReadOnly" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8"> <el-col :span="8">
<el-form-item label="退卡原因"> <el-form-item label="退卡原因">
<el-input v-model="form.withdrawReason" placeholder="请输入退卡原因" /> <el-input v-model="form.withdrawReason" placeholder="请输入退卡原因" :disabled="isReadOnly" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -322,15 +331,15 @@
<el-row :gutter="16" class="form-row"> <el-row :gutter="16" class="form-row">
<el-col :span="24"> <el-col :span="24">
<el-form-item label="备注"> <el-form-item label="备注">
<el-input v-model="form.remark" type="textarea" :rows="2" placeholder="请输入备注" /> <el-input v-model="form.remark" type="textarea" :rows="2" placeholder="请输入备注" :disabled="isReadOnly" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
</el-form> </el-form>
</div> </div>
<!-- 操作按钮区 --> <!-- 操作按钮区create/edit 模式下显示) -->
<div class="action-buttons"> <div v-if="mode !== 'view'" class="action-buttons">
<el-button type="primary" @click="handleSubmit" :loading="submitLoading">保 存</el-button> <el-button type="primary" @click="handleSubmit" :loading="submitLoading">保 存</el-button>
<el-button @click="handleReset"> </el-button> <el-button @click="handleReset"> </el-button>
</div> </div>
@@ -347,6 +356,9 @@ import { useDict } from '@/utils/dict';
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance();
const userStore = useUserStore(); const userStore = useUserStore();
// 是否只读模式
const isReadOnly = computed(() => props.mode === 'view');
// 获取职业字典数据 // 获取职业字典数据
const { prfs: occupationList } = useDict('prfs'); const { prfs: occupationList } = useDict('prfs');
@@ -418,9 +430,19 @@ const props = defineProps({
type: String, type: String,
default: '', default: '',
}, },
// 'create' | 'view' | 'edit'
mode: {
type: String,
default: 'create',
},
// 已有报卡数据view/edit 模式下使用)
cardData: {
type: Object,
default: null,
},
}); });
const emit = defineEmits(['saved']); const emit = defineEmits(['saved', 'submit-edit']);
// 地址级联选择器配置 // 地址级联选择器配置
const addressOptions = ref(pcas); const addressOptions = ref(pcas);
@@ -453,7 +475,7 @@ const form = ref({
addressTown: '', addressTown: '',
addressVillage: '', addressVillage: '',
addressHouse: '', addressHouse: '',
patientBelong: '1', patientBelong: 1,
occupation: '', occupation: '',
caseClass: '', caseClass: '',
onsetDate: '', onsetDate: '',
@@ -567,19 +589,27 @@ const isChildPatient = computed(() => {
// 监听疾病选择变化,自动清空分型选择 // 监听疾病选择变化,自动清空分型选择
watch(() => [form.value.selectedClassA, form.value.selectedClassB, form.value.selectedClassC], (newVal, oldVal) => { watch(() => [form.value.selectedClassA, form.value.selectedClassB, form.value.selectedClassC], (newVal, oldVal) => {
if (JSON.stringify(newVal) !== JSON.stringify(oldVal)) { // 在view/edit模式下初始化时不清空分型避免数据加载时被错误清空
if (JSON.stringify(newVal) !== JSON.stringify(oldVal) && props.mode !== 'view' && props.mode !== 'edit') {
form.value.diseaseType = ''; form.value.diseaseType = '';
} }
updateSelectedDiseases(); updateSelectedDiseases();
}, { deep: true }); }, { deep: true });
// 监听患者信息变化,自动填充表单 // 监听患者信息变化,自动填充表单(仅 create 模式)
watch(() => props.patientInfo, (newVal) => { watch(() => props.patientInfo, (newVal) => {
if (newVal && Object.keys(newVal).length > 0) { if (props.mode === 'create' && newVal && Object.keys(newVal).length > 0) {
initForm(); initForm();
} }
}, { deep: true, immediate: true }); }, { deep: true, immediate: true });
// 监听 cardData 变化,在 view/edit 模式下初始化
watch(() => props.cardData, (newVal) => {
if ((props.mode === 'view' || props.mode === 'edit') && newVal) {
initFormFromCard(newVal);
}
}, { immediate: true });
// 监听Tab切换重新初始化 // 监听Tab切换重新初始化
watch(() => props.activeTab, (newVal) => { watch(() => props.activeTab, (newVal) => {
if (newVal === 'infectiousReport' && props.patientInfo && Object.keys(props.patientInfo).length > 0) { if (newVal === 'infectiousReport' && props.patientInfo && Object.keys(props.patientInfo).length > 0) {
@@ -808,7 +838,7 @@ async function initForm() {
addressTown: patientInfo.addressStreet || '', addressTown: patientInfo.addressStreet || '',
addressVillage: '', addressVillage: '',
addressHouse: '', addressHouse: '',
patientBelong: '1', patientBelong: 1,
occupation: '', occupation: '',
caseClass: '', caseClass: '',
onsetDate: getCurrentDate(), onsetDate: getCurrentDate(),
@@ -893,7 +923,7 @@ function buildSubmitData() {
addressTown: formData.addressTown || '', addressTown: formData.addressTown || '',
addressVillage: formData.addressVillage || '', addressVillage: formData.addressVillage || '',
addressHouse: formData.addressHouse || '', addressHouse: formData.addressHouse || '',
patientBelong: parseInt(formData.patientBelong) || 1, patientBelong: formData.patientBelong || 1,
occupation: formData.occupation || null, occupation: formData.occupation || null,
diseaseCode: diseaseCode || null, diseaseCode: diseaseCode || null,
diseaseType: diseaseType || null, diseaseType: diseaseType || null,
@@ -1015,15 +1045,20 @@ async function handleSubmit() {
const submitData = buildSubmitData(); const submitData = buildSubmitData();
const res = await saveInfectiousDiseaseReport(submitData); if (props.mode === 'edit') {
// 编辑模式:通过事件通知父组件处理保存
if (res.code === 200) { emit('submit-edit', submitData);
proxy.$modal.msgSuccess('传染病报告卡保存成功');
emit('saved');
// 重新初始化表单,获取新的卡片编号
initForm();
} else { } else {
proxy.$modal.msgError(res.msg || '保存失败'); // 新建模式
const res = await saveInfectiousDiseaseReport(submitData);
if (res.code === 200) {
proxy.$modal.msgSuccess('传染病报告卡保存成功');
emit('saved');
// 重新初始化表单,获取新的卡片编号
initForm();
} else {
proxy.$modal.msgError(res.msg || '保存失败');
}
} }
} catch (err) { } catch (err) {
console.error('传染病报告卡保存失败:', err); console.error('传染病报告卡保存失败:', err);
@@ -1065,7 +1100,7 @@ function handleReset() {
form.value.contactPhone = ''; form.value.contactPhone = '';
form.value.occupation = ''; form.value.occupation = '';
form.value.caseClass = ''; form.value.caseClass = '';
form.value.patientBelong = '1'; form.value.patientBelong = 1;
form.value.otherDisease = ''; form.value.otherDisease = '';
form.value.correctName = ''; form.value.correctName = '';
form.value.withdrawReason = ''; form.value.withdrawReason = '';
@@ -1075,22 +1110,108 @@ function handleReset() {
updateSelectedDiseases(); updateSelectedDiseases();
} }
// 从已有报卡数据初始化表单view/edit 模式)
function initFormFromCard(card) {
if (!card) return;
const ageUnitReverseMap = { '1': '岁', '2': '月', '3': '天' };
const sexMap = { '1': '男', '2': '女', '0': '未知' };
// 拆解出生日期
let birthYear = '', birthMonth = '', birthDay = '';
if (card.birthday) {
const parts = card.birthday.split('-');
birthYear = parts[0] || '';
birthMonth = parts[1] || '';
birthDay = parts[2] || '';
}
// 还原疾病分类选中状态
let selectedClassA = '', selectedClassB = '', selectedClassC = '';
if (card.diseaseCode) {
if (card.diseaseCode.startsWith('01')) selectedClassA = card.diseaseCode;
else if (card.diseaseCode.startsWith('02')) selectedClassB = card.diseaseCode;
else if (card.diseaseCode.startsWith('03')) selectedClassC = card.diseaseCode;
}
form.value = {
cardNo: card.cardNo || '',
patName: card.patName || '',
parentName: card.parentName || '',
idNo: card.idNo || '',
sex: sexMap[card.sex] || card.sex || '男',
birthYear,
birthMonth,
birthDay,
age: card.age != null ? String(card.age) : '',
ageUnit: ageUnitReverseMap[card.ageUnit] || '岁',
workplace: card.workplace || '',
phone: card.phone || '',
contactPhone: card.contactPhone || '',
addressProv: card.addressProv || '',
addressCity: card.addressCity || '',
addressCounty: card.addressCounty || '',
addressTown: card.addressTown || '',
addressVillage: card.addressVillage || '',
addressHouse: card.addressHouse || '',
patientBelong: card.patientBelong || 1,
occupation: card.occupation || '',
caseClass: card.caseClass != null ? String(card.caseClass) : '',
onsetDate: card.onsetDate || '',
diagDate: card.diagDate ? card.diagDate.substring(0, 10) : '',
deathDate: card.deathDate || '',
selectedDiseases: card.diseaseCode && card.diseaseCode !== 'OTHER' ? [card.diseaseCode] : [],
selectedClassA,
selectedClassB,
selectedClassC,
otherDisease: card.diseaseCode === 'OTHER' ? (card.otherDisease || '') : (card.otherDisease || ''),
diseaseType: card.diseaseType || '',
reportOrg: card.reportOrg || '',
reportOrgPhone: card.reportOrgPhone || '',
reportDoc: card.reportDoc || '',
reportDate: card.reportDate || '',
correctName: card.correctName || '',
withdrawReason: card.withdrawReason || '',
remark: card.remark || '',
encounterId: card.visitId || '',
patientId: card.patId || '',
diagnosisId: card.diagId || '',
};
// 设置地址级联选择器
const provName = card.addressProv || '';
const cityName = card.addressCity || '';
const countyName = card.addressCounty || '';
const townName = card.addressTown || '';
let names = [];
if (municipalities.includes(provName)) {
names = [provName, countyName, townName].filter(n => n);
} else {
names = [provName, cityName, countyName, townName].filter(n => n);
}
addressCodes.value = findCodesByNames(names);
}
// 组件挂载时初始化 // 组件挂载时初始化
onMounted(() => { onMounted(() => {
if (props.patientInfo && Object.keys(props.patientInfo).length > 0) { if ((props.mode === 'view' || props.mode === 'edit') && props.cardData) {
initFormFromCard(props.cardData);
} else if (props.mode === 'create' && props.patientInfo && Object.keys(props.patientInfo).length > 0) {
initForm(); initForm();
} }
}); });
// 暴露方法供父组件调用 // 暴露方法供父组件调用
defineExpose({ defineExpose({
initForm initForm,
initFormFromCard
}); });
</script> </script>
<style scoped> <style scoped>
.infectious-report-container { .infectious-report-container {
height: 100%; height: auto;
min-height: 100%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
background: #fff; background: #fff;
@@ -1130,8 +1251,7 @@ defineExpose({
/* 表单区域样式 */ /* 表单区域样式 */
.report-form { .report-form {
flex: 1; overflow-y: visible;
overflow-y: auto;
padding-right: 8px; padding-right: 8px;
} }

View File

@@ -1,31 +1,33 @@
<template> <template>
<div class="my-card-management-container"> <div class="my-card-management-container">
<!-- 顶部标题 -->
<div class="page-header"> <div class="page-header">
<h2>我的报卡</h2> <h2 class="page-title">我的报卡</h2>
</div> </div>
<!-- 统计卡片区 -->
<div class="statistics-section"> <div class="statistics-section">
<div class="stat-card total"> <div class="stat-card">
<div class="stat-icon"> <div class="stat-icon-wrap stat-icon-purple">
<el-icon><Document /></el-icon> <el-icon class="stat-icon-inner"><DataAnalysis /></el-icon>
</div> </div>
<div class="stat-content"> <div class="stat-content">
<div class="stat-value">{{ statistics.totalCount || 0 }}</div> <div class="stat-value">{{ statistics.totalCount || 0 }}</div>
<div class="stat-label">总报卡数</div> <div class="stat-label">总报卡数</div>
</div> </div>
</div> </div>
<div class="stat-card pending"> <div class="stat-card">
<div class="stat-icon"> <div class="stat-icon-wrap stat-icon-red">
<el-icon><Clock /></el-icon> <el-icon class="stat-icon-inner"><Warning /></el-icon>
</div> </div>
<div class="stat-content"> <div class="stat-content">
<div class="stat-value">{{ statistics.pendingFailedCount || 0 }}</div> <div class="stat-value">{{ statistics.pendingFailedCount || 0 }}</div>
<div class="stat-label">处理/失败</div> <div class="stat-label">提交</div>
</div> </div>
</div> </div>
<div class="stat-card success"> <div class="stat-card">
<div class="stat-icon"> <div class="stat-icon-wrap stat-icon-green">
<el-icon><CircleCheck /></el-icon> <el-icon class="stat-icon-inner"><CircleCheck /></el-icon>
</div> </div>
<div class="stat-content"> <div class="stat-content">
<div class="stat-value">{{ statistics.reportedCount || 0 }}</div> <div class="stat-value">{{ statistics.reportedCount || 0 }}</div>
@@ -34,21 +36,25 @@
</div> </div>
</div> </div>
<!-- 高级筛选区 -->
<div class="filter-section"> <div class="filter-section">
<el-form :model="queryParams" :inline="true"> <div class="filter-title">高级筛选</div>
<el-form-item label="日期范围"> <div class="filter-row">
<div class="filter-item">
<span class="filter-label">日期范围</span>
<el-date-picker <el-date-picker
v-model="queryParams.dateRange" v-model="queryParams.dateRange"
type="daterange" type="daterange"
range-separator="" range-separator=""
start-placeholder="开始日期" start-placeholder="//"
end-placeholder="结束日期" end-placeholder="//"
value-format="YYYY-MM-DD" value-format="YYYY-MM-DD"
style="width: 240px" class="filter-date-picker"
/> />
</el-form-item> </div>
<el-form-item label="状态"> <div class="filter-item">
<el-select v-model="queryParams.status" placeholder="全部状态" clearable style="width: 140px"> <span class="filter-label">状态</span>
<el-select v-model="queryParams.status" placeholder="全部状态" clearable class="filter-select">
<el-option label="全部状态" value="" /> <el-option label="全部状态" value="" />
<el-option label="待提交" value="0" /> <el-option label="待提交" value="0" />
<el-option label="已提交" value="1" /> <el-option label="已提交" value="1" />
@@ -57,101 +63,65 @@
<el-option label="失败" value="4" /> <el-option label="失败" value="4" />
<el-option label="作废" value="6" /> <el-option label="作废" value="6" />
</el-select> </el-select>
</el-form-item> </div>
<el-form-item label="关键词"> <div class="filter-item">
<span class="filter-label">报卡名称</span>
<el-input <el-input
v-model="queryParams.keyword" v-model="queryParams.keyword"
placeholder="患者姓名/报卡名称" placeholder="输入报卡名称..."
clearable clearable
style="width: 180px" class="filter-input"
@keyup.enter="handleQuery" @keyup.enter="handleQuery"
/> />
</el-form-item> </div>
<el-form-item> <div class="filter-actions">
<el-button type="primary" @click="handleQuery"> <el-button class="btn-apply" type="primary" @click="handleQuery">
<el-icon><Search /></el-icon> <el-icon><Check /></el-icon>
应用筛选 应用筛选
</el-button> </el-button>
<el-button @click="handleReset"> <el-button class="btn-reset" @click="handleReset">
<el-icon><Refresh /></el-icon> <el-icon><RefreshRight /></el-icon>
重置条件 重置条件
</el-button> </el-button>
</el-form-item> </div>
</el-form> </div>
</div>
<div class="action-section">
<el-checkbox v-model="isAllSelected" @change="handleSelectAll">全选</el-checkbox>
<el-button type="primary" :disabled="selectedRows.length === 0" @click="handleBatchSubmit">
批量提交
</el-button>
<el-button type="danger" :disabled="selectedRows.length === 0" @click="handleBatchDelete">
批量删除
</el-button>
</div> </div>
<!-- 数据表格区 -->
<div class="table-section"> <div class="table-section">
<el-table <el-table
ref="tableRef"
v-loading="loading" v-loading="loading"
:data="cardList" :data="cardList"
@selection-change="handleSelectionChange" @selection-change="handleSelectionChange"
border border
stripe stripe
:height="tableHeight"
virtualized
:virtualized-row-height="48"
> >
<el-table-column type="selection" width="55" align="center" /> <el-table-column type="selection" width="50" align="center" />
<el-table-column label="卡片ID" prop="cardNo" min-width="150" /> <el-table-column label="卡片ID" prop="cardNo" min-width="155" />
<el-table-column label="患者姓名" prop="patName" width="100" /> <el-table-column label="患者姓名" prop="patName" width="90" />
<el-table-column label="身份证号" prop="idNo" min-width="180" /> <el-table-column label="身份证号" prop="idNo" min-width="170" />
<el-table-column label="联系电话" prop="phone" width="130" /> <el-table-column label="联系电话" prop="phone" width="120" />
<el-table-column label="就诊卡号" prop="visitCardNo" width="130" /> <el-table-column label="就诊卡号" prop="visitCardNo" width="110" />
<el-table-column label="报卡名称" prop="cardName" min-width="200" /> <el-table-column label="报卡名称" prop="cardName" min-width="120" />
<el-table-column label="提交时间" prop="submitTime" width="160" align="center" /> <el-table-column label="提交时间" prop="submitTime" width="110" align="center" />
<el-table-column label="状态" prop="status" width="100" align="center"> <el-table-column label="状态" prop="status" width="80" align="center">
<template #default="{ row }"> <template #default="{ row }">
<el-tag :type="getStatusType(row.status)" size="small"> <span :class="['status-tag', 'status-' + row.status]">
{{ getStatusName(row.status) }} {{ getStatusName(row.status) }}
</el-tag> </span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="操作" width="200" align="center" fixed="right"> <el-table-column label="操作" width="160" align="center" fixed="right">
<template #default="{ row }"> <template #default="{ row }">
<el-button type="primary" link size="small" @click="handleView(row)">查看</el-button> <el-button type="primary" link size="small" @click="handleView(row)">查看</el-button>
<el-button <el-button v-if="row.status == 0" type="primary" link size="small" @click="handleEdit(row)">编辑</el-button>
v-if="row.status === '0'" <el-button v-if="row.status == 0" type="success" link size="small" @click="handleSubmit(row)">提交</el-button>
type="primary" <el-button v-if="row.status == 1" type="warning" link size="small" @click="handleWithdraw(row)">撤回</el-button>
link <el-button v-if="row.status == 3" type="primary" link size="small" @click="handleExport(row)">导出</el-button>
size="small"
@click="handleEdit(row)"
>
编辑
</el-button>
<el-button
v-if="row.status === '0'"
type="success"
link
size="small"
@click="handleSubmit(row)"
>
提交
</el-button>
<el-button
v-if="row.status === '1'"
type="warning"
link
size="small"
@click="handleWithdraw(row)"
>
撤回
</el-button>
<el-button
v-if="row.status === '3'"
type="info"
link
size="small"
@click="handleExport(row)"
>
导出
</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@@ -169,149 +139,43 @@
</div> </div>
</div> </div>
<!-- 底部批量操作栏 -->
<div class="bottom-action-bar">
<div class="bottom-action-left">
<el-checkbox v-model="isAllSelected" @change="handleSelectAll">全选</el-checkbox>
<span class="selected-info">已选择 {{ selectedRows.length }} 个项目</span>
</div>
<div class="bottom-action-right">
<el-button class="btn-batch-delete" :disabled="selectedRows.length === 0" @click="handleBatchDelete">批量删除</el-button>
<el-button class="btn-batch-submit" type="primary" :disabled="selectedRows.length === 0" @click="handleBatchSubmit">批量提交</el-button>
</div>
</div>
<el-dialog <el-dialog
v-model="detailVisible" v-model="detailVisible"
:title="detailMode === 'view' ? '报卡详情' : '编辑报卡'" :title="detailMode === 'view' ? '报卡详情' : '编辑报卡'"
width="800px" width="900px"
destroy-on-close destroy-on-close
class="card-detail-dialog"
> >
<el-descriptions v-if="detailMode === 'view'" :column="2" border> <InfectiousReport
<el-descriptions-item label="卡片编号">{{ currentCard.cardNo }}</el-descriptions-item> :mode=" detailMode"
<el-descriptions-item label="状态"> :card-data="currentCard"
<el-tag :type="getStatusType(currentCard.status)">{{ getStatusName(currentCard.status) }}</el-tag> @submit-edit="handleSaveEdit"
</el-descriptions-item> style="max-height: 70vh; overflow-y: auto;"
<el-descriptions-item label="患者姓名">{{ currentCard.patName }}</el-descriptions-item> />
<el-descriptions-item label="身份证号">{{ currentCard.idNo }}</el-descriptions-item>
<el-descriptions-item label="联系电话">{{ currentCard.phone }}</el-descriptions-item>
<el-descriptions-item label="性别">{{ currentCard.sex === '1' ? '男' : currentCard.sex === '2' ? '女' : '未知' }}</el-descriptions-item>
<el-descriptions-item label="年龄">{{ currentCard.age }}{{ getAgeUnit(currentCard.ageUnit) }}</el-descriptions-item>
<el-descriptions-item label="疾病名称">{{ currentCard.diseaseName }}</el-descriptions-item>
<el-descriptions-item label="发病日期">{{ currentCard.onsetDate }}</el-descriptions-item>
<el-descriptions-item label="诊断日期">{{ currentCard.diagDate }}</el-descriptions-item>
<el-descriptions-item label="报告单位">{{ currentCard.reportOrg }}</el-descriptions-item>
<el-descriptions-item label="报告医生">{{ currentCard.reportDoc }}</el-descriptions-item>
<el-descriptions-item label="填卡日期">{{ currentCard.reportDate }}</el-descriptions-item>
<el-descriptions-item label="现住址" :span="2">
{{ currentCard.addressProv }}{{ currentCard.addressCity }}{{ currentCard.addressCounty }}{{ currentCard.addressTown }}{{ currentCard.addressVillage }}{{ currentCard.addressHouse }}
</el-descriptions-item>
</el-descriptions>
<el-form v-else ref="editFormRef" :model="editForm" :rules="editFormRules" label-width="100px">
<!-- 患者基本信息 -->
<el-divider content-position="left">患者基本信息</el-divider>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="患者姓名" prop="patName">
<el-input v-model="editForm.patName" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="身份证号" prop="idNo">
<el-input v-model="editForm.idNo" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="性别" prop="sex">
<el-input :value="editForm.sex === '1' ? '男' : editForm.sex === '2' ? '女' : '未知'" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="年龄" prop="age">
<el-input :value="`${editForm.age}${getAgeUnit(editForm.ageUnit)}`" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="联系电话" prop="phone" required>
<el-input v-model="editForm.phone" />
</el-form-item>
</el-col>
</el-row>
<!-- 临床信息 -->
<el-divider content-position="left">临床信息</el-divider>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="疾病名称" prop="diseaseName">
<el-input v-model="editForm.diseaseName" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="发病日期" prop="onsetDate">
<el-date-picker v-model="editForm.onsetDate" type="date" value-format="YYYY-MM-DD" style="width: 100%" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="诊断日期" prop="diagDate" required>
<el-date-picker v-model="editForm.diagDate" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" style="width: 100%" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="传染病类别" prop="diseaseType">
<el-select v-model="editForm.diseaseType" placeholder="请选择传染病类别" style="width: 100%">
<el-option label="甲类传染病" value="A" />
<el-option label="乙类传染病" value="B" />
<el-option label="丙类传染病" value="C" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<!-- 报告信息 -->
<el-divider content-position="left">报告信息</el-divider>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="报告单位" prop="reportOrg">
<el-input v-model="editForm.reportOrg" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="报告医生" prop="reportDoc">
<el-input v-model="editForm.reportDoc" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="填卡日期" prop="reportDate">
<el-input v-model="editForm.reportDate" disabled />
</el-form-item>
</el-col>
</el-row>
<!-- 现住址 -->
<el-divider content-position="left">现住址</el-divider>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="省" prop="addressProv">
<el-input v-model="editForm.addressProv" placeholder="请输入省份" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="市" prop="addressCity">
<el-input v-model="editForm.addressCity" placeholder="请输入城市" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="区县" prop="addressCounty">
<el-input v-model="editForm.addressCounty" placeholder="请输入区县" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="详细地址" prop="addressHouse">
<el-input v-model="editForm.addressHouse" type="textarea" placeholder="请输入详细地址" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer> <template #footer>
<el-button @click="detailVisible = false">取消</el-button> <el-button @click="detailVisible = false">关闭</el-button>
<el-button v-if="detailMode === 'edit'" type="primary" @click="handleSaveEdit">保存</el-button>
</template> </template>
</el-dialog> </el-dialog>
</div> </div>
</template> </template>
<script setup> <script setup>
import { ref, reactive, onMounted } from 'vue'; import { ref, reactive, onMounted, onActivated, onBeforeUnmount, nextTick, computed } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus'; import { ElMessage, ElMessageBox } from 'element-plus';
import { Document, Clock, CircleCheck, Search, Refresh } from '@element-plus/icons-vue'; import { DataAnalysis, Warning, CircleCheck, Check, RefreshRight } from '@element-plus/icons-vue';
import InfectiousReport from '../components/infectiousReport/index.vue';
import { import {
getDoctorCardStatistics, getDoctorCardStatistics,
getDoctorCardList, getDoctorCardList,
@@ -329,6 +193,7 @@ const cardList = ref([]);
const total = ref(0); const total = ref(0);
const selectedRows = ref([]); const selectedRows = ref([]);
const isAllSelected = ref(false); const isAllSelected = ref(false);
const tableRef = ref(null);
const statistics = ref({ const statistics = ref({
totalCount: 0, totalCount: 0,
@@ -347,28 +212,25 @@ const queryParams = reactive({
const detailVisible = ref(false); const detailVisible = ref(false);
const detailMode = ref('view'); const detailMode = ref('view');
const currentCard = ref({}); const currentCard = ref({});
const editForm = reactive({});
const editFormRef = ref(null);
// 编辑表单验证规则 // 计算表格高度:根据视口高度动态调整
const editFormRules = { const tableHeight = computed(() => {
phone: [ // 视口高度 - 顶部导航(约60px) - 标题(40px) - 统计卡片(120px) - 筛选区(100px)
{ required: true, message: '请输入联系电话', trigger: 'blur' }, // - 分页(60px) - 底部操作栏(60px) - 上下边距(80px) - 额外缓冲(20px)
{ pattern: /^1[3-9]\d{9}$/, message: '手机号格式不正确', trigger: 'blur' } return window.innerHeight - 540;
], });
diagDate: [
{ required: true, message: '请选择诊断日期', trigger: 'change' } // 监听窗口大小变化,确保表格高度自适应
] let resizeObserver = null;
};
const statusMap = { const statusMap = {
'0': { name: '待提交', type: 'warning' }, 0: { name: '待提交', type: 'warning' },
'1': { name: '已提交', type: 'primary' }, 1: { name: '已提交', type: 'primary' },
'2': { name: '已审核', type: 'success' }, 2: { name: '已审核', type: 'success' },
'3': { name: '已上报', type: 'success' }, 3: { name: '已上报', type: 'success' },
'4': { name: '失败', type: 'danger' }, 4: { name: '失败', type: 'danger' },
'5': { name: '退回', type: 'danger' }, 5: { name: '退回', type: 'danger' },
'6': { name: '作废', type: 'info' }, 6: { name: '作废', type: 'info' },
}; };
const ageUnitMap = { const ageUnitMap = {
@@ -454,11 +316,11 @@ function handleSelectionChange(selection) {
} }
function handleSelectAll(val) { function handleSelectAll(val) {
if (val) { nextTick(() => {
selectedRows.value = [...cardList.value]; if (tableRef.value) {
} else { tableRef.value.toggleAllSelection();
selectedRows.value = []; }
} });
} }
async function handleView(row) { async function handleView(row) {
@@ -478,7 +340,7 @@ async function handleEdit(row) {
try { try {
const res = await getCardDetail(row.cardNo); const res = await getCardDetail(row.cardNo);
if (res.code === 200) { if (res.code === 200) {
Object.assign(editForm, res.data || {}); currentCard.value = res.data || {};
detailMode.value = 'edit'; detailMode.value = 'edit';
detailVisible.value = true; detailVisible.value = true;
} }
@@ -487,26 +349,33 @@ async function handleEdit(row) {
} }
} }
async function handleSaveEdit() { async function handleSaveEdit(submitData) {
// 验证表单 // submitData 来自 InfectiousReport 组件的 submit-edit 事件
try {
await editFormRef.value.validate();
} catch (error) {
ElMessage.error('表单验证失败,请检查输入');
return;
}
try { try {
const updateData = { const updateData = {
cardNo: editForm.cardNo, cardNo: submitData.cardNo,
phone: editForm.phone, phone: submitData.phone,
onsetDate: editForm.onsetDate, contactPhone: submitData.contactPhone,
diagDate: editForm.diagDate, onsetDate: submitData.onsetDate,
diseaseType: editForm.diseaseType, diagDate: submitData.diagDate,
addressProv: editForm.addressProv, diseaseCode: submitData.diseaseCode,
addressCity: editForm.addressCity, diseaseType: submitData.diseaseType,
addressCounty: editForm.addressCounty, otherDisease: submitData.otherDisease,
addressHouse: editForm.addressHouse, caseClass: submitData.caseClass,
occupation: submitData.occupation,
patientBelong: submitData.patientBelong,
addressProv: submitData.addressProv,
addressCity: submitData.addressCity,
addressCounty: submitData.addressCounty,
addressTown: submitData.addressTown,
addressVillage: submitData.addressVillage,
addressHouse: submitData.addressHouse,
workplace: submitData.workplace,
parentName: submitData.parentName,
deathDate: submitData.deathDate,
correctName: submitData.correctName,
withdrawReason: submitData.withdrawReason,
remark: submitData.remark,
}; };
const res = await updateDoctorCard(updateData); const res = await updateDoctorCard(updateData);
@@ -567,7 +436,7 @@ async function handleWithdraw(row) {
} }
async function handleBatchSubmit() { async function handleBatchSubmit() {
const validRows = selectedRows.value.filter(row => row.status === '0'); const validRows = selectedRows.value.filter(row => row.status == 0);
if (validRows.length === 0) { if (validRows.length === 0) {
ElMessage.warning('只能提交待提交状态的报卡'); ElMessage.warning('只能提交待提交状态的报卡');
return; return;
@@ -595,7 +464,7 @@ async function handleBatchSubmit() {
} }
async function handleBatchDelete() { async function handleBatchDelete() {
const validRows = selectedRows.value.filter(row => row.status === '0'); const validRows = selectedRows.value.filter(row => row.status == 0);
if (validRows.length === 0) { if (validRows.length === 0) {
ElMessage.warning('只能删除待提交状态的报卡'); ElMessage.warning('只能删除待提交状态的报卡');
return; return;
@@ -638,9 +507,35 @@ async function handleExport(row) {
} }
onMounted(() => { onMounted(() => {
console.log('页面首次加载 - onMounted');
getStatistics();
getList();
// 添加窗口大小变化监听
window.addEventListener('resize', handleResize);
});
// 处理 keep-alive 缓存场景:从其他页面返回时重新加载数据
onActivated(() => {
console.log('页面被激活 - onActivated');
getStatistics(); getStatistics();
getList(); getList();
}); });
// 组件卸载时移除事件监听
onBeforeUnmount(() => {
window.removeEventListener('resize', handleResize);
});
// 窗口大小变化处理函数
function handleResize() {
// 触发计算属性重新计算
nextTick(() => {
if (tableRef.value) {
tableRef.value.doLayout();
}
});
}
</script> </script>
<style scoped> <style scoped>
@@ -648,109 +543,274 @@ onMounted(() => {
padding: 20px; padding: 20px;
background-color: #f5f7fa; background-color: #f5f7fa;
min-height: calc(100vh - 84px); min-height: calc(100vh - 84px);
display: flex;
flex-direction: column;
gap: 16px;
} }
/* 页面标题 */
.page-header { .page-header {
margin-bottom: 20px; margin-bottom: 0;
} }
.page-title {
.page-header h2 {
font-size: 20px; font-size: 20px;
font-weight: 600; font-weight: 600;
color: #1e293b; color: #1e293b;
margin: 0; margin: 0;
} }
/* 统计卡片区 */
.statistics-section { .statistics-section {
display: grid; display: grid;
grid-template-columns: repeat(3, 1fr); grid-template-columns: repeat(3, 1fr);
gap: 20px; gap: 16px;
margin-bottom: 20px;
} }
.stat-card { .stat-card {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); background: #fff;
border-radius: 12px; border-radius: 12px;
padding: 24px; padding: 20px 24px;
display: flex; display: flex;
align-items: center; align-items: center;
gap: 16px; gap: 16px;
color: #fff; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.06);
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3); border: 1px solid #f0f0f0;
transition: box-shadow 0.2s;
}
.stat-card:hover {
box-shadow: 0 4px 18px rgba(0, 0, 0, 0.1);
} }
.stat-card.pending { /* 图标容器 */
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); .stat-icon-wrap {
box-shadow: 0 4px 12px rgba(245, 87, 108, 0.3); width: 52px;
} height: 52px;
border-radius: 50%;
.stat-card.success {
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
box-shadow: 0 4px 12px rgba(0, 242, 254, 0.3);
}
.stat-icon {
width: 56px;
height: 56px;
background: rgba(255, 255, 255, 0.2);
border-radius: 12px;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
font-size: 28px; flex-shrink: 0;
}
.stat-icon-purple {
background: linear-gradient(135deg, #818cf8 0%, #6366f1 100%);
}
.stat-icon-red {
background: linear-gradient(135deg, #fca5a5 0%, #ef4444 100%);
}
.stat-icon-green {
background: linear-gradient(135deg, #6ee7b7 0%, #10b981 100%);
}
.stat-icon-inner {
font-size: 24px;
color: #fff;
} }
.stat-content { .stat-content {
flex: 1; flex: 1;
} }
.stat-value { .stat-value {
font-size: 32px; font-size: 28px;
font-weight: bold; font-weight: 700;
color: #1e293b;
line-height: 1.2; line-height: 1.2;
} }
.stat-label { .stat-label {
font-size: 14px; font-size: 13px;
opacity: 0.9; color: #64748b;
margin-top: 4px; margin-top: 4px;
} }
/* 高级筛选区 */
.filter-section { .filter-section {
background: #fff; background: #fff;
border-radius: 8px; border-radius: 8px;
padding: 16px 20px; padding: 16px 20px;
margin-bottom: 16px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
border: 1px solid #f0f0f0;
} }
.filter-title {
.action-section { font-size: 14px;
background: #fff; font-weight: 600;
border-radius: 8px; color: #1e293b;
padding: 12px 20px; margin-bottom: 14px;
margin-bottom: 16px; }
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); .filter-row {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 16px; flex-wrap: wrap;
gap: 12px;
}
.filter-item {
display: flex;
align-items: center;
gap: 8px;
}
.filter-label {
font-size: 13px;
color: #475569;
white-space: nowrap;
flex-shrink: 0;
}
.filter-date-picker {
width: 240px;
}
.filter-select {
width: 140px;
}
.filter-input {
width: 180px;
}
.filter-actions {
display: flex;
gap: 8px;
margin-left: auto;
}
.btn-apply {
background-color: #6366f1;
border-color: #6366f1;
}
.btn-apply:hover {
background-color: #4f46e5;
border-color: #4f46e5;
}
.btn-reset {
color: #475569;
} }
/* 表格区 */
.table-section { .table-section {
background: #fff; background: #fff;
border-radius: 8px; border-radius: 8px;
padding: 20px; padding: 20px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
border: 1px solid #f0f0f0;
} }
/* 状态标签 */
.status-tag {
display: inline-block;
padding: 2px 8px;
border-radius: 4px;
font-size: 12px;
font-weight: 500;
line-height: 1.6;
}
/* 已上报 - 绿 */
.status-3 {
color: #16a34a;
background: #dcfce7;
border: 1px solid #bbf7d0;
}
/* 已审核 - 蓝 */
.status-2 {
color: #2563eb;
background: #dbeafe;
border: 1px solid #bfdbfe;
}
/* 失败 - 红 */
.status-4 {
color: #dc2626;
background: #fee2e2;
border: 1px solid #fecaca;
}
/* 已提交 - 绿 */
.status-1 {
color: #16a34a;
background: #dcfce7;
border: 1px solid #bbf7d0;
}
/* 待提交 - 橙 */
.status-0 {
color: #d97706;
background: #fef3c7;
border: 1px solid #fde68a;
}
/* 作废 - 灰 */
.status-6 {
color: #64748b;
background: #f1f5f9;
border: 1px solid #e2e8f0;
}
/* 退回 - 红 */
.status-5 {
color: #dc2626;
background: #fee2e2;
border: 1px solid #fecaca;
}
/* 分页 */
.pagination-section { .pagination-section {
margin-top: 16px; margin-top: 16px;
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
} }
/* 底部批量操作栏 */
.bottom-action-bar {
background: #fff;
border-radius: 8px;
padding: 12px 20px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
border: 1px solid #f0f0f0;
display: flex;
align-items: center;
justify-content: space-between;
}
.bottom-action-left {
display: flex;
align-items: center;
gap: 12px;
}
.selected-info {
font-size: 13px;
color: #64748b;
}
.bottom-action-right {
display: flex;
gap: 8px;
}
.btn-batch-delete {
color: #dc2626;
border-color: #fecaca;
background: #fff;
}
.btn-batch-delete:hover {
background: #fee2e2;
border-color: #fca5a5;
}
.btn-batch-submit {
background-color: #6366f1;
border-color: #6366f1;
font-weight: 500;
}
.btn-batch-submit:hover {
background-color: #4f46e5;
border-color: #4f46e5;
}
@media (max-width: 992px) { @media (max-width: 992px) {
.statistics-section { .statistics-section {
grid-template-columns: 1fr; grid-template-columns: 1fr;
} }
.filter-row {
flex-direction: column;
align-items: flex-start;
}
.filter-actions {
margin-left: 0;
}
}
/* 报卡详情弹窗 */
:deep(.card-detail-dialog .el-dialog__body) {
padding: 0;
overflow: hidden;
}
:deep(.card-detail-dialog .infectious-report-container) {
padding: 16px;
height: auto;
max-height: 70vh;
overflow-y: auto;
} }
</style> </style>

1
test-acp.txt Normal file
View File

@@ -0,0 +1 @@
test Tue Apr 14 05:12:39 PM CST 2026