## 02_print_spec.md # 印刷・PDF出力 共通仕様書 **保存先**: `/backoffice/docs/02_print_spec.md` **対象**: 全担当(会計・案件管理・その他すべての印刷対応ファイル) --- ## 1. 基本方針 - 全出力は `generate_pdf.php`(mPDF)経由に一本化する - ブラウザの `window.print()` は使用しない - 渡す相手がファイリングすることを前提に、綴じ側に十分なクリアランスを確保する - PDF出力(データ納品)と紙印刷(片面・両面)でノド余白・センタリングが異なる - 縦出力・横出力でノド側の方向が変わる(下記参照) --- ## 2. 余白設定 ### 2.1 縦出力(A4縦・左綴じ) | モード | 天 | 地 | 左 | 右 | |--------|----|----|----|----| | PDF出力 | 20mm | 10mm | 15mm | 15mm | | 片面印刷 | 20mm | 10mm | 25mm(ノド) | 10mm | | 両面印刷・奇数ページ | 20mm | 10mm | 25mm(ノド) | 10mm | | 両面印刷・偶数ページ | 20mm | 10mm | 10mm | 25mm(ノド) | ### 2.2 横出力(A4横・天綴じ) | モード | 天 | 地 | 左 | 右 | |--------|----|----|----|----| | PDF出力 | 20mm | 10mm | 15mm | 15mm | | 片面印刷 | 25mm(ノド) | 10mm | 15mm | 15mm | | 両面印刷・奇数ページ | 25mm(ノド) | 10mm | 15mm | 15mm | | 両面印刷・偶数ページ | 10mm | 25mm(ノド) | 15mm | 15mm | --- ## 3. コンテンツ配置 ### 3.1 PDF出力 - コンテンツは余白内で左右センタリングして配置する - `generate_pdf.php` のHEADER_CSSで `.ledger-table { margin-left: auto; margin-right: auto; }` 等を注入して制御する - 各HTMLファイルで配置指定は不要 ### 3.2 片面印刷・両面印刷 - コンテンツは左寄り(ノド側25mmの余白内に収まる位置)に配置される - mPDFが余白設定に従って自動配置するため、各HTMLファイルで配置指定は不要 --- ## 4. フォント | 用途 | フォント | |------|---------| | 印刷・PDF出力 | IPAex明朝(ipaexm.ttf) | | 画面表示 | Inter(既存テーマ) | - mPDFでは游明朝は使用不可のためIPAex明朝を使用する - フォント設定は `generate_pdf.php` 側で制御する。各HTMLファイルの `@media print` に `font-family` を記載しても構わないが、mPDF出力には影響しない --- ## 5. 書類種別ごとの用紙・綴じ方向 | 書類 | 用紙 | 綴じ | |------|------|------| | 総勘定元帳 | A4縦 | 左綴じ | | 損益計算書 | A4縦 | 左綴じ | | 貸借対照表 | A4縦 | 左綴じ | | 試算表 | A4縦 | 左綴じ | | 消費税申告書 | A4縦 | 左綴じ | | 確定申告 | A4縦 | 左綴じ | | 法人税申告 | A4縦 | 左綴じ | | 案件報告書 | A4縦 | 左綴じ(予定) | | 現場写真報告書 | A4横 | 天綴じ(予定) | | ドラレコ画像報告書 | A4横 | 天綴じ(予定) | --- ## 6. 各書類固有の仕様 書類ごとの詳細仕様は各設計書を参照すること。 | 書類 | 設計書 | |------|--------| | 総勘定元帳 | `docs/07_accounting/05_tax_return.md` | | その他会計書類 | `docs/07_accounting/05_tax_return.md` | | 案件関連書類 | `docs/04_business_flow/case_management/10_case_export.md` | --- ## 7. 出力ボタンの実装方針 全書類で以下の3ボタンを実装すること。 | ボタン | 関数 | 用途 | |--------|------|------| | PDF出力 | `printPDF()` | データ納品・画面閲覧用。左右センタリング | | 片面印刷 | `printSingle()` | 紙納品(片面)。左ノド25mm | | 両面印刷 | `printDuplex()` | 紙納品(両面)。左右ノド振り分け | ```html ``` 全書類は `/common/js/print.js` を読み込んで使用すること(個別実装禁止)。 ```html ``` --- ## 8. 実装上の注意事項(全担当共通) ### 8.1 出力処理の仕組み 全出力は `print.js` → `generate_pdf.php`(mPDF)経由で行う。 ``` ボタン押下 → print.js の printPDF() / printSingle() / printDuplex() が呼ばれる → _buildPrintHtml() でHTMLを組み立て → generate_pdf.php にPOSTリクエスト → mPDFがPDFを生成してダウンロード ``` ### 8.2 HTMLの組み立てルール(_buildPrintHtml) - `@media print { }` ブロック内のCSSを抽出してmPDFに渡す - 印刷対象コンテナは `id="ledgerContent"` をデフォルトとし、`window._printTargetId` で上書き可 - 各HTMLファイルの `@media print` CSSはmPDFに渡るため、mPDFで動作しない記述は使用しないこと **mPDFで使用禁止のCSS:** | 禁止 | 理由 | |------|------| | `display: flex` / `display: grid` | mPDFは非対応 | | `position: fixed` / `position: absolute` | mPDFでレイアウト崩れ | | `:first-of-type` / `:last-of-type` 疑似クラス | mPDF非対応・空白ページが生成される | | `:first-child` / `:last-child` をHEADER_CSSで使用 | mPDFの優先順位が予期しない動作をする | | `margin: 0 auto`(テーブル等のセンタリング) | Chrome依存。PDFのセンタリングは `generate_pdf.php` のHEADER_CSSで制御する | **mPDFで使用可能なCSS:** | 使用可 | 備考 | |--------|------| | `page-break-after: always` | ページ区切りに使用。mPDFでも正常動作する標準プロパティ | | `page-break-before: always` | 同上 | | `width` / `height`(mm単位) | mPDFはmm単位を正しく解釈する | | `border` / `padding`(pt単位) | 正常動作 | ### 8.3 ページ末罫線のルール ページをまたぐテーブルの最終行(繰越行等)の `border-bottom` は、外枠と同じ太さ・色を明示指定すること。指定しない場合、データ行の細線が継承されてページ末の外枠が細くなる。 ```css .carryover-row td { border-bottom: 0.75pt solid #000 !important; } ``` ### 8.4 コンテンツサイズのルール(全書類共通) 印刷ページは以下のサイズの固定divとして出力する。borderなし・backgroundなし(不可視)。 | 出力方向 | 大枠div(不可視) | コンテンツ最大幅・高さ(太枠含む) | |---------|-----------------|----------------------------------| | 縦(A4縦) | H267mm × W175mm | H266mm × W174mm | | 横(A4横) | H175mm × W267mm | H174mm × W266mm | - コンテンツ最大幅・高さは大枠より各辺0.5mm内側。テーブル外枠などはこの寸法の外周に引くこと - コンテンツの左右配置は `generate_pdf.php` が自動制御する。各HTMLファイルで `margin: 0 auto` 等の配置指定は不要 - 大枠サイズ・コンテンツ最大幅はファイリング時の有効面確保のため変更禁止 ### 8.5 両面印刷時の空白ページ挿入 - 両面印刷で空白ページ挿入が必要な書類(総勘定元帳等)は、各HTMLファイルで制御すること - `printDuplex()` 呼び出し前に空白ページを挿入し、呼び出し後に削除する - `print.js` の `printDuplex()` 側では空白ページに関与しない ```javascript // 実装例(各HTMLファイル内) function myPrintDuplex() { applyBlankPages(); // 空白ページ挿入 printDuplex(); // mPDF出力 removeBlankPages(); // 空白ページ削除(非同期に注意) } ``` **注意**:`printDuplex()` はfetchを使った非同期処理のため、`removeBlankPages()` は `printDuplex()` のPromise完了後に実行すること。現状の `ledger.html` では `printDuplex()` 完了を待たずに削除しているが、PDFはサーバー側で生成されるためDOM上の空白ページはPDF生成後に削除する形でよい。 --- ## 9. print.js 仕様 **保存先**:`/backoffice/common/js/print.js` **読込方法**:全印刷対応HTMLファイルの `` 直前に記述 ```html ``` ### 9.1 提供する関数 | 関数 | モード | 用途 | |------|--------|------| | `printPDF()` | pdf | PDF出力(天20mm 地10mm 左右15mm均等・センタリング) | | `printSingle()` | single | 片面印刷(天20mm 地10mm 左25mm 右10mm) | | `printDuplex()` | duplex | 両面印刷(天20mm 地10mm 奇数左25mm/右10mm 偶数左10mm/右25mm) | ### 9.2 実装内容 ```javascript // /common/js/print.js // 全出力は generate_pdf.php(mPDF)経由 function _buildPrintHtml() { var targetId = window._printTargetId || 'ledgerContent'; var target = document.getElementById(targetId); var bodyHtml = target ? target.outerHTML : document.body.innerHTML; var printCss = ''; var styleNodes = document.querySelectorAll('style'); styleNodes.forEach(function(node) { printCss += _extractPrintCss(node.textContent); }); return '' + '' + '' + bodyHtml + ''; } function _postPrint(mode) { var orientation = window._printOrientation || 'portrait'; var html = _buildPrintHtml(); fetch('/master/api/generate_pdf.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ mode: mode, orientation: orientation, html: html }) }) .then(function(res) { if (!res.ok) { throw new Error('PDF生成に失敗しました'); } return res.blob(); }) .then(function(blob) { var url = URL.createObjectURL(blob); var a = document.createElement('a'); a.href = url; a.download = 'output.pdf'; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); }) .catch(function(err) { console.error('printError:', err); }); } function printPDF() { _postPrint('pdf'); } function printSingle() { _postPrint('single'); } function printDuplex() { _postPrint('duplex'); } ``` ### 9.3 横出力書類の対応 横出力が必要な書類は、各HTMLファイル内で `window._printOrientation = 'landscape'` を設定すること。 ```javascript // 横出力書類のHTMLファイル内で設定 window._printOrientation = 'landscape'; ``` --- ## 10. generate_pdf.php 仕様概要 **保存先**:`/backoffice/master/api/generate_pdf.php` **詳細設計**:`docs/08_pdf_engine/00_handover.md` 参照 | パラメータ | 値 | 説明 | |-----------|-----|------| | mode | pdf / single / duplex | 出力モード | | orientation | portrait / landscape | 用紙向き | | html | string | 出力するHTML | - 余白・センタリングはすべて `generate_pdf.php` 側で制御する - フォント:IPAex明朝(ipaexm.ttf) - mPDFで動作しないCSS(flex・grid・position:fixed等)は `generate_pdf.php` のHEADER_CSSで上書きまたは無効化する --- ## 11. 改訂履歴 | 日付 | 版 | 担当 | 内容 | 理由・影響範囲 | |------|----|------|------|--------------| | 2026-03-22 | 1.0 | 全体管理者 | 初版作成 | 印刷・PDF出力共通仕様を全担当共通の設計書として独立 | | 2026-03-22 | 1.1 | 会計担当 | 余白を全面改訂 | 総勘定元帳175mm幅に合わせた最小余白に統一 | | 2026-03-23 | 1.2 | 会計担当 | 8節・9節新設。@page定義・margin collapse対策・print.js仕様を追加 | ledger.html実装時の印刷不具合を横展開 | | 2026-03-23 | 1.3 | 会計担当(5代目) | 大枠サイズ(縦H267×W175・横H175×W267)を全書類共通仕様として明記 | 横出力大枠サイズ確定に伴う反映 | | 2026-03-23 | 1.4 | 会計担当(5代目) | 8.3節(テーブルのセンタリング)を削除 | margin:0 autoの禁止事項と矛盾するため | | 2026-03-27 | 1.5 | 会計担当(8代目) | @page CSS直書きを禁止しprint.js動的挿入に一本化。PDF余白修正 | Chrome印刷とprintPaper()の競合判明 | | 2026-03-28 | 1.6 | 会計担当 | printSingle/printDuplexに分離。@pageにsize:A4を追加 | 片面印刷需要対応 | | 2026-04-02 | 1.7 | PDFエンジン担当(3代目) | 8.4節改訂。コンテンツ最大幅(縦H266×W174・横H174×W266)を明記 | mPDF出力検証で太枠はみ出し問題を確認 | | 2026-04-02 | 2.1 | PDFエンジン担当(3代目) | 8.2節を改訂。mPDF使用禁止CSS・使用可能CSSの一覧表を追加。`:first-of-type`/`:last-of-type`/`:first-child`/`:last-child`のHEADER_CSS使用禁止を明記。`page-break-after/before: always`はmPDFでも正常動作する標準プロパティとして明記 | ledger.html調査でmPDFのCSS対応状況を確認。Chrome依存疑似クラスが空白ページ生成の原因と判明。全担当が誤ったCSSを書かないよう明文化 |