package com.vincent.rsf.server.common.service; import com.vincent.rsf.framework.exception.CoolException; import com.vincent.rsf.server.common.domain.BaseParam; import com.vincent.rsf.server.common.utils.ExcelUtil; import org.springframework.stereotype.Service; import jakarta.servlet.http.HttpServletResponse; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.function.Function; @Service public class ListExportService { private static final Set EXPORT_ONLY_KEYS = Set.of( "columns", "reportTitle", "reportDate", "printedAt", "operator", "count", "report_title", "report_date", "printed_at" ); public void export( Map map, Function, P> paramBuilder, ListExportHandler exportHandler, HttpServletResponse response ) throws Exception { Map sanitizedMap = sanitizeExportMap(map); P baseParam = paramBuilder.apply(sanitizedMap); List columns = buildExportColumns(map); if (columns.isEmpty()) { throw new CoolException("导出列不能为空"); } List records = getExportRecords(sanitizedMap, baseParam, exportHandler); exportHandler.fillExportFields(records); List> rows = records.stream() .map(record -> exportHandler.toExportRow(record, columns)) .toList(); ExcelUtil.ExportMeta exportMeta = buildExportMeta(map, rows.size(), exportHandler.defaultReportTitle()); ExcelUtil.build(ExcelUtil.create(rows, columns, exportMeta), response); } private Map sanitizeExportMap(Map map) { Map exportMap = new HashMap<>(map); EXPORT_ONLY_KEYS.forEach(exportMap::remove); exportMap.remove("meta"); sanitizeNestedMap(exportMap, "filter"); sanitizeNestedMap(exportMap, "filterValues"); return exportMap; } private void sanitizeNestedMap(Map exportMap, String key) { Object nestedObject = exportMap.get(key); if (nestedObject instanceof Map nestedMap) { Map sanitizedMap = new HashMap<>(); for (Map.Entry entry : nestedMap.entrySet()) { String nestedKey = String.valueOf(entry.getKey()); if (!EXPORT_ONLY_KEYS.contains(nestedKey)) { sanitizedMap.put(nestedKey, entry.getValue()); } } exportMap.put(key, sanitizedMap); } } private List buildExportColumns(Map map) { Object columnsObject = map.get("columns"); if (Objects.isNull(columnsObject)) { Object metaObject = map.get("meta"); if (metaObject instanceof Map metaMap) { columnsObject = metaMap.get("columns"); } } if (!(columnsObject instanceof List rawColumns)) { return Collections.emptyList(); } List columns = new ArrayList<>(); for (Object rawColumn : rawColumns) { if (!(rawColumn instanceof Map columnMap)) { continue; } Object source = columnMap.get("source"); Object label = columnMap.get("label"); if (Objects.isNull(source) || Objects.isNull(label)) { continue; } columns.add(new ExcelUtil.ExportColumn(String.valueOf(source), String.valueOf(label))); } return columns; } private List getExportRecords( Map sanitizedMap, P baseParam, ListExportHandler exportHandler ) { List ids = parseExportIds(sanitizedMap.get("ids")); if (!ids.isEmpty()) { return exportHandler.listByIds(ids); } return exportHandler.listByFilter(sanitizedMap, baseParam); } private List parseExportIds(Object idsObject) { if (idsObject instanceof List ids && !ids.isEmpty()) { return ids.stream() .map(String::valueOf) .map(Long::valueOf) .toList(); } if (idsObject instanceof Object[] ids && ids.length > 0) { List exportIds = new ArrayList<>(); for (Object id : ids) { exportIds.add(Long.valueOf(String.valueOf(id))); } return exportIds; } return Collections.emptyList(); } private ExcelUtil.ExportMeta buildExportMeta(Map map, int count, String defaultReportTitle) { Object metaObject = map.get("meta"); if (!(metaObject instanceof Map metaMap)) { return new ExcelUtil.ExportMeta(defaultReportTitle, "", "", "", count); } String reportTitle = getMetaValue(metaMap, "reportTitle", defaultReportTitle); String reportDate = getMetaValue(metaMap, "reportDate", ""); String printedAt = getMetaValue(metaMap, "printedAt", ""); String operator = getMetaValue(metaMap, "operator", ""); return new ExcelUtil.ExportMeta(reportTitle, reportDate, printedAt, operator, count); } private String getMetaValue(Map metaMap, String key, String defaultValue) { Object value = metaMap.get(key); return Objects.isNull(value) ? defaultValue : String.valueOf(value); } }