Odoo pdf 报告对html结构的要求 - xiaohao0576/odoo-doc GitHub Wiki

源码地址

函数名称: _prepare_html(self, html, report_model=False):

https://github.com/odoo/odoo/blob/61782d7163be2f6e277dba519bce5a059e788d57/odoo/addons/base/models/ir_actions_report.py#L367

函数的作用

该函数旨在从一个完整的HTML文档中提取出页眉(header)、页脚(footer)和多个报告主体(body),并将它们重新组织,以便于 wkhtmltopdf 工具进行批量处理。它通过查找特定的CSS类来识别这些部分。

    '''Divide and recreate the header/footer html by merging all found in html.
    The bodies are extracted and added to a list. Then, extract the specific_paperformat_args.
    The idea is to put all headers/footers together. Then, we will use a javascript trick
    (see minimal_layout template) to set the right header/footer during the processing of wkhtmltopdf.
    This allows the computation of multiple reports in a single call to wkhtmltopdf.

    :param html: The html rendered by render_qweb_html.
    :type: bodies: list of string representing each one a html body.
    :type header: string representing the html header.
    :type footer: string representing the html footer.
    :type specific_paperformat_args: dictionary of prioritized paperformat values.
    :return: bodies, header, footer, specific_paperformat_args
    '''

对HTML标签和class的要求

html根元素

  1. 整个HTML内容应该由一个根HTML元素包裹,通常是 <html>
  2. 根元素上可以有以 data-report- 开头的属性,这些属性会被收集到 specific_paperformat_args 字典中,用于覆盖纸张格式设置。

主体容器

所有报告的主体内容应该包含在

标签中。如果找不到 标签,函数会尝试将根元素的所有子元素作为主体内容。例如
<main>...</main>

页眉 (Header)

  • 页眉内容应该包含在一个
    或其他块级元素中,并带有 header 类。
  • 如果存在多个带有 header 类的元素,它们将被合并到一个 #minimal_layout_report_headers 的 div 中。
  • header内容,会放到web.minimal_layout的body中,渲染成一个完整的html文档,最终放到wkhtmltopdf的 --header-html后面
  • <div class="header">
        <h1>报告标题</h1>
        <img src="/logo.png" alt="Logo">
    </div>
    

    页脚 (Footer)

    • 页脚内容应该包含在一个
      或其他块级元素中,并带有 footer 类。
    • 如果存在多个带有 footer 类的元素,它们将被合并到一个 #minimal_layout_report_footers 的 div 中。
    • footer内容,会放到web.minimal_layout的body中,渲染成一个完整的html文档,最终放到wkhtmltopdf的 --footer-html后面
    • <div class="footer">
          <p>页码:<span class="page"></span> / <span class="topage"></span></p>
          <p>版权所有 &copy; 2025</p>
      </div>
      

      报告主体 (Article/Body)

      • 每个独立的报告主体应该包含在一个 或其他块级元素中,并带有 article 类。
      • 重要属性:

      data-oe-lang: 可选,用于设置该报告主体的语言上下文。

      data-oe-model: 可选,如果提供且与 report_model 参数匹配,则会收集 data-oe-id。

      data-oe-id: 可选,当 data-oe-model 匹配时,会收集其整数值。

      单个报告示例

      <article class="article" data-oe-lang="zh_CN" data-oe-model="res.partner" data-oe-id="123">
          <h2>客户信息</h2>
          <p>姓名:张三</p>
          <p>地址:北京市</p>
      </article>
      

      多个报告示例

      <article class="article" data-oe-lang="en_US" data-oe-model="product.product" data-oe-id="1">
          <h3>Product A</h3>
          <p>Price: $100</p>
      </article>
      
      <article class="article" data-oe-lang="en_US" data-oe-model="product.product" data-oe-id="2">
          <h3>Product B</h3>
          <p>Price: $150</p>
      </article>
      

      示例html

      <html data-report-dpi="96" data-report-orientation="Portrait">
      <head>
          <title>我的报告</title>
      </head>
      <body>
          <div class="header">
              <h1>Odoo 报告</h1>
          </div>
      
          <main>
              <article class="article" data-oe-lang="zh_CN" data-oe-model="your.report.model" data-oe-id="1">
                  <h2>报告主体 1</h2>
                  <p>这是第一个报告的正文内容。</p>
                  <ul>
                      <li>列表项 1</li>
                      <li>列表项 2</li>
                  </ul>
              </article>
      
              <article class="article" data-oe-lang="en_US" data-oe-model="your.report.model" data-oe-id="2">
                  <h2>Report Body 2</h2>
                  <p>This is the content of the second report.</p>
                  <ol>
                      <li>Item A</li>
                      <li>Item B</li>
                  </ol>
              </article>
      
              </main>
      
          <div class="footer">
              <p>页脚内容 - 第 <span class="page"></span> 页,共 <span class="topage"></span> 页</p>
          </div>
      </body>
      </html>
      
⚠️ **GitHub.com Fallback** ⚠️