前端各页面对接数据

This commit is contained in:
2026-02-02 17:34:31 +08:00
parent d57592ca7d
commit b6200cda28
25 changed files with 7634 additions and 1977 deletions

View File

@@ -373,7 +373,18 @@ export default {
// 尝试多种方式访问属性
const idValue = dbProduct.id !== undefined ? dbProduct.id : (dbProduct['id'] !== undefined ? dbProduct['id'] : undefined)
const nameValue = dbProduct.name !== undefined ? dbProduct.name : (dbProduct['name'] !== undefined ? dbProduct['name'] : undefined)
const priceValue = dbProduct.price !== undefined ? dbProduct.price : (dbProduct['price'] !== undefined ? dbProduct['price'] : undefined)
// 价格字段兼容性处理:优先查找 price其次查找 base_price
let priceValue = dbProduct.price
if (priceValue === undefined || priceValue === null) {
priceValue = dbProduct.base_price
}
if (priceValue === undefined || priceValue === null) {
priceValue = dbProduct['price']
}
if (priceValue === undefined || priceValue === null) {
priceValue = dbProduct['base_price']
}
const hasId = idValue !== undefined && idValue !== null
const hasName = nameValue !== undefined && nameValue !== null
@@ -396,33 +407,27 @@ export default {
// 数据库Product接口和本地ProductType接口字段可能不同
const images = [] as Array<string>
// 处理图片字段优先使用images字段其次使用image字段
console.log('处理数据库图片字段:')
console.log('dbProduct.images:', dbProduct.images, '类型:', typeof dbProduct.images)
console.log('dbProduct.image:', dbProduct.image, '类型:', typeof dbProduct.image)
// 处理图片字段优先使用image_urls字段其次使用main_image_url
console.log('处理数据库图片字段')
// 尝试从数据库的images字段获取图片可能是字符串或数组
if (dbProduct.images) {
// 尝试从数据库的image_urls字段获取图片JSON字符串或对象
if (dbProduct.image_urls) {
let imagesArray: any[] = []
if (typeof dbProduct.images === 'string') {
if (typeof dbProduct.image_urls === 'string') {
try {
imagesArray = JSON.parse(dbProduct.images)
console.log('解析images字符串成功:', imagesArray)
imagesArray = JSON.parse(dbProduct.image_urls)
} catch (e) {
console.error('解析images字段失败:', e, dbProduct.images)
// 如果不是JSON尝试逗号分割
if (dbProduct.images.includes(',')) {
imagesArray = dbProduct.images.split(',').map((img: string) => img.trim())
} else if (dbProduct.images) {
imagesArray = [dbProduct.images]
console.error('解析image_urls字段失败:', e, dbProduct.image_urls)
// 尝试逗号分割
if (dbProduct.image_urls.includes(',')) {
imagesArray = dbProduct.image_urls.split(',').map((img: string) => img.trim())
}
}
} else if (Array.isArray(dbProduct.images)) {
imagesArray = dbProduct.images
} else if (Array.isArray(dbProduct.image_urls)) {
imagesArray = dbProduct.image_urls
}
if (imagesArray.length > 0) {
console.log('从数据库images字段获取图片数组:', imagesArray)
for (const img of imagesArray) {
if (typeof img === 'string' && img) {
images.push(img)
@@ -430,11 +435,18 @@ export default {
}
}
}
// 如果没有从images字段获取到图片尝试使用image字段
// 如果没有获取到相册图,但有主图,放入相册
if (dbProduct.main_image_url) {
// 如果相册里没有这张图,把它加到第一位
if (!images.includes(dbProduct.main_image_url)) {
images.unshift(dbProduct.main_image_url)
}
}
// 兼容旧字段 image
if (images.length === 0 && dbProduct.image) {
console.log('使用单张图片字段:', dbProduct.image)
images.push(dbProduct.image)
images.push(dbProduct.image)
}
// 如果仍然没有图片,使用传入的图片或默认图片
@@ -461,9 +473,33 @@ export default {
const merchantId = dbProduct.shop_id || dbProduct.merchant_id || 'merchant_001'
// 确保数值字段有效
const price = typeof dbProduct.price === 'number' ? dbProduct.price : 0
const stock = (dbProduct.stock != null && !isNaN(Number(dbProduct.stock))) ? Math.floor(Number(dbProduct.stock)) : 100
const sales = (dbProduct.sales != null && !isNaN(Number(dbProduct.sales))) ? Math.floor(Number(dbProduct.sales)) : 50
// 优先使用 price不存在则使用 base_price
let productPrice = 0
if (typeof dbProduct.price === 'number') {
productPrice = dbProduct.price
} else if (typeof dbProduct.base_price === 'number') {
productPrice = dbProduct.base_price
} else if (priceValue !== undefined) {
// 使用上面校验时获取到的 priceValue
productPrice = Number(priceValue)
}
const stock = (dbProduct.stock != null && !isNaN(Number(dbProduct.stock))) ? Math.floor(Number(dbProduct.stock)) : ((dbProduct.total_stock != null && !isNaN(Number(dbProduct.total_stock))) ? Math.floor(Number(dbProduct.total_stock)) : 100)
const sales = (dbProduct.sales != null && !isNaN(Number(dbProduct.sales))) ? Math.floor(Number(dbProduct.sales)) : ((dbProduct.sale_count != null && !isNaN(Number(dbProduct.sale_count))) ? Math.floor(Number(dbProduct.sale_count)) : 50)
// 解析 attributes
let attributes: any = {}
if (dbProduct.attributes) {
try {
if (typeof dbProduct.attributes === 'string') {
attributes = JSON.parse(dbProduct.attributes)
} else {
attributes = dbProduct.attributes
}
} catch (e) {
console.error('解析 attributes 失败', e)
}
}
this.product = {
id: dbProduct.id || productId,
@@ -472,20 +508,20 @@ export default {
name: dbProduct.name || '商品名称',
description: dbProduct.description || '这是一个高品质的商品,具有优秀的性能和优美的外观设计。采用环保材料,经过严格质检,保证用户的使用体验。',
images: images,
price: price,
original_price: (dbProduct.original_price != null && !isNaN(Number(dbProduct.original_price))) ? Number(dbProduct.original_price) : null,
price: productPrice,
original_price: (dbProduct.original_price != null && !isNaN(Number(dbProduct.original_price))) ? Number(dbProduct.original_price) : ((dbProduct.market_price != null && !isNaN(Number(dbProduct.market_price))) ? Number(dbProduct.market_price) : null),
stock: stock,
sales: sales,
status: 1,
created_at: dbProduct.created_at || '2024-01-01',
// 药品相关字段
specification: dbProduct.specification || null,
usage: dbProduct.usage || null,
side_effects: dbProduct.side_effects || null,
precautions: dbProduct.precautions || null,
expiry_date: dbProduct.expiry_date || null,
storage_conditions: dbProduct.storage_conditions || null,
approval_number: dbProduct.approval_number || null,
specification: attributes.specification || dbProduct.specification || null,
usage: attributes.usage || dbProduct.usage || null,
side_effects: attributes.side_effects || dbProduct.side_effects || null,
precautions: attributes.precautions || dbProduct.precautions || null,
expiry_date: attributes.expiry_date || dbProduct.expiry_date || null,
storage_conditions: attributes.storage_conditions || dbProduct.storage_conditions || null,
approval_number: attributes.approval_number || dbProduct.approval_number || null,
tags: dbProduct.tags ? (typeof dbProduct.tags === 'string' ? JSON.parse(dbProduct.tags) : dbProduct.tags) : []
} as ProductType
console.log('页面 product 对象已更新:', this.product)
@@ -535,37 +571,109 @@ export default {
}
}
// 根据商家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: 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: shopDescriptions[merchantIndex],
contact_name: contactNames[merchantIndex],
contact_phone: '138' + (10000000 + merchantIndex * 1111111).toString().substring(0, 8),
shop_status: 1,
rating: 4.5 + (merchantIndex * 0.1),
total_sales: 10000 + merchantIndex * 5000,
created_at: '2023-06-01'
// 尝试加载真实商户信息
let realMerchantLoaded = false
// 只有当 ID 是 UUID 格式(包含-)或者是真实数据时才尝试查询
if (this.product.merchant_id && (this.product.merchant_id.includes('-') || !this.product.merchant_id.startsWith('merchant_'))) {
console.log('尝试加载商户信息:', this.product.merchant_id)
try {
const shop = await supabaseService.getShopByMerchantId(this.product.merchant_id)
if (shop) {
console.log('加载到商户信息:', shop.shop_name)
// 确保字段存在,避免 undefined 导致构造失败
this.merchant = {
id: shop.id || '',
user_id: shop.merchant_id || '',
shop_name: shop.shop_name || '未命名店铺',
shop_logo: shop.shop_logo || '/static/default-shop.png',
shop_banner: shop.shop_banner || '/static/default-banner.png',
shop_description: shop.description || '',
contact_name: shop.contact_name || '店主',
contact_phone: shop.contact_phone || '',
shop_status: 1,
// 优先使用 avg_rating没有则使用默认值
rating: shop.rating_avg !== undefined && shop.rating_avg !== null ? shop.rating_avg : 4.8,
// 使用 order_count 或 product_count 作为销量/活跃度指标,如果没有则默认 0
total_sales: shop.total_sales !== undefined ? shop.total_sales : (shop.order_count !== undefined ? shop.order_count : 0),
created_at: shop.created_at || new Date().toISOString()
} as MerchantType
realMerchantLoaded = true
}
} catch (e) {
console.error('加载商户信息失败', e)
}
}
if (!realMerchantLoaded) {
// 根据商家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: 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: shopDescriptions[merchantIndex],
contact_name: contactNames[merchantIndex],
contact_phone: '138' + (10000000 + merchantIndex * 1111111).toString().substring(0, 8),
shop_status: 1,
rating: 4.5 + (merchantIndex * 0.1),
total_sales: 10000 + merchantIndex * 5000,
created_at: '2023-06-01'
}
}
this.loadProductSkus(productId)
},
loadProductSkus(productId: string) {
async loadProductSkus(productId: string) {
// 尝试从数据库加载SKU
try {
const skus = await supabaseService.getProductSkus(productId)
if (skus.length > 0) {
console.log('加载到商品SKU:', skus.length)
this.productSkus = skus.map((sku): ProductSkuType => {
let specs: UTSJSONObject = {}
if (sku.specifications) {
try {
if (typeof sku.specifications === 'string') {
specs = JSON.parse(sku.specifications) as UTSJSONObject
} else {
// 假设已经是对象
specs = sku.specifications as unknown as UTSJSONObject
}
} catch(e) {
console.error('解析SKU规格失败', e)
}
}
return {
id: sku.id,
product_id: sku.product_id,
sku_code: sku.sku_code,
specifications: specs,
price: sku.price,
stock: sku.stock !== undefined ? sku.stock : 0,
image_url: sku.image_url || '',
status: sku.status !== undefined ? sku.status : 1
} as ProductSkuType
})
return
}
} catch (e) {
console.error('Fetch SKUs error', e)
}
// 模拟加载商品SKU数据
const basePrice = this.product.price
@@ -620,7 +728,7 @@ export default {
return sku.sku_code
},
addToCart() {
async addToCart() {
if (!this.selectedSkuId) {
uni.showToast({
title: '请选择规格',
@@ -629,50 +737,42 @@ export default {
return
}
// 获取现有购物车数据
const cartData = uni.getStorageSync('cart')
let cartItems: any[] = []
if (cartData) {
try {
cartItems = JSON.parse(cartData as string) as any[]
} catch (e) {
console.error('解析购物车数据失败', e)
}
}
// 检查商品是否已存在 (同一SKU)
const existingItem = cartItems.find((item: any) => item.id === this.selectedSkuId)
if (existingItem) {
existingItem.quantity += this.quantity
} else {
// 查找SKU信息
const sku = this.productSkus.find(s => s.id === this.selectedSkuId)
// 添加新商品
cartItems.push({
id: this.selectedSkuId, // 使用SKU ID作为购物车条目ID
productId: this.product.id,
shopId: this.merchant.id,
shopName: this.merchant.shop_name,
name: this.product.name,
price: sku ? sku.price : this.product.price,
image: (sku && sku.image_url) ? sku.image_url : this.product.images[0],
spec: this.selectedSpec,
quantity: this.quantity,
selected: true
})
}
// 保存回存储
uni.setStorageSync('cart', JSON.stringify(cartItems))
// 模拟添加到购物车
uni.showToast({
title: '已添加到购物车',
icon: 'success'
// 显示加载中
uni.showLoading({
title: '添加中...'
})
try {
// 调用 Supabase 服务添加到购物车
// 传递 productId, quantity, skuId
const success = await supabaseService.addToCart(
this.product.id,
this.quantity,
this.selectedSkuId
)
uni.hideLoading()
if (success) {
uni.showToast({
title: '已添加到购物车',
icon: 'success'
})
} else {
console.error('添加购物车返回失败')
uni.showToast({
title: '添加失败,请登录重试',
icon: 'none'
})
}
} catch (e) {
uni.hideLoading()
console.error('添加购物车异常', e)
uni.showToast({
title: '添加异常',
icon: 'none'
})
}
},
buyNow() {
@@ -787,6 +887,14 @@ export default {
})
},
goToShop() {
if (this.merchant.user_id) {
uni.navigateTo({
url: `/pages/mall/consumer/shop-detail?merchantId=${this.merchant.user_id}`
})
}
},
goToCart() {
uni.switchTab({
url: '/pages/mall/consumer/cart'