优化打印预览窗口的参数生成逻辑,支持根据合并字段顺序生成相应的 JSON 数据,增强打印模板的灵活性和可定制性。同时,修复了列级合并逻辑,确保在处理重复键时不会抛出异常。
This commit is contained in:
@@ -1017,14 +1017,18 @@ public static class NativePrintRenderService
|
|||||||
var colList = columns.OfType<JsonObject>().ToList();
|
var colList = columns.OfType<JsonObject>().ToList();
|
||||||
if (mergeColumnKeys.Length > 0)
|
if (mergeColumnKeys.Length > 0)
|
||||||
{
|
{
|
||||||
var byKey = colList.ToDictionary(
|
// 用 GroupBy 兜底,避免重复 key 抛异常;按 mergeColumnKeys 给定顺序输出对应 bindField/field
|
||||||
c => ReadAsString(c["key"]) ?? string.Empty,
|
var byKey = colList
|
||||||
c => ReadAsString(c["bindField"]) ?? ReadAsString(c["field"]) ?? string.Empty);
|
.GroupBy(c => ReadAsString(c["key"]) ?? string.Empty)
|
||||||
|
.ToDictionary(
|
||||||
|
g => g.Key,
|
||||||
|
g => ReadAsString(g.First()["bindField"]) ?? ReadAsString(g.First()["field"]) ?? string.Empty);
|
||||||
return mergeColumnKeys
|
return mergeColumnKeys
|
||||||
.Select(k => byKey.TryGetValue(k, out var f) ? f : string.Empty)
|
.Select(k => byKey.TryGetValue(k, out var f) ? f : string.Empty)
|
||||||
.Where(f => !string.IsNullOrEmpty(f))
|
.Where(f => !string.IsNullOrEmpty(f))
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
|
// 兼容老的列级 mergeByValue 开关
|
||||||
return colList
|
return colList
|
||||||
.Where(c => string.Equals(ReadAsString(c["mergeByValue"]), "true", StringComparison.OrdinalIgnoreCase))
|
.Where(c => string.Equals(ReadAsString(c["mergeByValue"]), "true", StringComparison.OrdinalIgnoreCase))
|
||||||
.Select(c => ReadAsString(c["bindField"]) ?? ReadAsString(c["field"]) ?? string.Empty)
|
.Select(c => ReadAsString(c["bindField"]) ?? ReadAsString(c["field"]) ?? string.Empty)
|
||||||
|
|||||||
@@ -109,6 +109,8 @@ public partial class PrintPreviewWindow : HandyControl.Controls.Window
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 根据模板绑定字段生成参数 JSON(便于用户直接编辑并预览)。
|
/// 根据模板绑定字段生成参数 JSON(便于用户直接编辑并预览)。
|
||||||
|
/// 与 web 端 nativeMockData.ts 保持一致:识别 mergeColumnKeys 让同组相邻行字段值相同,
|
||||||
|
/// 以便在预览中触发 rowSpan 合并显示。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static string BuildMockParamJson(string templateJson)
|
private static string BuildMockParamJson(string templateJson)
|
||||||
{
|
{
|
||||||
@@ -121,6 +123,7 @@ public partial class PrintPreviewWindow : HandyControl.Controls.Window
|
|||||||
var obj = new JsonObject();
|
var obj = new JsonObject();
|
||||||
var elements = root?["elements"]?.AsArray() ?? new JsonArray();
|
var elements = root?["elements"]?.AsArray() ?? new JsonArray();
|
||||||
var fields = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
var fields = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
var rng = new Random();
|
||||||
|
|
||||||
foreach (var el in elements.OfType<JsonObject>())
|
foreach (var el in elements.OfType<JsonObject>())
|
||||||
{
|
{
|
||||||
@@ -130,28 +133,73 @@ public partial class PrintPreviewWindow : HandyControl.Controls.Window
|
|||||||
var source = (el["source"]?.ToString() ?? "mainTable").Trim();
|
var source = (el["source"]?.ToString() ?? "mainTable").Trim();
|
||||||
if (!obj.ContainsKey(source))
|
if (!obj.ContainsKey(source))
|
||||||
{
|
{
|
||||||
var rows = new JsonArray();
|
|
||||||
var columns = el["columns"]?.AsArray() ?? new JsonArray();
|
var columns = el["columns"]?.AsArray() ?? new JsonArray();
|
||||||
for (var i = 1; i <= 8; i++)
|
var colList = columns.OfType<JsonObject>().ToList();
|
||||||
|
|
||||||
|
// 解析合并字段顺序:根据 mergeColumnKeys 按 column.key 映射到 bindField
|
||||||
|
var mergeKeys = (el["mergeColumnKeys"]?.AsArray() ?? new JsonArray())
|
||||||
|
.Select(n => n?.ToString() ?? string.Empty)
|
||||||
|
.Where(s => !string.IsNullOrEmpty(s))
|
||||||
|
.ToList();
|
||||||
|
var strictGrouping = !string.Equals(
|
||||||
|
el["strictGrouping"]?.ToString() ?? "true", "false",
|
||||||
|
StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
var mergeFieldOrder = mergeKeys
|
||||||
|
.Select(k => colList.FirstOrDefault(c => string.Equals(c["key"]?.ToString() ?? string.Empty, k, StringComparison.Ordinal)))
|
||||||
|
.Where(c => c != null)
|
||||||
|
.Select(c => (c!["bindField"]?.ToString() ?? c!["field"]?.ToString() ?? string.Empty).Trim())
|
||||||
|
.Where(s => !string.IsNullOrEmpty(s))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var rows = new JsonArray();
|
||||||
|
JsonObject? prevRow = null;
|
||||||
|
for (var i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
var row = new JsonObject();
|
var row = new JsonObject();
|
||||||
foreach (var col in columns.OfType<JsonObject>())
|
foreach (var col in colList)
|
||||||
{
|
{
|
||||||
var field = (col["bindField"]?.ToString() ?? col["field"]?.ToString() ?? string.Empty).Trim();
|
var field = (col["bindField"]?.ToString() ?? col["field"]?.ToString() ?? string.Empty).Trim();
|
||||||
if (string.IsNullOrWhiteSpace(field)) continue;
|
if (string.IsNullOrWhiteSpace(field)) continue;
|
||||||
var contentType = (col["contentType"]?.ToString() ?? "text").Trim().ToLowerInvariant();
|
var contentType = (col["contentType"]?.ToString() ?? "text").Trim().ToLowerInvariant();
|
||||||
|
fields.Add(field);
|
||||||
|
|
||||||
|
var mergeIndex = mergeFieldOrder.IndexOf(field);
|
||||||
|
var enableMerge = mergeIndex >= 0;
|
||||||
|
|
||||||
|
if (enableMerge)
|
||||||
|
{
|
||||||
|
// 父级合并字段在 strictGrouping 下必须与前一行一致,才允许沿用前一行值
|
||||||
|
var canFollowPrev = !strictGrouping || mergeIndex == 0 || (prevRow != null &&
|
||||||
|
mergeFieldOrder.Take(mergeIndex).All(parent =>
|
||||||
|
(prevRow[parent]?.ToString() ?? string.Empty) == (row[parent]?.ToString() ?? string.Empty)));
|
||||||
|
|
||||||
|
if (i > 0 && prevRow != null && canFollowPrev && rng.NextDouble() < 0.5)
|
||||||
|
{
|
||||||
|
// 沿用前一行此字段值,从而触发合并
|
||||||
|
var prevVal = prevRow[field];
|
||||||
|
row[field] = prevVal != null ? JsonNode.Parse(prevVal.ToJsonString()) : (JsonNode?)$"{field}_合并组1";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 新合并组:随机 0-3 表示组编号
|
||||||
|
row[field] = $"{field}_合并组{rng.Next(1, 5)}";
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
row[field] = contentType switch
|
row[field] = contentType switch
|
||||||
{
|
{
|
||||||
"number" => i * 123.45,
|
"number" => (i + 1) * 123.45,
|
||||||
"amount" => i * 24567.89,
|
"amount" => (i + 1) * 24567.89,
|
||||||
"qrcode" => $"QR_{field}_{i}",
|
"qrcode" => $"QR_{field}_{i + 1}",
|
||||||
"barcode" => $"BAR_{field}_{i}",
|
"barcode" => $"BAR_{field}_{i + 1}",
|
||||||
"image" => $"https://picsum.photos/seed/{Uri.EscapeDataString(field + "_" + i)}/260/120",
|
"image" => $"https://picsum.photos/seed/{Uri.EscapeDataString(field + "_" + (i + 1))}/260/120",
|
||||||
_ => $"{field}_示例值_{i}"
|
_ => $"{field}_示例值_{i + 1}"
|
||||||
};
|
};
|
||||||
fields.Add(field);
|
|
||||||
}
|
}
|
||||||
rows.Add(row);
|
rows.Add(row);
|
||||||
|
prevRow = row;
|
||||||
}
|
}
|
||||||
obj[source] = rows;
|
obj[source] = rows;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user