diff --git a/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/plugin/form/PPPReportBillPlugin.java b/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/plugin/form/PPPReportBillPlugin.java new file mode 100644 index 0000000..9fe010d --- /dev/null +++ b/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/plugin/form/PPPReportBillPlugin.java @@ -0,0 +1,197 @@ +package shkd.sys.sys.plugin.form; + +import dm.jdbc.util.StringUtil; +import kd.bos.bill.AbstractBillPlugIn; +import kd.bos.cache.CacheFactory; +import kd.bos.cache.TempFileCache; +import kd.bos.dataentity.entity.DynamicObject; +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.ValueMapItem; +import kd.bos.entity.datamodel.FmtField; +import kd.bos.entity.report.*; +import kd.bos.form.control.Toolbar; +import kd.bos.form.control.events.ItemClickEvent; +import kd.bos.logging.Log; +import kd.bos.logging.LogFactory; +import kd.bos.report.ReportList; +import kd.bos.report.proxy.ReportListProxy; +import kd.sdk.plugin.Plugin; +import shkd.sys.sys.plugin.report.AccountbankReportFormPlugin; +import shkd.sys.sys.plugin.report.util.CsvExportUtil; + +import java.io.IOException; +import java.math.BigDecimal; +import java.nio.file.Files; +import java.nio.file.Path; +import java.sql.Timestamp; +import java.text.SimpleDateFormat; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.util.concurrent.ThreadLocalRandom; +import java.util.stream.Collectors; + +import static shkd.sys.sys.plugin.report.util.ReportUtils.processFieldValue; + +/** + * 单据界面插件 + */ +public class PPPReportBillPlugin extends AbstractBillPlugIn implements Plugin { + private static final Log logger = LogFactory.getLog(AccountbankReportFormPlugin.class); + + @Override + public void registerListener(EventObject e) { + super.registerListener(e); + // 获取工具栏,监听整个工具栏 + Toolbar export = this.getView().getControl("toolbarap"); + // 监听工具栏这个按钮的点击事件 + 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(); + + // 获取报表列表控件及模型,并取得行数和列信息 + ReportList reportList = this.getControl("reportlistap"); + IReportListModel reportListModel = reportList.getReportModel(); + int rowCount = reportListModel.getRowCount(); + ReportListProxy reportListProxy = new ReportListProxy(reportList); + List columns = reportListProxy.getColumnList(reportListModel); + List cols = reportListProxy.getReportColumnList(columns, true); + + // 获取所有行数据并初始化数字格式化提供器 + DynamicObjectCollection rowData = reportListModel.getRowData(0, rowCount, false); + NumberFormatProvider numberFormatProvider = ReportColumn.initNumberFormatProvider(rowData, cols); + + // 提取需要导出的字段名(排除 fseq 字段) + List headerKeys = numberFormatProvider.getFmtFields().stream() + .map(FmtField::getFieldName) + .filter(fieldName -> !Objects.equals(fieldName, "fseq")) + .collect(Collectors.toList()); + + // 构建属性名到显示名称的映射表,便于快速查找 + Map nameToDisplay = + properties.stream() + .filter(Objects::nonNull) + .filter(p -> p.getDisplayName() != null) + .collect(Collectors.toMap( + IMetadata::getName, + p -> p.getDisplayName().getLocaleValue(), + (v1, v2) -> v1)); + + // 按照字段顺序获取对应的显示名称,缺失则使用空字符串 + List headers = headerKeys.stream() + .map(k -> nameToDisplay.getOrDefault(k, "")) + .collect(Collectors.toList()); + + // 构造每一行的数据列表,处理复杂对象的name属性及本地化 + List> rows2 = rowData.stream() + .map(obj -> headerKeys.stream() + .map(key -> processFieldValue(obj.get(key))) + .collect(Collectors.toList())) + .collect(Collectors.toList()); + + // 获取日期值 + Date dateValue = (Date) this.getModel().getValue("shkd_sjrqfilter"); + + // 转换为 LocalDate 并格式化 + LocalDate localDate = dateValue.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); + String formattedDate = localDate.format(DateTimeFormatter.ofPattern("yyyyMMdd")); + + try { + String customFileName = "四川能源发展集团有限责任公司_PPP项目_18_" + formattedDate + ".csv"; + Path tempDir = Files.createTempDirectory("csv_export"); + Path tempFile = tempDir.resolve(customFileName); + CsvExportUtil.writeCsvToFile(tempFile, headers, rows2); + // 上传到临时文件服务器 获取压缩包下载地址 + TempFileCache tempFileCache = CacheFactory.getCommonCacheFactory().getTempFileCache(); + String url = tempFileCache.saveAsUrl(tempFile.getFileName().toString(), Files.newInputStream(tempFile), 3 * 60); + // 下载压缩包 + this.getView().download(url); + Files.delete(tempFile); + } catch (IOException e) { + throw new RuntimeException(e); + } + + } + } + + /** + * 处理字段值,支持简单值和复杂对象(如含name属性的对象) + * + * @param value 原始字段值 + * @return 处理后的字符串值 + */ + public static Object processFieldValue(Object value) { + if (value == null) { + return ""; + } + + // 添加日期类型处理 - 处理 Date 对象 + if (value instanceof java.util.Date) { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + return sdf.format((java.util.Date) value); + } + + // 如果是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(); + } + + // 都没有则返回默认toString() + return localizedObj.toString(); + } catch (Exception e) { + // 异常情况下返回toString() + return localizedObj.toString(); + } + } +} \ No newline at end of file diff --git a/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/plugin/report/PPPProjectReportPlugin.java b/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/plugin/report/PPPProjectReportPlugin.java new file mode 100644 index 0000000..086d4ff --- /dev/null +++ b/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/plugin/report/PPPProjectReportPlugin.java @@ -0,0 +1,269 @@ +package shkd.sys.sys.plugin.report; + +import com.grapecity.documents.excel.Q; +import kd.bos.algo.*; +import kd.bos.algo.input.CollectionInput; +import kd.bos.dataentity.entity.DynamicObject; +import kd.bos.dataentity.entity.DynamicObjectCollection; +import kd.bos.dataentity.metadata.clr.DataEntityPropertyCollection; +import kd.bos.entity.report.AbstractReportListDataPlugin; +import kd.bos.entity.report.FastFilter; +import kd.bos.entity.report.FilterItemInfo; +import kd.bos.entity.report.ReportQueryParam; +import kd.bos.krpc.common.utils.CollectionUtils; +import kd.bos.logging.Log; +import kd.bos.logging.LogFactory; +import kd.bos.orm.query.QCP; +import kd.bos.orm.query.QFilter; +import kd.bos.servicehelper.BusinessDataServiceHelper; +import kd.sdk.plugin.Plugin; +import shkd.sys.sys.plugin.form.PaymentProcessingBillPlugin; +import shkd.sys.sys.plugin.report.util.ReportUtils; + +import java.math.BigDecimal; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.List; + +/** + * 描述:PPP项目报表 + * 报表取数插件 + */ +public class PPPProjectReportPlugin extends AbstractReportListDataPlugin implements Plugin { + + private static final Log logger = LogFactory.getLog(PPPProjectReportPlugin.class); + + @Override + public DataSet query(ReportQueryParam reportQueryParam, Object o) throws Throwable { + //获取筛选器的值 + List listQFilter = getListQFilter(reportQueryParam); + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + Date dateValue = null; + for (QFilter filter : listQFilter) { + if ("shkd_sjrqfilter".equals(filter.getProperty())) { + Object value = filter.getValue(); + // 判断并转换为Date类型 + if (value instanceof Date) { + dateValue = (Date) value; + } else if (value instanceof String) { + // 如果是字符串,先解析为Date + dateValue = sdf.parse((String) value); + } + } + } + + DataSet finish = null; + + DynamicObject[] dynamicObjects = BusinessDataServiceHelper.load("shkd_pppproject", + "id,shkd_ssjtbm,shkd_ssjtmc,shkd_xm.shkd_lcxmbm,shkd_xm.name,shkd_xm.shkd_xmdwbm," + + "shkd_xm.shkd_xmdwmc,shkd_entryentity.shkd_xmdwcdztze,shkd_entryentity.shkd_xmhtsxr," + + "shkd_entryentity.shkd_yjxmxjljlrhjs,shkd_entryentity.shkd_sjjzdtbyfxjljlrhjs,shkd_entryentity.shkd_xmhzqx," + + "shkd_entryentity.shkd_snxjljlr,shkd_entryentity.shkd_yjxnxjljlr,shkd_entryentity.shkd_sjrq", + new QFilter("id", QCP.not_equals, 0L).toArray()); + + logger.info("查询数据长度{}:{}", dynamicObjects.length, dynamicObjects[0]); + + // 创建一个空的DataSet 将DynamicObjectCollection转化为DataSet + Collection coll = new ArrayList<>();//报表展示数据 + // 遍历修改后的数据的所有字段 + List displayFields = new ArrayList<>();//列标识 + displayFields.add("shkd_ssjtbm");// 所属集团编码 + displayFields.add("shkd_ssjtmc");// 所属集团名称 + displayFields.add("shkd_xmdwbm");// 项目单位编码 + displayFields.add("shkd_xmdwmc");// 项目单位名称 + displayFields.add("shkd_xmbm");// 项目编码 + displayFields.add("shkd_xmmc");// 项目名称 + displayFields.add("shkd_xmdwcdztze");// 项目单位承担总投资额 + displayFields.add("shkd_xmhtsxr");// 项目合同生效日 + displayFields.add("shkd_yjxmxjljlrhjs");// 预计项目现金流净流入合计数 + displayFields.add("shkd_sjjzdtbyfxjljlrhjs");// 实际截止到填报月份现金流净流入合计数 + displayFields.add("shkd_xmhzqx");// 项目合作期限 + displayFields.add("shkd_snxjljlr");// 上年现金流净流入 + displayFields.add("shkd_yjxnxjljlr");// 预计下年现金流净流入 + displayFields.add("shkd_sjrq");// 数据日期 + + for (DynamicObject dataRow : dynamicObjects) { + DynamicObject shkd_xm = dataRow.getDynamicObject("shkd_xm"); + DynamicObjectCollection dynamicObjectCollection = dataRow.getDynamicObjectCollection("shkd_entryentity"); + for (DynamicObject dynamicObject : dynamicObjectCollection) { + + Date shkdSjrq = dynamicObject.getDate("shkd_sjrq"); + if (dateValue == null || shkdSjrq.compareTo(dateValue) <= 0) { + Object[] objects = new Object[displayFields.size()]; + for (int i = 0; i < displayFields.size(); i++) { + switch (displayFields.get(i)) { + case "shkd_ssjtbm": + objects[i] = dataRow.get("shkd_ssjtbm"); + break; + case "shkd_ssjtmc": + objects[i] = dataRow.get("shkd_ssjtmc"); + break; + case "shkd_xmdwbm": + objects[i] = shkd_xm.get("shkd_xmdwbm"); + break; + case "shkd_xmdwmc": + objects[i] = shkd_xm.get("shkd_xmdwmc"); + break; + case "shkd_xmbm": + objects[i] = shkd_xm.get("shkd_lcxmbm"); + break; + case "shkd_xmmc": + objects[i] = shkd_xm.get("name"); + break; + case "shkd_xmdwcdztze": + Object shkd_xmdwcdztze = dynamicObject.get("shkd_xmdwcdztze"); + if (shkd_xmdwcdztze != null) { + BigDecimal bd = new BigDecimal(shkd_xmdwcdztze.toString()); + objects[i] = bd.setScale(2, BigDecimal.ROUND_HALF_UP); + } else { + objects[i] = shkd_xmdwcdztze; + } + break; + case "shkd_xmhtsxr": + + objects[i] = dynamicObject.getDate("shkd_xmhtsxr"); + break; + case "shkd_yjxmxjljlrhjs": + Object shkd_yjxmxjljlrhjs = dynamicObject.get("shkd_yjxmxjljlrhjs"); + if (shkd_yjxmxjljlrhjs != null) { + BigDecimal bd = new BigDecimal(shkd_yjxmxjljlrhjs.toString()); + objects[i] = bd.setScale(2, BigDecimal.ROUND_HALF_UP); + } else { + objects[i] = shkd_yjxmxjljlrhjs; + } + break; + case "shkd_sjjzdtbyfxjljlrhjs": + Object shkd_sjjzdtbyfxjljlrhjs = dynamicObject.get("shkd_sjjzdtbyfxjljlrhjs"); + if (shkd_sjjzdtbyfxjljlrhjs != null) { + BigDecimal bd = new BigDecimal(shkd_sjjzdtbyfxjljlrhjs.toString()); + objects[i] = bd.setScale(2, BigDecimal.ROUND_HALF_UP); + } else { + objects[i] = shkd_sjjzdtbyfxjljlrhjs; + } + break; + case "shkd_xmhzqx": + objects[i] = dynamicObject.get("shkd_xmhzqx"); + break; + case "shkd_snxjljlr": + Object shkd_snxjljlr = dynamicObject.get("shkd_snxjljlr"); + if (shkd_snxjljlr != null) { + BigDecimal bd = new BigDecimal(shkd_snxjljlr.toString()); + objects[i] = bd.setScale(2, BigDecimal.ROUND_HALF_UP); + } else { + objects[i] = shkd_snxjljlr; + } + break; + case "shkd_yjxnxjljlr": + Object shkd_yjxnxjljlr = dynamicObject.get("shkd_yjxnxjljlr"); + if (shkd_yjxnxjljlr != null) { + BigDecimal bd = new BigDecimal(shkd_yjxnxjljlr.toString()); + objects[i] = bd.setScale(2, BigDecimal.ROUND_HALF_UP); + } else { + objects[i] = shkd_yjxnxjljlr; + } + break; + case "shkd_sjrq": + objects[i] = dynamicObject.getDate("shkd_sjrq"); + break; + } + } + coll.add(objects); + } + } + } + + DataType stringType = DataType.StringType;//字符串 + DataType dateType = DataType.DateType;//日期 + DataType integerType = DataType.IntegerType;//整数 + + List dataTypes = new ArrayList<>();//列类型 + + for (String field : displayFields) { + switch (field) { + case "shkd_ssjtbm": + dataTypes.add(stringType); + break; + case "shkd_ssjtmc": + dataTypes.add(stringType); + break; + case "shkd_xmdwbm": + dataTypes.add(stringType); + break; + case "shkd_xmdwmc": + dataTypes.add(stringType); + break; + case "shkd_xmbm": + dataTypes.add(stringType); + break; + case "shkd_xmmc": + dataTypes.add(stringType); + break; + case "shkd_xmdwcdztze": + dataTypes.add(stringType); + break; + case "shkd_xmhtsxr": + dataTypes.add(dateType); + break; + case "shkd_yjxmxjljlrhjs": + dataTypes.add(stringType); + break; + case "shkd_sjjzdtbyfxjljlrhjs": + dataTypes.add(stringType); + break; + case "shkd_xmhzqx": + dataTypes.add(integerType); + break; + case "shkd_snxjljlr": + dataTypes.add(stringType); + break; + case "shkd_yjxnxjljlr": + dataTypes.add(stringType); + break; + case "shkd_sjrq": + dataTypes.add(dateType); + break; + } + } + + RowMeta rowMeta = RowMetaFactory.createRowMeta(displayFields.toArray(new String[0]), dataTypes.toArray(new DataType[0])); + CollectionInput inputs = new CollectionInput(rowMeta, coll); + + try { + finish = Algo.create(this.getClass().getName()).createDataSet(inputs); + } catch (Exception e) { + logger.error("数据集创建失败:{}", e.getMessage()); + } + return finish; + } + + /** + * 获取报表所有过滤条件 + * + * @param reportQueryParam + * @return + */ + public List getListQFilter(ReportQueryParam reportQueryParam) { + //过滤条件数组 + List qFilters = new ArrayList<>(); + //初始化过滤数据 + List filterItems = reportQueryParam.getFilter().getFilterItems(); + if (CollectionUtils.isNotEmpty(filterItems)) { + for (FilterItemInfo info : filterItems) { + //获取过滤字段名 获取比较符 获取过滤比较值 + qFilters.add(new QFilter(info.getPropName(), QCP.equals, info.getValue())); + } + } + //快速过滤 + FastFilter fastFilter = reportQueryParam.getFilter().getFastFilter(); + if (fastFilter != null) { + List qFilters1 = fastFilter.getQFilters(); + if (CollectionUtils.isNotEmpty(qFilters1)) { + qFilters.addAll(qFilters1); + } + } + return qFilters; + } +} \ No newline at end of file