From 2495c01f68097b3a6dd03364ab4790b2581f2d6f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=A0=E5=90=8D=E9=94=90?= <1565842059@qq.com>
Date: Thu, 16 Jul 2026 21:25:46 +0800
Subject: [PATCH] =?UTF-8?q?feat(report):=20=E6=B7=BB=E5=8A=A0=E4=BA=92?=
=?UTF-8?q?=E6=8D=A2=E4=BC=B0=E5=80=BC=E5=88=97=E9=85=8D=E7=BD=AE=E5=8A=9F?=
=?UTF-8?q?=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 引入 Newtonsoft.Json 用于列配置的序列化处理
- 实现 ApplySwapValuationColumnConfig 方法应用用户自定义列配置
- 添加 ReorderSwapValuationColumns 方法重新排序可见列
- 在每日估值报告导出时同步业务字段显示状态和列顺序
- 使用临时工作表避免 EPPlus 扩列时的 ColumnMax 冲突
- 确保列配置损坏时不影响报告导出功能
---
.../SettlementReportFotShanXiService.cs | 131 ++++++++++++++++++
1 file changed, 131 insertions(+)
diff --git a/YLErpDAL/Modules/ReportModule/SettlementReportModule/SettlementReportFotShanXiService.cs b/YLErpDAL/Modules/ReportModule/SettlementReportModule/SettlementReportFotShanXiService.cs
index 565e604f..21736f28 100644
--- a/YLErpDAL/Modules/ReportModule/SettlementReportModule/SettlementReportFotShanXiService.cs
+++ b/YLErpDAL/Modules/ReportModule/SettlementReportModule/SettlementReportFotShanXiService.cs
@@ -1,4 +1,5 @@
using BaseOUDAL;
+using Newtonsoft.Json;
using OfficeOpenXml;
using OfficeOpenXml.Style;
using Org.BouncyCastle.Ocsp;
@@ -309,6 +310,7 @@ namespace YLErp.Modules.ReportModule.SettlementReportModule
, shouldDeleteSheet: true, needToPdf: false, callback: sheets =>
{
FormatSwapValuationDisplayCells(sheets, report.EodSwapPositions);
+ ApplySwapValuationColumnConfig(sheets);
});
if (needToPdf)
{
@@ -384,6 +386,135 @@ namespace YLErp.Modules.ReportModule.SettlementReportModule
cell.Style.Numberformat.Format = "@";
}
+ ///
+ /// 每日估值报告的互换估值导出使用当前用户已保存的列配置,
+ /// 同时同步业务字段的显示状态和列顺序。
+ ///
+ private void ApplySwapValuationColumnConfig(IEnumerable sheets)
+ {
+ var worksheet = sheets.FirstOrDefault(x => x.Name == "互换估值");
+ if (worksheet == null)
+ {
+ return;
+ }
+
+ var config = configcolumnBLL.GetData(UserId, configcolumn_data.互换估值V1);
+ if (string.IsNullOrWhiteSpace(config?.data))
+ {
+ return;
+ }
+
+ List columns;
+ try
+ {
+ columns = JsonConvert.DeserializeObject>(config.data);
+ }
+ catch (JsonException)
+ {
+ // 列配置损坏时保留完整的模板字段,不能导致每日估值报告导出失败。
+ return;
+ }
+
+ if (columns == null || !columns.Any())
+ {
+ return;
+ }
+
+ var columnIndexByName = new Dictionary
+ {
+ ["ConfrimNo"] = 1,
+ ["TradeNumber"] = 2,
+ ["position.PosiStartDate"] = 3,
+ ["MaturitySettlementDate"] = 4,
+ ["position.ValueDate"] = 5,
+ ["position.UnderlyingCode"] = 6,
+ ["InterestRate"] = 7,
+ ["position.PosiNotionalValue"] = 8,
+ ["position.PosiQuantity"] = 9,
+ ["PeriodAmount"] = 10,
+ ["DividendAmount"] = 11,
+ ["position.PosiGrossPrice"] = 12,
+ ["InitYtm"] = 13,
+ ["position.UnderlyingPrice"] = 14,
+ ["DayCount"] = 15,
+ ["FloatRateAbs"] = 16,
+ ["InterestAmount"] = 17,
+ ["position.PosiProfitSum"] = 18,
+ ["position.PosiFeePending"] = 19,
+ ["OpenMarginRate"] = 20,
+ ["MarginInterestAmount"] = 21,
+ ["OpenMarginAmount"] = 22,
+ ["AdditionalMarginAmount"] = 23,
+ ["NetSettmentAmount"] = 24,
+ ["TrsValue"] = 25
+ };
+ // 前端 _.uniqBy 保留首次出现的配置项,导出按相同规则过滤重复字段,
+ // 并保留该列表的原始顺序作为 Excel 列顺序。
+ var visibleColumnIndexes = new List();
+ var configuredNames = new HashSet();
+ foreach (var column in columns)
+ {
+ if (column == null || string.IsNullOrEmpty(column.name) || !configuredNames.Add(column.name))
+ {
+ continue;
+ }
+
+ if (!column.hidden && columnIndexByName.TryGetValue(column.name, out var index))
+ {
+ visibleColumnIndexes.Add(index);
+ }
+ }
+
+ // 与前端一致:旧配置缺少的新增字段默认隐藏;若没有任何业务列可见,
+ // 前端会回退展示全部默认列,导出保持模板默认顺序。
+ if (!visibleColumnIndexes.Any())
+ {
+ return;
+ }
+
+ ReorderSwapValuationColumns(worksheet, visibleColumnIndexes);
+ }
+
+ ///
+ /// 使用临时工作表保存可见列,再按目标顺序复制回原工作表。
+ /// 原工作表始终保持在模板的 25 列范围内,避免 EPPlus 扩列时触发 ColumnMax 冲突。
+ ///
+ private static void ReorderSwapValuationColumns(ExcelWorksheet worksheet, IReadOnlyList visibleSourceIndexes)
+ {
+ var lastRow = worksheet.Dimension.End.Row;
+ var originalColumnCount = worksheet.Dimension.End.Column;
+ var workbook = worksheet.Workbook;
+ var bufferName = "__swap_cols_" + Guid.NewGuid().ToString("N").Substring(0, 12);
+ var buffer = workbook.Worksheets.Add(bufferName);
+ try
+ {
+ for (var targetIndex = 0; targetIndex < visibleSourceIndexes.Count; targetIndex++)
+ {
+ var sourceColumn = visibleSourceIndexes[targetIndex];
+ var bufferColumn = targetIndex + 1;
+ worksheet.Cells[1, sourceColumn, lastRow, sourceColumn]
+ .Copy(buffer.Cells[1, bufferColumn, lastRow, bufferColumn]);
+ }
+
+ for (var targetIndex = 0; targetIndex < visibleSourceIndexes.Count; targetIndex++)
+ {
+ var targetColumn = targetIndex + 1;
+ buffer.Cells[1, targetColumn, lastRow, targetColumn]
+ .Copy(worksheet.Cells[1, targetColumn, lastRow, targetColumn]);
+ }
+
+ var columnsToDelete = originalColumnCount - visibleSourceIndexes.Count;
+ if (columnsToDelete > 0)
+ {
+ worksheet.DeleteColumn(visibleSourceIndexes.Count + 1, columnsToDelete);
+ }
+ }
+ finally
+ {
+ workbook.Worksheets.Delete(buffer);
+ }
+ }
+
///
/// 财务状况
///