fix(订单列表): 批量注入售后单号修复查看售后跳转

列表与详情两条 order_buttons 组装路径不一致,列表缺 after_sale_no 致 viewAfterSale 跳转报「售后单信息异常」;按订单号一次批量取最新售后单注入按钮参数,避免逐行点查
This commit is contained in:
吴昊天 2026-10-16 15:15:29 +08:00
parent 48ae01d903
commit 9c106bf692
2 changed files with 78 additions and 0 deletions

View File

@ -155,6 +155,35 @@ class AfterSaleDao extends BaseDao
return $model ? (string)($model['after_sale_no'] ?? '') : '';
}
/**
* 批量查询多个订单的最新售后单号
* 与 getLatestNoByOrderNo 同口径(每单取 id 最大一条),一次查询避免逐单点查
* @param array $orderNos 订单号数组
* @return array 返回以 order_no 为键的最新售后单号映射,无售后记录的订单不在结果中
*/
public function getLatestNoMapByOrderNos(array $orderNos): array
{
if (empty($orderNos)) {
return [];
}
$rows = $this->getModel()
->whereIn('order_no', $orderNos)
->where('is_del', 0)
->order('id DESC')
->field('order_no, after_sale_no')
->select()
->toArray();
$map = [];
foreach ($rows as $row) {
$orderNo = (string)($row['order_no'] ?? '');
// 按 id 倒序遍历,每个订单号首次命中即其最新一条售后单
if ($orderNo !== '' && !isset($map[$orderNo])) {
$map[$orderNo] = (string)($row['after_sale_no'] ?? '');
}
}
return $map;
}
/**
* 统计指定订单的售后数量
* @param string $orderNo

View File

@ -3,6 +3,7 @@ declare(strict_types=1);
namespace app\services\order;
use app\dao\order\AfterSaleDao;
use app\model\order\OrderCenter;
use app\services\pay\PayRecordServices;
use app\services\order\StoreCartServices;
@ -105,6 +106,10 @@ class OrderCenterUserServices extends OrderCenterServices
$item['type_label'] = $this->resolveTypeLabel($item);
}
// 为 viewAfterSale 按钮批量注入 after_sale_no(与详情接口 getOrderButtonsFromHandler 同口径)
// 前端 viewAfterSale action 依赖 params.after_sale_no 才能跳转到售后详情页
$this->injectAfterSaleNoForList($list);
$eventData = ['list' => &$list];
// 触发事件,允许第三方扩展订单列表
event('OrderCenterListExtend', $eventData);
@ -113,6 +118,50 @@ class OrderCenterUserServices extends OrderCenterServices
return compact('total', 'list');
}
/**
* 为列表项 viewAfterSale 按钮批量注入 after_sale_no
* 取订单最新一条售后单(不限状态),与详情接口 getOrderButtonsFromHandler 同口径;
* 仅含该按钮的订单才参与查询,按订单号一次批量取回,避免逐行点查
* @param array $list 订单列表(引用传递,原地补齐按钮参数)
*/
protected function injectAfterSaleNoForList(array &$list): void
{
$orderNos = [];
foreach ($list as $item) {
foreach ($item['order_buttons'] ?? [] as $button) {
if (($button['action'] ?? '') === 'viewAfterSale') {
$orderNos[(string)($item['order_no'] ?? '')] = true;
break;
}
}
}
$orderNos = array_filter(array_keys($orderNos));
if (empty($orderNos)) {
return;
}
try {
$map = $this->app->make(AfterSaleDao::class)->getLatestNoMapByOrderNos($orderNos);
} catch (\Throwable $e) {
Log::warning('[OrderCenter] injectAfterSaleNoForList failed: ' . $e->getMessage());
return;
}
foreach ($list as &$item) {
$afterSaleNo = $map[(string)($item['order_no'] ?? '')] ?? '';
if ($afterSaleNo === '') {
continue;
}
foreach ($item['order_buttons'] as &$button) {
if (($button['action'] ?? '') === 'viewAfterSale') {
$button['params'] = array_merge($button['params'] ?? [], ['after_sale_no' => $afterSaleNo]);
}
}
unset($button);
}
unset($item);
}
/**
* 批量加载列表项的扩展表子状态
* 按 source_type 分组后一次性查询各扩展表,避免 N+1