You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Prawn Gem渲染动态页眉时report_date不更新的问题

Prawn Gem 页眉日期不更新问题修复

问题根源

你在render_page方法里使用了pdf.repeat(:all, dynamic: true),但这个方法的作用是为所有页面添加重复渲染的内容。当循环处理每个页面时,每次调用render_page都会重新定义这个repeat块,后面的定义会覆盖前面的,最终所有页面的页眉都会使用最后一次循环传入的report_date值。

快速修复方案

去掉repeat(:all)逻辑,直接在每个页面创建时渲染页眉页脚即可——毕竟你本来就是逐个循环生成页面的:

修改后的完整代码

def render_pages(pdf)
  grouped_items = rows.group_by { |item| item[0] }

  grouped_items.each_with_index do |(report_date, booking_items), index|
    render_page(pdf, report_date, booking_items)
    pdf.start_new_page unless index == grouped_items.size - 1
  end
end

# 渲染单页PDF
#
# @param pdf [Prawn::Document] PDF对象
def render_page(pdf, report_date, booking_items)
  # 直接渲染当前页面页眉
  pdf.bounding_box([pdf.bounds.left, pdf.bounds.top], width: pdf.bounds.width) do
    render_header(pdf, report_date, organisation_name)
  end
  # 直接渲染当前页面页脚
  pdf.bounding_box([pdf.bounds.left, pdf.bounds.bottom + 150 ], width: pdf.bounds.width) do
    render_footer(pdf)
  end
  render_body(pdf, report_date , booking_items)
end

def render_header(pdf, report_date, organisation_name)
  pdf.image open("https://s3.amazonaws.com/www-inside-design/uploads/2019/05/woolmarkimagelogo-1024x576.png"), width: 80, height: 80, position: :center
  pdf.text "HEY #{report_date}"
  pdf.table(
    [
      ["#{"Sumanth Samala PVT LTD"} - #{format_report_date(report_date)} \n Attendance Register", "Customer to complete all sections below \n Generated on #{Time.now.strftime("%d/%m/%Y %H:%M")}"]
    ],
    width: pdf.bounds.width,
    row_colors: ["808080"],
    cell_style: header_cell_style
  ) do |table|
    table.column(0).width = 464
  end
end

进阶方案(保留repeat逻辑)

如果需要后续新增页面也自动带页眉页脚,可以把所有日期提前存入数组,结合页码动态获取对应日期:

def render_pages(pdf)
  grouped_items = rows.group_by { |item| item[0] }
  @report_dates = grouped_items.keys # 提前存储所有页面的日期

  # 只定义一次repeat块
  pdf.repeat(:all, dynamic: true) do
    pdf.bounding_box([pdf.bounds.left, pdf.bounds.top], width: pdf.bounds.width) do
      current_date = @report_dates[pdf.page_number - 1] # 页码从1开始,数组索引从0开始
      render_header(pdf, current_date, organisation_name)
    end
    pdf.bounding_box([pdf.bounds.left, pdf.bounds.bottom + 150 ], width: pdf.bounds.width) do
      render_footer(pdf)
    end
  end

  # 循环渲染页面主体内容
  grouped_items.each_with_index do |(report_date, booking_items), index|
    render_body(pdf, report_date , booking_items)
    pdf.start_new_page unless index == grouped_items.size - 1
  end
end

内容的提问来源于stack exchange,提问作者Samala Sumanth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 16:05:20