配置化:同步失败原因TOPN与展示截断长度

This commit is contained in:
萝卜
2026-03-11 10:09:03 +00:00
parent 0b36ae8baf
commit 916796f58e
3 changed files with 16 additions and 6 deletions

View File

@@ -178,12 +178,15 @@ class PlatformOrderController extends Controller
// 同步失败原因聚合Top 5用于运营快速判断“常见失败原因” // 同步失败原因聚合Top 5用于运营快速判断“常见失败原因”
// 注意:这里用 JSON_EXTRACT 做 group byMySQL 会返回带引号的 JSON 字符串,展示时做一次 trim 处理。 // 注意:这里用 JSON_EXTRACT 做 group byMySQL 会返回带引号的 JSON 字符串,展示时做一次 trim 处理。
$topN = (int) config('saasshop.platform_orders.sync_failed_reason_top_n', 5);
$topN = max(1, min(20, $topN));
$failedReasonRows = (clone $baseQuery) $failedReasonRows = (clone $baseQuery)
->whereRaw("JSON_EXTRACT(meta, '$.subscription_activation_error.message') IS NOT NULL") ->whereRaw("JSON_EXTRACT(meta, '$.subscription_activation_error.message') IS NOT NULL")
->selectRaw("JSON_EXTRACT(meta, '$.subscription_activation_error.message') as reason, count(*) as cnt") ->selectRaw("JSON_EXTRACT(meta, '$.subscription_activation_error.message') as reason, count(*) as cnt")
->groupBy('reason') ->groupBy('reason')
->orderByDesc('cnt') ->orderByDesc('cnt')
->limit(5) ->limit($topN)
->get(); ->get();
$failedReasonStats = $failedReasonRows->map(function ($row) { $failedReasonStats = $failedReasonRows->map(function ($row) {

View File

@@ -1,9 +1,15 @@
<?php <?php
return [ return [
// 平台订单列表中“同步失败原因”链接的最大长度阈值。
// 失败原因过长时不生成 sync_error_keyword 链接,避免 URL 过长/特殊字符破坏 query。
'platform_orders' => [ 'platform_orders' => [
// 平台订单列表中“同步失败原因”链接的最大长度阈值。
// 失败原因过长时不生成 sync_error_keyword 链接,避免 URL 过长/特殊字符破坏 query。
'sync_error_keyword_link_max_len' => 200, 'sync_error_keyword_link_max_len' => 200,
// 平台订单列表“同步失败原因 TOPN”聚合条数。
'sync_failed_reason_top_n' => 5,
// 同步失败原因展示截断长度(用于列表/聚合展示,避免撑坏布局)。
'sync_failed_reason_display_truncate_len' => 60,
], ],
]; ];

View File

@@ -7,6 +7,7 @@
@php @php
// 失败原因过长时不生成 sync_error_keyword 链接,避免 URL 过长/特殊字符破坏 query // 失败原因过长时不生成 sync_error_keyword 链接,避免 URL 过长/特殊字符破坏 query
$SYNC_ERROR_KEYWORD_LINK_MAX_LEN = (int) config('saasshop.platform_orders.sync_error_keyword_link_max_len', 200); $SYNC_ERROR_KEYWORD_LINK_MAX_LEN = (int) config('saasshop.platform_orders.sync_error_keyword_link_max_len', 200);
$SYNC_FAILED_REASON_TRUNCATE_LEN = (int) config('saasshop.platform_orders.sync_failed_reason_display_truncate_len', 60);
@endphp @endphp
<div class="card mb-20"> <div class="card mb-20">
<p class="muted muted-tight">这里是总台视角的平台收费主链骨架页,当前阶段先承接套餐订购 / 续费 / 生效跟踪。</p> <p class="muted muted-tight">这里是总台视角的平台收费主链骨架页,当前阶段先承接套餐订购 / 续费 / 生效跟踪。</p>
@@ -250,7 +251,7 @@
<div> <div>
@if($reason !== '' && $reason !== '(空)') @if($reason !== '' && $reason !== '(空)')
@php @php
$reasonText = mb_substr($reason, 0, 60); $reasonText = mb_substr($reason, 0, $SYNC_FAILED_REASON_TRUNCATE_LEN);
$reasonTooLong = mb_strlen($reason) > $SYNC_ERROR_KEYWORD_LINK_MAX_LEN; $reasonTooLong = mb_strlen($reason) > $SYNC_ERROR_KEYWORD_LINK_MAX_LEN;
@endphp @endphp
@@ -605,11 +606,11 @@
@endphp @endphp
@if($syncErrMsg !== '') @if($syncErrMsg !== '')
@if($syncErrTooLong) @if($syncErrTooLong)
<span class="muted text-danger" title="{{ $syncErrMsg }}">{{ mb_substr($syncErrMsg, 0, 60) }}</span> <span class="muted text-danger" title="{{ $syncErrMsg }}">{{ mb_substr($syncErrMsg, 0, $SYNC_FAILED_REASON_TRUNCATE_LEN) }}</span>
<div class="muted text-danger muted-xs">原因过长,请复制到筛选框</div> <div class="muted text-danger muted-xs">原因过长,请复制到筛选框</div>
<a class="link" href="{{ request()->fullUrlWithQuery(['sync_status' => 'failed', 'page' => null]) }}">进入同步失败集合</a> <a class="link" href="{{ request()->fullUrlWithQuery(['sync_status' => 'failed', 'page' => null]) }}">进入同步失败集合</a>
@else @else
<a class="link text-danger" href="{!! request()->fullUrlWithQuery(['sync_error_keyword' => $syncErrMsg, 'sync_status' => 'failed', 'page' => null]) !!}">{{ mb_substr($syncErrMsg, 0, 60) }}</a> <a class="link text-danger" href="{!! request()->fullUrlWithQuery(['sync_error_keyword' => $syncErrMsg, 'sync_status' => 'failed', 'page' => null]) !!}">{{ mb_substr($syncErrMsg, 0, $SYNC_FAILED_REASON_TRUNCATE_LEN) }}</a>
@endif @endif
@else @else
<span class="muted">-</span> <span class="muted">-</span>