From e6eee91eb3defb271c8cf87c9e00bdefa734665c Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 27 Jul 2026 13:40:23 +0800 Subject: [PATCH 1/2] =?UTF-8?q?fix(orders):=20drop=20secondary=20"?= =?UTF-8?q?=E6=88=91=E7=9A=84=E4=BD=99=E9=A2=9D/=E4=BC=9A=E5=91=98/?= =?UTF-8?q?=E7=A7=AF=E5=88=86"=20link=20from=20detail=20modal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The user center already has a dedicated tab for these; showing the secondary shortcut inside the order detail modal is redundant noise. The view-model field is kept for other consumers. --- assets/js/order-center.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/assets/js/order-center.js b/assets/js/order-center.js index a8dc6bba..5807ac7b 100644 --- a/assets/js/order-center.js +++ b/assets/js/order-center.js @@ -610,9 +610,6 @@ if (actions.can_view_product && order.permalink) { footer += '查看商品'; } - if (order.secondary_url && order.secondary_label) { - footer += '' + escapeHtml(order.secondary_label) + ""; - } if (footer === "") { footer = ''; } From eac58f07bf31de1dbc684cfae1385166e7d2cecd Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 27 Jul 2026 13:54:34 +0800 Subject: [PATCH 2/2] feat(orders): polish detail modal layout and visuals Restructure the order detail modal into status-tinted hero, product card, info list with copyable order number, multi-item lines, and a newest-first timeline. Refresh spacing, dark mode, and footer buttons. --- assets/css/routes/orders.css | 480 ++++++++++++++++++++++++++--------- assets/js/order-center.js | 156 +++++++++--- 2 files changed, 474 insertions(+), 162 deletions(-) diff --git a/assets/css/routes/orders.css b/assets/css/routes/orders.css index 52157e87..32c43a60 100644 --- a/assets/css/routes/orders.css +++ b/assets/css/routes/orders.css @@ -523,59 +523,100 @@ /* Order detail modal content */ .aksrt-order-detail-dialog { - width: min(560px, 100%); - border-radius: 18px; + width: min(520px, 100%); + border-radius: 20px; overflow: hidden; - background: - linear-gradient(180deg, color-mix(in srgb, var(--color-primary, #3b82f6) 6%, var(--surface-1, #fff)) 0%, var(--surface-1, #fff) 64px); + background: var(--surface-1, #fff); + box-shadow: + 0 24px 60px rgba(15, 23, 42, 0.18), + 0 0 0 1px color-mix(in srgb, var(--color-line, #e5e7eb) 60%, transparent); } .aksrt-order-detail-dialog .aksrt-modal__header { background: transparent; border-bottom: none; - padding: 18px 20px 12px; + padding: 16px 18px 4px; } .aksrt-order-detail-dialog .aksrt-modal__header h3 { - font-size: 17px; + font-size: 16px; + font-weight: 750; letter-spacing: 0.01em; } .aksrt-order-detail-dialog .aksrt-modal__close { - background: color-mix(in srgb, var(--surface-2, #f3f4f6) 70%, transparent); + width: 34px; + height: 34px; + background: color-mix(in srgb, var(--surface-2, #f3f4f6) 88%, transparent); + color: var(--color-ink-3, #8b8f97); +} + +.aksrt-order-detail-dialog .aksrt-modal__close:hover { + color: var(--color-ink, #1f2329); + background: var(--surface-3, #e8eaed); } .aksrt-order-detail-dialog .aksrt-modal__body { - padding: 0 20px 18px; - gap: 18px; + padding: 8px 18px 16px; + gap: 14px; } +/* Hero: status + amount */ .aksrt-order-detail__hero { position: relative; - margin: 0 -20px 0; - padding: 14px 20px 18px; + margin: 0 -18px; + padding: 16px 18px 18px; background: - radial-gradient(circle at 100% 0%, color-mix(in srgb, var(--color-primary, #3b82f6) 12%, transparent) 0%, transparent 60%), - linear-gradient(180deg, color-mix(in srgb, var(--color-primary, #3b82f6) 8%, var(--surface-1, #fff)) 0%, transparent 100%); - border-bottom: 1px solid color-mix(in srgb, var(--color-line, #e5e7eb) 70%, transparent); + radial-gradient(120% 90% at 100% 0%, color-mix(in srgb, var(--color-primary, #3b82f6) 16%, transparent) 0%, transparent 55%), + linear-gradient(165deg, + color-mix(in srgb, var(--color-primary, #3b82f6) 10%, var(--surface-1, #fff)) 0%, + var(--surface-1, #fff) 70%); + border-bottom: 1px solid color-mix(in srgb, var(--color-line, #e5e7eb) 65%, transparent); } -.aksrt-order-detail__hero-main { - display: grid; - grid-template-columns: auto 1fr; - grid-template-rows: auto auto; - column-gap: 12px; - row-gap: 2px; +.aksrt-order-detail__hero.is-pending, +.aksrt-order-detail__hero.is-created { + background: + radial-gradient(120% 90% at 100% 0%, color-mix(in srgb, var(--color-warning, #d97706) 18%, transparent) 0%, transparent 55%), + linear-gradient(165deg, + color-mix(in srgb, var(--color-warning, #d97706) 10%, var(--surface-1, #fff)) 0%, + var(--surface-1, #fff) 70%); +} + +.aksrt-order-detail__hero.is-paid, +.aksrt-order-detail__hero.is-delivered, +.aksrt-order-detail__hero.is-completed { + background: + radial-gradient(120% 90% at 100% 0%, color-mix(in srgb, var(--color-success, #16a34a) 16%, transparent) 0%, transparent 55%), + linear-gradient(165deg, + color-mix(in srgb, var(--color-success, #16a34a) 10%, var(--surface-1, #fff)) 0%, + var(--surface-1, #fff) 70%); +} + +.aksrt-order-detail__hero.is-cancelled, +.aksrt-order-detail__hero.is-expired, +.aksrt-order-detail__hero.is-refunded, +.aksrt-order-detail__hero.is-refunding { + background: + radial-gradient(120% 90% at 100% 0%, color-mix(in srgb, var(--color-ink-3, #8b8f97) 14%, transparent) 0%, transparent 55%), + linear-gradient(165deg, + color-mix(in srgb, var(--color-ink-3, #8b8f97) 8%, var(--surface-1, #fff)) 0%, + var(--surface-1, #fff) 70%); +} + +.aksrt-order-detail__hero-top { + display: flex; + flex-wrap: wrap; align-items: center; + gap: 8px; + margin-bottom: 14px; } .aksrt-order-detail__status-pill { - grid-column: 1; - grid-row: 1; - justify-self: start; display: inline-flex; align-items: center; - padding: 4px 12px; + gap: 6px; + padding: 5px 12px; border-radius: 999px; font-size: 12px; font-weight: 700; @@ -584,8 +625,18 @@ color: var(--color-primary, #3b82f6); } +.aksrt-order-detail__status-pill::before { + content: ""; + width: 6px; + height: 6px; + border-radius: 50%; + background: currentColor; + box-shadow: 0 0 0 3px color-mix(in srgb, currentColor 18%, transparent); +} + .aksrt-order-detail__status-pill.is-pending, -.aksrt-order-detail__status-pill.is-created { +.aksrt-order-detail__status-pill.is-created, +.aksrt-order-detail__status-pill.is-pending-review { background: color-mix(in srgb, var(--color-warning, #d97706) 14%, transparent); color: var(--color-warning, #d97706); } @@ -605,37 +656,135 @@ color: var(--color-ink-3, #8b8f97); } -.aksrt-order-detail__status-pill.is-pending-review { - background: color-mix(in srgb, var(--color-warning, #d97706) 14%, transparent); - color: var(--color-warning, #d97706); +.aksrt-order-detail__type-chip { + display: inline-flex; + align-items: center; + padding: 4px 10px; + border-radius: 999px; + font-size: 11.5px; + font-weight: 600; + color: var(--color-ink-2, #4b5563); + background: color-mix(in srgb, var(--surface-2, #f3f4f6) 90%, transparent); + border: 1px solid color-mix(in srgb, var(--color-line, #e5e7eb) 80%, transparent); } -.aksrt-order-detail__hero-amount { - grid-column: 2; - grid-row: 1; - text-align: right; - font-size: 22px; - font-weight: 800; - color: var(--color-error, #ef4444); - font-variant-numeric: tabular-nums; - letter-spacing: -0.01em; +.aksrt-order-detail__hero-amount-wrap { + display: flex; + flex-direction: column; + gap: 4px; } .aksrt-order-detail__hero-label { - grid-column: 1 / -1; - grid-row: 2; font-size: 12px; color: var(--color-ink-3, #8b8f97); - margin-top: 8px; letter-spacing: 0.02em; } +.aksrt-order-detail__hero-amount { + font-size: 28px; + font-weight: 800; + line-height: 1.15; + color: var(--color-error, #ef4444); + font-variant-numeric: tabular-nums; + letter-spacing: -0.02em; +} + +/* Product card */ +.aksrt-order-detail__product { + display: grid; + grid-template-columns: 64px minmax(0, 1fr); + gap: 12px; + align-items: center; + padding: 12px; + border-radius: 14px; + background: color-mix(in srgb, var(--surface-2, #f6f7f9) 70%, var(--surface-1, #fff)); + border: 1px solid color-mix(in srgb, var(--color-line, #e5e7eb) 80%, transparent); +} + +.aksrt-order-detail__thumb { + width: 64px; + height: 64px; + border-radius: 12px; + object-fit: cover; + background: var(--surface-3, #eef0f3); + border: 1px solid color-mix(in srgb, var(--color-line, #e5e7eb) 70%, transparent); +} + +.aksrt-order-detail__thumb--empty { + display: inline-flex; + align-items: center; + justify-content: center; + color: color-mix(in srgb, var(--color-primary, #3b82f6) 55%, var(--color-ink-4, #c0c4cc)); + font-size: 20px; + background: + radial-gradient(circle at 30% 30%, color-mix(in srgb, var(--color-primary, #3b82f6) 12%, transparent), transparent 65%), + var(--surface-3, #eef0f3); +} + +.aksrt-order-detail__product-info { + min-width: 0; + display: grid; + gap: 6px; +} + +.aksrt-order-detail__product-title { + font-size: 14.5px; + font-weight: 700; + color: var(--color-ink, #1f2329); + line-height: 1.4; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} + +.aksrt-order-detail__product-meta { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 6px 8px; + font-size: 12.5px; + color: var(--color-ink-3, #8b8f97); +} + +.aksrt-order-detail__dot { + width: 3px; + height: 3px; + border-radius: 50%; + background: var(--color-ink-4, #c0c4cc); +} + +/* Sections */ +.aksrt-order-detail__section { + display: grid; + gap: 10px; +} + +.aksrt-order-detail__section-title { + margin: 0; + font-size: 13px; + font-weight: 700; + color: var(--color-ink, #1f2329); + display: flex; + align-items: center; + gap: 8px; +} + +.aksrt-order-detail__section-title::before { + content: ""; + width: 3px; + height: 13px; + border-radius: 2px; + background: linear-gradient(180deg, var(--color-primary, #3b82f6), color-mix(in srgb, var(--color-primary, #3b82f6) 40%, #fff)); + display: inline-block; +} + .aksrt-order-detail__list { margin: 0; - padding: 4px 0 0; + padding: 0; display: grid; gap: 0; - border-radius: 12px; + border-radius: 14px; background: var(--surface-1, #fff); border: 1px solid color-mix(in srgb, var(--color-line, #e5e7eb) 88%, transparent); overflow: hidden; @@ -643,22 +792,29 @@ .aksrt-order-detail__row { display: grid; - grid-template-columns: 96px minmax(0, 1fr); - gap: 10px 14px; + grid-template-columns: 88px minmax(0, 1fr); + gap: 10px 12px; align-items: center; - padding: 12px 14px; + padding: 11px 14px; font-size: 13.5px; - border-bottom: 1px solid color-mix(in srgb, var(--color-line, #e5e7eb) 70%, transparent); + border-bottom: 1px solid color-mix(in srgb, var(--color-line, #e5e7eb) 65%, transparent); + background: transparent; + transition: background 0.12s ease; } .aksrt-order-detail__row:last-child { border-bottom: none; } +.aksrt-order-detail__row:hover { + background: color-mix(in srgb, var(--surface-2, #f6f7f9) 55%, transparent); +} + .aksrt-order-detail__row dt { margin: 0; color: var(--color-ink-3, #8b8f97); font-weight: 500; + font-size: 12.5px; } .aksrt-order-detail__row dd { @@ -668,72 +824,91 @@ word-break: break-all; font-variant-numeric: tabular-nums; text-align: right; -} - -.aksrt-order-detail__items, -.aksrt-order-detail__timeline { - margin: 0; - padding: 0; - border: none; -} - -.aksrt-order-detail__items h4, -.aksrt-order-detail__timeline h4 { - margin: 0 0 10px; - font-size: 13px; - font-weight: 700; - color: var(--color-ink, #1f2329); - display: flex; + display: inline-flex; align-items: center; + justify-content: flex-end; gap: 6px; + min-width: 0; } -.aksrt-order-detail__items h4::before, -.aksrt-order-detail__timeline h4::before { - content: ""; - width: 3px; - height: 14px; - border-radius: 2px; - background: var(--color-primary, #3b82f6); - display: inline-block; +.aksrt-order-detail__value { + min-width: 0; } -.aksrt-order-detail__items ul, -.aksrt-order-detail__timeline ol { +.aksrt-order-detail__row.is-discount dd { + color: var(--color-success, #16a34a); +} + +.aksrt-order-detail__copy { + flex: 0 0 auto; + width: 28px; + height: 28px; + border: none; + border-radius: 8px; + background: color-mix(in srgb, var(--surface-2, #f3f4f6) 90%, transparent); + color: var(--color-ink-3, #8b8f97); + cursor: pointer; + display: inline-flex; + align-items: center; + justify-content: center; + font-size: 12px; + transition: background 0.15s ease, color 0.15s ease, transform 0.15s ease; +} + +.aksrt-order-detail__copy:hover { + color: var(--color-primary, #3b82f6); + background: color-mix(in srgb, var(--color-primary, #3b82f6) 12%, transparent); +} + +.aksrt-order-detail__copy.is-copied { + color: var(--color-success, #16a34a); + background: color-mix(in srgb, var(--color-success, #16a34a) 14%, transparent); + transform: scale(1.05); +} + +/* Multi-item list */ +.aksrt-order-detail__items { margin: 0; padding: 0; list-style: none; display: grid; - gap: 8px; -} - -.aksrt-order-detail__items ul { - border-radius: 12px; + gap: 0; + border-radius: 14px; background: var(--surface-1, #fff); border: 1px solid color-mix(in srgb, var(--color-line, #e5e7eb) 88%, transparent); overflow: hidden; } -.aksrt-order-detail__items li { +.aksrt-order-detail__item { display: grid; - grid-template-columns: minmax(0, 1fr) auto auto; + grid-template-columns: 40px minmax(0, 1fr) auto auto; gap: 10px; align-items: center; - padding: 10px 14px; + padding: 10px 12px; font-size: 13px; color: var(--color-ink-2, #4b5563); - border-bottom: 1px solid color-mix(in srgb, var(--color-line, #e5e7eb) 70%, transparent); + border-bottom: 1px solid color-mix(in srgb, var(--color-line, #e5e7eb) 65%, transparent); } -.aksrt-order-detail__items li:last-child { +.aksrt-order-detail__item:last-child { border-bottom: none; } +.aksrt-order-detail__item-img { + width: 40px; + height: 40px; + border-radius: 8px; + object-fit: cover; + background: var(--surface-3, #eef0f3); +} + .aksrt-order-detail__item-title { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; + font-weight: 600; + color: var(--color-ink, #1f2329); } .aksrt-order-detail__item-qty { @@ -746,41 +921,44 @@ font-weight: 700; color: var(--color-ink, #1f2329); font-variant-numeric: tabular-nums; - min-width: 72px; + min-width: 64px; text-align: right; } -.aksrt-order-detail__timeline ol { +/* Timeline */ +.aksrt-order-detail__timeline { position: relative; - padding-left: 16px; - gap: 10px; + margin: 0; + padding: 4px 0 2px 18px; + list-style: none; + display: grid; + gap: 12px; } -.aksrt-order-detail__timeline ol::before { +.aksrt-order-detail__timeline::before { content: ""; position: absolute; left: 5px; - top: 6px; - bottom: 6px; + top: 10px; + bottom: 10px; width: 2px; border-radius: 2px; - background: color-mix(in srgb, var(--color-line, #e5e7eb) 90%, transparent); + background: linear-gradient( + 180deg, + color-mix(in srgb, var(--color-primary, #3b82f6) 55%, transparent), + color-mix(in srgb, var(--color-line, #e5e7eb) 90%, transparent) + ); } -.aksrt-order-detail__timeline li { +.aksrt-order-detail__timeline-item { position: relative; display: grid; - grid-template-columns: 1fr; - gap: 2px; - font-size: 13px; - color: var(--color-ink-2, #4b5563); - padding: 2px 0; } .aksrt-order-detail__timeline-dot { position: absolute; - left: -16px; - top: 7px; + left: -18px; + top: 6px; width: 10px; height: 10px; border-radius: 50%; @@ -788,29 +966,43 @@ box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-primary, #3b82f6) 14%, transparent); } -.aksrt-order-detail__timeline li:first-child .aksrt-order-detail__timeline-dot { +.aksrt-order-detail__timeline-item.is-latest .aksrt-order-detail__timeline-dot { background: var(--color-success, #16a34a); - box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-success, #16a34a) 14%, transparent); + box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-success, #16a34a) 16%, transparent); } .aksrt-order-detail__timeline-body { display: grid; - grid-template-columns: 140px minmax(0, 1fr); - gap: 10px; - align-items: baseline; + gap: 2px; } -.aksrt-order-detail__timeline time { +.aksrt-order-detail__timeline-label { + font-size: 13.5px; + font-weight: 650; + color: var(--color-ink, #1f2329); +} + +.aksrt-order-detail__timeline-item.is-latest .aksrt-order-detail__timeline-label { + color: var(--color-success, #16a34a); +} + +.aksrt-order-detail__timeline-time { + font-size: 12px; color: var(--color-ink-3, #8b8f97); font-variant-numeric: tabular-nums; - font-size: 12.5px; } +/* Footer actions */ .aksrt-order-detail-dialog .aksrt-modal__footer { - padding: 16px 20px 18px; - background: color-mix(in srgb, var(--surface-2, #f6f7f9) 65%, transparent); + padding: 14px 18px 16px; + background: color-mix(in srgb, var(--surface-2, #f6f7f9) 72%, transparent); border-top: 1px solid color-mix(in srgb, var(--color-line, #e5e7eb) 70%, transparent); gap: 8px; + justify-content: flex-end; +} + +.aksrt-order-detail-dialog .aksrt-modal__footer:empty { + display: none; } .aksrt-modal__footer .btn-primary, @@ -818,12 +1010,12 @@ .aksrt-modal__footer .btn-ghost, .aksrt-modal__footer a.btn-ghost, .aksrt-modal__footer a.btn-outline { - min-height: 36px; + min-height: 38px; padding: 0 18px; - border-radius: 10px; + border-radius: 11px; font-size: 13.5px; - font-weight: 600; - line-height: 34px; + font-weight: 650; + line-height: 36px; display: inline-flex; align-items: center; justify-content: center; @@ -834,19 +1026,19 @@ .aksrt-modal__footer .btn-primary { border: 1px solid transparent; - background: var(--color-primary, #3b82f6); + background: linear-gradient(180deg, color-mix(in srgb, var(--color-primary, #3b82f6) 92%, #fff), var(--color-primary, #3b82f6)); color: var(--color-on-primary, #fff); - box-shadow: 0 6px 16px color-mix(in srgb, var(--color-primary, #3b82f6) 30%, transparent); + box-shadow: 0 8px 18px color-mix(in srgb, var(--color-primary, #3b82f6) 28%, transparent); } .aksrt-modal__footer .btn-primary:hover { - filter: brightness(1.05); + filter: brightness(1.04); transform: translateY(-1px); } .aksrt-modal__footer .btn-primary.c-green { - background: var(--color-success, #16a34a); - box-shadow: 0 6px 16px color-mix(in srgb, var(--color-success, #16a34a) 30%, transparent); + background: linear-gradient(180deg, color-mix(in srgb, var(--color-success, #16a34a) 90%, #fff), var(--color-success, #16a34a)); + box-shadow: 0 8px 18px color-mix(in srgb, var(--color-success, #16a34a) 28%, transparent); } .aksrt-modal__footer .btn-outline { @@ -856,7 +1048,7 @@ } .aksrt-modal__footer .btn-outline:hover { - border-color: var(--color-primary, #3b82f6); + border-color: color-mix(in srgb, var(--color-primary, #3b82f6) 45%, var(--color-line, #e5e7eb)); color: var(--color-primary, #3b82f6); transform: translateY(-1px); } @@ -872,24 +1064,58 @@ background: color-mix(in srgb, var(--surface-2, #f3f4f6) 80%, transparent); } +/* Dark mode polish */ +html.dark .aksrt-order-detail-dialog { + background: var(--surface-1, #1a1d24); + box-shadow: 0 24px 60px rgba(0, 0, 0, 0.45); +} + +html.dark .aksrt-order-detail__product, +html.dark .aksrt-order-detail__list, +html.dark .aksrt-order-detail__items { + background: color-mix(in srgb, var(--surface-2, #12151b) 55%, var(--surface-1, #1a1d24)); + border-color: color-mix(in srgb, var(--color-line, #333) 90%, transparent); +} + +html.dark .aksrt-order-detail__type-chip, +html.dark .aksrt-order-detail__copy { + background: var(--surface-2, #12151b); + border-color: var(--color-line, #333); +} + +html.dark .aksrt-order-detail-dialog .aksrt-modal__footer { + background: color-mix(in srgb, var(--surface-2, #12151b) 80%, transparent); +} + @media (max-width: 767px) { .aksrt-order-detail-dialog { - border-radius: 16px 16px 0 0; + width: 100%; + max-width: 100%; + border-radius: 18px 18px 0 0; margin-top: auto; + max-height: 92vh; + } + + .aksrt-order-detail__hero-amount { + font-size: 26px; + } + + .aksrt-order-detail__product { + grid-template-columns: 56px minmax(0, 1fr); + } + + .aksrt-order-detail__thumb { + width: 56px; + height: 56px; } .aksrt-order-detail__row { - grid-template-columns: 1fr 1fr; - gap: 2px 12px; + grid-template-columns: 76px minmax(0, 1fr); + padding: 10px 12px; } - .aksrt-order-detail__row dt { - text-align: left; - } - - .aksrt-order-detail__timeline-body { - grid-template-columns: 1fr; - gap: 2px; + .aksrt-order-detail__item { + grid-template-columns: 36px minmax(0, 1fr) auto auto; } .aksrt-modal__footer { diff --git a/assets/js/order-center.js b/assets/js/order-center.js index 5807ac7b..c7cba0aa 100644 --- a/assets/js/order-center.js +++ b/assets/js/order-center.js @@ -514,53 +514,96 @@ var status = order.status || ""; var statusLabel = order.status_label || status || "—"; var statusClass = "is-" + String(status).replace(/[^a-z0-9_-]/gi, "-"); + var title = order.product_name || (order.product && order.product.title) || "订单"; + var image = order.image || (order.product && order.product.image) || ""; + if (!image && order.items && order.items.length && order.items[0].image) { + image = order.items[0].image; + } + var orderNo = order.order_number || "—"; + // Meta fields only — amount lives in hero; type is already on the list card. var rows = [ - ["订单名称", order.product_name || (order.product && order.product.title) || "—"], - ["订单数量", String(qty)], - ["应付金额", formatMoneyText(order)], - ["订单编号", order.order_number || "—"], - ["创建时间", order.created_at || "—"], - ["支付时间", order.paid_at || "—"], - ["支付方式", paymentLabel] + { key: "qty", label: "数量", value: "×" + String(qty) }, + { key: "no", label: "订单编号", value: orderNo, copyable: true }, + { key: "created", label: "创建时间", value: order.created_at || "—" }, + { key: "paid", label: "支付时间", value: order.paid_at || "—" }, + { key: "pay", label: "支付方式", value: paymentLabel } ]; if (Number(order.shipping_fee || 0) > 0) { - rows.push(["运费", "¥" + Number(order.shipping_fee || 0).toFixed(2)]); + rows.push({ key: "ship", label: "运费", value: "¥" + Number(order.shipping_fee || 0).toFixed(2) }); } if (Number(order.discount || 0) > 0) { - rows.push(["优惠", "¥" + Number(order.discount || 0).toFixed(2)]); + rows.push({ key: "disc", label: "优惠", value: "-¥" + Number(order.discount || 0).toFixed(2), accent: "discount" }); } if (order.customer_note) { - rows.push(["备注", order.customer_note]); + rows.push({ key: "note", label: "备注", value: order.customer_note }); } var html = ""; - html += '
'; - html += '
'; + html += '
'; + html += '
'; html += ' ' + escapeHtml(statusLabel) + ""; - html += ' ' + escapeHtml(formatMoneyText(order)) + ""; + if (order.product_type_label) { + html += ' ' + escapeHtml(order.product_type_label) + ""; + } + html += "
"; + html += '
'; html += ' 应付金额'; + html += ' ' + escapeHtml(formatMoneyText(order)) + ""; html += "
"; html += "
"; - html += '
'; - rows.forEach(function (row) { - html += '
'; - html += '
' + escapeHtml(row[0]) + '
'; - html += '
' + escapeHtml(row[1]) + '
'; - html += '
'; - }); - html += "
"; + html += '
'; + if (image) { + html += ''; + } else { + html += ''; + } + html += '
'; + html += '
' + escapeHtml(title) + "
"; + html += '
'; + html += ' 数量 ' + escapeHtml(String(qty)) + ""; + if (paymentLabel && paymentLabel !== "—") { + html += ' '; + html += ' ' + escapeHtml(paymentLabel) + ""; + } + html += "
"; + html += "
"; + html += "
"; - if (order.items && order.items.length) { - html += '

商品明细

    '; + html += '
    '; + html += '

    订单信息

    '; + html += '
    '; + rows.forEach(function (row) { + html += '
    '; + html += '
    ' + escapeHtml(row.label) + '
    '; + html += '
    '; + html += '' + escapeHtml(row.value) + ""; + if (row.copyable && orderNo && orderNo !== "—") { + html += '"; + } + html += "
    "; + html += "
    "; + }); + html += "
    "; + + if (order.items && order.items.length > 1) { + html += '
    '; + html += '

    商品明细

    '; + html += '
      '; order.items.forEach(function (item) { - var title = item.product_title || item.title || order.product_name || "商品"; + var itemTitle = item.product_title || item.title || order.product_name || "商品"; var itemQty = item.quantity || item.qty || 1; var price = item.pay_price != null ? item.pay_price : (item.unit_price || 0); - html += '
    • '; - html += ' ' + escapeHtml(title) + ""; + var itemImg = item.image || ""; + html += '
    • '; + if (itemImg) { + html += ''; + } + html += ' ' + escapeHtml(itemTitle) + ""; html += ' ×' + escapeHtml(String(itemQty)) + ''; if (order.is_points) { html += '' + escapeHtml(order.currency_symbol || "积分") + " " + Math.round(Number(price || 0)) + ""; @@ -569,26 +612,30 @@ } html += "
    • "; }); - html += "
"; + html += ""; } if (order.timeline && order.timeline.length) { - html += '

订单进度

    '; - order.timeline.forEach(function (tl) { - html += '
  1. '; + // Newest first for a natural "latest activity on top" feel. + var timeline = order.timeline.slice().reverse(); + html += '
    '; + html += '

    订单进度

    '; + html += '
      '; + timeline.forEach(function (tl, idx) { + html += '
    1. '; + html += ''; html += '
      '; - html += '"; - html += "" + escapeHtml(tl.label || "") + ""; + html += '' + escapeHtml(tl.label || "") + ""; + html += '"; html += "
    2. "; }); - html += "
"; + html += ""; } detailBody.innerHTML = html; var footer = ""; - // Status-aware footer actions. The modal's own ✕ button (top-right) is the only - // dismiss control, so do not add a duplicate "关闭" button here. + // Status-aware footer. Top-right ✕ is the only generic dismiss control. if (actions.can_cancel) { footer += ''; } @@ -616,6 +663,37 @@ detailFooter.innerHTML = footer; } + function copyOrderNumber(code, trigger) { + if (!code) return; + function done() { + showToast("已复制订单号"); + if (trigger) { + trigger.classList.add("is-copied"); + window.setTimeout(function () { trigger.classList.remove("is-copied"); }, 1200); + } + } + if (navigator.clipboard && navigator.clipboard.writeText) { + navigator.clipboard.writeText(code).then(done).catch(function () { + showToast(code); + }); + return; + } + try { + var ta = document.createElement("textarea"); + ta.value = code; + ta.setAttribute("readonly", ""); + ta.style.position = "fixed"; + ta.style.opacity = "0"; + document.body.appendChild(ta); + ta.select(); + document.execCommand("copy"); + document.body.removeChild(ta); + done(); + } catch (e) { + showToast(code); + } + } + /* ── After-Sale Modal ── */ var afterSaleModal = page.querySelector("[data-aksrt-aftersale-modal]"); var afterSaleForm = page.querySelector("[data-aksrt-aftersale-form]"); @@ -706,6 +784,14 @@ return; } + // Copy order number inside detail modal + var copyBtn = event.target.closest("[data-aksrt-copy-order]"); + if (copyBtn) { + event.preventDefault(); + copyOrderNumber(copyBtn.getAttribute("data-aksrt-copy-order") || "", copyBtn); + return; + } + // Order detail close if (event.target.closest("[data-aksrt-order-detail-close]")) { closeOrderDetailModal();