feat(web-admin): add mobile print preview for transport plan slips.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
wuzilongandCursor committed 2026-09-14 16:47:12 +08:00
1 parent bc7a1c225a
commit 866a87f747
2 files changed
+266 -9

No files matched your search

+127
View File
@@ -0,0 +1,127 @@
import { fetchProductDetail } from '@/api/crm/product'
import { planApi, type Plan } from '@/api/pl'
import { useDictStore } from '@/store/modules/dict'
import { useUserStore } from '@/store/modules/user'
import { applyDeliveryCustomerToPlan } from '@/utils/pl-delivery-slip-print'
import {
generateDeliverySlipTemplate,
renderBlankDeliverySlipHtml,
replaceDeliverySlipPlaceholders
} from '@/utils/pl-delivery-slip-template'
import {
generateInboundSlipTemplate,
renderBlankInboundSlipHtml,
replaceInboundSlipPlaceholders
} from '@/utils/pl-inbound-slip-template'
import {
formatSubpackSlipDateIso,
generateSubpackSlipTemplate,
renderBlankSubpackSlipHtml,
replaceSubpackSlipPlaceholders
} from '@/utils/pl-subpack-slip-template'
export type MpPlanPrintKind =
| 'inbound'
| 'delivery'
| 'subpack'
| 'blank-inbound'
| 'blank-delivery'
| 'blank-subpack'
async function loadProductCodeContext(plan: Plan) {
const dictStore = useDictStore()
await dictStore.loadAllDict()
const productIds = [
...new Set(
(plan.products || []).map((item) => String(item.productId || '').trim()).filter(Boolean)
)
]
const productCodeById: Record<string, string> = {}
await Promise.all(
productIds.map(async (productId) => {
try {
const res = await fetchProductDetail({ id: productId })
const data = (res as { data?: { productNo?: string }; productNo?: string }).data ?? res
const productNo = String((data as { productNo?: string }).productNo || '').trim()
if (productNo) productCodeById[productId] = productNo
} catch {
// 单个产品查询失败时保留计划明细中的冗余字段
}
})
)
return {
productCodeById,
getUnitLabel: (unitCode: string) => dictStore.getLabel('crm_product_unit', unitCode) || unitCode
}
}
async function loadSavedTemplate(
loader: (id: string) => Promise<unknown>,
id: string,
fallback: () => string
) {
try {
const templateRes = await loader(id)
const saved = (templateRes as { data?: string }).data ?? templateRes
if (typeof saved === 'string' && saved.trim()) return saved
} catch {
// 无模板时用默认
}
return fallback()
}
export async function buildMpPlanPrintHtml(
kind: MpPlanPrintKind,
plan: Plan,
options?: { customerId?: string }
): Promise<string> {
if (kind === 'blank-inbound') return renderBlankInboundSlipHtml()
if (kind === 'blank-delivery') return renderBlankDeliverySlipHtml()
if (kind === 'blank-subpack') return renderBlankSubpackSlipHtml()
const id = String(plan.id || '').trim()
if (!id) throw new Error('无法获取计划ID')
if (kind === 'inbound') {
const htmlContent = await loadSavedTemplate(
(planId) => planApi.getInboundSlipTemplate(planId),
id,
() => generateInboundSlipTemplate(plan)
)
const ctx = await loadProductCodeContext(plan)
return replaceInboundSlipPlaceholders(htmlContent, plan, ctx)
}
if (kind === 'delivery') {
let view = plan
const customerId = String(options?.customerId || '').trim()
if (customerId) view = applyDeliveryCustomerToPlan(plan, customerId)
const htmlContent = await loadSavedTemplate(
(planId) => planApi.getDeliverySlipTemplate(planId),
id,
() => generateDeliverySlipTemplate(view)
)
const ctx = await loadProductCodeContext(view)
return replaceDeliverySlipPlaceholders(htmlContent, view, ctx)
}
const slipNoRes = await planApi.ensureSubpackSlipNo(id)
const subpackSlipNo = String((slipNoRes as { data?: string }).data ?? slipNoRes ?? '').trim()
const htmlContent = await loadSavedTemplate(
(planId) => planApi.getSubpackSlipTemplate(planId),
id,
() => generateSubpackSlipTemplate(plan)
)
const dictStore = useDictStore()
const userStore = useUserStore()
await dictStore.loadAllDict()
const userInfo = userStore.getUserInfo as { realName?: string; userName?: string } | null
const loginUserName = String(userInfo?.realName || userInfo?.userName || '').trim()
return replaceSubpackSlipPlaceholders(htmlContent, plan, {
getUnitLabel: (unitCode: string) => dictStore.getLabel('crm_product_unit', unitCode) || unitCode,
subpackSlipNo,
orderDate: formatSubpackSlipDateIso(),
orderUser: loginUserName,
preparerUser: loginUserName
})
}