shinnosuke
2026-08-25 aabd3fb155475168427f1c14966beb873bff6763
talent-card-server/src/main/java/com/talentcard/server/service/ServiceAppointmentAdminService.java
@@ -59,13 +59,13 @@
    @Transactional(readOnly = true)
    public PageResult<Map<String, Object>> page(String applicationType, String keyword, String applicantName,
                                                String applicantMobile, String serviceKeyword,
                                                String cardLevel, String status, String submittedStart,
                                                String cardLevel, String subsidy, String submissionType, String status, String submittedStart,
                                                String submittedEnd, int page, int size) {
        int safePage = Math.max(page, 1);
        int safeSize = Math.min(Math.max(size, 1), 100);
        QueryWrapper<ServiceApplication> countWrapper = filter(applicationType, keyword, applicantName, applicantMobile, serviceKeyword, cardLevel, status, submittedStart, submittedEnd);
        QueryWrapper<ServiceApplication> countWrapper = filter(applicationType, keyword, applicantName, applicantMobile, serviceKeyword, cardLevel, subsidy, submissionType, status, submittedStart, submittedEnd);
        Long total = applicationMapper.selectCount(countWrapper);
        QueryWrapper<ServiceApplication> pageWrapper = filter(applicationType, keyword, applicantName, applicantMobile, serviceKeyword, cardLevel, status, submittedStart, submittedEnd)
        QueryWrapper<ServiceApplication> pageWrapper = filter(applicationType, keyword, applicantName, applicantMobile, serviceKeyword, cardLevel, subsidy, submissionType, status, submittedStart, submittedEnd)
                .orderByDesc("submitted_at", "id")
                .last("limit " + safeSize + " offset " + ((safePage - 1) * safeSize));
        List<Map<String, Object>> records = applicationMapper.selectList(pageWrapper).stream()
@@ -101,7 +101,7 @@
        if (REJECTED_STATUSES.contains(nextStatus) && remark.isBlank()) {
            throw new BusinessException(ErrorCode.BAD_REQUEST, "拒绝或驳回时必须填写处理备注");
        }
        String handlerName = first(request.handlerName(), operatorId == null ? "" : "管理员" + operatorId, "管理员");
        String handlerName = first(operatorName(operatorId), request.handlerName(), "管理员");
        LocalDateTime handledAt = PENDING_STATUSES.contains(nextStatus) ? null : LocalDateTime.now();
        UpdateWrapper<ServiceApplication> update = new UpdateWrapper<ServiceApplication>()
                .set("status", nextStatus)
@@ -135,8 +135,8 @@
    @Transactional(readOnly = true)
    public byte[] exportExcel(String applicationType, String keyword, String applicantName,
                              String applicantMobile, String serviceKeyword,
                              String cardLevel, String status, String submittedStart, String submittedEnd) {
        QueryWrapper<ServiceApplication> wrapper = filter(applicationType, keyword, applicantName, applicantMobile, serviceKeyword, cardLevel, status, submittedStart, submittedEnd)
                              String cardLevel, String subsidy, String submissionType, String status, String submittedStart, String submittedEnd) {
        QueryWrapper<ServiceApplication> wrapper = filter(applicationType, keyword, applicantName, applicantMobile, serviceKeyword, cardLevel, subsidy, submissionType, status, submittedStart, submittedEnd)
                .orderByDesc("submitted_at", "id");
        List<ServiceApplication> applications = applicationMapper.selectList(wrapper);
        String[] headers = {
@@ -175,7 +175,7 @@
    private QueryWrapper<ServiceApplication> filter(String applicationType, String keyword, String applicantName,
                                                    String applicantMobile, String serviceKeyword,
                                                    String cardLevel, String status, String submittedStart, String submittedEnd) {
                                                    String cardLevel, String subsidy, String submissionType, String status, String submittedStart, String submittedEnd) {
        QueryWrapper<ServiceApplication> wrapper = new QueryWrapper<ServiceApplication>().eq("deleted", 0);
        String type = normalizeFilterType(applicationType);
        if (!type.isBlank()) {
@@ -218,6 +218,17 @@
        if (!clean(cardLevel).isBlank()) {
            wrapper.eq("talent_level", clean(cardLevel));
        }
        String subsidyValue = clean(subsidy);
        if ("是".equals(subsidyValue)) {
            wrapper.eq("subsidy", "是");
        } else if ("否".equals(subsidyValue)) {
            wrapper.and(query -> query.eq("subsidy", "否").or().isNull("subsidy").or().eq("subsidy", ""));
        } else if (!subsidyValue.isBlank()) {
            wrapper.eq("subsidy", subsidyValue);
        }
        if (!clean(submissionType).isBlank()) {
            wrapper.eq("submission_type", clean(submissionType));
        }
        if (!clean(status).isBlank()) {
            wrapper.eq("status", clean(status));
        }
@@ -258,6 +269,7 @@
        result.put("appointmentTime", first(application.getExpectedTime(), "以专员通知为准"));
        result.put("applicantName", participantName(application));
        result.put("applicantMobile", sensitiveDataCrypto.decrypt(first(application.getApplicantMobile(), application.getSpouseMobile(), application.getTalentMobile())));
        result.put("guestCount", guestCount(application));
        if (ServiceAppointmentApplicationService.TYPE_SPOUSE.equals(application.getApplicationType())) {
            result.put("spouseName", first(application.getSpouseName(), application.getApplicantName()));
            result.put("spouseMobile", sensitiveDataCrypto.decrypt(first(application.getSpouseMobile(), application.getApplicantMobile())));
@@ -270,6 +282,7 @@
    private Map<String, Object> detailView(ServiceApplication application) {
        Map<String, Object> result = listView(application);
        result.put("handlerName", handlerName(application));
        result.put("talentId", application.getTalentId());
        result.put("cardId", application.getCardId());
        result.put("merchantId", application.getMerchantId());
@@ -280,7 +293,7 @@
        result.put("applicantIdCardNo", sensitiveDataCrypto.decrypt(application.getApplicantIdCardNo()));
        result.put("checkInDate", application.getCheckInDate());
        result.put("checkOutDate", application.getCheckOutDate());
        result.put("guestCount", application.getGuestCount());
        result.put("guestCount", guestCount(application));
        result.put("subsidy", application.getSubsidy());
        result.put("remark", application.getRejectReason());
        result.put("estimatedProcessingTime", application.getEstimatedProcessingTime());
@@ -444,6 +457,36 @@
        return first(application.getApplicantName(), application.getSpouseName(), application.getChildName(), application.getTalentName());
    }
    private Integer guestCount(ServiceApplication application) {
        if (application.getGuestCount() != null) {
            return application.getGuestCount();
        }
        return ServiceAppointmentApplicationService.TYPE_HOTEL.equals(application.getApplicationType()) ? 1 : null;
    }
    private String handlerName(ServiceApplication application) {
        if (application.getHandledAt() == null) {
            return first(application.getHandlerName());
        }
        ServiceApplicationOperationLog log = operationLogMapper.selectOne(
                new QueryWrapper<ServiceApplicationOperationLog>()
                        .eq("application_id", application.getId())
                        .eq("operation_type", "STATUS_UPDATE")
                        .eq("after_status", application.getStatus())
                        .orderByDesc("created_at", "id")
                        .last("limit 1")
        );
        return first(
                log == null ? "" : operatorName(log.getOperatorId()),
                log == null ? "" : log.getOperatorName(),
                application.getHandlerName()
        );
    }
    private String operatorName(Long operatorId) {
        return operatorId == null ? "" : first(operationLogMapper.selectOperatorName(operatorId));
    }
    private List<String> proofFileIds(String value) {
        if (value == null || value.isBlank()) {
            return List.of();