fix table
This commit is contained in:
@@ -14,7 +14,7 @@ from reportlab.pdfbase.ttfonts import TTFont
|
|||||||
from reportlab.pdfgen import canvas
|
from reportlab.pdfgen import canvas
|
||||||
|
|
||||||
from app.core.config import get_settings
|
from app.core.config import get_settings
|
||||||
from app.services.pdf_gost_frame import draw_gost_frame
|
from app.services.pdf_gost_frame import TABLE_LEFT, draw_gost_frame
|
||||||
|
|
||||||
_font_registered = False
|
_font_registered = False
|
||||||
FONT_NAME = "GOST_A"
|
FONT_NAME = "GOST_A"
|
||||||
@@ -231,7 +231,8 @@ def _draw_rotated_header(
|
|||||||
line = lines[0] if lines else text
|
line = lines[0] if lines else text
|
||||||
line = _elide(c, line, font, size, h - mm)
|
line = _elide(c, line, font, size, h - mm)
|
||||||
tw = c.stringWidth(line, font, size)
|
tw = c.stringWidth(line, font, size)
|
||||||
c.drawString((h - tw) / 2, (w - size * 0.35) / 2, line)
|
# Текст растёт внутрь таблицы (+x после поворота), не влево в поле подшивки
|
||||||
|
c.drawString(max(0, (h - tw) / 2), (w - size * 0.35) / 2, line)
|
||||||
c.restoreState()
|
c.restoreState()
|
||||||
|
|
||||||
|
|
||||||
@@ -344,7 +345,7 @@ def _draw_table_page(
|
|||||||
font = _ensure_font()
|
font = _ensure_font()
|
||||||
c.setLineWidth(LINE_WIDTH)
|
c.setLineWidth(LINE_WIDTH)
|
||||||
|
|
||||||
table_x = layout.margin_left_mm * mm
|
table_x = TABLE_LEFT
|
||||||
table_top = page_h - layout.margin_top_mm * mm
|
table_top = page_h - layout.margin_top_mm * mm
|
||||||
row_h = layout.row_height_mm * mm
|
row_h = layout.row_height_mm * mm
|
||||||
header_h = layout.header_height_mm * mm
|
header_h = layout.header_height_mm * mm
|
||||||
|
|||||||
@@ -10,6 +10,10 @@ M_LEFT = 20 * mm
|
|||||||
M_TOP = 5 * mm
|
M_TOP = 5 * mm
|
||||||
M_RIGHT = 5 * mm
|
M_RIGHT = 5 * mm
|
||||||
M_BOTTOM = 5 * mm
|
M_BOTTOM = 5 * mm
|
||||||
|
BINDING_WIDTH = 12 * mm
|
||||||
|
# Поле подшивки: 8–20 мм от левого края листа; таблица начинается ровно на inner.left (20 мм).
|
||||||
|
TABLE_LEFT = M_LEFT
|
||||||
|
BINDING_LEFT = TABLE_LEFT - BINDING_WIDTH
|
||||||
|
|
||||||
DOC_TYPES = {
|
DOC_TYPES = {
|
||||||
"perechen": 1,
|
"perechen": 1,
|
||||||
@@ -45,6 +49,22 @@ def _set_frame_pen(c: canvas.Canvas) -> None:
|
|||||||
c.setStrokeColorRGB(0, 0, 0)
|
c.setStrokeColorRGB(0, 0, 0)
|
||||||
|
|
||||||
|
|
||||||
|
def _elide(c: canvas.Canvas, text: str, font: str, size: float, max_w: float) -> str:
|
||||||
|
if not text:
|
||||||
|
return text
|
||||||
|
if c.stringWidth(text, font, size) <= max_w:
|
||||||
|
return text
|
||||||
|
ell = "…"
|
||||||
|
lo, hi = 0, len(text)
|
||||||
|
while lo < hi:
|
||||||
|
mid = (lo + hi + 1) // 2
|
||||||
|
if c.stringWidth(text[:mid] + ell, font, size) <= max_w:
|
||||||
|
lo = mid
|
||||||
|
else:
|
||||||
|
hi = mid - 1
|
||||||
|
return text[:lo] + ell if lo else ell
|
||||||
|
|
||||||
|
|
||||||
def _txt(
|
def _txt(
|
||||||
c: canvas.Canvas,
|
c: canvas.Canvas,
|
||||||
x: float,
|
x: float,
|
||||||
@@ -60,6 +80,7 @@ def _txt(
|
|||||||
if not text:
|
if not text:
|
||||||
return
|
return
|
||||||
c.setFont(font, size)
|
c.setFont(font, size)
|
||||||
|
text = _elide(c, text, font, size, w - mm)
|
||||||
tw = c.stringWidth(text, font, size)
|
tw = c.stringWidth(text, font, size)
|
||||||
if align == "center":
|
if align == "center":
|
||||||
tx = x + (w - tw) / 2
|
tx = x + (w - tw) / 2
|
||||||
@@ -116,26 +137,38 @@ def _draw_inner_border(c: canvas.Canvas, inner: Inner) -> None:
|
|||||||
c.rect(inner.left, inner.bottom, inner.right - inner.left, inner.top - inner.bottom)
|
c.rect(inner.left, inner.bottom, inner.right - inner.left, inner.top - inner.bottom)
|
||||||
|
|
||||||
|
|
||||||
|
def _clip_binding_zone(c: canvas.Canvas, inner: Inner) -> None:
|
||||||
|
"""Ограничить рисование полосы подшивки: 8–20 мм, не заходить в таблицу."""
|
||||||
|
p = c.beginPath()
|
||||||
|
p.rect(BINDING_LEFT, inner.bottom, BINDING_WIDTH, inner.top - inner.bottom)
|
||||||
|
c.clipPath(p, stroke=0, fill=0)
|
||||||
|
|
||||||
|
|
||||||
def _draw_left_binding_strip(c: canvas.Canvas, inner: Inner) -> tuple[float, float, float, float]:
|
def _draw_left_binding_strip(c: canvas.Canvas, inner: Inner) -> tuple[float, float, float, float]:
|
||||||
"""Left vertical strip (12×145 mm) at bottom-left of inner area."""
|
"""Left vertical strip (12×145 mm) — strictly left of the table (8–20 mm)."""
|
||||||
w = 12 * mm
|
w = BINDING_WIDTH
|
||||||
h = 145 * mm
|
h = 145 * mm
|
||||||
x = inner.left - w
|
x = BINDING_LEFT
|
||||||
y = inner.bottom
|
y = inner.bottom
|
||||||
|
c.saveState()
|
||||||
|
_set_frame_pen(c)
|
||||||
|
_clip_binding_zone(c, inner)
|
||||||
c.rect(x, y, w, h)
|
c.rect(x, y, w, h)
|
||||||
# horizontal dividers (from bottom): 25, 35, 25, 25, 35 mm sections
|
|
||||||
offsets = [25, 60, 85, 110, 145]
|
offsets = [25, 60, 85, 110, 145]
|
||||||
for off in offsets:
|
for off in offsets:
|
||||||
yy = y + off * mm
|
yy = y + off * mm
|
||||||
c.line(x, yy, inner.left, yy)
|
c.line(x, yy, TABLE_LEFT, yy)
|
||||||
c.line(x + w + 5 * mm, y, x + w + 5 * mm, y + h)
|
c.restoreState()
|
||||||
return x, y, w, h
|
return x, y, w, h
|
||||||
|
|
||||||
|
|
||||||
def _draw_left_binding_text(c: canvas.Canvas, strip_x: float, strip_y: float, inscriptions: dict[int, str], font: str) -> None:
|
def _draw_left_binding_text(
|
||||||
|
c: canvas.Canvas, inner: Inner, strip_x: float, strip_y: float, inscriptions: dict[int, str], font: str
|
||||||
|
) -> None:
|
||||||
size = 12
|
size = 12
|
||||||
c.saveState()
|
c.saveState()
|
||||||
c.translate(strip_x + 12 * mm, strip_y + 145 * mm)
|
_clip_binding_zone(c, inner)
|
||||||
|
c.translate(strip_x + BINDING_WIDTH, strip_y + 145 * mm)
|
||||||
c.rotate(-90)
|
c.rotate(-90)
|
||||||
labels = [
|
labels = [
|
||||||
(0, 25, "Инв. № подл"),
|
(0, 25, "Инв. № подл"),
|
||||||
@@ -153,16 +186,17 @@ def _draw_left_binding_text(c: canvas.Canvas, strip_x: float, strip_y: float, in
|
|||||||
|
|
||||||
|
|
||||||
def _draw_top_left_strip(c: canvas.Canvas, inner: Inner, inscriptions: dict[int, str], doc_type: int, font: str) -> None:
|
def _draw_top_left_strip(c: canvas.Canvas, inner: Inner, inscriptions: dict[int, str], doc_type: int, font: str) -> None:
|
||||||
w = 12 * mm
|
w = BINDING_WIDTH
|
||||||
h = 120 * mm
|
h = 120 * mm
|
||||||
x = inner.left - w
|
x = BINDING_LEFT
|
||||||
y = inner.top - h
|
y = inner.top - h
|
||||||
c.rect(x, y, w, h)
|
|
||||||
c.line(x + w + 5 * mm, y, x + w + 5 * mm, y + h)
|
|
||||||
c.line(x, y + 60 * mm, inner.left, y + 60 * mm)
|
|
||||||
|
|
||||||
c.saveState()
|
c.saveState()
|
||||||
c.translate(x + w, y)
|
_set_frame_pen(c)
|
||||||
|
_clip_binding_zone(c, inner)
|
||||||
|
c.rect(x, y, w, h)
|
||||||
|
c.line(x, y + 60 * mm, TABLE_LEFT, y + 60 * mm)
|
||||||
|
|
||||||
|
c.translate(TABLE_LEFT, y)
|
||||||
c.rotate(-90)
|
c.rotate(-90)
|
||||||
_txt(c, 0, 0, 60 * mm, 5 * mm, "Справ. №", font, 12)
|
_txt(c, 0, 0, 60 * mm, 5 * mm, "Справ. №", font, 12)
|
||||||
_txt(c, 60 * mm, 0, 60 * mm, 5 * mm, "Перв. примен.", font, 12)
|
_txt(c, 60 * mm, 0, 60 * mm, 5 * mm, "Перв. примен.", font, 12)
|
||||||
@@ -333,7 +367,7 @@ def draw_gost_frame(
|
|||||||
inner = Inner(page_w, page_h)
|
inner = Inner(page_w, page_h)
|
||||||
_draw_inner_border(c, inner)
|
_draw_inner_border(c, inner)
|
||||||
sx, sy, sw, sh = _draw_left_binding_strip(c, inner)
|
sx, sy, sw, sh = _draw_left_binding_strip(c, inner)
|
||||||
_draw_left_binding_text(c, sx, sy, inscriptions, font)
|
_draw_left_binding_text(c, inner, sx, sy, inscriptions, font)
|
||||||
|
|
||||||
if page == 1:
|
if page == 1:
|
||||||
_draw_top_left_strip(c, inner, inscriptions, doc_type, font)
|
_draw_top_left_strip(c, inner, inscriptions, doc_type, font)
|
||||||
|
|||||||
Reference in New Issue
Block a user