import type { Plan, PlanProduct } from '@/api/pl' import { applyPdfStableTableCellBorders } from '@/utils/pl-slip-pdf-render' /** 分装单打印默认公司信息(可在富文本中修改) */ export const SUBPACK_SLIP_DEFAULTS = { companyName: '安庆市山峡化工有限公司', receivingUnit: '安庆市山峡化工有限公司', companyAddress: '安庆市高新区霞虹路5号', companyPhone: '0556-5999710', contactPhone: '方总13395560066' } as const const DOC_FONT = "SimSun, 'Songti SC', serif" const FONT_TITLE = 'font-size:26px;font-weight:bold;' const FONT_BODY = 'font-size:20px;' const FONT_SIGN = 'font-size:14px;' const FONT_SIDE = 'font-size:18px;' const DOC_PADDING = '8px 10px 24px' /** 单据内容区最大宽度(编辑预览居中,略窄于 A4 像素宽) */ export const SUBPACK_SLIP_DOC_MAX_WIDTH = '960px' const DOC_WRAP_EXTRA = `max-width:${SUBPACK_SLIP_DOC_MAX_WIDTH};margin:0 auto;box-sizing:border-box;` const LOGO_HEIGHT = 23 const LOGO_LEFT = 50 const TITLE_STYLE = `${FONT_TITLE}font-weight:700 !important;letter-spacing:6px;line-height:1.35;` const TITLE_SUB_STYLE = `${TITLE_STYLE}margin-top:2px;letter-spacing:10px;` const TABLE_ROW_PADDING = '4px' /** 物料网格 padding(编辑器预览) */ const PRODUCT_GRID_CELL_PADDING = '8px 6px' const PRODUCT_GRID_TH_PADDING = '10px 6px' /** PDF 专用:padding 直接写在 td/th(html2canvas 对 flex/vertical-align 支持差,底部多留白) */ const PRODUCT_GRID_PDF_TD_PADDING = '8px 6px 12px 6px' const PRODUCT_GRID_PDF_TH_PADDING = '10px 6px 16px 6px' const PRODUCT_GRID_PDF_LINE_HEIGHT = '24px' /** PDF 专用:备注/条款/地址等左对齐合并单元格 */ const PRODUCT_FOOTER_PDF_PADDING = '10px 6px 16px 6px' const PRODUCT_FOOTER_PDF_LINE_HEIGHT = '1.35' /** 物料表格边框线宽(备注/条款等合并单元格,与网格一致便于 PDF 衔接) */ const PRODUCT_TABLE_BORDER = '0.3px solid #000' /** 物料明细网格线(与合同 PDF 一致:全边框 inline + 0.3px,html2canvas 渲染稳定) */ const PRODUCT_GRID_BORDER = '0.3px solid #000' /** 物料表格单元格:长文本自动换行 */ const PRODUCT_CELL_WRAP = 'white-space:normal;word-wrap:break-word;overflow-wrap:break-word;word-break:break-word;' const PRODUCT_GRID_CELL = `padding:${PRODUCT_GRID_CELL_PADDING};box-sizing:border-box;border:${PRODUCT_GRID_BORDER} !important;text-align:center;${FONT_BODY}line-height:normal;background-color:#fff !important;${PRODUCT_CELL_WRAP}` const PRODUCT_CELL = `padding:4px 6px;border:${PRODUCT_TABLE_BORDER} !important;text-align:center;${FONT_BODY}line-height:1.35;background-color:#fff !important;${PRODUCT_CELL_WRAP}` const PRODUCT_TH = `padding:${PRODUCT_GRID_TH_PADDING};box-sizing:border-box;border:${PRODUCT_GRID_BORDER} !important;text-align:center;${FONT_BODY}line-height:normal;font-weight:bold;background-color:#fff !important;${PRODUCT_CELL_WRAP}` const PRODUCT_TABLE_CELL_LEFT = `padding:10px 6px 14px 6px;border:${PRODUCT_TABLE_BORDER} !important;text-align:left;${FONT_BODY}line-height:1.35;vertical-align:top;background-color:#fff !important;` /** 条款单元格:行高随内容,避免被右侧印章区 min-height 撑出底部空白 */ const PRODUCT_TERMS_CELL_LEFT = `padding:10px 6px 14px 6px;border:${PRODUCT_TABLE_BORDER} !important;text-align:left;${FONT_BODY}line-height:1.35;vertical-align:top;background-color:#fff !important;` const TERMS_TEXT_STYLE = 'line-height:1.35;' const SEAL_BLOCK_LINE_STYLE = 'line-height:1.35;' /** 分装单印章:public/sxshzyz.png,定位在地址单元格右上角(相对原位置向上 100px) */ const SUBPACK_SLIP_SEAL_IMAGE_SRC = '/sxshzyz.png' const SUBPACK_SLIP_SEAL_TOP = -96 const SUBPACK_SLIP_SEAL_IMAGE_STYLE = `position:absolute;right:4px;top:${SUBPACK_SLIP_SEAL_TOP}px;width:140px;height:140px;opacity:0.85;z-index:10;` const HANDWRITE_BLANK_INNER = ' ' const HANDWRITE_BLANK = `(${HANDWRITE_BLANK_INNER})` const PLAIN_CELL = `border:none !important;padding:${TABLE_ROW_PADDING};${FONT_BODY}line-height:1.8;vertical-align:top;background:transparent !important;` const NO_BORDER = `${PLAIN_CELL} vertical-align:bottom;` /** 基本信息:label 与值同一行,值区域占满剩余宽度并带下划线 */ const INFO_ROW = `display:flex;align-items:flex-end;width:100%;box-sizing:border-box;` const INFO_LABEL = `white-space:nowrap;flex-shrink:0;padding-right:2px;` const INFO_UNDERLINE = '1px solid #000' const SIGN_UNDERLINE = '1px solid #000' /** 签字值下划线与文字间距(底部 padding 把 border-bottom 推离字模) */ const SIGN_VALUE_PADDING = '0 2px 6px 2px' const SIGN_VALUE_PDF_PADDING = '0 2px 8px 2px' const INFO_VALUE_INLINE_LEFT = `flex:1;min-width:0;box-sizing:border-box;border-bottom:${INFO_UNDERLINE} !important;padding:0 2px 2px;text-align:left;min-height:1.3em;` const INFO_VALUE_INLINE_CENTER = `flex:1;min-width:0;box-sizing:border-box;border-bottom:${INFO_UNDERLINE} !important;padding:0 2px 2px;text-align:center;min-height:1.3em;` const INFO_CELL_LEFT = `${NO_BORDER}text-align:left;` const INFO_CELL_RIGHT = `${NO_BORDER}text-align:left;` const INFO_GAP_BEFORE_PRODUCT = 24 const GAP_BEFORE_PRODUCT_CELL = `border:none !important;padding:0 !important;line-height:0 !important;font-size:0 !important;background:transparent !important;height:${INFO_GAP_BEFORE_PRODUCT}px !important;min-height:${INFO_GAP_BEFORE_PRODUCT}px !important;` const INFO_GAP_BEFORE_SIGN = 24 const GAP_BEFORE_SIGN_CELL = `border:none !important;padding:0 !important;line-height:0 !important;font-size:0 !important;background:transparent !important;height:${INFO_GAP_BEFORE_SIGN}px !important;min-height:${INFO_GAP_BEFORE_SIGN}px !important;` const SIDE_LABELS_COL_WIDTH = 36 /** 签字区下划线最小宽度 */ const SUBPACK_SLIP_SIGN_VALUE_MIN_WIDTH = '120px' function buildSubpackSlipSignItem(label: string, valueContent: string, minWidth: string = SUBPACK_SLIP_SIGN_VALUE_MIN_WIDTH): string { return `${label}${valueContent}` } function buildSubpackSlipSignRowHtml(): string { return `
]*>([\s\S]*?)<\/p>$/i, '$1') .trim() return plain || ' ' } function formatDateIso(value?: string | Date | null): string { const date = value instanceof Date ? value : value ? new Date(value) : new Date() if (Number.isNaN(date.getTime())) return '' const y = date.getFullYear() const m = String(date.getMonth() + 1).padStart(2, '0') const d = String(date.getDate()).padStart(2, '0') return `${y}-${m}-${d}` } /** 分装单默认下单日期(当天 YYYY-MM-DD) */ export function formatSubpackSlipDateIso(value?: string | Date | null): string { return formatDateIso(value) } function buildSubpackSlipCompleteCheckHtml(): string { return `` } const SUBPACK_SLIP_PRODUCT_MIN_ROWS = 5 function buildSubpackSlipProductRow( rowIndex: number, product: PlanProduct | undefined, ctx?: SubpackSlipRenderContext ): string { if (product) { const qty = product.outboundQty ?? product.outboundEstimateQty ?? product.quantity ?? '' return `