fix: 运单列表 enrichment 改为顺序查询,避免 MySqlConnection 并发复用 #13
@ -0,0 +1,88 @@
|
||||
using QuestPDF.Drawing;
|
||||
|
||||
namespace Oms.Application.Labeling.Hiprint;
|
||||
|
||||
/// <summary>
|
||||
/// 面单 PDF 中文字体:QuestPDF 默认字体无 CJK,不注册会显示 □ / ?。
|
||||
/// </summary>
|
||||
public static class LabelPdfFontRegistrar
|
||||
{
|
||||
public const string FamilyName = "OmsLabelSans";
|
||||
|
||||
private static int _state; // 0=未试 1=成功 2=失败
|
||||
private static string? _sourcePath;
|
||||
|
||||
/// <summary>
|
||||
/// 确保已注册可用中文字体;成功返回 <see cref="FamilyName"/>,否则 null(仅西文)。
|
||||
/// </summary>
|
||||
public static string? EnsureRegistered()
|
||||
{
|
||||
var state = Volatile.Read(ref _state);
|
||||
if (state == 1)
|
||||
{
|
||||
return FamilyName;
|
||||
}
|
||||
|
||||
if (state == 2)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach (var path in EnumerateCandidates())
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path) || !File.Exists(path))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
using var stream = File.OpenRead(path);
|
||||
FontManager.RegisterFontWithCustomName(FamilyName, stream);
|
||||
_sourcePath = path;
|
||||
Interlocked.Exchange(ref _state, 1);
|
||||
return FamilyName;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// 试下一个候选
|
||||
}
|
||||
}
|
||||
|
||||
Interlocked.Exchange(ref _state, 2);
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>已成功注册时的字体文件路径(诊断用)。</summary>
|
||||
public static string? RegisteredSourcePath => _sourcePath;
|
||||
|
||||
private static IEnumerable<string> EnumerateCandidates()
|
||||
{
|
||||
var fromEnv = Environment.GetEnvironmentVariable("OMS_LABEL_FONT");
|
||||
if (!string.IsNullOrWhiteSpace(fromEnv))
|
||||
{
|
||||
yield return fromEnv.Trim();
|
||||
}
|
||||
|
||||
var baseDir = AppContext.BaseDirectory;
|
||||
yield return Path.Combine(baseDir, "Fonts", "NotoSansSC-Regular.otf");
|
||||
yield return Path.Combine(baseDir, "Fonts", "NotoSansSC-Regular.ttf");
|
||||
yield return Path.Combine(baseDir, "Fonts", "NotoSansCJKsc-Regular.otf");
|
||||
|
||||
// Windows
|
||||
var winFonts = Environment.GetFolderPath(Environment.SpecialFolder.Fonts);
|
||||
if (!string.IsNullOrWhiteSpace(winFonts))
|
||||
{
|
||||
yield return Path.Combine(winFonts, "msyh.ttc");
|
||||
yield return Path.Combine(winFonts, "msyhbd.ttc");
|
||||
yield return Path.Combine(winFonts, "simhei.ttf");
|
||||
yield return Path.Combine(winFonts, "simsun.ttc");
|
||||
}
|
||||
|
||||
// Debian/Ubuntu(Dockerfile 安装 fonts-noto-cjk)
|
||||
yield return "/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc";
|
||||
yield return "/usr/share/fonts/opentype/noto/NotoSansCJKsc-Regular.otf";
|
||||
yield return "/usr/share/fonts/truetype/noto/NotoSansCJK-Regular.ttc";
|
||||
yield return "/usr/share/fonts/truetype/wqy/wqy-microhei.ttc";
|
||||
}
|
||||
}
|
||||
@ -23,6 +23,8 @@ public sealed class QuestPdfLabelRenderer(HiprintTemplateParser parser) : ILabel
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
EnsureLicense();
|
||||
// SKU 名称等含中文;未注册 CJK 字体会输出 □
|
||||
_ = LabelPdfFontRegistrar.EnsureRegistered();
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (printDataPages == null || printDataPages.Count == 0)
|
||||
@ -90,6 +92,12 @@ public sealed class QuestPdfLabelRenderer(HiprintTemplateParser parser) : ILabel
|
||||
.FontSize(text.FontSizePt)
|
||||
.FontColor(ParseColor(text.ColorHex));
|
||||
|
||||
var fontFamily = LabelPdfFontRegistrar.EnsureRegistered();
|
||||
if (!string.IsNullOrEmpty(fontFamily))
|
||||
{
|
||||
span.FontFamily(fontFamily);
|
||||
}
|
||||
|
||||
if (text.Bold)
|
||||
{
|
||||
span.Bold();
|
||||
|
||||
@ -61,6 +61,7 @@ public static class InboundBoxLabelPrintDataBuilder
|
||||
|
||||
["boxId"] = box.Id,
|
||||
["boxSeqNo"] = box.BoxSeqNo,
|
||||
["boxCount"] = pageCount,
|
||||
["markBoxNo"] = box.MarkBoxNo,
|
||||
["barcode"] = barcode,
|
||||
|
||||
@ -103,6 +104,7 @@ public static class InboundBoxLabelPrintDataBuilder
|
||||
["remark"] = null,
|
||||
["boxId"] = 1,
|
||||
["boxSeqNo"] = "1",
|
||||
["boxCount"] = 2,
|
||||
["markBoxNo"] = "BOX-001",
|
||||
["barcode"] = "BOX-001",
|
||||
["warehouseName"] = "SZ-01",
|
||||
|
||||
@ -85,6 +85,7 @@ public static class LabelFieldDictionary
|
||||
Field("markReference", "唛头参考"),
|
||||
Field("markBoxNo", "箱唛号"),
|
||||
Field("boxSeqNo", "箱序号"),
|
||||
Field("boxCount", "箱子总数"),
|
||||
Field("barcode", "条码内容"),
|
||||
Field("boxIndexText", "箱序页码"),
|
||||
Field("skuSummary", "SKU 摘要"),
|
||||
|
||||
@ -24,6 +24,10 @@ RUN dotnet publish "SimpleAdmin.Api.csproj" -c $BUILD_CONFIGURATION -o /app/publ
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
|
||||
WORKDIR /app
|
||||
# 面单 QuestPDF 需 CJK 字体,否则中文 SKU 等渲染为 □
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends fonts-noto-cjk \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
COPY --from=build /app/publish .
|
||||
# Local 存储落盘 wwwroot;非 root 用户需可写 uploads(Provider=Cos 时可不依赖此目录)
|
||||
RUN mkdir -p /app/wwwroot/uploads \
|
||||
|
||||
Loading…
Reference in New Issue
Block a user