feat(payment): 新增「售后策略」配置与前台售后弹窗链路
- 后台「支付&付费 → 售后策略」:售后功能开关、申请时效、超时效提示(HTML)、 预置原因、申请售后说明、所需材料、申请说明占位文案、可上传图片开关; PHP schema 与 SPA schema 1:1 对齐,group 字段支持拖拽排序 - PaymentRuntime 新增售后设置解析(缺键回退 schema 默认、HTML 走 kses、 中文原因稳定 slug)与 after_sale_expired 时效判定(支付时间起算) - 售后工单支持举证图片(order_aftersale.images 列,最多 3 张, 复用评论图片上传校验)与上传路由;订单视图模型输出 after_sale 按钮状态 - 前台申请 / 超时效提示 / 售后详细三个独立弹窗(modal-mini + 蓝色炫彩头), 订单详情弹窗不再内嵌售后表单并清理相关死代码 - 新增 after-sale-policy 契约测试与运行时 harness,527 项契约测试通过
This commit is contained in:
+184
-5
@@ -6429,14 +6429,15 @@ body.aksrt-modal-runtime-open {
|
||||
color: var(--color-ink, #111);
|
||||
}
|
||||
|
||||
:is(.order-comment-from, .aksrt-report-modal) .form-upload .preview {
|
||||
:is(.order-comment-from, .aksrt-report-modal, .aksrt-after-sale-apply-modal) .form-upload .preview {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
:is(.order-comment-from, .aksrt-report-modal) .form-upload .preview .add,
|
||||
:is(.order-comment-from, .aksrt-report-modal) .form-upload .preview .preview-item {
|
||||
:is(.order-comment-from, .aksrt-report-modal, .aksrt-after-sale-apply-modal) .form-upload .preview .add,
|
||||
:is(.order-comment-from, .aksrt-report-modal, .aksrt-after-sale-apply-modal) .form-upload .preview .preview-item {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
border-radius: 10px;
|
||||
@@ -6452,14 +6453,14 @@ body.aksrt-modal-runtime-open {
|
||||
此前这里的 left/top:50% + translate 版本与该规则叠加导致过约束,
|
||||
加号被推到 75%/75% 只剩“L”形,故整体删除、统一走主样式包。 */
|
||||
|
||||
:is(.order-comment-from, .aksrt-report-modal) .form-upload .preview .preview-item img {
|
||||
:is(.order-comment-from, .aksrt-report-modal, .aksrt-after-sale-apply-modal) .form-upload .preview .preview-item img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
}
|
||||
|
||||
:is(.order-comment-from, .aksrt-report-modal) .form-upload .preview .preview-item .remove {
|
||||
:is(.order-comment-from, .aksrt-report-modal, .aksrt-after-sale-apply-modal) .form-upload .preview .preview-item .remove {
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
right: 2px;
|
||||
@@ -6474,7 +6475,7 @@ body.aksrt-modal-runtime-open {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
:is(.order-comment-from, .aksrt-report-modal) .form-upload .hide {
|
||||
:is(.order-comment-from, .aksrt-report-modal, .aksrt-after-sale-apply-modal) .form-upload .hide {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
@@ -6490,6 +6491,184 @@ body.aksrt-modal-runtime-open {
|
||||
}
|
||||
}
|
||||
|
||||
/* ---- 售后弹窗(申请 / 售后详细 / 超时效提示,参考主题 modal-mini 几何 1:1)----
|
||||
三个弹窗与禁封申诉弹窗同几何:data_class='modal-mini'(宽 400px),圆角与
|
||||
底色走 --main-radius / --main-bg-color;移动端由 --bottom 底部抽屉接管。 */
|
||||
.aksrt-after-sale-apply-modal:not(.aksrt-modal-runtime--bottom) .aksrt-modal-runtime__dialog,
|
||||
.aksrt-after-sale-detail-modal:not(.aksrt-modal-runtime--bottom) .aksrt-modal-runtime__dialog,
|
||||
.aksrt-after-sale-expired-modal:not(.aksrt-modal-runtime--bottom) .aksrt-modal-runtime__dialog {
|
||||
width: min(400px, calc(100vw - 32px));
|
||||
border-radius: var(--main-radius, 8px);
|
||||
background: var(--main-bg-color, #fff);
|
||||
}
|
||||
|
||||
.aksrt-after-sale-apply-modal .aksrt-modal-runtime__skeleton,
|
||||
.aksrt-after-sale-detail-modal .aksrt-modal-runtime__skeleton,
|
||||
.aksrt-after-sale-expired-modal .aksrt-modal-runtime__skeleton {
|
||||
padding: 24px 18px;
|
||||
}
|
||||
|
||||
/* 蓝色炫彩标题区(参考主题 zib_get_modal_colorful_header('jb-blue', ...)):120px
|
||||
绝对定位横幅 + 旋转彩斑,后续内容整体下移 120px,与禁封记录弹窗同构。 */
|
||||
.aksrt-after-sale-apply-modal .modal-colorful-header,
|
||||
.aksrt-after-sale-detail-modal .modal-colorful-header,
|
||||
.aksrt-after-sale-expired-modal .modal-colorful-header,
|
||||
.aksrt-after-sale-apply-modal .colorful-bg,
|
||||
.aksrt-after-sale-detail-modal .colorful-bg,
|
||||
.aksrt-after-sale-expired-modal .colorful-bg {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
color: var(--this-color);
|
||||
background: var(--this-bg);
|
||||
background-size: 120%;
|
||||
}
|
||||
|
||||
.aksrt-after-sale-apply-modal .modal-colorful-header,
|
||||
.aksrt-after-sale-detail-modal .modal-colorful-header,
|
||||
.aksrt-after-sale-expired-modal .modal-colorful-header {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 120px;
|
||||
border-radius: var(--main-radius, 8px) var(--main-radius, 8px) 0 0;
|
||||
}
|
||||
|
||||
.aksrt-after-sale-apply-modal .modal-colorful-header + *,
|
||||
.aksrt-after-sale-detail-modal .modal-colorful-header + *,
|
||||
.aksrt-after-sale-expired-modal .modal-colorful-header + * {
|
||||
margin-top: 120px;
|
||||
}
|
||||
|
||||
.aksrt-after-sale-apply-modal .modal-colorful-header > .close,
|
||||
.aksrt-after-sale-detail-modal .modal-colorful-header > .close,
|
||||
.aksrt-after-sale-expired-modal .modal-colorful-header > .close {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
z-index: 9;
|
||||
color: var(--this-color);
|
||||
font-size: 18px;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.aksrt-after-sale-apply-modal .colorful-bg > .colorful-make,
|
||||
.aksrt-after-sale-apply-modal .colorful-bg > .colorful-make::before,
|
||||
.aksrt-after-sale-apply-modal .colorful-bg > .colorful-make::after,
|
||||
.aksrt-after-sale-detail-modal .colorful-bg > .colorful-make,
|
||||
.aksrt-after-sale-detail-modal .colorful-bg > .colorful-make::before,
|
||||
.aksrt-after-sale-detail-modal .colorful-bg > .colorful-make::after,
|
||||
.aksrt-after-sale-expired-modal .colorful-bg > .colorful-make,
|
||||
.aksrt-after-sale-expired-modal .colorful-bg > .colorful-make::before,
|
||||
.aksrt-after-sale-expired-modal .colorful-bg > .colorful-make::after {
|
||||
position: absolute;
|
||||
color: var(--this-color);
|
||||
background: var(--this-bg);
|
||||
border-radius: 100%;
|
||||
content: '';
|
||||
}
|
||||
|
||||
.aksrt-after-sale-apply-modal .colorful-bg > .colorful-make,
|
||||
.aksrt-after-sale-detail-modal .colorful-bg > .colorful-make,
|
||||
.aksrt-after-sale-expired-modal .colorful-bg > .colorful-make {
|
||||
top: 60%;
|
||||
bottom: 0;
|
||||
width: 323px;
|
||||
height: 290px;
|
||||
animation: aksrt-ban-colorful 120s linear infinite;
|
||||
}
|
||||
|
||||
.aksrt-after-sale-apply-modal .colorful-bg > .colorful-make::before,
|
||||
.aksrt-after-sale-detail-modal .colorful-bg > .colorful-make::before,
|
||||
.aksrt-after-sale-expired-modal .colorful-bg > .colorful-make::before {
|
||||
top: -325px;
|
||||
right: -558px;
|
||||
bottom: 0;
|
||||
width: 677px;
|
||||
height: 300px;
|
||||
opacity: 0.6;
|
||||
transform: rotate(341deg);
|
||||
}
|
||||
|
||||
.aksrt-after-sale-apply-modal .colorful-bg > .colorful-make::after,
|
||||
.aksrt-after-sale-detail-modal .colorful-bg > .colorful-make::after,
|
||||
.aksrt-after-sale-expired-modal .colorful-bg > .colorful-make::after {
|
||||
top: -170px;
|
||||
bottom: 0;
|
||||
left: -262px;
|
||||
width: 402px;
|
||||
height: 214px;
|
||||
opacity: 0.4;
|
||||
transform: rotate(326deg);
|
||||
}
|
||||
|
||||
/* 售后原因徽章:与举报弹窗一致,可换行且间距走 mr6/mb6 工具类。 */
|
||||
.aksrt-after-sale-apply-modal .form-but-radio .badg {
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
/* 订单摘要与售后明细行 */
|
||||
.aksrt-after-sale-summary__row,
|
||||
.aksrt-after-sale-detail__row {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.aksrt-after-sale-summary__row:last-child,
|
||||
.aksrt-after-sale-detail__row:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.aksrt-after-sale-summary__value,
|
||||
.aksrt-after-sale-detail__value {
|
||||
min-width: 0;
|
||||
text-align: right;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.aksrt-after-sale-detail__statusRow {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.aksrt-after-sale-reason-text {
|
||||
color: var(--color-ink-2, #4e5358);
|
||||
background: var(--surface-2, #eee);
|
||||
border-radius: 6px;
|
||||
padding: 10px 12px;
|
||||
}
|
||||
|
||||
.aksrt-after-sale-images {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.aksrt-after-sale-images img {
|
||||
width: 72px;
|
||||
height: 72px;
|
||||
object-fit: cover;
|
||||
border-radius: 6px;
|
||||
border: 1px solid var(--color-line, #e5e7eb);
|
||||
display: block;
|
||||
}
|
||||
|
||||
.aksrt-after-sale-status.is-pending { color: var(--color-warning, #f59e0b); }
|
||||
.aksrt-after-sale-status.is-processing { color: var(--color-info, #3b82f6); }
|
||||
.aksrt-after-sale-status.is-approved,
|
||||
.aksrt-after-sale-status.is-completed { color: var(--color-success, #10b981); }
|
||||
.aksrt-after-sale-status.is-rejected,
|
||||
.aksrt-after-sale-status.is-cancelled { color: var(--color-error, #ef4444); }
|
||||
|
||||
/* source: assets/css/frontend/notyf.css */
|
||||
/**
|
||||
* legacy-compatible frontend notifications.
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user