fix(发票): 订单详情以申请表为开票状态真源并兼容旧字段名

开票状态/票号/开票时间以申请表为准,快照仅补展示字段;详情契约统一 title/tax_number,兼容历史订单 name/duty_number(后端归一+移动端卡片双兜底)
This commit is contained in:
吴昊天 2026-10-21 11:49:15 +08:00
parent eab07f2f04
commit de8fe8d87f
2 changed files with 59 additions and 7 deletions

View File

@ -454,9 +454,13 @@ class OrderCenterServices extends BaseService implements OrderCenterSyncInterfac
$detail['custom_form'] = $this->parseExtraInfo($detail['custom_form']);
$detail['custom_form'] = $this->transformCustomForm($detail['custom_form']);
}
// 解析发票信息
// 解析发票信息:中台 invoice 仅是下单时抬头快照,不含开票状态;
// 开票状态(is_invoice/票号/开票时间)以申请表 eb_order_invoice 为真源,后台开票只写该表
$invoiceSnapshot = [];
if (!empty($detail['invoice'])) {
$detail['invoice'] = $this->parseExtraInfo($detail['invoice']);
// 中台订单创建时保存的是用户发票原始字段(name/duty_number),
// 详情契约统一使用 title/tax_number,避免前端因数据来源不同而漏显示。
$invoiceSnapshot = $this->normalizeInvoice($this->parseExtraInfo($detail['invoice']));
}
// 支付方式从 eb_pay_channel 读取中文名称
$detail['pay_type_name'] = $this->getPayTypeName($detail['pay_type']);
@ -465,9 +469,13 @@ class OrderCenterServices extends BaseService implements OrderCenterSyncInterfac
// 必须在构建时间线、按钮、进度条之前调用,确保这些字段基于实时状态
$this->loadSourceOrderInfo($detail);
// 发票信息:order_center.invoice 字段为空时,从发票申请表查询
if (empty($detail['invoice'])) {
$detail['invoice'] = $this->loadOrderInvoice((int)$detail['id']);
// 发票信息:优先取申请表(含开票状态),无申请记录时回退下单快照
$invoiceLive = $this->loadOrderInvoice((int)$detail['id']);
if (!empty($invoiceLive)) {
// 快照可补齐申请表未存的展示字段,但状态类字段必须以申请表为准
$detail['invoice'] = array_merge($invoiceSnapshot, $invoiceLive);
} else {
$detail['invoice'] = $invoiceSnapshot ?: null;
}
// loadSourceOrderInfo 可能重算 status_code,需同步刷新 status_text
@ -1261,6 +1269,37 @@ class OrderCenterServices extends BaseService implements OrderCenterSyncInterfac
}
}
/**
* 规范化订单详情发票字段
* 兼容中台历史订单保存的 name/duty_number 字段,并统一类型,供各端详情页使用。
* @param mixed $invoice 发票信息
* @return array
*/
protected function normalizeInvoice($invoice): array
{
if (!is_array($invoice)) {
return [];
}
$title = trim((string)($invoice['title'] ?? ''));
if ($title === '') {
$title = trim((string)($invoice['name'] ?? ''));
}
$taxNumber = trim((string)($invoice['tax_number'] ?? ''));
if ($taxNumber === '') {
$taxNumber = trim((string)($invoice['duty_number'] ?? ''));
}
return array_merge($invoice, [
'title' => $title,
'header_type' => (int)($invoice['header_type'] ?? 1),
'type' => (int)($invoice['type'] ?? 1),
'tax_number' => $taxNumber,
'is_invoice' => (int)($invoice['is_invoice'] ?? 0),
'invoice_time' => (int)($invoice['invoice_time'] ?? 0),
]);
}
/**
* 按订单状态生成运营提示条
* @param string $statusCode 订单状态码

View File

@ -76,8 +76,21 @@ const props = defineProps({
const p = computed(() => (props.section && props.section.props) || {});
/** 引擎注入的全局状态(预留,当前 InvoiceCard 不依赖全局状态) */
const ctx = computed(() => (props.section && props.section._ctx) || {});
/** 发票信息对象(后端下发在 section.props.fields),含 title/header_type/type/tax_number/email/is_invoice/invoice_number/invoice_time */
const invoice = computed(() => p.value.fields || {});
/**
* 发票信息对象(后端下发在 section.props.fields)。
* 兼容历史订单仍返回的 name/duty_number 字段,确保抬头和税号始终可见。
*/
const invoice = computed(() => {
const fields = p.value.fields || {};
return {
...fields,
title: fields.title || fields.name || '',
tax_number: fields.tax_number || fields.duty_number || '',
header_type: Number(fields.header_type || 1),
type: Number(fields.type || 1),
is_invoice: Number(fields.is_invoice || 0),
};
});
/**
* 格式化时间戳为可读字符串