fix: 面单自定义文本支持 testData,并避免文本框高度裁切
All checks were successful
Build and Deploy / deploy (push) Successful in 1m11s
All checks were successful
Build and Deploy / deploy (push) Successful in 1m11s
无 field 时按 title/testData 输出;框高至少字号×1.4,防止设计器矮框打成空白。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
7b54eff764
commit
af7909948e
@ -63,6 +63,10 @@ public sealed class HiprintElementOptions
|
||||
[JsonPropertyName("title")]
|
||||
public string? Title { get; set; }
|
||||
|
||||
/// <summary>设计器「测试数据」;无 field 的纯文本有时只把文案写在这里。</summary>
|
||||
[JsonPropertyName("testData")]
|
||||
public string? TestData { get; set; }
|
||||
|
||||
[JsonPropertyName("field")]
|
||||
public string? Field { get; set; }
|
||||
|
||||
|
||||
@ -105,14 +105,15 @@ public sealed class HiprintTemplateParser
|
||||
Src = ResolveValue(opt.Field, opt.Src ?? opt.Title, printData)
|
||||
};
|
||||
case "longtext":
|
||||
return BuildTextOp(opt, left, top, width, height, printData, wrap: true);
|
||||
return BuildTextOp(
|
||||
opt, left, top, width, height, printData, wrap: true, element.PrintElementType?.Title);
|
||||
case "text":
|
||||
default:
|
||||
{
|
||||
var textType = opt.TextType?.Trim().ToLowerInvariant();
|
||||
if (textType is "barcode" or "qrcode")
|
||||
{
|
||||
var content = ResolveValue(opt.Field, opt.Title, printData);
|
||||
var content = ResolveValue(opt.Field, FirstNonEmpty(opt.Title, opt.TestData), printData);
|
||||
if (string.IsNullOrWhiteSpace(content))
|
||||
{
|
||||
return null;
|
||||
@ -129,7 +130,8 @@ public sealed class HiprintTemplateParser
|
||||
};
|
||||
}
|
||||
|
||||
return BuildTextOp(opt, left, top, width, height, printData, wrap: false);
|
||||
return BuildTextOp(
|
||||
opt, left, top, width, height, printData, wrap: false, element.PrintElementType?.Title);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -141,25 +143,38 @@ public sealed class HiprintTemplateParser
|
||||
float width,
|
||||
float height,
|
||||
IReadOnlyDictionary<string, object?> printData,
|
||||
bool wrap)
|
||||
bool wrap,
|
||||
string? elementTypeTitle = null)
|
||||
{
|
||||
var value = ResolveValue(opt.Field, null, printData);
|
||||
// 与 vg-print 一致:无 field 时打印 title;有 field 时按 hideTitle 决定是否带标题
|
||||
var title = FirstNonEmpty(opt.Title, elementTypeTitle);
|
||||
string text;
|
||||
if (!string.IsNullOrWhiteSpace(opt.Field))
|
||||
{
|
||||
// 有 field:默认只打字段值;hideTitle=false 且有 title 时拼「标题:值」
|
||||
if (opt.HideTitle == false && !string.IsNullOrWhiteSpace(opt.Title) && !string.IsNullOrWhiteSpace(value))
|
||||
var hideTitle = opt.HideTitle != false; // null/true → 隐藏标题(OMS 字段默认 hideTitle:true)
|
||||
if (!hideTitle && !string.IsNullOrWhiteSpace(title) && !string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
text = $"{opt.Title}:{value}";
|
||||
text = $"{title}:{value}";
|
||||
}
|
||||
else if (!string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
text = value!;
|
||||
}
|
||||
else if (!hideTitle && !string.IsNullOrWhiteSpace(title))
|
||||
{
|
||||
// 仅标题(值为空时仍保留自定义标题文案)
|
||||
text = title!;
|
||||
}
|
||||
else
|
||||
{
|
||||
text = value ?? string.Empty;
|
||||
text = string.Empty;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
text = opt.Title ?? string.Empty;
|
||||
// 纯自定义文本:title → testData → 元素类型名
|
||||
text = FirstNonEmpty(opt.Title, opt.TestData, elementTypeTitle) ?? string.Empty;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
@ -169,15 +184,18 @@ public sealed class HiprintTemplateParser
|
||||
|
||||
var bold = string.Equals(opt.FontWeight, "bold", StringComparison.OrdinalIgnoreCase)
|
||||
|| opt.FontWeight is "700" or "600";
|
||||
var fontSize = opt.FontSize is > 0 ? opt.FontSize.Value : 10f;
|
||||
// 设计器文本框常只有十余 pt 高,行高略大于字号时会被裁成「空白」
|
||||
var boxHeight = Math.Max(height, fontSize * 1.4f);
|
||||
|
||||
return new LabelTextOp
|
||||
{
|
||||
LeftPt = left,
|
||||
TopPt = top,
|
||||
WidthPt = width,
|
||||
HeightPt = height,
|
||||
HeightPt = boxHeight,
|
||||
Text = text,
|
||||
FontSizePt = opt.FontSize is > 0 ? opt.FontSize.Value : 10f,
|
||||
FontSizePt = fontSize,
|
||||
Bold = bold,
|
||||
ColorHex = opt.Color,
|
||||
Align = (opt.TextAlign ?? "left").ToLowerInvariant(),
|
||||
@ -185,6 +203,9 @@ public sealed class HiprintTemplateParser
|
||||
};
|
||||
}
|
||||
|
||||
private static string? FirstNonEmpty(params string?[] values) =>
|
||||
values.FirstOrDefault(x => !string.IsNullOrWhiteSpace(x));
|
||||
|
||||
private static string? ResolveValue(
|
||||
string? field,
|
||||
string? fallback,
|
||||
|
||||
@ -49,6 +49,59 @@ public class HiprintTemplateParserTests
|
||||
act.Should().Throw<Exception>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_StaticCustomText_ShouldKeepTitleAndNotClipHeight()
|
||||
{
|
||||
const string json = """
|
||||
{
|
||||
"panels": [{
|
||||
"width": 100,
|
||||
"height": 50,
|
||||
"printElements": [{
|
||||
"options": {
|
||||
"left": 10,
|
||||
"top": 10,
|
||||
"width": 80,
|
||||
"height": 13,
|
||||
"title": "箱子数量",
|
||||
"fontSize": 10,
|
||||
"hideTitle": true
|
||||
},
|
||||
"printElementType": { "type": "text", "title": "文本" }
|
||||
}]
|
||||
}]
|
||||
}
|
||||
""";
|
||||
|
||||
var page = new HiprintTemplateParser().Parse(json, new Dictionary<string, object?>());
|
||||
var text = page.Ops.OfType<LabelTextOp>().Should().ContainSingle().Subject;
|
||||
text.Text.Should().Be("箱子数量");
|
||||
text.HeightPt.Should().BeGreaterThanOrEqualTo(14f);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_StaticTextFromTestData_WhenTitleEmpty()
|
||||
{
|
||||
const string json = """
|
||||
{
|
||||
"panels": [{
|
||||
"width": 100,
|
||||
"height": 50,
|
||||
"printElements": [{
|
||||
"options": {
|
||||
"left": 1, "top": 1, "width": 50, "height": 16,
|
||||
"testData": "仅测试数据文案"
|
||||
},
|
||||
"printElementType": { "type": "text" }
|
||||
}]
|
||||
}]
|
||||
}
|
||||
""";
|
||||
|
||||
var page = new HiprintTemplateParser().Parse(json, new Dictionary<string, object?>());
|
||||
page.Ops.OfType<LabelTextOp>().Should().ContainSingle(x => x.Text == "仅测试数据文案");
|
||||
}
|
||||
|
||||
internal static string LoadFixture(string fileName)
|
||||
{
|
||||
var dir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user