parent
							
								
									bbb8917039
								
							
						
					
					
						commit
						7e8eb690cb
					
				| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package shkd.sys.sys.plugin.report.util;
 | 
			
		||||
package shkd.sys.sys.plugin.report;
 | 
			
		||||
 | 
			
		||||
import dm.jdbc.util.StringUtil;
 | 
			
		||||
import kd.bos.cache.CacheFactory;
 | 
			
		||||
| 
						 | 
				
			
			@ -7,12 +7,17 @@ import kd.bos.dataentity.entity.DynamicObjectCollection;
 | 
			
		|||
import kd.bos.dataentity.metadata.IMetadata;
 | 
			
		||||
import kd.bos.dataentity.metadata.clr.DataEntityPropertyCollection;
 | 
			
		||||
import kd.bos.entity.MainEntityType;
 | 
			
		||||
import kd.bos.entity.NumberFormatProvider;
 | 
			
		||||
import kd.bos.entity.datamodel.FmtField;
 | 
			
		||||
import kd.bos.entity.report.AbstractReportColumn;
 | 
			
		||||
import kd.bos.entity.report.IReportListModel;
 | 
			
		||||
import kd.bos.entity.report.ReportColumn;
 | 
			
		||||
import kd.bos.form.control.Toolbar;
 | 
			
		||||
import kd.bos.form.control.events.ItemClickEvent;
 | 
			
		||||
import kd.bos.report.ReportList;
 | 
			
		||||
import kd.bos.report.plugin.AbstractReportFormPlugin;
 | 
			
		||||
import org.apache.commons.io.FileUtils;
 | 
			
		||||
import kd.bos.report.proxy.ReportListProxy;
 | 
			
		||||
import shkd.sys.sys.plugin.report.util.CsvExportUtil;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.nio.file.Files;
 | 
			
		||||
| 
						 | 
				
			
			@ -22,9 +27,10 @@ import java.time.format.DateTimeFormatter;
 | 
			
		|||
import java.util.*;
 | 
			
		||||
import java.util.concurrent.ThreadLocalRandom;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
import java.util.stream.IntStream;
 | 
			
		||||
 | 
			
		||||
public class ExportCSV extends AbstractReportFormPlugin {
 | 
			
		||||
import static shkd.sys.sys.plugin.report.util.ReportUtils.processFieldValue;
 | 
			
		||||
 | 
			
		||||
public class ExportCSVReportFormPlugin extends AbstractReportFormPlugin {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void registerListener(EventObject e) {
 | 
			
		||||
| 
						 | 
				
			
			@ -34,45 +40,69 @@ public class ExportCSV extends AbstractReportFormPlugin {
 | 
			
		|||
        // 监听工具栏这个按钮的点击事件
 | 
			
		||||
        export.addItemClickListener(this);
 | 
			
		||||
        export.addClickListener(this);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 处理列表项点击事件,当点击的项为 "shkd_exportcsv" 时,执行导出 CSV 文件的操作。
 | 
			
		||||
     *
 | 
			
		||||
     * @param evt 列表项点击事件对象,包含被点击项的相关信息
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    public void itemClick(ItemClickEvent evt) {
 | 
			
		||||
        super.itemClick(evt);
 | 
			
		||||
        String itemKey = evt.getItemKey();
 | 
			
		||||
        if (StringUtil.equals("shkd_exportcsv", itemKey)) {
 | 
			
		||||
            // 获取数据实体类型及其属性集合
 | 
			
		||||
            MainEntityType dataEntityType = this.getModel().getDataEntityType();
 | 
			
		||||
            DataEntityPropertyCollection properties = dataEntityType.getProperties();
 | 
			
		||||
            String reportName = dataEntityType.getDisplayName().getLocaleValue();
 | 
			
		||||
 | 
			
		||||
            List<String> keyHeaders = properties.stream()
 | 
			
		||||
                    .filter(Objects::nonNull)
 | 
			
		||||
                    .map(IMetadata::getName)
 | 
			
		||||
                    .collect(Collectors.toList());
 | 
			
		||||
            List<String> headers = properties.stream()
 | 
			
		||||
                    .filter(Objects::nonNull)
 | 
			
		||||
                    .filter(o -> Objects.nonNull(o.getDisplayName()))
 | 
			
		||||
                    .map(o -> o.getDisplayName().getLocaleValue())
 | 
			
		||||
            // 获取报表列表控件及模型,并取得行数和列信息
 | 
			
		||||
            ReportList reportList = this.getControl("reportlistap");
 | 
			
		||||
            IReportListModel reportListModel = reportList.getReportModel();
 | 
			
		||||
            int rowCount = reportListModel.getRowCount();
 | 
			
		||||
            ReportListProxy reportListProxy = new ReportListProxy(reportList);
 | 
			
		||||
            List<AbstractReportColumn> columns = reportListProxy.getColumnList(reportListModel);
 | 
			
		||||
            List<ReportColumn> cols = reportListProxy.getReportColumnList(columns, true);
 | 
			
		||||
 | 
			
		||||
            // 获取所有行数据并初始化数字格式化提供器
 | 
			
		||||
            DynamicObjectCollection rowData = reportListModel.getRowData(0, rowCount, false);
 | 
			
		||||
            NumberFormatProvider numberFormatProvider = ReportColumn.initNumberFormatProvider(rowData, cols);
 | 
			
		||||
 | 
			
		||||
            // 提取需要导出的字段名(排除 fseq 字段)
 | 
			
		||||
            List<String> headerKeys = numberFormatProvider.getFmtFields().stream()
 | 
			
		||||
                    .filter(o -> !Objects.equals(o.getFieldName(), "fseq"))
 | 
			
		||||
                    .map(FmtField::getFieldName)
 | 
			
		||||
                    .collect(Collectors.toList());
 | 
			
		||||
 | 
			
		||||
            String timestamp = LocalDateTime.now()
 | 
			
		||||
                    .format(DateTimeFormatter.ofPattern("yyyyMMddHHmm"));
 | 
			
		||||
            // 构建属性名到显示名称的映射表,便于快速查找
 | 
			
		||||
            Map<String, String> nameToDisplay =
 | 
			
		||||
                    properties.stream()
 | 
			
		||||
                            .filter(Objects::nonNull)
 | 
			
		||||
                            .filter(p -> p.getDisplayName() != null)
 | 
			
		||||
                            .collect(Collectors.toMap(
 | 
			
		||||
                                    IMetadata::getName,
 | 
			
		||||
                                    p -> p.getDisplayName().getLocaleValue(),
 | 
			
		||||
                                    (v1, v2) -> v1));
 | 
			
		||||
 | 
			
		||||
            int random = ThreadLocalRandom.current().nextInt(100, 1000); // 3 位随机数
 | 
			
		||||
 | 
			
		||||
            String reportNameExt = timestamp + random;
 | 
			
		||||
 | 
			
		||||
            IReportListModel reportList = ((ReportList) this.getControl("reportlistap")).getReportModel();
 | 
			
		||||
            int rowCount = reportList.getRowCount();
 | 
			
		||||
 | 
			
		||||
            DynamicObjectCollection rowData = reportList.getRowData(0, rowCount, false);
 | 
			
		||||
            // 按照字段顺序获取对应的显示名称,缺失则使用空字符串
 | 
			
		||||
            List<String> headers = headerKeys.stream()
 | 
			
		||||
                    .map(k -> nameToDisplay.getOrDefault(k, ""))
 | 
			
		||||
                    .collect(Collectors.toList());
 | 
			
		||||
 | 
			
		||||
            // 构造每一行的数据列表,处理复杂对象的name属性及本地化
 | 
			
		||||
            List<List<?>> rows2 = rowData.stream()
 | 
			
		||||
                    .map(obj -> keyHeaders.stream()
 | 
			
		||||
                            .map(obj::get)  // 使用 DynamicObject 的 get 方法获取属性值
 | 
			
		||||
                    .map(obj -> headerKeys.stream()
 | 
			
		||||
                            .map(key -> processFieldValue(obj.get(key)))
 | 
			
		||||
                            .collect(Collectors.toList()))
 | 
			
		||||
                    .collect(Collectors.toList());
 | 
			
		||||
 | 
			
		||||
            // 生成时间戳和随机数作为文件名的一部分
 | 
			
		||||
            String timestamp = LocalDateTime.now()
 | 
			
		||||
                    .format(DateTimeFormatter.ofPattern("yyyyMMddHHmm"));
 | 
			
		||||
            int random = ThreadLocalRandom.current().nextInt(100, 1000); // 3 位随机数
 | 
			
		||||
            String reportNameExt = timestamp + random;
 | 
			
		||||
 | 
			
		||||
            try {
 | 
			
		||||
                // 定义本地测试目录和完整文件路径
 | 
			
		||||
| 
						 | 
				
			
			@ -84,8 +114,8 @@ public class ExportCSV extends AbstractReportFormPlugin {
 | 
			
		|||
//
 | 
			
		||||
//                Path tempFile = dirPath.resolve(reportName + reportNameExt + ".csv");
 | 
			
		||||
//                CsvExportUtil.writeCsvToFile(tempFile, headers, rows2);
 | 
			
		||||
//
 | 
			
		||||
//                // 打印文件路径用于本地验证
 | 
			
		||||
 | 
			
		||||
                // 打印文件路径用于本地验证
 | 
			
		||||
//                System.out.println("CSV 文件已保存至: " + tempFile.toAbsolutePath());
 | 
			
		||||
 | 
			
		||||
                Path tempFile = Files.createTempFile(reportName + reportNameExt, ".csv");
 | 
			
		||||
| 
						 | 
				
			
			@ -49,4 +49,63 @@ public class ReportUtils {
 | 
			
		|||
        }
 | 
			
		||||
        return filters;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 处理字段值,支持简单值和复杂对象(如含name属性的对象)
 | 
			
		||||
     *
 | 
			
		||||
     * @param value 原始字段值
 | 
			
		||||
     * @return 处理后的字符串值
 | 
			
		||||
     */
 | 
			
		||||
    public static Object processFieldValue(Object value) {
 | 
			
		||||
        if (value == null) {
 | 
			
		||||
            return "";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 如果是DynamicObject或类似结构,尝试获取name属性
 | 
			
		||||
        try {
 | 
			
		||||
            // 尝试调用get("name")方法获取name属性
 | 
			
		||||
            Object nameValue = value.getClass().getMethod("get", String.class).invoke(value, "name");
 | 
			
		||||
            if (nameValue != null) {
 | 
			
		||||
                // 如果name是一个本地化对象,则进一步处理
 | 
			
		||||
                return processLocalizedValue(nameValue);
 | 
			
		||||
            }
 | 
			
		||||
            // 如果没有name属性,直接返回原值的toString()
 | 
			
		||||
            return value.toString();
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            // 如果调用失败,说明不是复杂对象,直接返回toString()
 | 
			
		||||
            return value.toString();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 处理本地化值对象,优先获取ZH_TW,其次ZH_CN
 | 
			
		||||
     *
 | 
			
		||||
     * @param localizedObj 本地化对象
 | 
			
		||||
     * @return 对应语言的值
 | 
			
		||||
     */
 | 
			
		||||
    public static String processLocalizedValue(Object localizedObj) {
 | 
			
		||||
        if (localizedObj == null) {
 | 
			
		||||
            return "";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
 | 
			
		||||
            // 尝试获取ZH_CN本地化值
 | 
			
		||||
            Object zhCnValue = localizedObj.getClass().getMethod("get", String.class).invoke(localizedObj, "zh_CN");
 | 
			
		||||
            if (zhCnValue != null) {
 | 
			
		||||
                return zhCnValue.toString();
 | 
			
		||||
            }
 | 
			
		||||
//            // 尝试获取ZH_TW本地化值
 | 
			
		||||
//            Object zhTwValue = localizedObj.getClass().getMethod("get", String.class).invoke(localizedObj, "zh_TW");
 | 
			
		||||
//            if (zhTwValue != null) {
 | 
			
		||||
//                return zhTwValue.toString();
 | 
			
		||||
//            }
 | 
			
		||||
 | 
			
		||||
            // 都没有则返回默认toString()
 | 
			
		||||
            return localizedObj.toString();
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            // 异常情况下返回toString()
 | 
			
		||||
            return localizedObj.toString();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue