继续完善购物逻辑闭环,consumer模块完成度80%
This commit is contained in:
@@ -41,6 +41,26 @@
|
||||
<text class="spec-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"
|
||||
v-model="quantity"
|
||||
: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>
|
||||
|
||||
<!-- 商品详情 -->
|
||||
<view class="product-description">
|
||||
<view class="section-title">商品详情</view>
|
||||
@@ -131,13 +151,32 @@ export default {
|
||||
}
|
||||
},
|
||||
onLoad(options: any) {
|
||||
const productId = options.productId as string
|
||||
const productId = options.productId as string || options.id as string
|
||||
const productPrice = options.price ? parseFloat(options.price) : null
|
||||
const productOriginalPrice = options.original_price ? parseFloat(options.original_price) : null
|
||||
const productName = options.name as string
|
||||
const productImage = options.image as string
|
||||
|
||||
if (productId) {
|
||||
this.loadProductDetail(productId)
|
||||
this.loadProductDetail(productId, {
|
||||
price: productPrice,
|
||||
originalPrice: productOriginalPrice,
|
||||
name: productName,
|
||||
image: productImage
|
||||
})
|
||||
this.checkFavoriteStatus(productId)
|
||||
this.saveFootprint(productId)
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
displayPrice(): number {
|
||||
if (this.selectedSkuId) {
|
||||
const sku = this.productSkus.find(s => s.id === this.selectedSkuId)
|
||||
if (sku) return sku.price
|
||||
}
|
||||
return this.product.price
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
saveFootprint(productId: string) {
|
||||
const footprintData = uni.getStorageSync('footprints')
|
||||
@@ -175,39 +214,89 @@ export default {
|
||||
uni.setStorageSync('footprints', JSON.stringify(footprints))
|
||||
},
|
||||
|
||||
loadProductDetail(productId: string) {
|
||||
// 模拟加载商品详情数据
|
||||
loadProductDetail(productId: string, options: any = {}) {
|
||||
// 根据商品ID生成一个基础价格(如果没有传入价格)
|
||||
const generatePriceFromId = (id: string): number => {
|
||||
// 简单哈希函数,将字符串转换为一个在50-500之间的价格
|
||||
let hash = 0
|
||||
for (let i = 0; i < id.length; i++) {
|
||||
hash = (hash << 5) - hash + id.charCodeAt(i)
|
||||
hash |= 0 // 转换为32位整数
|
||||
}
|
||||
// 将哈希值映射到50-500之间
|
||||
const price = 50 + Math.abs(hash % 450)
|
||||
// 保留两位小数
|
||||
return parseFloat(price.toFixed(2))
|
||||
}
|
||||
|
||||
// 优先使用传入的参数,否则根据商品ID生成价格
|
||||
const basePrice = options.price ? parseFloat(options.price) : generatePriceFromId(productId)
|
||||
// 原价比现价高20%左右
|
||||
const originalPrice = options.originalPrice ? parseFloat(options.originalPrice) : parseFloat((basePrice * 1.2).toFixed(2))
|
||||
|
||||
// 根据商品ID生成不同的商品名称,使其更真实
|
||||
const productNames = [
|
||||
'高品质运动休闲鞋',
|
||||
'时尚简约双肩背包',
|
||||
'多功能智能手环',
|
||||
'便携式蓝牙音箱',
|
||||
'全自动雨伞',
|
||||
'抗菌防螨床上四件套',
|
||||
'不锈钢保温杯',
|
||||
'无线充电器',
|
||||
'高清行车记录仪',
|
||||
'智能体脂秤'
|
||||
]
|
||||
const nameIndex = Math.abs(productId.split('').reduce((acc, char) => acc + char.charCodeAt(0), 0)) % productNames.length
|
||||
const productName = options.name ? options.name : productNames[nameIndex]
|
||||
|
||||
// 模拟销量和库存,使其更真实
|
||||
const sales = 1000 + Math.abs(productId.split('').reduce((acc, char) => acc + char.charCodeAt(0), 0)) % 5000
|
||||
const stock = 50 + Math.abs(productId.split('').reduce((acc, char) => acc + char.charCodeAt(0), 0)) % 200
|
||||
|
||||
this.product = {
|
||||
id: productId,
|
||||
merchant_id: 'merchant_001',
|
||||
category_id: 'cat_001',
|
||||
name: '精选好物商品',
|
||||
description: '这是一个高品质的商品,具有优秀的性能和优美的外观设计。',
|
||||
merchant_id: 'merchant_' + (Math.abs(productId.split('').reduce((acc, char) => acc + char.charCodeAt(0), 0)) % 5 + 1).toString().padStart(3, '0'),
|
||||
category_id: 'cat_' + (Math.abs(productId.split('').reduce((acc, char) => acc + char.charCodeAt(0), 0)) % 10 + 1).toString().padStart(3, '0'),
|
||||
name: productName,
|
||||
description: '这是一个高品质的商品,具有优秀的性能和优美的外观设计。采用环保材料,经过严格质检,保证用户的使用体验。',
|
||||
images: [
|
||||
'/static/product1.jpg',
|
||||
'/static/product2.jpg',
|
||||
'/static/product3.jpg'
|
||||
],
|
||||
price: 199.99,
|
||||
original_price: 299.99,
|
||||
stock: 100,
|
||||
sales: 1256,
|
||||
price: basePrice,
|
||||
original_price: originalPrice,
|
||||
stock: stock,
|
||||
sales: sales,
|
||||
status: 1,
|
||||
created_at: '2024-01-15'
|
||||
}
|
||||
|
||||
// 根据商家ID生成不同的商家信息
|
||||
const merchantIndex = Math.abs(this.product.merchant_id.split('').reduce((acc, char) => acc + char.charCodeAt(0), 0)) % 5
|
||||
const shopNames = ['优质好店', '品牌直营店', '官方旗舰店', '专卖店', '精品小店']
|
||||
const shopDescriptions = [
|
||||
'专注品质生活',
|
||||
'品牌官方直营,正品保障',
|
||||
'厂家直销,价格优惠',
|
||||
'专注本领域十年老店',
|
||||
'用心服务每一位顾客'
|
||||
]
|
||||
const contactNames = ['店主小王', '店长小李', '经理小张', '客服小赵', '老板小钱']
|
||||
|
||||
this.merchant = {
|
||||
id: 'merchant_001',
|
||||
user_id: 'user_001',
|
||||
shop_name: '优质好店',
|
||||
id: this.product.merchant_id,
|
||||
user_id: 'user_' + (merchantIndex + 1).toString().padStart(3, '0'),
|
||||
shop_name: shopNames[merchantIndex],
|
||||
shop_logo: '/static/shop-logo.png',
|
||||
shop_banner: '/static/shop-banner.png',
|
||||
shop_description: '专注品质生活',
|
||||
contact_name: '店主小王',
|
||||
contact_phone: '13800138000',
|
||||
shop_description: shopDescriptions[merchantIndex],
|
||||
contact_name: contactNames[merchantIndex],
|
||||
contact_phone: '138' + (10000000 + merchantIndex * 1111111).toString().substring(0, 8),
|
||||
shop_status: 1,
|
||||
rating: 4.8,
|
||||
total_sales: 15680,
|
||||
rating: 4.5 + (merchantIndex * 0.1),
|
||||
total_sales: 10000 + merchantIndex * 5000,
|
||||
created_at: '2023-06-01'
|
||||
}
|
||||
|
||||
@@ -216,13 +305,15 @@ export default {
|
||||
|
||||
loadProductSkus(productId: string) {
|
||||
// 模拟加载商品SKU数据
|
||||
const basePrice = this.product.price
|
||||
|
||||
this.productSkus = [
|
||||
{
|
||||
id: 'sku_001',
|
||||
product_id: productId,
|
||||
sku_code: 'SKU001',
|
||||
specifications: { color: '红色', size: 'M' },
|
||||
price: 199.99,
|
||||
price: basePrice,
|
||||
stock: 50,
|
||||
image_url: '/static/sku1.jpg',
|
||||
status: 1
|
||||
@@ -232,7 +323,7 @@ export default {
|
||||
product_id: productId,
|
||||
sku_code: 'SKU002',
|
||||
specifications: { color: '蓝色', size: 'L' },
|
||||
price: 219.99,
|
||||
price: parseFloat((basePrice * 1.1).toFixed(2)),
|
||||
stock: 30,
|
||||
image_url: '/static/sku2.jpg',
|
||||
status: 1
|
||||
@@ -328,16 +419,30 @@ export default {
|
||||
|
||||
const sku = this.productSkus.find(s => s.id === this.selectedSkuId)
|
||||
|
||||
const selectedItem = {
|
||||
id: this.selectedSkuId,
|
||||
product_id: this.product.id,
|
||||
sku_id: this.selectedSkuId,
|
||||
product_name: this.product.name,
|
||||
product_image: (sku && sku.image_url) ? sku.image_url : this.product.images[0],
|
||||
sku_specifications: sku ? sku.specifications : {},
|
||||
price: sku ? sku.price : this.product.price,
|
||||
quantity: this.quantity
|
||||
}
|
||||
// 调试:打印价格信息
|
||||
console.log('立即购买 - 商品价格信息:')
|
||||
console.log('SKU价格:', sku ? sku.price : '无SKU')
|
||||
console.log('商品价格:', this.product.price)
|
||||
console.log('选择的价格:', (sku ? sku.price : this.product.price))
|
||||
console.log('数量:', this.quantity)
|
||||
|
||||
const selectedItem = {
|
||||
id: this.selectedSkuId,
|
||||
product_id: this.product.id,
|
||||
sku_id: this.selectedSkuId,
|
||||
product_name: this.product.name,
|
||||
product_image: (sku && sku.image_url) ? sku.image_url : this.product.images[0],
|
||||
sku_specifications: sku ? sku.specifications : {},
|
||||
price: Number(parseFloat((sku ? sku.price : this.product.price).toString()).toFixed(2)),
|
||||
quantity: Number(this.quantity)
|
||||
}
|
||||
|
||||
// 调试:打印最终传递的数据
|
||||
console.log('立即购买 - 传递的商品数据:', selectedItem)
|
||||
|
||||
// 使用Storage传递数据,避免EventChannel可能的问题
|
||||
uni.setStorageSync('checkout_type', 'buy_now')
|
||||
uni.setStorageSync('checkout_items', JSON.stringify([selectedItem]))
|
||||
|
||||
// 跳转到订单确认页
|
||||
uni.navigateTo({
|
||||
@@ -393,6 +498,7 @@ export default {
|
||||
id: this.product.id,
|
||||
name: this.product.name,
|
||||
price: this.product.price,
|
||||
original_price: this.product.original_price, // 保存原价
|
||||
image: this.product.images[0],
|
||||
sales: this.product.sales,
|
||||
shopId: this.merchant.id,
|
||||
@@ -418,6 +524,60 @@ export default {
|
||||
uni.switchTab({
|
||||
url: '/pages/mall/consumer/cart'
|
||||
})
|
||||
},
|
||||
|
||||
// 数量选择相关方法
|
||||
decreaseQuantity() {
|
||||
if (this.quantity > 1) {
|
||||
this.quantity--
|
||||
}
|
||||
},
|
||||
|
||||
increaseQuantity() {
|
||||
const maxQuantity = this.getMaxQuantity()
|
||||
if (this.quantity < maxQuantity) {
|
||||
this.quantity++
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: `最多只能购买${maxQuantity}件`,
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
validateQuantity() {
|
||||
// 确保数量是数字
|
||||
let num = parseInt(this.quantity)
|
||||
if (isNaN(num)) {
|
||||
num = 1
|
||||
}
|
||||
|
||||
// 限制在1和最大库存之间
|
||||
const maxQuantity = this.getMaxQuantity()
|
||||
if (num < 1) {
|
||||
num = 1
|
||||
} else if (num > maxQuantity) {
|
||||
num = maxQuantity
|
||||
uni.showToast({
|
||||
title: `最多只能购买${maxQuantity}件`,
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
|
||||
this.quantity = num
|
||||
},
|
||||
|
||||
getMaxQuantity() {
|
||||
// 如果有选择SKU,使用SKU的库存,否则使用商品总库存
|
||||
if (this.selectedSkuId) {
|
||||
const sku = this.productSkus.find(s => s.id === this.selectedSkuId)
|
||||
if (sku) return sku.stock
|
||||
}
|
||||
return this.product.stock
|
||||
},
|
||||
|
||||
getAvailableStock() {
|
||||
return this.getMaxQuantity()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -565,6 +725,66 @@ export default {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.quantity-section {
|
||||
background-color: #fff;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.quantity-title {
|
||||
font-size: 30rpx;
|
||||
color: #333;
|
||||
width: 120rpx;
|
||||
}
|
||||
|
||||
.quantity-selector {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: 1rpx solid #e5e5e5;
|
||||
border-radius: 8rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.quantity-btn {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.quantity-btn.minus {
|
||||
border-right: 1rpx solid #e5e5e5;
|
||||
}
|
||||
|
||||
.quantity-btn.plus {
|
||||
border-left: 1rpx solid #e5e5e5;
|
||||
}
|
||||
|
||||
.quantity-btn-text {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.quantity-input {
|
||||
width: 80rpx;
|
||||
height: 60rpx;
|
||||
text-align: center;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
border: none;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.quantity-stock {
|
||||
font-size: 24rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.product-description {
|
||||
background-color: #fff;
|
||||
padding: 30rpx;
|
||||
|
||||
Reference in New Issue
Block a user