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")]
|
[JsonPropertyName("title")]
|
||||||
public string? Title { get; set; }
|
public string? Title { get; set; }
|
||||||
|
|
||||||
|
/// <summary>设计器「测试数据」;无 field 的纯文本有时只把文案写在这里。</summary>
|
||||||
|
[JsonPropertyName("testData")]
|
||||||
|
public string? TestData { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("field")]
|
[JsonPropertyName("field")]
|
||||||
public string? Field { get; set; }
|
public string? Field { get; set; }
|
||||||
|
|
||||||
|
|||||||
@ -105,14 +105,15 @@ public sealed class HiprintTemplateParser
|
|||||||
Src = ResolveValue(opt.Field, opt.Src ?? opt.Title, printData)
|
Src = ResolveValue(opt.Field, opt.Src ?? opt.Title, printData)
|
||||||
};
|
};
|
||||||
case "longtext":
|
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":
|
case "text":
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
var textType = opt.TextType?.Trim().ToLowerInvariant();
|
var textType = opt.TextType?.Trim().ToLowerInvariant();
|
||||||
if (textType is "barcode" or "qrcode")
|
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))
|
if (string.IsNullOrWhiteSpace(content))
|
||||||
{
|
{
|
||||||
return null;
|
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 width,
|
||||||
float height,
|
float height,
|
||||||
IReadOnlyDictionary<string, object?> printData,
|
IReadOnlyDictionary<string, object?> printData,
|
||||||
bool wrap)
|
bool wrap,
|
||||||
|
string? elementTypeTitle = null)
|
||||||
{
|
{
|
||||||
var value = ResolveValue(opt.Field, null, printData);
|
var value = ResolveValue(opt.Field, null, printData);
|
||||||
|
// 与 vg-print 一致:无 field 时打印 title;有 field 时按 hideTitle 决定是否带标题
|
||||||
|
var title = FirstNonEmpty(opt.Title, elementTypeTitle);
|
||||||
string text;
|
string text;
|
||||||
if (!string.IsNullOrWhiteSpace(opt.Field))
|
if (!string.IsNullOrWhiteSpace(opt.Field))
|
||||||
{
|
{
|
||||||
// 有 field:默认只打字段值;hideTitle=false 且有 title 时拼「标题:值」
|
var hideTitle = opt.HideTitle != false; // null/true → 隐藏标题(OMS 字段默认 hideTitle:true)
|
||||||
if (opt.HideTitle == false && !string.IsNullOrWhiteSpace(opt.Title) && !string.IsNullOrWhiteSpace(value))
|
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
|
else
|
||||||
{
|
{
|
||||||
text = value ?? string.Empty;
|
text = string.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
text = opt.Title ?? string.Empty;
|
// 纯自定义文本:title → testData → 元素类型名
|
||||||
|
text = FirstNonEmpty(opt.Title, opt.TestData, elementTypeTitle) ?? string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(text))
|
if (string.IsNullOrWhiteSpace(text))
|
||||||
@ -169,15 +184,18 @@ public sealed class HiprintTemplateParser
|
|||||||
|
|
||||||
var bold = string.Equals(opt.FontWeight, "bold", StringComparison.OrdinalIgnoreCase)
|
var bold = string.Equals(opt.FontWeight, "bold", StringComparison.OrdinalIgnoreCase)
|
||||||
|| opt.FontWeight is "700" or "600";
|
|| 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
|
return new LabelTextOp
|
||||||
{
|
{
|
||||||
LeftPt = left,
|
LeftPt = left,
|
||||||
TopPt = top,
|
TopPt = top,
|
||||||
WidthPt = width,
|
WidthPt = width,
|
||||||
HeightPt = height,
|
HeightPt = boxHeight,
|
||||||
Text = text,
|
Text = text,
|
||||||
FontSizePt = opt.FontSize is > 0 ? opt.FontSize.Value : 10f,
|
FontSizePt = fontSize,
|
||||||
Bold = bold,
|
Bold = bold,
|
||||||
ColorHex = opt.Color,
|
ColorHex = opt.Color,
|
||||||
Align = (opt.TextAlign ?? "left").ToLowerInvariant(),
|
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(
|
private static string? ResolveValue(
|
||||||
string? field,
|
string? field,
|
||||||
string? fallback,
|
string? fallback,
|
||||||
|
|||||||
@ -49,6 +49,59 @@ public class HiprintTemplateParserTests
|
|||||||
act.Should().Throw<Exception>();
|
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)
|
internal static string LoadFixture(string fileName)
|
||||||
{
|
{
|
||||||
var dir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!;
|
var dir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user