+
+
+
- {{ chip.label }}:{{ chip.value }}
+ {{ chip.label }}
+ {{ chip.value }}
diff --git a/frontend/src/features/listings/views/MobileListingDetailView.css b/frontend/src/features/listings/views/MobileListingDetailView.css
index 0fe21ed..6d1d172 100644
--- a/frontend/src/features/listings/views/MobileListingDetailView.css
+++ b/frontend/src/features/listings/views/MobileListingDetailView.css
@@ -1,28 +1,36 @@
+/* ==========================================================================
+ 移动端商品详情页全新重构样式 (完全对标 PC 端设计语言规范)
+ ========================================================================== */
+
.mobile-detail {
min-height: 100dvh;
- background: #f5f7fa;
- padding-bottom: calc(80px + env(safe-area-inset-bottom));
+ background: #f1f5f9;
+ padding-bottom: calc(84px + env(safe-area-inset-bottom));
+ box-sizing: border-box;
}
/* ========== 顶部导航 ========== */
.page-header {
position: sticky;
top: 0;
- z-index: 10;
+ z-index: 50;
display: flex;
align-items: center;
+ justify-content: space-between;
height: 48px;
padding: 0 12px;
- background: #fff;
- border-bottom: 1px solid #eee;
+ background: #ffffff;
+ border-bottom: 1px solid #e2e8f0;
}
.page-header h1 {
flex: 1;
margin: 0;
- font-size: 17px;
- font-weight: 700;
+ font-size: 16px;
+ font-weight: 800;
+ color: #0f172a;
text-align: center;
+ letter-spacing: -0.01em;
}
.back-btn,
@@ -33,324 +41,759 @@
place-items: center;
border: none;
background: none;
- color: #333;
+ color: #334155;
cursor: pointer;
+ border-radius: 8px;
+}
+
+.back-btn:active,
+.favorite-header-btn:active {
+ background: #f1f5f9;
}
.favorite-header-btn {
color: #ff6a00;
}
-.header-spacer {
- width: 36px;
-}
-
.center-loading {
display: flex;
justify-content: center;
- padding: 60px 0;
+ padding: 80px 0;
}
-/* ========== 防骗提示 ========== */
+/* ========== 平台官方安全保障提示条 ========== */
.fraud-tip {
display: flex;
align-items: center;
- gap: 6px;
- padding: 8px 16px;
- background: #fff8e1;
- font-size: 11px;
- color: #e65100;
- line-height: 1.4;
+ gap: 8px;
+ margin: 10px 12px 6px;
+ padding: 8px 12px;
+ background: #fffcf5;
+ border: 1px solid #fef3c7;
+ border-radius: 10px;
+ font-size: 11.5px;
+ color: #92400e;
+ line-height: 1.45;
+ box-shadow: 0 1px 3px rgba(245, 158, 11, 0.05);
}
-/* ========== 封面图 ========== */
-.cover-area {
- position: relative;
- width: 100%;
- aspect-ratio: 16 / 9;
- background: #e8e8e8;
- overflow: hidden;
+.fraud-tip span {
+ font-weight: 500;
}
-.cover-img {
- width: 100%;
- height: 100%;
- cursor: zoom-in;
-}
-
-.cover-img :deep(.el-image__inner) {
- width: 100%;
- height: 100%;
- object-fit: cover;
-}
-
-.cover-placeholder {
- width: 100%;
- height: 100%;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- gap: 6px;
- color: #999;
- font-size: 12px;
-}
-
-.cover-count {
- position: absolute;
- right: 10px;
- bottom: 10px;
- padding: 2px 8px;
- border-radius: 8px;
- background: rgba(0, 0, 0, 0.5);
- color: #fff;
- font-size: 11px;
-}
-
-/* ========== 信息卡片 ========== */
+/* ========== 通用信息卡片 (对齐 PC detail-card) ========== */
.info-card {
margin: 10px 12px;
- padding: 14px;
- background: #fff;
- border-radius: 12px;
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
+ padding: 16px;
+ background: #ffffff;
+ border-radius: 16px;
+ border: 1px solid #e8edf5;
+ box-shadow: 0 3px 12px rgba(15, 23, 42, 0.03);
}
-.info-tag-row {
+.card-header-row {
display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 8px;
+ margin-bottom: 12px;
+}
+
+.header-left {
+ display: flex;
+ flex-direction: column;
+ gap: 2px;
+}
+
+.card-subtitle {
+ margin: 0;
+ font-size: 15px;
+ font-weight: 800;
+ color: #0f172a;
+}
+
+.card-subtitle-tip {
+ font-size: 11px;
+ color: #64748b;
+}
+
+.gallery-count {
+ font-size: 11px;
+ font-weight: 600;
+ color: #94a3b8;
+ flex-shrink: 0;
+}
+
+/* ========== 1. 账号抬头卡片 (Header Card) ========== */
+.header-meta-row {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 8px;
+ margin-bottom: 10px;
+}
+
+.meta-tags-wrap {
+ display: flex;
+ align-items: center;
+ flex-wrap: wrap;
gap: 6px;
- margin-bottom: 8px;
}
.mobile-code-chip {
- margin-bottom: 8px;
- padding: 4px 9px;
- border: 1px solid #dbeafe;
- border-radius: 999px;
+ display: inline-flex;
+ align-items: center;
+ gap: 4px;
+ padding: 3px 8px;
+ border-radius: 6px;
background: #eff6ff;
+ border: 1px solid #bfdbfe;
color: #2563eb;
- font-size: 12px;
- font-weight: 800;
+ font-size: 11px;
+ font-weight: 700;
+ cursor: pointer;
+}
+
+.platform-pill {
+ display: inline-flex;
+ align-items: center;
+ gap: 3px;
+ padding: 2px 7px;
+ border-radius: 5px;
+ font-size: 11px;
+ font-weight: 600;
+}
+
+.platform-pill.wechat {
+ background: #ecfdf5;
+ color: #059669;
+}
+
+.platform-pill.qq {
+ background: #eff6ff;
+ color: #0284c7;
+}
+
+.platform-pill.scan {
+ background: #fff7ed;
+ color: #ea580c;
+}
+
+.platform-pill.password,
+.platform-pill.default {
+ background: #f1f5f9;
+ color: #475569;
+}
+
+.platform-pill.steam {
+ background: #eef2ff;
+ color: #4f46e5;
+}
+
+.platform-pill.rank {
+ background: #f5f3ff;
+ color: #7c3aed;
+}
+
+.status-pill {
+ display: inline-flex;
+ align-items: center;
+ gap: 5px;
+ padding: 2px 8px;
+ border-radius: 5px;
+ background: #f0fdf4;
+ border: 1px solid #dcfce7;
+ color: #15803d;
+ font-size: 11px;
+ font-weight: 700;
+}
+
+.status-dot {
+ width: 6px;
+ height: 6px;
+ border-radius: 999px;
+ background: #16a34a;
+}
+
+.status-pill.is-busy {
+ background: #fff7ed;
+ border-color: #fed7aa;
+ color: #ea580c;
+}
+
+.status-pill.is-busy .status-dot {
+ background: #ea580c;
}
.mobile-favorite-chip {
display: inline-flex;
align-items: center;
- gap: 4px;
- margin-left: 6px;
- margin-bottom: 8px;
- padding: 4px 9px;
- border: 1px solid #fed7aa;
+ gap: 3px;
+ padding: 3px 9px;
+ border: 1px solid #e2e8f0;
border-radius: 999px;
+ background: #ffffff;
+ color: #64748b;
+ font-size: 11px;
+ font-weight: 600;
+ cursor: pointer;
+ flex-shrink: 0;
+}
+
+.mobile-favorite-chip.is-active {
+ border-color: #fed7aa;
background: #fff7ed;
- color: #ff6a00;
- font-size: 12px;
- font-weight: 800;
+ color: #ea580c;
}
.detail-title {
margin: 0 0 6px;
- font-size: 20px;
- font-weight: 700;
- color: #1a1a1a;
- line-height: 1.35;
+ font-size: 17px;
+ font-weight: 800;
+ color: #0f172a;
+ line-height: 1.4;
+ letter-spacing: -0.015em;
}
.detail-desc {
- margin: 0;
- font-size: 13px;
- color: #666;
+ margin: 0 0 12px;
+ font-size: 12px;
+ color: #64748b;
line-height: 1.5;
}
-/* ========== 资产指标 ========== */
-.metric-row {
- display: grid;
- grid-template-columns: repeat(3, minmax(0, 1fr));
- gap: 8px;
- padding: 0 12px;
-}
-
-.metric-item {
- background: #fff;
- border-radius: 10px;
- padding: 10px 4px;
- text-align: center;
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
-}
-
-.metric-label {
- display: block;
- font-size: 11px;
- color: #999;
- margin-bottom: 4px;
-}
-
-.metric-value {
- display: block;
- overflow: hidden;
- font-size: 15px;
- color: #1a1a1a;
- text-overflow: ellipsis;
- white-space: nowrap;
-}
-
-.metric-value.coin {
- color: #1477ff;
-}
-
-.metric-value.price {
- color: #ff5f00;
-}
-
-/* ========== 账号资料 ========== */
-.info-line {
- display: flex;
- justify-content: space-between;
- padding: 8px 0;
- border-bottom: 1px solid #f5f5f5;
- font-size: 13px;
-}
-
-.info-line:last-child {
- border-bottom: none;
-}
-
-.info-label {
- color: #999;
-}
-
-.info-text {
- color: #333;
- font-weight: 500;
-}
-
-/* ========== 截图列表 ========== */
-.card-subtitle {
- margin: 0 0 10px;
- font-size: 14px;
- font-weight: 700;
-}
-
-.detail-chip-row {
- display: flex;
- flex-wrap: wrap;
- gap: 7px;
- margin-bottom: 10px;
-}
-
-.detail-chip-row span {
- display: inline-flex;
- align-items: center;
- min-height: 28px;
- border: 1px solid #ff8a1f;
- border-radius: 5px;
- color: #ff7900;
- padding: 0 7px;
- font-size: 12px;
- font-weight: 800;
-}
-
-.resource-grid {
- display: grid;
- grid-template-columns: repeat(2, minmax(0, 1fr));
- gap: 8px;
-}
-
-.resource-pill {
- display: grid;
- grid-template-columns: minmax(0, 1fr) auto;
- gap: 4px 8px;
- border-radius: 8px;
- background: #f7f9fc;
- padding: 10px;
-}
-
-.resource-pill span {
- min-width: 0;
- color: #5f6b7a;
- font-size: 12px;
- font-weight: 700;
-}
-
-.resource-pill strong {
- color: #17233d;
- font-size: 14px;
-}
-
-.resource-pill em {
- display: flex;
- align-items: center;
- justify-content: space-between;
- gap: 6px;
- grid-column: 1 / -1;
- font-size: 11px;
- font-style: normal;
- font-weight: 800;
-}
-
-.resource-pill em b {
- color: #ff7900;
-}
-
-.resource-pill em small {
- min-width: 0;
- color: #17233d;
- font-size: 11px;
- font-weight: 800;
- text-align: right;
-}
-
-.skin-detail-group + .skin-detail-group {
- margin-top: 12px;
-}
-
-.skin-detail-group p {
- margin: 0 0 8px;
- color: #5f6b7a;
- font-size: 12px;
- font-weight: 900;
-}
-
-.screenshot-grid {
+/* 核心资产四大微卡 (2x2 网格对齐移动端体验) */
+.core-assets-bar {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 8px;
+ margin-top: 10px;
}
-.screenshot-item {
- margin: 0;
-}
-
-.screenshot-thumb {
- width: 100%;
- aspect-ratio: 4 / 3;
- overflow: hidden;
- border-radius: 8px;
+.asset-tile {
+ display: flex;
+ flex-direction: column;
+ gap: 4px;
+ padding: 10px 12px;
+ border-radius: 10px;
background: #f8fafc;
- cursor: pointer;
+ border: 1px solid #e2e8f0;
}
-.screenshot-thumb :deep(.el-image__inner) {
+.coin-tile {
+ background: #fff9f5;
+ border-color: #fed7aa;
+}
+
+.slot-tile.top-insurance {
+ background: #fff9f5;
+ border-color: #fed7aa;
+}
+
+.tile-label {
+ font-size: 11px;
+ font-weight: 500;
+ color: #64748b;
+}
+
+.tile-value {
+ font-size: 19px;
+ font-weight: 800;
+ line-height: 1.15;
+ letter-spacing: -0.02em;
+}
+
+.text-orange {
+ color: #ea580c;
+}
+
+.text-slate {
+ color: #0f172a;
+}
+
+.tile-subvalues {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 4px;
+ align-items: center;
+}
+
+.val-pill {
+ display: inline-flex;
+ align-items: center;
+ padding: 2px 6px;
+ border-radius: 4px;
+ font-size: 11px;
+ font-weight: 700;
+}
+
+.val-pill.green {
+ background: #f0fdf4;
+ border: 1px solid #dcfce7;
+ color: #15803d;
+}
+
+.val-pill.warm {
+ background: #fffbeb;
+ border: 1px solid #fef3c7;
+ color: #b45309;
+}
+
+/* ========== 2. 验号多图互动展台 (Gallery Stage) ========== */
+.gallery-stage {
+ position: relative;
+ width: 100%;
+ aspect-ratio: 16 / 10;
+ border-radius: 10px;
+ overflow: hidden;
+ background: #0f172a;
+}
+
+.stage-viewer {
+ width: 100%;
+ height: 100%;
+ position: relative;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.stage-image {
+ width: 100%;
+ height: 100%;
+ object-fit: contain;
+}
+
+.stage-viewer :deep(.el-image) {
+ width: 100%;
+ height: 100%;
+}
+
+.stage-viewer :deep(.el-image__inner) {
+ width: 100%;
+ height: 100%;
+ object-fit: contain;
+}
+
+.stage-tag {
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ padding: 3px 8px;
+ border-radius: 5px;
+ background: rgba(15, 23, 42, 0.75);
+ backdrop-filter: blur(4px);
+ color: #ffffff;
+ font-size: 11px;
+ font-weight: 600;
+ z-index: 2;
+}
+
+.stage-zoom-hint {
+ position: absolute;
+ bottom: 8px;
+ right: 8px;
+ display: inline-flex;
+ align-items: center;
+ gap: 4px;
+ padding: 3px 8px;
+ border-radius: 999px;
+ background: rgba(15, 23, 42, 0.65);
+ backdrop-filter: blur(4px);
+ color: #f1f5f9;
+ font-size: 10px;
+ z-index: 2;
+}
+
+.stage-empty {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 100%;
+ color: #64748b;
+ font-size: 12px;
+}
+
+/* 胶卷导轨缩略图 */
+.thumbnail-filmstrip {
+ display: flex;
+ gap: 8px;
+ margin-top: 10px;
+ overflow-x: auto;
+ padding-bottom: 2px;
+}
+
+.thumbnail-item {
+ flex: 0 0 76px;
+ height: 52px;
+ position: relative;
+ border-radius: 6px;
+ overflow: hidden;
+ border: 2px solid transparent;
+ background: #0f172a;
+ cursor: pointer;
+ padding: 0;
+ transition: all 0.15s ease;
+}
+
+.thumbnail-item.is-active {
+ border-color: #ff6a00;
+ box-shadow: 0 0 0 1px rgba(255, 106, 0, 0.3);
+}
+
+.thumb-img {
width: 100%;
height: 100%;
object-fit: cover;
}
-.screenshot-item figcaption {
- margin-top: 4px;
- color: #6b7280;
- font-size: 11px;
- font-weight: 700;
+.thumbnail-item :deep(.el-image) {
+ width: 100%;
+ height: 100%;
+}
+
+.thumbnail-item :deep(.el-image__inner) {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+}
+
+.thumb-label {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ background: rgba(15, 23, 42, 0.78);
+ color: #ffffff;
+ font-size: 9.5px;
+ font-weight: 500;
text-align: center;
+ padding: 1px 2px;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+/* ========== 3. 账号核心档案矩阵 (Specs Card) ========== */
+.secondary-chips-flow {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 6px;
+ margin-bottom: 12px;
+}
+
+.secondary-spec-pill {
+ display: inline-flex;
+ align-items: center;
+ gap: 4px;
+ padding: 3px 8px;
+ border-radius: 6px;
+ background: #f8fafc;
+ border: 1px solid #e2e8f0;
+ font-size: 11px;
+}
+
+.pill-k {
+ color: #64748b;
+}
+
+.pill-v {
+ color: #0f172a;
+ font-weight: 700;
+}
+
+.specs-grid {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 8px;
+}
+
+.spec-cell {
+ display: flex;
+ flex-direction: column;
+ gap: 2px;
+ padding: 8px 10px;
+ border-radius: 8px;
+ background: #f8fafc;
+ border: 1px solid #edf2f7;
+}
+
+.cell-label {
+ font-size: 11px;
+ font-weight: 500;
+ color: #64748b;
+}
+
+.cell-val {
+ font-size: 13px;
+ font-weight: 700;
+ color: #0f172a;
+ overflow-wrap: anywhere;
+}
+
+/* ========== 4. 精选皮肤展台 (Skin Card) ========== */
+.skin-groups-container {
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
+}
+
+.skin-group-block {
+ display: flex;
+ flex-direction: column;
+ gap: 6px;
+}
+
+.skin-group-header {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+}
+
+.skin-group-title {
+ font-size: 12px;
+ font-weight: 700;
+ color: #334155;
+}
+
+.skin-group-count {
+ padding: 1px 6px;
+ border-radius: 999px;
+ background: #f1f5f9;
+ color: #64748b;
+ font-size: 10px;
+ font-weight: 600;
+}
+
+.skin-pill-wrap {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 6px;
+}
+
+.skin-pill {
+ display: inline-flex;
+ align-items: center;
+ gap: 5px;
+ padding: 3px 8px;
+ border-radius: 6px;
+ background: #f8fafc;
+ border: 1px solid #e2e8f0;
+ font-size: 11.5px;
+ font-weight: 600;
+ color: #1e293b;
+}
+
+.quality-dot {
+ width: 6px;
+ height: 6px;
+ border-radius: 999px;
+ background: #94a3b8;
+ flex-shrink: 0;
+}
+
+/* 皮肤各品级颜色 */
+.skin-type-melee {
+ background: #fff7ed;
+ border-color: #fed7aa;
+ color: #c2410c;
+}
+.skin-type-melee .quality-dot {
+ background: #ea580c;
+}
+
+.skin-type-operatorRed {
+ background: #fef2f2;
+ border-color: #fecaca;
+ color: #b91c1c;
+}
+.skin-type-operatorRed .quality-dot {
+ background: #ef4444;
+}
+
+.skin-type-operatorGold {
+ background: #fffbeb;
+ border-color: #fde68a;
+ color: #b45309;
+}
+.skin-type-operatorGold .quality-dot {
+ background: #f59e0b;
+}
+
+.skin-type-weapon {
+ background: #f0fdf4;
+ border-color: #bbf7d0;
+ color: #15803d;
+}
+.skin-type-weapon .quality-dot {
+ background: #22c55e;
+}
+
+/* ========== 5. 仓库物资与额外消耗品 (Resources Card) ========== */
+.resources-grid {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 8px;
+}
+
+.resource-tile {
+ display: flex;
+ flex-direction: column;
+ gap: 6px;
+ padding: 10px;
+ border-radius: 8px;
+ background: #f8fafc;
+ border: 1px solid #edf2f7;
+}
+
+.res-top {
+ display: flex;
+ justify-content: space-between;
+ align-items: baseline;
+ gap: 4px;
+}
+
+.res-name {
+ font-size: 12px;
+ font-weight: 600;
+ color: #334155;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.res-qty {
+ font-size: 14px;
+ font-weight: 800;
+ color: #0f172a;
+ flex-shrink: 0;
+}
+
+.res-bottom {
+ display: flex;
+}
+
+.res-badge {
+ display: inline-flex;
+ align-items: center;
+ gap: 3px;
+ padding: 2px 6px;
+ border-radius: 4px;
+ font-size: 10px;
+ font-weight: 700;
+}
+
+.res-badge.gift {
+ background: #ecfdf5;
+ color: #059669;
+}
+
+.res-badge.charge {
+ background: #fff7ed;
+ color: #ea580c;
+}
+
+.res-badge.charge small {
+ font-weight: 800;
+}
+
+.res-badge.standard {
+ background: #f1f5f9;
+ color: #64748b;
+}
+
+/* ========== 6. 号主留言卡片 (Note Card) ========== */
+.seller-note-box {
+ display: flex;
+ gap: 10px;
+ align-items: flex-start;
+ padding: 12px 14px;
+ border-radius: 8px;
+ background: #f8fafc;
+ border-left: 3px solid #ff8533;
+}
+
+.note-quote-icon {
+ color: #ff8533;
+ flex-shrink: 0;
+ margin-top: 2px;
+}
+
+.note-content {
+ margin: 0;
+ font-size: 13px;
+ line-height: 1.6;
+ color: #334155;
+}
+
+/* ========== 7. 平台官方保障卡片 (Trust Card) ========== */
+.trust-features-grid {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 8px;
+}
+
+.trust-item {
+ display: flex;
+ gap: 8px;
+ align-items: flex-start;
+ padding: 10px;
+ border-radius: 8px;
+ background: #f8fafc;
+ border: 1px solid #f1f5f9;
+}
+
+.trust-icon-box {
+ width: 32px;
+ height: 32px;
+ border-radius: 6px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-shrink: 0;
+}
+
+.trust-icon-box.orange {
+ background: #fff7ed;
+ color: #ea580c;
+}
+
+.trust-icon-box.blue {
+ background: #eff6ff;
+ color: #2563eb;
+}
+
+.trust-icon-box.green {
+ background: #ecfdf5;
+ color: #059669;
+}
+
+.trust-icon-box.amber {
+ background: #fffbeb;
+ color: #d97706;
+}
+
+.trust-text strong {
+ display: block;
+ font-size: 11.5px;
+ font-weight: 700;
+ color: #0f172a;
+ margin-bottom: 2px;
+}
+
+.trust-text p {
+ margin: 0;
+ font-size: 10px;
+ color: #64748b;
+ line-height: 1.35;
}
/* ========== 底部留白 ========== */
.bottom-spacer {
- height: 20px;
+ height: 24px;
}
-/* ========== 底部下单栏 ========== */
+/* ========== 底部下单栏 (Fixed Bar) ========== */
.order-bar {
position: fixed;
left: 0;
@@ -359,18 +802,19 @@
z-index: 100;
display: flex;
align-items: center;
- gap: 10px;
- padding: 8px 12px calc(8px + env(safe-area-inset-bottom));
- background: #fff;
- border-top: 1px solid #eee;
- box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.04);
+ justify-content: space-between;
+ gap: 12px;
+ padding: 10px 14px calc(10px + env(safe-area-inset-bottom));
+ background: #ffffff;
+ border-top: 1px solid #e2e8f0;
+ box-shadow: 0 -4px 16px rgba(15, 23, 42, 0.06);
}
.order-bar-left {
- flex: 1;
display: flex;
flex-direction: column;
gap: 2px;
+ min-width: 0;
}
.order-price {
@@ -379,37 +823,74 @@
gap: 4px;
}
-.price-label {
+.price-caption {
font-size: 11px;
- color: #999;
+ font-weight: 500;
+ color: #64748b;
+}
+
+.price-total-wrap {
+ display: inline-flex;
+ align-items: baseline;
+ gap: 1px;
+}
+
+.price-currency {
+ font-size: 14px;
+ font-weight: 800;
+ color: #ff5f00;
}
.price-amount {
- font-size: 18px;
+ font-size: 20px;
font-weight: 900;
color: #ff5f00;
+ letter-spacing: -0.02em;
}
.order-price-detail {
display: flex;
- flex-wrap: wrap;
- gap: 4px 8px;
- color: #8a5a12;
+ align-items: center;
+ gap: 6px;
+ font-size: 10.5px;
+ font-weight: 600;
+ color: #64748b;
+}
+
+.deposit-tag {
+ display: inline-block;
+ padding: 1px 5px;
+ border-radius: 4px;
+ background: #f1f5f9;
+ color: #475569;
font-size: 10px;
- font-weight: 700;
- line-height: 1.3;
}
.order-btn {
flex-shrink: 0;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ gap: 6px;
+ height: 42px;
padding: 0 20px;
- height: 40px;
font-size: 14px;
- font-weight: 700;
- background: #ff6a00 !important;
+ font-weight: 800;
+ background: linear-gradient(135deg, #ff8533 0%, #ff5f00 100%) !important;
border: none !important;
+ box-shadow: 0 4px 12px rgba(255, 95, 0, 0.25);
}
+.order-btn:active {
+ opacity: 0.9;
+ transform: scale(0.98);
+}
+
+.order-btn-icon {
+ margin-right: 2px;
+}
+
+/* ========== 协议弹窗 ========== */
.agreement-popup {
max-height: 92vh;
}
diff --git a/frontend/src/features/listings/views/MobileListingDetailView.vue b/frontend/src/features/listings/views/MobileListingDetailView.vue
index 12bf339..5f29c0e 100644
--- a/frontend/src/features/listings/views/MobileListingDetailView.vue
+++ b/frontend/src/features/listings/views/MobileListingDetailView.vue
@@ -13,7 +13,7 @@ import {
} from '@/features/orders/api/orders'
import { useSessionStore } from '@/stores/session'
import AuthImage from '@/shared/components/business/AuthImage.vue'
-import { formatCent, formatMoney } from '@/shared/utils/money'
+import { formatCent, formatMoney, roundMoney } from '@/shared/utils/money'
import {
assetRegions,
formatAssetNumber,
@@ -31,9 +31,12 @@ import {
getListingSubtitle,
getListingTitle,
getLoginMethod,
+ getOnlineTimeText,
getServerRegion,
readAssetNumber,
readAssetString,
+ getRatioValue,
+ isTopTierInsurance,
} from '@/shared/utils/listingDisplay'
const route = useRoute()
@@ -75,6 +78,7 @@ onMounted(async () => {
const listingFavorited = computed(() => (listing.value ? isFavorite(listing.value.id) : false))
+// 价格拆解与格式化
const orderTotal = computed(() => {
if (!listing.value) return '0.0'
return formatMoney(getListingDisplayPrice(listing.value))
@@ -85,44 +89,71 @@ const orderPriceBreakdown = computed(() => {
return {
rent: 0,
consumable: 0,
+ total: 0,
}
}
return {
rent: getListingRentPrice(listing.value),
consumable: getListingConsumablePrice(listing.value),
+ total: roundMoney(getListingDisplayPrice(listing.value)),
}
})
-const detailMetrics = computed(() => {
- if (!listing.value) return []
- const dailyLoss = getDailyLoss(listing.value)
- const secretKD = readAssetNumber(listing.value, 'secret_kd')
- return [
- { label: '纯币', value: formatHafCoinM(getCoinWan(listing.value)), tone: 'coin' },
- {
- label: '绝密KD',
- value: secretKD > 0 ? formatAssetNumber(secretKD) : '--',
- tone: 'coin',
- },
- {
- label: '日损耗',
- value: dailyLoss ? `${dailyLoss}/天` : '--',
- tone: 'coin',
- },
- {
- label: '预计可租',
- value: formatEstimatedRentalDuration(listing.value),
- tone: 'coin',
- },
- {
- label: '价格',
- value: `¥${formatMoney(getListingDisplayPrice(listing.value))}`,
- tone: 'price',
- },
- { label: '押金', value: `¥${formatCent(listing.value.deposit_amount_cent)}`, tone: '' },
- ]
+// 核心资产微卡计算(完全对齐 PC 首页及详情页设计标准)
+const hafCoinDisplay = computed(() => {
+ if (!listing.value) return '--'
+ return formatHafCoinM(getCoinWan(listing.value))
})
+const insuranceSlot = computed(() => {
+ if (!listing.value) return '--'
+ return readAssetString(listing.value, 'season_insurance') || '--'
+})
+
+const isTopTierInsuranceSlot = computed(() => isTopTierInsurance(insuranceSlot.value))
+
+const ratioValue = computed(() => {
+ if (!listing.value) return 0
+ return getRatioValue(listing.value)
+})
+
+const ratioDisplay = computed(() => {
+ if (ratioValue.value <= 0) return null
+ return `1元 = ${ratioValue.value.toFixed(1)}w`
+})
+
+const rentalDuration = computed(() => {
+ if (!listing.value) return '--'
+ return formatEstimatedRentalDuration(listing.value)
+})
+
+const dailyLoss = computed(() => {
+ if (!listing.value) return ''
+ return getDailyLoss(listing.value)
+})
+
+// 平台/区服特性徽标
+const accessTags = computed(() => {
+ if (!listing.value) return []
+ return [getServerRegion(listing.value), getLoginMethod(listing.value)]
+ .filter(Boolean)
+ .map(item => accessBadgeMeta(item))
+})
+
+function accessBadgeMeta(value: string) {
+ const text = value.trim()
+ if (text.includes('微信')) return { label: text, icon: 'wechat', tone: 'wechat' }
+ if (text.toUpperCase().includes('QQ')) return { label: text, icon: 'qq', tone: 'qq' }
+ if (text.includes('扫码')) return { label: text, icon: 'scan', tone: 'scan' }
+ if (text.includes('账') || text.includes('密码'))
+ return { label: text, icon: 'lock', tone: 'password' }
+ if (text.includes('Steam')) return { label: text, icon: 'desktop-o', tone: 'steam' }
+ return { label: text, icon: 'bookmark-o', tone: 'default' }
+}
+
+// 截图多图展台与当前选中的大图
+const activeImageIndex = ref(0)
+
const detailScreenshots = computed(() => {
if (!listing.value) return []
const groupedScreenshots = readGroupedScreenshots(listing.value)
@@ -135,15 +166,20 @@ const detailScreenshots = computed(() => {
})
const detailScreenshotUrls = computed(() => detailScreenshots.value.map(shot => shot.url))
+const activeScreenshot = computed(() => {
+ if (detailScreenshots.value.length === 0) return null
+ return detailScreenshots.value[activeImageIndex.value] || detailScreenshots.value[0]
+})
+
function readGroupedScreenshots(item: Listing) {
const groups = item.asset_summary?.screenshot_groups
if (typeof groups !== 'object' || groups === null) return []
const slots = [
{ key: 'coin', label: '纯币截图' },
- { key: 'gameId', label: '游戏ID截图' },
- { key: 'totalAsset', label: '总资产截图' },
{ key: 'tencentSecurity', label: '腾讯安全中心截图' },
{ key: 'skin', label: '皮肤截图' },
+ { key: 'gameId', label: '游戏ID截图' },
+ { key: 'totalAsset', label: '总资产截图' },
]
return slots.flatMap(slot => {
const urls = (groups as Record
)[slot.key]
@@ -156,30 +192,84 @@ function readGroupedScreenshots(item: Listing) {
})
}
+// 皮肤清单(带高光品级)
const detailSkinGroups = computed(() => {
if (!listing.value) return []
const groups = listing.value.asset_summary?.skin_groups
if (typeof groups !== 'object' || groups === null) return []
- const titles: Record = {
- melee: '近战皮肤',
- operator: '干员皮肤',
- operatorGold: '干员金皮',
- operatorRed: '干员红皮',
- weapon: '武器皮肤',
- other: '其他皮肤',
- imported: '其他皮肤',
+ const titles: Record = {
+ melee: { title: '近战皮肤', type: 'melee' },
+ operatorRed: { title: '干员红皮', type: 'operatorRed' },
+ operatorGold: { title: '干员金皮', type: 'operatorGold' },
+ operator: { title: '干员皮肤', type: 'operator' },
+ weapon: { title: '武器皮肤', type: 'weapon' },
+ other: { title: '其他皮肤', type: 'other' },
+ imported: { title: '其他皮肤', type: 'other' },
}
return Object.entries(groups as Record)
- .map(([key, value]) => ({
- key,
- title: titles[key] || key,
- options: Array.isArray(value)
- ? value.filter((skin): skin is string => typeof skin === 'string')
- : [],
- }))
+ .map(([key, value]) => {
+ const meta = titles[key] || { title: key, type: 'other' }
+ return {
+ key,
+ type: meta.type,
+ title: meta.title,
+ options: Array.isArray(value)
+ ? value.filter((skin): skin is string => typeof skin === 'string')
+ : [],
+ }
+ })
.filter(group => group.options.length)
})
+const totalSkinCount = computed(() => {
+ return detailSkinGroups.value.reduce((acc, g) => acc + g.options.length, 0)
+})
+
+// 次要规格胶囊(过滤已展示的哈夫币、保险、AWM)
+const secondaryChips = computed(() => {
+ if (!listing.value) return []
+ return getListingChips(listing.value).filter(
+ chip =>
+ chip.label !== '哈夫币' &&
+ chip.label !== '保险格数' &&
+ chip.label !== 'AWM'
+ )
+})
+
+// 账号基础档案(与 PC 对齐)
+const accountRows = computed(() => {
+ if (!listing.value) return []
+ const regions = assetRegions(listing.value)
+ const secretKD = readAssetNumber(listing.value, 'secret_kd')
+ const fireLevel = readAssetNumber(listing.value, 'fire_level')
+ return [
+ { label: '所属区服', value: getServerRegion(listing.value) || '--' },
+ { label: '上号方式', value: getLoginMethod(listing.value) || '--' },
+ { label: '游戏段位', value: listing.value.rank_level || '--' },
+ { label: '烽火等级', value: fireLevel > 0 ? `${fireLevel}级` : '--' },
+ { label: '体力等级', value: readAssetString(listing.value, 'stamina_level') || '--' },
+ { label: '负重等级', value: readAssetString(listing.value, 'load_level') || '--' },
+ { label: '绝密KD', value: secretKD > 0 ? formatAssetNumber(secretKD) : '--' },
+ { label: 'M单价', value: formatRatio(listing.value) },
+ { label: '方便上号', value: getOnlineTimeText(listing.value) || '--' },
+ { label: '预计可租', value: formatEstimatedRentalDuration(listing.value) },
+ { label: '常用登录地', value: regions.length ? regions.join('、') : '--' },
+ { label: '封禁记录', value: readAssetString(listing.value, 'ban_record') || '无封禁记录' },
+ ]
+})
+
+// 仓库物资
+const resourceItems = computed(() => {
+ if (!listing.value) return []
+ return getListingResources(listing.value)
+})
+
+function formatResourceQuantity(resource: any) {
+ const suffix = resource.key === 'awmAmmo' ? '发' : ''
+ const val = Number.isInteger(resource.quantity) ? String(resource.quantity) : resource.quantity.toFixed(1)
+ return `${val}${suffix}`
+}
+
/* 下单 */
async function handleCreateOrder() {
if (!listing.value) return
@@ -318,174 +408,307 @@ function handleToggleFavorite() {
-
+
-
- 防骗提示:下单后请按平台交接流程确认收号与归还,不要私下交易。
+
+ 平台官方担保:下单后请按平台交接流程确认收号与归还,切勿脱离平台私下交易。
-
-
-
-
-
- 暂无截图
-
-
-
- {{ detailScreenshots.length }}张
-
-
+
+