longz
2026-07-13 5882ba8863d77fdcc168b176c3ffb30e8a20556a
backend/src/main/java/com/sinata/appointment/service/AppointmentApplicationService.java
@@ -38,7 +38,10 @@
import com.sinata.appointment.util.MobileMaskUtil;
import com.sinata.appointment.util.SensitiveDataUtil;
import com.sinata.appointment.util.UuidAssert;
import java.io.ByteArrayOutputStream;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@@ -110,7 +113,8 @@
        return buildAdminPage(pagedOrders);
    }
    public byte[] exportExcel(
    public void exportExcel(
            HttpServletResponse response,
            String visitedUserName,
            Long visitedDeptId,
            Long accessAreaId,
@@ -121,49 +125,60 @@
            String displayStatus,
            String approvalStatus,
            String visitorKeyword,
            String visitReasonCode) {
            String visitReasonCode)
            throws IOException {
        prepareExcelResponse(response, "appointments.xlsx");
        List<Long> accessAreaIds = resolveAccessAreaFilterIds(accessAreaId);
        long pageNo = 1L;
        long pageSize = 200L;
        List<AppointmentAdminExportRow> rows = new ArrayList<>();
        while (true) {
            Page<AppointmentOrder> orderPage = new Page<>(pageNo, pageSize);
            IPage<AppointmentOrder> pagedOrders =
                    appointmentOrderMapper.pageAdminOrders(
                            orderPage,
                            trimToNull(visitedUserName),
                            visitedDeptId,
                            accessAreaIds,
                            trimToNull(accessArea),
                            trimToNull(localUnit),
                            visitDateStart,
                            visitDateEnd,
                            trimToNull(displayStatus),
                            trimToNull(approvalStatus),
                            trimToNull(visitorKeyword),
                            trimToNull(visitReasonCode));
            List<AppointmentOrder> orders = pagedOrders.getRecords();
            if (orders == null || orders.isEmpty()) {
                break;
        boolean wroteAnyPage = false;
        try (ExcelWriter writer =
                EasyExcel.write(response.getOutputStream(), AppointmentAdminExportRow.class).build()) {
            WriteSheet sheet = EasyExcel.writerSheet("预约记录").build();
            while (true) {
                Page<AppointmentOrder> orderPage = new Page<>(pageNo, pageSize);
                IPage<AppointmentOrder> pagedOrders =
                        appointmentOrderMapper.pageAdminOrders(
                                orderPage,
                                trimToNull(visitedUserName),
                                visitedDeptId,
                                accessAreaIds,
                                trimToNull(accessArea),
                                trimToNull(localUnit),
                                visitDateStart,
                                visitDateEnd,
                                trimToNull(displayStatus),
                                trimToNull(approvalStatus),
                                trimToNull(visitorKeyword),
                                trimToNull(visitReasonCode));
                List<AppointmentOrder> orders = pagedOrders.getRecords();
                if (orders == null || orders.isEmpty()) {
                    break;
                }
                AdminPageData pageData = loadAdminPageData(orders);
                writer.write(
                        buildExportRows(
                                orders,
                                pageData.visitorRowsMap(),
                                pageData.approvalInstanceMap(),
                                pageData.reasonNameMap()),
                        sheet);
                wroteAnyPage = true;
                if (pageNo * pageSize >= pagedOrders.getTotal()) {
                    break;
                }
                pageNo++;
            }
            AdminPageData pageData = loadAdminPageData(orders);
            rows.addAll(
                    buildExportRows(
                            orders,
                            pageData.visitorRowsMap(),
                            pageData.approvalInstanceMap(),
                            pageData.reasonNameMap()));
            if (pageNo * pageSize >= pagedOrders.getTotal()) {
                break;
            if (!wroteAnyPage) {
                writer.write(List.of(), sheet);
            }
            pageNo++;
        }
        try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
            EasyExcel.write(bos, AppointmentAdminExportRow.class).sheet("预约记录").doWrite(rows);
            return bos.toByteArray();
        } catch (Exception e) {
            return new byte[0];
        }
    }
    private void prepareExcelResponse(HttpServletResponse response, String filename) {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
    }
    public AppointmentOrder getById(Long id, String uuid) {
@@ -196,6 +211,7 @@
        vo.setLocalUnitText(defaultText(buildJsonNameText(order.getPassLocalUnitNames())));
        vo.setPlateNoText(defaultText(loadOrderPlateText(id)));
        vo.setVisitReasonText(defaultText(buildVisitReasonText(order, reasonNameMap)));
        vo.setVisitReasonOther(defaultText(trimToNull(order.getVisitReasonOther())));
        vo.setVisitTimeMode(trimToNull(order.getVisitTimeMode()));
        vo.setVisitTimeSlot(trimToNull(order.getVisitTimeSlot()));
        vo.setVisitStartText(defaultText(resolveVisitStartText(order)));
@@ -471,6 +487,7 @@
        vo.setLocalUnitText(defaultText(buildJsonNameText(order.getPassLocalUnitNames())));
        vo.setPlateNoText(defaultText(firstNonBlank(orderPlateText, joinUniqueTexts(visitorRows, AppointmentVisitor::getPlateNo), null)));
        vo.setVisitReasonText(defaultText(buildVisitReasonText(order, reasonNameMap)));
        vo.setVisitReasonOther(defaultText(trimToNull(order.getVisitReasonOther())));
        vo.setVisitTimeText(defaultText(buildVisitTimeText(order)));
        vo.setVisitorNamesText(defaultText(joinUniqueTexts(visitorRows, AppointmentVisitor::getName)));
        vo.setStatus(order.getStatus());
@@ -545,6 +562,7 @@
        row.setLocalUnitText(summary.getLocalUnitText());
        row.setPlateNoText(defaultText(summary.getPlateNoText()));
        row.setVisitReasonText(summary.getVisitReasonText());
        row.setVisitReasonOther(summary.getVisitReasonOther());
        row.setVisitTimeText(summary.getVisitTimeText());
        row.setDisplayStatusText(summary.getDisplayStatusText());
        MpVisitor visitor = visitorRow == null ? null : visitorMap.get(visitorRow.getMpVisitorId());
@@ -787,8 +805,7 @@
            return null;
        }
        if ("OTHER".equalsIgnoreCase(code)) {
            String other = trimToNull(row.getVisitReasonOther());
            return StringUtils.hasText(other) ? other : "其他";
            return "其他";
        }
        String reasonName = reasonNameMap.get(code);
        return StringUtils.hasText(reasonName) ? reasonName : code;