feat(pl): add blank HTML renderers for inbound and delivery slips

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
zlwuandCursor committed 2026-08-22 11:23:50 +08:00
1 parent 7ebe635fca
commit 3ec188666c
2 files changed
+87 -17

No files matched your search

@@ -168,11 +168,31 @@ function formatDeliverySlipProductGridCellContent(content: string): string {
return plain || '&nbsp;'
}
/** 空白单据物料空行数(与分装单最小行数对齐) */
export const BLANK_SLIP_PRODUCT_MIN_ROWS = 5
function buildBlankDeliveryProductRow(): string {
const cells = Array.from({ length: 8 })
.map(
() =>
`<td class="delivery-slip-product-cell delivery-slip-product-grid-cell" style="${PRODUCT_GRID_CELL}">&nbsp;</td>`
)
.join('\n ')
return `<tr>\n ${cells}\n </tr>`
}
function buildProductRows(
products: PlanProduct[] = [],
planNo = '',
ctx?: DeliverySlipRenderContext
ctx?: DeliverySlipRenderContext,
options?: { blank?: boolean }
): string {
if (options?.blank) {
return Array.from({ length: BLANK_SLIP_PRODUCT_MIN_ROWS })
.map(() => buildBlankDeliveryProductRow())
.join('')
}
if (!products.length) {
return `<tr><td class="delivery-slip-product-cell" colspan="8" style="${PRODUCT_CELL}">暂无产品信息</td></tr>`
}
@@ -449,7 +469,7 @@ export const DELIVERY_SLIP_PRINT_CSS = `
min-height: 0 !important;
height: auto !important;
}
.delivery-slip-doc .delivery-slip-seal-block img[alt="印章"] {
.delivery-slip-doc .delivery-slip-seal-block .delivery-slip-seal-img {
position: absolute !important;
right: 4px !important;
top: ${DELIVERY_SLIP_SEAL_TOP}px !important;
@@ -571,7 +591,7 @@ export const DELIVERY_SLIP_STYLE_BLOCK = `<style type="text/css">${DELIVERY_SLIP
/** 生成公司印章 HTML(地址/电话单元格右上角) */
export function buildDeliverySlipCompanySealHtml(): string {
return `<img src="${DELIVERY_SLIP_SEAL_IMAGE_SRC}" alt="印章" style="${DELIVERY_SLIP_SEAL_IMAGE_STYLE}" />`
return `<img class="delivery-slip-seal-img" src="${DELIVERY_SLIP_SEAL_IMAGE_SRC}" alt="印章" style="${DELIVERY_SLIP_SEAL_IMAGE_STYLE}" />`
}
const SEAL_BLOCK = `<div class="delivery-slip-seal-block" style="position:relative;padding:0;${FONT_BODY}${SEAL_BLOCK_LINE_STYLE}">
@@ -1790,23 +1810,26 @@ function normalizeDeliverySlipSideLabelsPlaceholder(html: string): string {
export function replaceDeliverySlipPlaceholders(
htmlContent: string,
plan: Plan,
ctx?: DeliverySlipRenderContext
ctx?: DeliverySlipRenderContext,
options?: { blank?: boolean }
): string {
if (!htmlContent || !plan) return htmlContent
const isBlank = options?.blank === true
const replacements: Record<string, string> = {
'{{companyName}}': DELIVERY_SLIP_DEFAULTS.companyName,
'{{receivingUnit}}': buildReceivingUnit(plan),
'{{planNo}}': plan.planNo || '',
'{{receivingUnit}}': isBlank ? '' : buildReceivingUnit(plan),
'{{planNo}}': isBlank ? '' : plan.planNo || '',
'{{receiveContact}}': '',
'{{driverInfo}}': '',
'{{planDateChinese}}': formatPlanDateChinese(plan.planDate),
'{{productTable}}': buildProductRows(plan.products, plan.planNo || '', ctx),
'{{remark}}': formatRemarkForSlipHtml(plan.remark),
'{{planDateChinese}}': isBlank ? '' : formatPlanDateChinese(plan.planDate),
'{{productTable}}': buildProductRows(plan.products, plan.planNo || '', ctx, options),
'{{remark}}': isBlank ? '' : formatRemarkForSlipHtml(plan.remark),
'{{companyAddress}}': DELIVERY_SLIP_DEFAULTS.companyAddress,
'{{companyPhone}}': DELIVERY_SLIP_DEFAULTS.companyPhone,
'{{contactPhone}}': DELIVERY_SLIP_DEFAULTS.contactPhone,
'{{companySeal}}': buildDeliverySlipCompanySealHtml(),
'{{companySeal}}': isBlank ? '' : buildDeliverySlipCompanySealHtml(),
'{{sideLabels}}': buildDeliverySlipSideLabelsHtml()
}
@@ -1841,6 +1864,18 @@ export function replaceDeliverySlipPlaceholders(
return result
}
export function renderBlankDeliverySlipHtml(): string {
const blankPlan = {
id: '',
planNo: '',
products: [],
customerName: '',
remark: ''
} as Plan
const html = generateDeliverySlipTemplate(blankPlan)
return replaceDeliverySlipPlaceholders(html, blankPlan, undefined, { blank: true })
}
/** 保存模板前:将动态字段还原为占位符 */
export function restoreDeliverySlipPlaceholders(template: string, plan: Plan): string {
let result = template
@@ -166,11 +166,31 @@ function formatInboundSlipProductGridCellContent(content: string): string {
return plain || '&nbsp;'
}
/** 空白单据物料空行数(与分装单最小行数对齐) */
export const BLANK_SLIP_PRODUCT_MIN_ROWS = 5
function buildBlankInboundProductRow(): string {
const cells = Array.from({ length: 8 })
.map(
() =>
`<td class="inbound-slip-product-cell inbound-slip-product-grid-cell" style="${PRODUCT_GRID_CELL}">&nbsp;</td>`
)
.join('\n ')
return `<tr>\n ${cells}\n </tr>`
}
function buildProductRows(
products: PlanProduct[] = [],
planNo = '',
ctx?: InboundSlipRenderContext
ctx?: InboundSlipRenderContext,
options?: { blank?: boolean }
): string {
if (options?.blank) {
return Array.from({ length: BLANK_SLIP_PRODUCT_MIN_ROWS })
.map(() => buildBlankInboundProductRow())
.join('')
}
if (!products.length) {
return `<tr><td class="inbound-slip-product-cell" colspan="8" style="${PRODUCT_CELL}">暂无产品信息</td></tr>`
}
@@ -1354,19 +1374,22 @@ function normalizeInboundSlipSideLabelsPlaceholder(html: string): string {
export function replaceInboundSlipPlaceholders(
htmlContent: string,
plan: Plan,
ctx?: InboundSlipRenderContext
ctx?: InboundSlipRenderContext,
options?: { blank?: boolean }
): string {
if (!htmlContent || !plan) return htmlContent
const isBlank = options?.blank === true
const replacements: Record<string, string> = {
'{{companyName}}': INBOUND_SLIP_DEFAULTS.companyName,
'{{receivingUnit}}': buildDeliveryUnit(plan),
'{{planNo}}': plan.planNo || '',
'{{receivingUnit}}': isBlank ? '' : buildDeliveryUnit(plan),
'{{planNo}}': isBlank ? '' : plan.planNo || '',
'{{receiveContact}}': '',
'{{driverInfo}}': '',
'{{planDateChinese}}': formatPlanDateChinese(plan.planDate),
'{{productTable}}': buildProductRows(plan.products, plan.planNo || '', ctx),
'{{remark}}': formatRemarkForSlipHtml(plan.remark),
'{{planDateChinese}}': isBlank ? '' : formatPlanDateChinese(plan.planDate),
'{{productTable}}': buildProductRows(plan.products, plan.planNo || '', ctx, options),
'{{remark}}': isBlank ? '' : formatRemarkForSlipHtml(plan.remark),
'{{companyAddress}}': INBOUND_SLIP_DEFAULTS.companyAddress,
'{{companyPhone}}': INBOUND_SLIP_DEFAULTS.companyPhone,
'{{contactPhone}}': INBOUND_SLIP_DEFAULTS.contactPhone,
@@ -1405,6 +1428,18 @@ export function replaceInboundSlipPlaceholders(
return result
}
export function renderBlankInboundSlipHtml(): string {
const blankPlan = {
id: '',
planNo: '',
products: [],
customerName: '',
remark: ''
} as Plan
const html = generateInboundSlipTemplate(blankPlan)
return replaceInboundSlipPlaceholders(html, blankPlan, undefined, { blank: true })
}
/** 保存模板前:将动态字段还原为占位符 */
export function restoreInboundSlipPlaceholders(template: string, plan: Plan): string {
let result = template