Adjust packing list layout: merge detail-area bottom border, double-line title, dashed detail separators

- Merge the detail area's bottom border into the last record's thick line; remove the redundant thick line above the total (keep vertical spacing, total position unchanged)
- Add a thick line below the "Packing List" title matching the detail header's thickness, forming a "thick-above-thin-below" double line
- Change the detail list inner separators to dashed lines (simulated with multiple short solid segments, as ReportBro lines do not support native dashes); line weight raised from hairline to 1pt
This commit is contained in:
Misaka_Company
2026-07-30 14:51:37 +08:00
parent 4dc563cdd9
commit 22b764ef19

View File

@@ -175,6 +175,25 @@ def _line(id_, x, y, w, *, style_id, weight=0):
}
def _dashed_line(nid_, x, y, w, *, style_id, weight=0.2, dash_mm=3.0, gap_mm=2.0):
"""用多段短实线模拟虚线reportbro 线条元素本身不支持 dash
用于详情列表内的细分隔线:保持浅灰(style 201)配色,线粗由 weight 控制。
坐标/尺寸与 _line 一致,均为 ptdash/gap 以 mm 设计后经 mm() 换算。
"""
els: list[dict] = []
dash = mm(dash_mm)
gap = mm(gap_mm)
pos = x
end = x + w
# 末尾余量 < 0.5pt 时不再画,避免极小残段
while pos < end - 0.5:
seg_w = min(dash, end - pos)
els.append(_line(nid_(), pos, y, seg_w, style_id=style_id, weight=weight))
pos += dash + gap
return els
def build_doc_elements(context: dict[str, Any]) -> list[dict]:
"""按数据动态生成所有文档元素(标题/信息条/列头/明细行/合计/页脚)。
@@ -202,7 +221,9 @@ def build_doc_elements(context: dict[str, Any]) -> list[dict]:
# ===== 标题(紧贴内容区顶部,容器原点已在 marginTop 处)=====
y = mm(1)
els.append(_text(nid_(), L, y, CW, mm(10), "装箱单", style_id=101))
els.append(_line(nid_(), L, y + mm(12), CW, style_id=202))
# 标题双线:粗线(与详情列表表头下粗线同款 weight=0.45)在上,细线在下
els.append(_line(nid_(), L, y + mm(12), CW, style_id=202, weight=0.45))
els.append(_line(nid_(), L, y + mm(13.5), CW, style_id=202))
# ===== 信息条2×2 网格,标签灰 + 值用 Bahnschrift=====
# 行1排产号 | 箱号行2订单号 | 装箱日期(订单号在排产号正下方)
@@ -234,6 +255,12 @@ def build_doc_elements(context: dict[str, Any]) -> list[dict]:
# ===== 明细行(逐行定位,高度自适应)=====
y = y + mm(2)
row_heights: list[float] = context.get("row_heights", [])
# 最后一条可见行下标:用其底部粗线框住明细区底部(替代原「合计上方」那条重复横线)。
# build_context 保证至少有 1 行(空箱会抛 EmptyBoxError故 last_idx 恒 >= 0。
last_idx = max(
(i for i in range(len(row_heights)) if row_heights[i] > 0),
default=-1,
)
for i in range(8):
h = mm(row_heights[i]) if i < len(row_heights) else 0
show = f"${{r{i}_show}}" # printIf: r{i}_show 为 "1" 才渲染
@@ -244,15 +271,23 @@ def build_doc_elements(context: dict[str, Any]) -> list[dict]:
style_id=field_style.get(field, col_style[align]), print_if=show,
))
y += h
# 行间极细线(仅在有数据的行之后)
if i < 7 and row_heights[i] > 0:
els.append(_line(nid_(), L, y + mm(1), CW, style_id=201))
# 行分隔线非最后一条可见行画虚线reportbro 线条元素不支持 dash
# 用短实线段模拟),并略粗一点点;最后一条可见行的底线为粗实线,框住明细区底部。
# 去掉原 i<7 限制——占位空行 row_heights=0 本就不画线;且最后一条若恰为
# 第 8 行(i=7) 时也需能画粗线。
if row_heights[i] > 0:
if i == last_idx:
els.append(_line(nid_(), L, y + mm(1), CW, style_id=202, weight=0.45))
else:
els.extend(_dashed_line(nid_, L, y + mm(1), CW, style_id=201,
weight=0.2, dash_mm=3.0, gap_mm=2.0))
y += mm(2)
# ===== 合计 =====
# 标签框宽度对齐量程列x=86-106宽20数量框与数量列同宽(x=106-120)、居中。
els.append(_line(nid_(), L, y + mm(2), CW, style_id=202, weight=0.45))
# 明细区底部框线已合并到最后一条记录的粗线(见上行循环),此处不再重复画横线;
# 保留原「合计上方横线」所占的纵向间距,使合计整体位置与改动前一致。
y = y + mm(4)
# 标签框宽度对齐量程列x=86-106宽20数量框与数量列同宽(x=106-120)、居中。
range_x = COLS[3][2] # 量程列起点 86
range_w = COLS[3][3] # 量程列宽 20
qty_x = COLS[4][2] # 数量列起点 106