fix(after-sale): 前台售后不再展示「退款金额」字段
并非每次售后都真的退款——换货、补偿、仅作记录的情况都会把工单标成已完成, 此时退款金额要么是 0 要么没有实际意义,摆在前台只会让人误解钱已经退回去了。 两个前台入口都撤掉该字段: - 售后详细弹窗:明细行只留「申请时间」,处理记录时间线不受影响 - 订单详情弹窗的售后记录卡片:撤掉退款金额后 meta 的 dl 会空壳,连同 dl 一起移除;卡片仍保留状态徽章 + 申请时间 + 原因 + 「查看详细」 连带清理死代码:aftersaleAmountText / afterSaleAmount 两个格式化助手各自 只剩这一处调用,orders.css 里 5 条 .aksrt-order-detail__after-sale-meta 规则也随之无人引用。后台售后页与订单明细页的退款金额列不动——那边是运营 核对账目的口径,需要看到金额。 验证:tests/widget-system/ 462 项、tests/admin/ 76 项通过;抽取 buildDetailHtml 跑样例载荷,确认退款金额不再出现、申请时间 / 处理记录 / 再次申请售后按钮都还在。未做浏览器视觉验收。
This commit is contained in:
@@ -211,10 +211,5 @@ html.dark .aksrt-orders-page__stat, html.dark .aksrt-orders-page__card { backgro
|
|||||||
.aksrt-order-detail__after-sale-badge { padding: 3px 11px; border-radius: 999px; background: color-mix(in srgb, var(--as-accent) 12%, transparent); color: var(--as-accent); font-size: 12px; font-weight: 700; line-height: 1.5; }
|
.aksrt-order-detail__after-sale-badge { padding: 3px 11px; border-radius: 999px; background: color-mix(in srgb, var(--as-accent) 12%, transparent); color: var(--as-accent); font-size: 12px; font-weight: 700; line-height: 1.5; }
|
||||||
.aksrt-order-detail__after-sale-head time { color: var(--detail-muted); font-size: 11.5px; font-variant-numeric: tabular-nums; }
|
.aksrt-order-detail__after-sale-head time { color: var(--detail-muted); font-size: 11.5px; font-variant-numeric: tabular-nums; }
|
||||||
.aksrt-order-detail__after-sale-reason { margin: 0; color: var(--detail-ink); font-size: 13px; line-height: 1.65; white-space: pre-wrap; word-break: break-word; }
|
.aksrt-order-detail__after-sale-reason { margin: 0; color: var(--detail-ink); font-size: 13px; line-height: 1.65; white-space: pre-wrap; word-break: break-word; }
|
||||||
.aksrt-order-detail__after-sale-meta { display: grid; margin: 0; overflow: hidden; border: 1px solid var(--detail-line); border-radius: 10px; background: var(--detail-surface-3); }
|
|
||||||
.aksrt-order-detail__after-sale-meta > div { display: grid; grid-template-columns: 76px minmax(0, 1fr); gap: 10px; padding: 9px 12px; border-bottom: 1px solid var(--detail-line); font-size: 12.5px; }
|
|
||||||
.aksrt-order-detail__after-sale-meta > div:last-child { border-bottom: 0; }
|
|
||||||
.aksrt-order-detail__after-sale-meta dt { color: var(--detail-muted); }
|
|
||||||
.aksrt-order-detail__after-sale-meta dd { margin: 0; color: var(--detail-ink); font-size: 12.5px; text-align: right; word-break: break-word; }
|
|
||||||
.aksrt-order-detail__after-sale-field { color: var(--detail-muted); }
|
.aksrt-order-detail__after-sale-field { color: var(--detail-muted); }
|
||||||
.aksrt-order-detail__after-sale-foot { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; }
|
.aksrt-order-detail__after-sale-foot { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; }
|
||||||
|
|||||||
@@ -91,11 +91,6 @@
|
|||||||
return '¥' + raw;
|
return '¥' + raw;
|
||||||
}
|
}
|
||||||
|
|
||||||
function aftersaleAmountText(value, order) {
|
|
||||||
var amount = String(value == null ? '' : value);
|
|
||||||
return order && order.is_points ? amount + ' ' + String((order && order.currency_symbol) || '积分') : '¥' + amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
function orderSummaryHtml(order) {
|
function orderSummaryHtml(order) {
|
||||||
if (!order) return '';
|
if (!order) return '';
|
||||||
return '<div class="muted-box padding-10 mb20 em09 aksrt-after-sale-summary">' +
|
return '<div class="muted-box padding-10 mb20 em09 aksrt-after-sale-summary">' +
|
||||||
@@ -231,7 +226,6 @@
|
|||||||
|
|
||||||
html += '<div class="aksrt-after-sale-detail__rows">';
|
html += '<div class="aksrt-after-sale-detail__rows">';
|
||||||
html += detailRow('申请时间', String(latest.created_at || ''));
|
html += detailRow('申请时间', String(latest.created_at || ''));
|
||||||
html += detailRow('退款金额', aftersaleAmountText(latest.refund_amount, order));
|
|
||||||
html += '</div>';
|
html += '</div>';
|
||||||
// 处理记录:每次后台提交一条,替代原先单行的「处理备注 / 完成时间」。
|
// 处理记录:每次后台提交一条,替代原先单行的「处理备注 / 完成时间」。
|
||||||
html += handlingLogHtml(latest.handling_log);
|
html += handlingLogHtml(latest.handling_log);
|
||||||
|
|||||||
@@ -106,11 +106,6 @@
|
|||||||
return "<div><dt>" + escapeHtml(label) + "</dt><dd>" + cell + "</dd></div>";
|
return "<div><dt>" + escapeHtml(label) + "</dt><dd>" + cell + "</dd></div>";
|
||||||
}
|
}
|
||||||
|
|
||||||
function afterSaleAmount(value, order) {
|
|
||||||
var amount = String(value == null ? "" : value);
|
|
||||||
return order && order.is_points ? amount + " " + String(order.currency_symbol || "积分") : "¥" + amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
function colorfulHeader(title, icon) {
|
function colorfulHeader(title, icon) {
|
||||||
return '<div class="modal-colorful-header colorful-bg jb-blue">' +
|
return '<div class="modal-colorful-header colorful-bg jb-blue">' +
|
||||||
'<button type="button" class="close" data-aksrt-modal-close aria-label="关闭"><svg class="ic-close" aria-hidden="true"><use xlink:href="#icon-close"></use></svg></button>' +
|
'<button type="button" class="close" data-aksrt-modal-close aria-label="关闭"><svg class="ic-close" aria-hidden="true"><use xlink:href="#icon-close"></use></svg></button>' +
|
||||||
@@ -190,9 +185,6 @@
|
|||||||
} else if (item.reason) {
|
} else if (item.reason) {
|
||||||
html += '<p class="aksrt-order-detail__after-sale-reason">' + escapeHtml(item.reason).replace(/\r\n|\r|\n/g, "<br>") + "</p>";
|
html += '<p class="aksrt-order-detail__after-sale-reason">' + escapeHtml(item.reason).replace(/\r\n|\r|\n/g, "<br>") + "</p>";
|
||||||
}
|
}
|
||||||
html += '<dl class="aksrt-order-detail__after-sale-meta">';
|
|
||||||
html += "<div><dt>退款金额</dt><dd>" + escapeHtml(afterSaleAmount(item.refund_amount, order)) + "</dd></div>";
|
|
||||||
html += "</dl>";
|
|
||||||
// 查看详细:逐记录构造售后详细弹窗载荷(after_sale.latest 指向本条记录);
|
// 查看详细:逐记录构造售后详细弹窗载荷(after_sale.latest 指向本条记录);
|
||||||
// 再次申请仅对最新一条且订单级可再申请时开放(after_sales 按 id 倒序,首条即最新)。
|
// 再次申请仅对最新一条且订单级可再申请时开放(after_sales 按 id 倒序,首条即最新)。
|
||||||
var recordPayload = escapeHtml(JSON.stringify({
|
var recordPayload = escapeHtml(JSON.stringify({
|
||||||
|
|||||||
@@ -533,12 +533,19 @@ test('frontend renders the handling log as a rope-knot timeline', () => {
|
|||||||
assert.match(js, /'<span class="aksrt-after-sale-timeline__knot"><\/span>'/)
|
assert.match(js, /'<span class="aksrt-after-sale-timeline__knot"><\/span>'/)
|
||||||
assert.match(js, /'<div class="aksrt-after-sale-timeline__head">' \+/)
|
assert.match(js, /'<div class="aksrt-after-sale-timeline__head">' \+/)
|
||||||
assert.match(js, /'<div class="aksrt-after-sale-timeline__body">';/)
|
assert.match(js, /'<div class="aksrt-after-sale-timeline__body">';/)
|
||||||
|
// 退款金额不展示:并非每次售后都真的退款,工单被标完成也不代表把钱退回去了
|
||||||
|
assert.ok(!js.includes("detailRow('退款金额'"), 'after-sale detail modal must not show 退款金额')
|
||||||
|
assert.ok(!js.includes('aftersaleAmountText'), 'dead aftersaleAmountText must be removed')
|
||||||
|
assert.match(js, /detailRow\('申请时间', String\(latest\.created_at \|\| ''\)\)/)
|
||||||
|
|
||||||
// 订单详情弹窗:不再渲染售后状态节点进程,只保留状态徽章 + 原因 + 金额 + 「查看详细」;
|
// 订单详情弹窗:不再渲染售后状态节点进程与退款金额,只保留状态徽章 + 原因 + 「查看详细」;
|
||||||
// 完整处理记录由点开的售后详细弹窗呈现,载荷仍带上 handling_log
|
// 完整处理记录由点开的售后详细弹窗呈现,载荷仍带上 handling_log
|
||||||
assert.ok(!center.includes('gatewayResultText'), 'dead gateway-result renderer must be removed')
|
assert.ok(!center.includes('gatewayResultText'), 'dead gateway-result renderer must be removed')
|
||||||
assert.ok(!center.includes('<dt>渠道结果</dt>'), 'dead 渠道结果 row must be removed')
|
assert.ok(!center.includes('<dt>渠道结果</dt>'), 'dead 渠道结果 row must be removed')
|
||||||
assert.ok(!center.includes('<dt>处理备注</dt>'), 'single 处理备注 row must be removed')
|
assert.ok(!center.includes('<dt>处理备注</dt>'), 'single 处理备注 row must be removed')
|
||||||
|
assert.ok(!center.includes('<dt>退款金额</dt>'), 'order detail card must not show 退款金额')
|
||||||
|
assert.ok(!center.includes('afterSaleAmount'), 'dead afterSaleAmount must be removed')
|
||||||
|
assert.ok(!center.includes('aksrt-order-detail__after-sale-meta'), 'empty meta dl must be removed')
|
||||||
assert.ok(!center.includes('orderDetailHandlingLogHtml'), 'order detail modal must not render the timeline')
|
assert.ok(!center.includes('orderDetailHandlingLogHtml'), 'order detail modal must not render the timeline')
|
||||||
assert.ok(!center.includes('AFTER_SALE_STATUS_LABELS'), 'order detail modal must not carry timeline labels')
|
assert.ok(!center.includes('AFTER_SALE_STATUS_LABELS'), 'order detail modal must not carry timeline labels')
|
||||||
assert.ok(!center.includes('handlingEntryTitle'), 'order detail modal must not carry the timeline title helper')
|
assert.ok(!center.includes('handlingEntryTitle'), 'order detail modal must not carry the timeline title helper')
|
||||||
@@ -555,6 +562,8 @@ test('frontend renders the handling log as a rope-knot timeline', () => {
|
|||||||
assert.match(css, /\.aksrt-after-sale-timeline__head \{ display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; \}/)
|
assert.match(css, /\.aksrt-after-sale-timeline__head \{ display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; \}/)
|
||||||
assert.match(css, /\.aksrt-after-sale-timeline__knot/)
|
assert.match(css, /\.aksrt-after-sale-timeline__knot/)
|
||||||
assert.match(css, /\.aksrt-after-sale-timeline__note/)
|
assert.match(css, /\.aksrt-after-sale-timeline__note/)
|
||||||
|
const ordersCss = read('assets/css/routes/orders.css')
|
||||||
|
assert.ok(!ordersCss.includes('aksrt-order-detail__after-sale-meta'), 'dead after-sale-meta rules must be removed')
|
||||||
// 旧的两列结构(aside / main)已移除
|
// 旧的两列结构(aside / main)已移除
|
||||||
assert.ok(!css.includes('aksrt-after-sale-timeline__aside'), 'left-column aside must be removed')
|
assert.ok(!css.includes('aksrt-after-sale-timeline__aside'), 'left-column aside must be removed')
|
||||||
assert.ok(!css.includes('aksrt-after-sale-timeline__main'), 'right-column main must be removed')
|
assert.ok(!css.includes('aksrt-after-sale-timeline__main'), 'right-column main must be removed')
|
||||||
|
|||||||
Reference in New Issue
Block a user