consumer模块完成度95%,准备部署消费者端测试
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
<!-- 消费者端 - 商品详情页 -->
|
||||
<!-- 消费者端 - 商品详情页 -->
|
||||
<template>
|
||||
<view class="product-detail-page">
|
||||
<scroll-view class="page-scroll" scroll-y="true">
|
||||
@@ -42,54 +42,54 @@
|
||||
</view>
|
||||
|
||||
<!-- 优惠券入口 (新增) -->
|
||||
<view class="coupon-entry" @click="showCouponModal" v-if="coupons.length > 0">
|
||||
<view class="coupon-entry-left">
|
||||
<text class="coupon-entry-label">优惠</text>
|
||||
<view class="coupon-tags-row">
|
||||
<text class="coupon-tag" v-for="(coupon, index) in coupons.slice(0, 2)" :key="index">
|
||||
{{ coupon.name }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="detail-cell coupon-entry" @click="showCouponModal" v-if="coupons.length > 0">
|
||||
<text class="cell-label">优惠</text>
|
||||
<view class="cell-content flex-row">
|
||||
<text class="coupon-tag" v-for="(coupon, index) in coupons.slice(0, 2)" :key="index">
|
||||
{{ coupon.name }}
|
||||
</text>
|
||||
</view>
|
||||
<text class="coupon-arrow">领券 ></text>
|
||||
<text class="cell-arrow">领券 ></text>
|
||||
</view>
|
||||
|
||||
<!-- 商品参数 -->
|
||||
<view class="params-section" @click="showParamsModal">
|
||||
<text class="params-title">商品参数</text>
|
||||
<view class="params-summary">
|
||||
<text class="params-item" v-if="product.specification">规格: {{ product.specification }}</text>
|
||||
<text class="params-item" v-if="product.expiry_date">有效期: {{ product.expiry_date }}</text>
|
||||
<text class="params-item" v-if="product.approval_number">批准文号: {{ product.approval_number }}</text>
|
||||
<view class="detail-cell params-section" @click="showParamsModal">
|
||||
<text class="cell-label">参数</text>
|
||||
<view class="cell-content">
|
||||
<text class="params-summary-text">{{ getParamsSummary() }}</text>
|
||||
</view>
|
||||
<text class="params-arrow">></text>
|
||||
<text class="cell-arrow">></text>
|
||||
</view>
|
||||
|
||||
<!-- 规格选择 -->
|
||||
<view class="spec-section" @click="showSpecModal" v-if="productSkus.length > 0">
|
||||
<text class="spec-title">规格</text>
|
||||
<text class="spec-selected">{{ selectedSpec ?? '请选择规格' }}</text>
|
||||
<text class="spec-arrow">></text>
|
||||
<view class="detail-cell spec-section" @click="showSpecModal" v-if="productSkus.length > 0">
|
||||
<text class="cell-label">规格</text>
|
||||
<view class="cell-content">
|
||||
<text class="spec-selected">{{ selectedSpec ?? '请选择规格' }}</text>
|
||||
</view>
|
||||
<text class="cell-arrow">></text>
|
||||
</view>
|
||||
|
||||
<!-- 数量选择 -->
|
||||
<view class="quantity-section">
|
||||
<text class="quantity-title">数量</text>
|
||||
<view class="quantity-selector">
|
||||
<view class="quantity-btn minus" @click="decreaseQuantity">
|
||||
<text class="quantity-btn-text">-</text>
|
||||
</view>
|
||||
<input class="quantity-input"
|
||||
type="number"
|
||||
:value="quantity.toString()"
|
||||
:min="1"
|
||||
:max="getMaxQuantity()"
|
||||
@input="validateQuantity" />
|
||||
<view class="quantity-btn plus" @click="increaseQuantity">
|
||||
<text class="quantity-btn-text">+</text>
|
||||
<view class="detail-cell quantity-section">
|
||||
<text class="cell-label">数量</text>
|
||||
<view class="cell-content flex-row align-center justify-between">
|
||||
<view class="quantity-selector flex-row align-center">
|
||||
<view class="quantity-btn minus" @click="decreaseQuantity">
|
||||
<text class="quantity-btn-text">-</text>
|
||||
</view>
|
||||
<input class="quantity-input"
|
||||
type="number"
|
||||
:value="quantity.toString()"
|
||||
:min="1"
|
||||
:max="getMaxQuantity()"
|
||||
@input="validateQuantity" />
|
||||
<view class="quantity-btn plus" @click="increaseQuantity">
|
||||
<text class="quantity-btn-text">+</text>
|
||||
</view>
|
||||
</view>
|
||||
<text class="quantity-stock">库存{{ getAvailableStock() }}件</text>
|
||||
</view>
|
||||
<text class="quantity-stock">库存{{ getAvailableStock() }}件</text>
|
||||
</view>
|
||||
|
||||
<!-- 商品详情 -->
|
||||
@@ -111,23 +111,23 @@
|
||||
<!-- 底部操作栏 -->
|
||||
<view class="bottom-actions">
|
||||
<view class="action-buttons">
|
||||
<!-- 客服按钮 (新增) -->
|
||||
<!-- 客服按钮 -->
|
||||
<view class="action-btn" @click="contactMerchant">
|
||||
<text class="action-icon">💬</text>
|
||||
<image src="/static/icons/customer-service.png" class="action-icon-img" />
|
||||
<text class="action-text">客服</text>
|
||||
</view>
|
||||
<view class="action-btn" @click="goToCart">
|
||||
<text class="action-icon">🛒</text>
|
||||
<image src="/static/tabbar/cart.png" class="action-icon-img" />
|
||||
<text class="action-text">购物车</text>
|
||||
</view>
|
||||
<view class="action-btn" @click="toggleFavorite">
|
||||
<text class="action-icon">{{ isFavorite ? '❤️' : '🤍' }}</text>
|
||||
<image :src="isFavorite ? '/static/icons/favorite.png' : '/static/icons/favorite-active.png'" class="action-icon-img" />
|
||||
<text class="action-text">{{ isFavorite ? '已收藏' : '收藏' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="btn-group">
|
||||
<button class="cart-btn" @click="addToCart">加入购物车</button>
|
||||
<button class="buy-btn" @click="buyNow">立即购买</button>
|
||||
<button class="buy-btn" @click="buyNow">立即购买</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -696,8 +696,17 @@ export default {
|
||||
getSkuSpecText(sku: ProductSkuType): string {
|
||||
if (sku.specifications != null) {
|
||||
const specs = sku.specifications as UTSJSONObject
|
||||
// 简化处理,直接返回 JSON 字符串
|
||||
return JSON.stringify(specs)
|
||||
let specStr = ''
|
||||
// 在 UTS 中遍历 UTSJSONObject 的推荐方式
|
||||
for (const key in specs) {
|
||||
const val = specs[key]
|
||||
if (val != null) {
|
||||
specStr += (specStr === '' ? '' : ' ') + val.toString()
|
||||
}
|
||||
}
|
||||
if (specStr !== '') {
|
||||
return specStr
|
||||
}
|
||||
}
|
||||
return sku.sku_code ?? ''
|
||||
},
|
||||
@@ -877,6 +886,15 @@ export default {
|
||||
|
||||
hideParamsModal() {
|
||||
this.showParams = false
|
||||
},
|
||||
|
||||
getParamsSummary(): string {
|
||||
let summary = ''
|
||||
if (this.product.specification != null && (this.product.specification as string) != '') summary += '规格 '
|
||||
if (this.product.expiry_date != null && (this.product.expiry_date as string) != '') summary += '有效期 '
|
||||
if (this.product.approval_number != null && (this.product.approval_number as string) != '') summary += '批准文号 '
|
||||
const finalSummary = summary.trim()
|
||||
return finalSummary != '' ? finalSummary : '查看详情'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -936,7 +954,7 @@ export default {
|
||||
.current-price {
|
||||
font-size: 48rpx;
|
||||
font-weight: bold;
|
||||
color: #ff4444;
|
||||
color: #ff5000;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
@@ -1006,44 +1024,6 @@ export default {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* Coupon Entry Styles */
|
||||
.coupon-entry {
|
||||
background-color: #fff;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.coupon-entry-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
}
|
||||
.coupon-entry-label {
|
||||
font-size: 30rpx;
|
||||
color: #333;
|
||||
width: 120rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
.coupon-tags-row {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
.coupon-tag {
|
||||
font-size: 20rpx;
|
||||
color: #ff4444;
|
||||
border: 1px solid #ff4444;
|
||||
padding: 2rpx 10rpx;
|
||||
border-radius: 4rpx;
|
||||
margin-right: 15rpx;
|
||||
}
|
||||
.coupon-arrow {
|
||||
font-size: 26rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* Modal Popup Styles */
|
||||
.popup-mask {
|
||||
position: fixed;
|
||||
@@ -1100,7 +1080,7 @@ export default {
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-right: 1px dashed #ffccc7;
|
||||
color: #ff4444;
|
||||
color: #ff5000;
|
||||
}
|
||||
.coupon-amount {
|
||||
font-size: 40rpx;
|
||||
@@ -1135,7 +1115,7 @@ export default {
|
||||
color: #999;
|
||||
}
|
||||
.coupon-btn {
|
||||
background-color: #ff4444;
|
||||
background-color: #ff5000;
|
||||
color: #fff;
|
||||
font-size: 24rpx;
|
||||
padding: 0 24rpx;
|
||||
@@ -1145,48 +1125,86 @@ export default {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.spec-section {
|
||||
.product-description {
|
||||
background-color: #fff;
|
||||
padding: 30rpx;
|
||||
padding-bottom: 140rpx;
|
||||
margin-bottom: 20rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.spec-title {
|
||||
font-size: 30rpx;
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
width: 120rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.spec-selected {
|
||||
flex: 1;
|
||||
.description-text {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.spec-arrow {
|
||||
/* 统一Cell样式优化 */
|
||||
.detail-cell {
|
||||
background-color: #fff;
|
||||
padding: 32rpx 30rpx;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
border-bottom: 1rpx solid #f8f8f8;
|
||||
}
|
||||
|
||||
.cell-label {
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
width: 90rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.cell-content {
|
||||
flex: 1;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
|
||||
.cell-arrow {
|
||||
font-size: 24rpx;
|
||||
color: #ccc;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
|
||||
/* 覆盖具体板块样式 */
|
||||
.coupon-entry, .params-section, .spec-section {
|
||||
margin-bottom: 0; /* 连在一起显示 */
|
||||
}
|
||||
|
||||
.quantity-section {
|
||||
background-color: #fff;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
margin-bottom: 20rpx; /* 数量选择作为最后一项保留底边距 */
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.params-summary-text, .spec-selected {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.flex-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.align-center {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.justify-between {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.quantity-title {
|
||||
font-size: 30rpx;
|
||||
color: #333;
|
||||
width: 120rpx;
|
||||
}
|
||||
|
||||
/* 数量加减器样式 */
|
||||
.quantity-selector {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
border: 1rpx solid #e5e5e5;
|
||||
border-radius: 8rpx;
|
||||
@@ -1230,26 +1248,6 @@ export default {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.product-description {
|
||||
background-color: #fff;
|
||||
padding: 30rpx;
|
||||
padding-bottom: 140rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.description-text {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.bottom-actions {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
@@ -1280,8 +1278,9 @@ export default {
|
||||
min-width: 80rpx;
|
||||
}
|
||||
|
||||
.action-icon {
|
||||
font-size: 40rpx;
|
||||
.action-icon-img {
|
||||
width: 44rpx;
|
||||
height: 44rpx;
|
||||
margin-bottom: 4rpx;
|
||||
}
|
||||
|
||||
@@ -1308,12 +1307,13 @@ export default {
|
||||
}
|
||||
|
||||
.cart-btn {
|
||||
background-color: #ffa726;
|
||||
background-color: #ff5000;
|
||||
opacity: 0.8;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.buy-btn {
|
||||
background-color: #ff4444;
|
||||
background-color: #ff5000;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
@@ -1378,7 +1378,7 @@ export default {
|
||||
|
||||
.spec-price {
|
||||
font-size: 26rpx;
|
||||
color: #ff4444;
|
||||
color: #ff5000;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
@@ -1550,3 +1550,6 @@ export default {
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user