20260227-1
This commit is contained in:
@@ -55,6 +55,7 @@ export type Product = {
|
||||
shop_id?: string
|
||||
tags?: string
|
||||
attributes?: string
|
||||
specification?: string
|
||||
created_at?: string
|
||||
updated_at?: string
|
||||
price?: number
|
||||
@@ -374,14 +375,22 @@ class SupabaseService {
|
||||
for (let i = 0; i < rawList.length; i++) {
|
||||
const item = rawList[i]
|
||||
const icon = this.getCategoryIcon(item)
|
||||
|
||||
// 安全获取属性
|
||||
const idVal = item['id']
|
||||
const nameVal = item['name']
|
||||
const descVal = item['description']
|
||||
const colorVal = item['color']
|
||||
const slugVal = item['slug']
|
||||
|
||||
const cat: Category = {
|
||||
id: item['id'] as string,
|
||||
name: item['name'] as string,
|
||||
id: (typeof idVal == 'string') ? (idVal as string) : '',
|
||||
name: (typeof nameVal == 'string') ? (nameVal as string) : '',
|
||||
icon: icon,
|
||||
description: (item['description'] as string) ?? '',
|
||||
color: (item['color'] as string) ?? '#4CAF50',
|
||||
description: (typeof descVal == 'string') ? (descVal as string) : '',
|
||||
color: (typeof colorVal == 'string') ? (colorVal as string) : '#4CAF50',
|
||||
level: 1,
|
||||
slug: item['slug'] as string
|
||||
slug: (typeof slugVal == 'string') ? (slugVal as string) : ''
|
||||
}
|
||||
categories.push(cat)
|
||||
}
|
||||
@@ -463,6 +472,7 @@ class SupabaseService {
|
||||
// 获取所有品牌
|
||||
async getBrands(): Promise<Brand[]> {
|
||||
try {
|
||||
console.log('[getBrands] 开始获取品牌数据...')
|
||||
const response = await supa
|
||||
.from('ml_brands')
|
||||
.select('*')
|
||||
@@ -476,28 +486,32 @@ class SupabaseService {
|
||||
}
|
||||
|
||||
const rawData = response.data
|
||||
console.log('[getBrands] 原始数据:', rawData)
|
||||
if (rawData == null) {
|
||||
console.log('[getBrands] 数据为空')
|
||||
return []
|
||||
}
|
||||
|
||||
const brands: Brand[] = []
|
||||
const rawList = rawData as any[]
|
||||
console.log('[getBrands] 数据条数:', rawList.length)
|
||||
for (let i: number = 0; i < rawList.length; i++) {
|
||||
const item = rawList[i]
|
||||
const brandObj = item as UTSJSONObject
|
||||
const brandObj = JSON.parse(JSON.stringify(item)) as UTSJSONObject
|
||||
const idVal = brandObj.get('id')
|
||||
const nameVal = brandObj.get('name')
|
||||
const logoVal = brandObj.get('logo_url')
|
||||
const descVal = brandObj.get('description')
|
||||
|
||||
const brand: Brand = {
|
||||
id: (typeof idVal == 'string') ? (idVal as string) : '',
|
||||
name: (typeof nameVal == 'string') ? (nameVal as string) : '',
|
||||
logo_url: (typeof logoVal == 'string') ? (logoVal as string) : '',
|
||||
description: (typeof descVal == 'string') ? (descVal as string) : ''
|
||||
id: (idVal != null && typeof idVal == 'string') ? (idVal as string) : '',
|
||||
name: (nameVal != null && typeof nameVal == 'string') ? (nameVal as string) : '',
|
||||
logo_url: (logoVal != null && typeof logoVal == 'string') ? (logoVal as string) : '',
|
||||
description: (descVal != null && typeof descVal == 'string') ? (descVal as string) : ''
|
||||
} as Brand
|
||||
brands.push(brand)
|
||||
}
|
||||
console.log('[getBrands] 返回品牌数量:', brands.length)
|
||||
return brands
|
||||
} catch (error) {
|
||||
console.error('获取品牌异常:', error)
|
||||
@@ -861,11 +875,98 @@ class SupabaseService {
|
||||
|
||||
console.log(`Fallback (Raw) found: ${(res2.data as any[]).length} products`)
|
||||
|
||||
// Map raw data to Product interface (manually if needed for extra safety)
|
||||
const mappedData: Product[] = []
|
||||
const rawData = res2.data as any[]
|
||||
for(let i = 0; i < rawData.length; i++) {
|
||||
mappedData.push(rawData[i] as Product)
|
||||
const item = rawData[i] as UTSJSONObject
|
||||
const images: string[] = []
|
||||
|
||||
const mainImageUrl = item.getString('main_image_url')
|
||||
if (mainImageUrl != null && mainImageUrl !== '') {
|
||||
images.push(mainImageUrl)
|
||||
}
|
||||
|
||||
const imageUrlsRaw = item.get('image_urls')
|
||||
if (imageUrlsRaw != null) {
|
||||
try {
|
||||
if (Array.isArray(imageUrlsRaw)) {
|
||||
const arr = imageUrlsRaw as string[]
|
||||
if (arr.length > 0 && images.length === 0) {
|
||||
for (let j = 0; j < arr.length; j++) {
|
||||
images.push(arr[j])
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const rawUrlStr = imageUrlsRaw as string
|
||||
if (rawUrlStr.startsWith('[')) {
|
||||
const parsed = JSON.parse(rawUrlStr)
|
||||
if (Array.isArray(parsed) && images.length === 0) {
|
||||
for (let j = 0; j < parsed.length; j++) {
|
||||
images.push(parsed[j] as string)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (images.indexOf(rawUrlStr) === -1) images.push(rawUrlStr)
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
console.error('解析图片数组失败:', e)
|
||||
}
|
||||
}
|
||||
|
||||
if (images.length === 0) {
|
||||
images.push('/static/default-product.png')
|
||||
}
|
||||
|
||||
let safePrice = item.getNumber('base_price')
|
||||
if (safePrice == null) {
|
||||
const p = item.getNumber('price')
|
||||
safePrice = p != null ? p : 0
|
||||
}
|
||||
|
||||
let safeOriginalPrice = item.getNumber('market_price')
|
||||
if (safeOriginalPrice == null) {
|
||||
const op = item.getNumber('original_price')
|
||||
safeOriginalPrice = op != null ? op : safePrice
|
||||
}
|
||||
|
||||
let safeStock = item.getNumber('total_stock')
|
||||
if (safeStock == null) {
|
||||
let as_ = item.getNumber('available_stock')
|
||||
if (as_ == null) {
|
||||
const s = item.getNumber('stock')
|
||||
safeStock = s != null ? s : 0
|
||||
} else {
|
||||
safeStock = as_
|
||||
}
|
||||
}
|
||||
|
||||
let safeSales = item.getNumber('sale_count')
|
||||
if (safeSales == null) {
|
||||
const s = item.getNumber('sales')
|
||||
safeSales = s != null ? s : 0
|
||||
}
|
||||
|
||||
const product: Product = {
|
||||
id: item.getString('id') ?? '',
|
||||
category_id: item.getString('category_id') ?? '',
|
||||
merchant_id: item.getString('merchant_id') ?? '',
|
||||
name: item.getString('name') ?? '',
|
||||
description: item.getString('description') ?? '',
|
||||
images: images,
|
||||
price: safePrice,
|
||||
original_price: safeOriginalPrice,
|
||||
stock: safeStock,
|
||||
sales: safeSales,
|
||||
status: item.getNumber('status') ?? 1,
|
||||
created_at: item.getString('created_at') ?? '',
|
||||
base_price: safePrice,
|
||||
market_price: safeOriginalPrice,
|
||||
main_image_url: images.length > 0 ? images[0] : '',
|
||||
sale_count: safeSales,
|
||||
total_stock: safeStock
|
||||
} as Product
|
||||
mappedData.push(product)
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -897,6 +998,171 @@ class SupabaseService {
|
||||
}
|
||||
}
|
||||
|
||||
// 根据店铺ID获取商品列表(新增)
|
||||
async getProductsByShopId(shopId: string, page: number = 1, limit: number = 20): Promise<PaginatedResponse<Product>> {
|
||||
try {
|
||||
console.log('getProductsByShopId querying for:', shopId)
|
||||
|
||||
// 1. Try fetching from view with shop_id
|
||||
let query = supa
|
||||
.from('ml_products_detail_view')
|
||||
.select('*', { count: 'exact' })
|
||||
.eq('shop_id', shopId)
|
||||
.order('created_at', { ascending: false })
|
||||
.page(page)
|
||||
.limit(limit)
|
||||
|
||||
const response = await query.execute()
|
||||
|
||||
// 检查视图结果:如果有错误 OR 数据为空,都尝试去查原始表
|
||||
if (response.error != null || (response.data != null && (response.data as any[]).length === 0)) {
|
||||
if (response.error != null) {
|
||||
console.error('获取店铺商品失败 (View):', response.error)
|
||||
} else {
|
||||
console.log('View returned 0 products, trying raw table fallback...')
|
||||
}
|
||||
|
||||
// Fallback: Try raw table with shop_id
|
||||
console.log('Falling back to raw ml_products table with shop_id...')
|
||||
const query2 = supa
|
||||
.from('ml_products')
|
||||
.select('*', { count: 'exact' })
|
||||
.eq('shop_id', shopId)
|
||||
.order('created_at', { ascending: false })
|
||||
.page(page)
|
||||
.limit(limit)
|
||||
|
||||
const res2 = await query2.execute()
|
||||
if (res2.error != null) {
|
||||
console.error('获取店铺商品失败 (Raw):', res2.error)
|
||||
return {data:[] as Product[], total:0, page, limit, hasmore:false}
|
||||
}
|
||||
|
||||
console.log(`Fallback (Raw) found: ${(res2.data as any[]).length} products`)
|
||||
|
||||
const mappedData: Product[] = []
|
||||
const rawData = res2.data as any[]
|
||||
for(let i = 0; i < rawData.length; i++) {
|
||||
const item = rawData[i] as UTSJSONObject
|
||||
const images: string[] = []
|
||||
|
||||
const mainImageUrl = item.getString('main_image_url')
|
||||
if (mainImageUrl != null && mainImageUrl !== '') {
|
||||
images.push(mainImageUrl)
|
||||
}
|
||||
|
||||
const imageUrlsRaw = item.get('image_urls')
|
||||
if (imageUrlsRaw != null) {
|
||||
try {
|
||||
if (Array.isArray(imageUrlsRaw)) {
|
||||
const arr = imageUrlsRaw as string[]
|
||||
if (arr.length > 0 && images.length === 0) {
|
||||
for (let j = 0; j < arr.length; j++) {
|
||||
images.push(arr[j])
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const rawUrlStr = imageUrlsRaw as string
|
||||
if (rawUrlStr.startsWith('[')) {
|
||||
const parsed = JSON.parse(rawUrlStr)
|
||||
if (Array.isArray(parsed) && images.length === 0) {
|
||||
for (let j = 0; j < parsed.length; j++) {
|
||||
images.push(parsed[j] as string)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (images.indexOf(rawUrlStr) === -1) images.push(rawUrlStr)
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
console.error('解析图片数组失败:', e)
|
||||
}
|
||||
}
|
||||
|
||||
if (images.length === 0) {
|
||||
images.push('/static/default-product.png')
|
||||
}
|
||||
|
||||
let safePrice = item.getNumber('base_price')
|
||||
if (safePrice == null) {
|
||||
const p = item.getNumber('price')
|
||||
safePrice = p != null ? p : 0
|
||||
}
|
||||
|
||||
let safeOriginalPrice = item.getNumber('market_price')
|
||||
if (safeOriginalPrice == null) {
|
||||
const op = item.getNumber('original_price')
|
||||
safeOriginalPrice = op != null ? op : safePrice
|
||||
}
|
||||
|
||||
let safeStock = item.getNumber('total_stock')
|
||||
if (safeStock == null) {
|
||||
let as_ = item.getNumber('available_stock')
|
||||
if (as_ == null) {
|
||||
const s = item.getNumber('stock')
|
||||
safeStock = s != null ? s : 0
|
||||
} else {
|
||||
safeStock = as_
|
||||
}
|
||||
}
|
||||
|
||||
let safeSales = item.getNumber('sale_count')
|
||||
if (safeSales == null) {
|
||||
const s = item.getNumber('sales')
|
||||
safeSales = s != null ? s : 0
|
||||
}
|
||||
|
||||
const product: Product = {
|
||||
id: item.getString('id') ?? '',
|
||||
category_id: item.getString('category_id') ?? '',
|
||||
merchant_id: item.getString('merchant_id') ?? '',
|
||||
name: item.getString('name') ?? '',
|
||||
description: item.getString('description') ?? '',
|
||||
images: images,
|
||||
price: safePrice,
|
||||
original_price: safeOriginalPrice,
|
||||
stock: safeStock,
|
||||
sales: safeSales,
|
||||
status: item.getNumber('status') ?? 1,
|
||||
created_at: item.getString('created_at') ?? '',
|
||||
base_price: safePrice,
|
||||
market_price: safeOriginalPrice,
|
||||
main_image_url: images.length > 0 ? images[0] : '',
|
||||
sale_count: safeSales,
|
||||
total_stock: safeStock
|
||||
} as Product
|
||||
mappedData.push(product)
|
||||
}
|
||||
|
||||
return {
|
||||
data: mappedData,
|
||||
total: res2.total ?? 0,
|
||||
page,
|
||||
limit,
|
||||
hasmore: res2.hasmore ?? false
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Shop products found: ${(response.data as any[]).length}`)
|
||||
return {
|
||||
data: response.data as Product[],
|
||||
total: response.total ?? 0,
|
||||
page,
|
||||
limit,
|
||||
hasmore: response.hasmore ?? false
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取店铺商品异常:', error)
|
||||
return {
|
||||
data: [] as Product[],
|
||||
total: 0,
|
||||
page,
|
||||
limit,
|
||||
hasmore: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取热销商品(按销量排序)
|
||||
async getHotProducts(limit: number = 10): Promise<Product[]> {
|
||||
try {
|
||||
@@ -914,7 +1180,53 @@ class SupabaseService {
|
||||
return []
|
||||
}
|
||||
|
||||
return response.data as Product[]
|
||||
const rawData = response.data
|
||||
if (rawData == null) {
|
||||
return []
|
||||
}
|
||||
|
||||
const products: Product[] = []
|
||||
const rawList = rawData as any[]
|
||||
for (let i: number = 0; i < rawList.length; i++) {
|
||||
const item = rawList[i]
|
||||
const prodObj = item as UTSJSONObject
|
||||
const imagesRaw = prodObj.getArray('images')
|
||||
let safePrice = prodObj.getNumber('base_price')
|
||||
if (safePrice == null) {
|
||||
const p = prodObj.getNumber('price')
|
||||
safePrice = p != null ? p : 0
|
||||
}
|
||||
let safeOriginalPrice = prodObj.getNumber('market_price')
|
||||
if (safeOriginalPrice == null) {
|
||||
const op = prodObj.getNumber('original_price')
|
||||
safeOriginalPrice = op != null ? op : safePrice
|
||||
}
|
||||
const product: Product = {
|
||||
id: prodObj.getString('id') ?? '',
|
||||
name: prodObj.getString('name') ?? '',
|
||||
description: prodObj.getString('description') ?? '',
|
||||
base_price: safePrice,
|
||||
price: safePrice,
|
||||
original_price: safeOriginalPrice,
|
||||
market_price: safeOriginalPrice,
|
||||
main_image_url: prodObj.getString('main_image_url') ?? prodObj.getString('image_url') ?? '',
|
||||
image_url: prodObj.getString('image_url') ?? '',
|
||||
images: imagesRaw != null ? (imagesRaw as string[]) : [] as string[],
|
||||
category_id: prodObj.getString('category_id') ?? '',
|
||||
brand_id: prodObj.getString('brand_id') ?? '',
|
||||
shop_id: prodObj.getString('shop_id') ?? '',
|
||||
stock: prodObj.getNumber('stock') ?? 0,
|
||||
sale_count: prodObj.getNumber('sale_count') ?? 0,
|
||||
status: prodObj.getNumber('status') ?? 1,
|
||||
is_featured: prodObj.getBoolean('is_featured') ?? false,
|
||||
is_new: prodObj.getBoolean('is_new') ?? false,
|
||||
rating: prodObj.getNumber('rating') ?? 0,
|
||||
review_count: prodObj.getNumber('review_count') ?? 0,
|
||||
merchant_id: prodObj.getString('merchant_id') ?? ''
|
||||
} as Product
|
||||
products.push(product)
|
||||
}
|
||||
return products
|
||||
} catch (error) {
|
||||
console.error('获取热销商品异常:', error)
|
||||
return []
|
||||
@@ -937,7 +1249,53 @@ class SupabaseService {
|
||||
return []
|
||||
}
|
||||
|
||||
return response.data as Product[]
|
||||
const rawData = response.data
|
||||
if (rawData == null) {
|
||||
return []
|
||||
}
|
||||
|
||||
const products: Product[] = []
|
||||
const rawList = rawData as any[]
|
||||
for (let i: number = 0; i < rawList.length; i++) {
|
||||
const item = rawList[i]
|
||||
const prodObj = item as UTSJSONObject
|
||||
const imagesRaw = prodObj.getArray('images')
|
||||
let safePrice = prodObj.getNumber('base_price')
|
||||
if (safePrice == null) {
|
||||
const p = prodObj.getNumber('price')
|
||||
safePrice = p != null ? p : 0
|
||||
}
|
||||
let safeOriginalPrice = prodObj.getNumber('market_price')
|
||||
if (safeOriginalPrice == null) {
|
||||
const op = prodObj.getNumber('original_price')
|
||||
safeOriginalPrice = op != null ? op : safePrice
|
||||
}
|
||||
const product: Product = {
|
||||
id: prodObj.getString('id') ?? '',
|
||||
name: prodObj.getString('name') ?? '',
|
||||
description: prodObj.getString('description') ?? '',
|
||||
base_price: safePrice,
|
||||
price: safePrice,
|
||||
original_price: safeOriginalPrice,
|
||||
market_price: safeOriginalPrice,
|
||||
main_image_url: prodObj.getString('main_image_url') ?? prodObj.getString('image_url') ?? '',
|
||||
image_url: prodObj.getString('image_url') ?? '',
|
||||
images: imagesRaw != null ? (imagesRaw as string[]) : [] as string[],
|
||||
category_id: prodObj.getString('category_id') ?? '',
|
||||
brand_id: prodObj.getString('brand_id') ?? '',
|
||||
shop_id: prodObj.getString('shop_id') ?? '',
|
||||
stock: prodObj.getNumber('stock') ?? 0,
|
||||
sale_count: prodObj.getNumber('sale_count') ?? 0,
|
||||
status: prodObj.getNumber('status') ?? 1,
|
||||
is_featured: prodObj.getBoolean('is_featured') ?? false,
|
||||
is_new: prodObj.getBoolean('is_new') ?? false,
|
||||
rating: prodObj.getNumber('rating') ?? 0,
|
||||
review_count: prodObj.getNumber('review_count') ?? 0,
|
||||
merchant_id: prodObj.getString('merchant_id') ?? ''
|
||||
} as Product
|
||||
products.push(product)
|
||||
}
|
||||
return products
|
||||
} catch (error) {
|
||||
console.error('获取价格排序商品异常:', error)
|
||||
return []
|
||||
@@ -952,7 +1310,7 @@ class SupabaseService {
|
||||
.select('*')
|
||||
.eq('is_new', true)
|
||||
.eq('status', 1)
|
||||
.order('published_at', { ascending: false }) // Use published_at for newest
|
||||
.order('published_at', { ascending: false })
|
||||
.limit(limit)
|
||||
.execute()
|
||||
|
||||
@@ -961,7 +1319,53 @@ class SupabaseService {
|
||||
return []
|
||||
}
|
||||
|
||||
return response.data as Product[]
|
||||
const rawData = response.data
|
||||
if (rawData == null) {
|
||||
return []
|
||||
}
|
||||
|
||||
const products: Product[] = []
|
||||
const rawList = rawData as any[]
|
||||
for (let i: number = 0; i < rawList.length; i++) {
|
||||
const item = rawList[i]
|
||||
const prodObj = item as UTSJSONObject
|
||||
const imagesRaw = prodObj.getArray('images')
|
||||
let safePrice = prodObj.getNumber('base_price')
|
||||
if (safePrice == null) {
|
||||
const p = prodObj.getNumber('price')
|
||||
safePrice = p != null ? p : 0
|
||||
}
|
||||
let safeOriginalPrice = prodObj.getNumber('market_price')
|
||||
if (safeOriginalPrice == null) {
|
||||
const op = prodObj.getNumber('original_price')
|
||||
safeOriginalPrice = op != null ? op : safePrice
|
||||
}
|
||||
const product: Product = {
|
||||
id: prodObj.getString('id') ?? '',
|
||||
name: prodObj.getString('name') ?? '',
|
||||
description: prodObj.getString('description') ?? '',
|
||||
base_price: safePrice,
|
||||
price: safePrice,
|
||||
original_price: safeOriginalPrice,
|
||||
market_price: safeOriginalPrice,
|
||||
main_image_url: prodObj.getString('main_image_url') ?? prodObj.getString('image_url') ?? '',
|
||||
image_url: prodObj.getString('image_url') ?? '',
|
||||
images: imagesRaw != null ? (imagesRaw as string[]) : [] as string[],
|
||||
category_id: prodObj.getString('category_id') ?? '',
|
||||
brand_id: prodObj.getString('brand_id') ?? '',
|
||||
shop_id: prodObj.getString('shop_id') ?? '',
|
||||
stock: prodObj.getNumber('stock') ?? 0,
|
||||
sale_count: prodObj.getNumber('sale_count') ?? 0,
|
||||
status: prodObj.getNumber('status') ?? 1,
|
||||
is_featured: prodObj.getBoolean('is_featured') ?? false,
|
||||
is_new: prodObj.getBoolean('is_new') ?? false,
|
||||
rating: prodObj.getNumber('rating') ?? 0,
|
||||
review_count: prodObj.getNumber('review_count') ?? 0,
|
||||
merchant_id: prodObj.getString('merchant_id') ?? ''
|
||||
} as Product
|
||||
products.push(product)
|
||||
}
|
||||
return products
|
||||
} catch (error) {
|
||||
console.error('获取新品异常:', error)
|
||||
return []
|
||||
@@ -997,12 +1401,25 @@ class SupabaseService {
|
||||
const item = rawList[i]
|
||||
const prodObj = item as UTSJSONObject
|
||||
const imagesRaw = prodObj.getArray('images')
|
||||
let safePrice = prodObj.getNumber('base_price')
|
||||
if (safePrice == null) {
|
||||
const p = prodObj.getNumber('price')
|
||||
safePrice = p != null ? p : 0
|
||||
}
|
||||
let safeOriginalPrice = prodObj.getNumber('market_price')
|
||||
if (safeOriginalPrice == null) {
|
||||
const op = prodObj.getNumber('original_price')
|
||||
safeOriginalPrice = op != null ? op : safePrice
|
||||
}
|
||||
const product: Product = {
|
||||
id: prodObj.getString('id') ?? '',
|
||||
name: prodObj.getString('name') ?? '',
|
||||
description: prodObj.getString('description') ?? '',
|
||||
price: prodObj.getNumber('price') ?? 0,
|
||||
original_price: prodObj.getNumber('original_price') ?? 0,
|
||||
base_price: safePrice,
|
||||
price: safePrice,
|
||||
original_price: safeOriginalPrice,
|
||||
market_price: safeOriginalPrice,
|
||||
main_image_url: prodObj.getString('main_image_url') ?? prodObj.getString('image_url') ?? '',
|
||||
image_url: prodObj.getString('image_url') ?? '',
|
||||
images: imagesRaw != null ? (imagesRaw as string[]) : [] as string[],
|
||||
category_id: prodObj.getString('category_id') ?? '',
|
||||
@@ -1015,7 +1432,7 @@ class SupabaseService {
|
||||
is_new: prodObj.getBoolean('is_new') ?? false,
|
||||
rating: prodObj.getNumber('rating') ?? 0,
|
||||
review_count: prodObj.getNumber('review_count') ?? 0,
|
||||
merchant_id: ''
|
||||
merchant_id: prodObj.getString('merchant_id') ?? ''
|
||||
} as Product
|
||||
products.push(product)
|
||||
}
|
||||
@@ -1169,6 +1586,7 @@ class SupabaseService {
|
||||
let selected: boolean = false
|
||||
let createdAt: string = ''
|
||||
let updatedAt: string = ''
|
||||
let cartMerchantId: string = ''
|
||||
|
||||
if (item instanceof UTSJSONObject) {
|
||||
itemId = item.getString('id') ?? ''
|
||||
@@ -1179,6 +1597,7 @@ class SupabaseService {
|
||||
selected = item.getBoolean('selected') ?? false
|
||||
createdAt = item.getString('created_at') ?? ''
|
||||
updatedAt = item.getString('updated_at') ?? ''
|
||||
cartMerchantId = item.getString('merchant_id') ?? ''
|
||||
} else {
|
||||
const iObj = JSON.parse(JSON.stringify(item)) as UTSJSONObject
|
||||
itemId = iObj.getString('id') ?? ''
|
||||
@@ -1189,12 +1608,13 @@ class SupabaseService {
|
||||
selected = iObj.getBoolean('selected') ?? false
|
||||
createdAt = iObj.getString('created_at') ?? ''
|
||||
updatedAt = iObj.getString('updated_at') ?? ''
|
||||
cartMerchantId = iObj.getString('merchant_id') ?? ''
|
||||
}
|
||||
|
||||
const product = productMap.get(productId)
|
||||
const sku = (skuId !== '' && skuMap.has(skuId)) ? skuMap.get(skuId) : null
|
||||
|
||||
let merchantId: string = ''
|
||||
let merchantId: string = cartMerchantId
|
||||
let productName: string = ''
|
||||
let productImage: string = ''
|
||||
let productPrice: number = 0
|
||||
@@ -1203,7 +1623,10 @@ class SupabaseService {
|
||||
|
||||
if (product != null) {
|
||||
if (product instanceof UTSJSONObject) {
|
||||
merchantId = product.getString('merchant_id') ?? ''
|
||||
// 优先使用购物车中的 merchant_id,如果没有则使用商品中的
|
||||
if (merchantId == '') {
|
||||
merchantId = product.getString('merchant_id') ?? ''
|
||||
}
|
||||
productName = product.getString('name') ?? ''
|
||||
productImage = product.getString('main_image_url') ?? ''
|
||||
productPrice = product.getNumber('base_price') ?? 0
|
||||
@@ -1531,7 +1954,7 @@ class SupabaseService {
|
||||
}
|
||||
|
||||
// 添加商品到购物车
|
||||
async addToCart(productId: string, quantity: number = 1, skuId?: string): Promise<boolean> {
|
||||
async addToCart(productId: string, quantity: number = 1, skuId: string = '', merchantId: string = ''): Promise<boolean> {
|
||||
try {
|
||||
const userId = this.getCurrentUserId()
|
||||
if (userId == null) {
|
||||
@@ -1540,6 +1963,7 @@ class SupabaseService {
|
||||
}
|
||||
|
||||
const realSkuId = (skuId != null && skuId.length > 0) ? skuId : null
|
||||
const realMerchantId = (merchantId != null && merchantId.length > 0) ? merchantId : null
|
||||
|
||||
// 检查商品是否已在购物车中
|
||||
// 注意:必须处理 sku_id 为空的情况,使用 is.null 过滤器
|
||||
@@ -1602,6 +2026,7 @@ class SupabaseService {
|
||||
.from('ml_shopping_cart')
|
||||
.update({
|
||||
quantity: newQty,
|
||||
merchant_id: realMerchantId,
|
||||
updated_at: new Date().toISOString()
|
||||
})
|
||||
.eq('id', itemId)
|
||||
@@ -1612,17 +2037,21 @@ class SupabaseService {
|
||||
}
|
||||
} else {
|
||||
// 商品不存在,添加新记录
|
||||
const cartPayload = new UTSJSONObject()
|
||||
cartPayload.set('user_id', userId)
|
||||
cartPayload.set('product_id', productId)
|
||||
cartPayload.set('sku_id', realSkuId)
|
||||
cartPayload.set('quantity', quantity)
|
||||
cartPayload.set('selected', true)
|
||||
cartPayload.set('created_at', new Date().toISOString())
|
||||
cartPayload.set('updated_at', new Date().toISOString())
|
||||
if (realMerchantId != null) {
|
||||
cartPayload.set('merchant_id', realMerchantId)
|
||||
}
|
||||
|
||||
response = await supa
|
||||
.from('ml_shopping_cart')
|
||||
.insert({
|
||||
user_id: userId,
|
||||
product_id: productId,
|
||||
sku_id: realSkuId,
|
||||
quantity: quantity,
|
||||
selected: true,
|
||||
created_at: new Date().toISOString(),
|
||||
updated_at: new Date().toISOString()
|
||||
})
|
||||
.insert(cartPayload)
|
||||
.execute()
|
||||
}
|
||||
|
||||
@@ -1738,12 +2167,10 @@ class SupabaseService {
|
||||
|
||||
// 删除购物车商品
|
||||
async deleteCartItem(cartItemId: string): Promise<boolean> {
|
||||
return true
|
||||
/*
|
||||
try {
|
||||
console.log('正在执行删除购物车商品,ID:', cartItemId)
|
||||
const userId = this.getCurrentUserId()
|
||||
if (!userId) {
|
||||
if (userId == null) {
|
||||
console.error('用户未登录,无法删除购物车商品')
|
||||
return false
|
||||
}
|
||||
@@ -1755,7 +2182,7 @@ class SupabaseService {
|
||||
.delete()
|
||||
.execute()
|
||||
|
||||
if (response.error) {
|
||||
if (response.error != null) {
|
||||
console.error('删除购物车商品失败:', response.error)
|
||||
return false
|
||||
}
|
||||
@@ -1765,16 +2192,13 @@ class SupabaseService {
|
||||
console.error('删除购物车商品异常:', error)
|
||||
return false
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
// 批量删除购物车商品
|
||||
async batchDeleteCartItems(cartItemIds: string[]): Promise<boolean> {
|
||||
return true
|
||||
/*
|
||||
try {
|
||||
const userId = this.getCurrentUserId()
|
||||
if (!userId) {
|
||||
if (userId == null) {
|
||||
console.error('用户未登录,无法删除购物车商品')
|
||||
return false
|
||||
}
|
||||
@@ -1782,11 +2206,11 @@ class SupabaseService {
|
||||
const response = await supa
|
||||
.from('ml_shopping_cart')
|
||||
.eq('user_id', userId)
|
||||
.in('id', cartItemIds)
|
||||
.in('id', cartItemIds as any[])
|
||||
.delete()
|
||||
.execute()
|
||||
|
||||
if (response.error) {
|
||||
if (response.error != null) {
|
||||
console.error('批量删除购物车商品失败:', response.error)
|
||||
return false
|
||||
}
|
||||
@@ -1796,16 +2220,13 @@ class SupabaseService {
|
||||
console.error('批量删除购物车商品异常:', error)
|
||||
return false
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
// 清空购物车
|
||||
async clearCart(): Promise<boolean> {
|
||||
return true
|
||||
/*
|
||||
try {
|
||||
const userId = this.getCurrentUserId()
|
||||
if (!userId) {
|
||||
if (userId == null) {
|
||||
console.error('用户未登录,无法清空购物车')
|
||||
return false
|
||||
}
|
||||
@@ -1816,7 +2237,7 @@ class SupabaseService {
|
||||
.delete()
|
||||
.execute()
|
||||
|
||||
if (response.error) {
|
||||
if (response.error != null) {
|
||||
console.error('清空购物车失败:', response.error)
|
||||
return false
|
||||
}
|
||||
@@ -1826,7 +2247,6 @@ class SupabaseService {
|
||||
console.error('清空购物车异常:', error)
|
||||
return false
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
// 获取当前用户的所有地址
|
||||
@@ -2125,9 +2545,12 @@ class SupabaseService {
|
||||
const orderNo = 'ML' + Date.now() + Math.floor(Math.random() * 1000)
|
||||
|
||||
let merchantId = orderData.merchant_id
|
||||
console.log('[CreateOrder] 原始 merchant_id:', merchantId)
|
||||
if (merchantId == null || merchantId == '' || merchantId == 'unknown') {
|
||||
console.warn('[CreateOrder] merchant_id 为空或无效,将使用 userId 作为 fallback')
|
||||
merchantId = userId
|
||||
}
|
||||
console.log('[CreateOrder] 最终使用的 merchant_id:', merchantId)
|
||||
|
||||
let shippingAddrStr = '{}'
|
||||
if (orderData.shipping_address != null) {
|
||||
@@ -2341,8 +2764,17 @@ class SupabaseService {
|
||||
const sId = group.getString('shopId')
|
||||
const shopName = group.getString('shopName')
|
||||
|
||||
console.log('[createOrdersByShop] 店铺组信息:', {
|
||||
merchant_id: mId,
|
||||
shopId: sId,
|
||||
shopName: shopName
|
||||
})
|
||||
|
||||
const finalMerchantId = (mId != null && mId != '') ? mId : (sId ?? '')
|
||||
console.log('[createOrdersByShop] 最终使用的 merchant_id:', finalMerchantId)
|
||||
|
||||
const orderId = await this.createOrder({
|
||||
merchant_id: (mId != null && mId != '') ? mId : (sId ?? ''), // 兼容旧字段
|
||||
merchant_id: finalMerchantId,
|
||||
product_amount: productAmount,
|
||||
shipping_fee: shopShippingFee,
|
||||
total_amount: shopTotal,
|
||||
@@ -2597,7 +3029,7 @@ class SupabaseService {
|
||||
const quantity = item.getNumber('quantity') ?? 1
|
||||
|
||||
if (productId != null) {
|
||||
await this.addToCart(productId, quantity, skuId ?? null)
|
||||
await this.addToCart(productId, quantity, skuId ?? '', '')
|
||||
}
|
||||
}
|
||||
return true
|
||||
@@ -3443,6 +3875,7 @@ class SupabaseService {
|
||||
fpObj.set('sales', pSales)
|
||||
fpObj.set('shopId', pShopId)
|
||||
fpObj.set('shopName', pShopName)
|
||||
fpObj.set('merchant_id', pShopId)
|
||||
fpObj.set('viewTime', viewTime)
|
||||
result.push(fpObj)
|
||||
}
|
||||
@@ -3512,6 +3945,97 @@ class SupabaseService {
|
||||
}
|
||||
}
|
||||
|
||||
// 删除单个足迹
|
||||
async deleteFootprint(productId: string): Promise<boolean> {
|
||||
try {
|
||||
const userId = this.getCurrentUserId()
|
||||
if (userId == null) {
|
||||
console.log('[deleteFootprint] 用户未登录')
|
||||
return false
|
||||
}
|
||||
|
||||
const response = await supa
|
||||
.from('ml_user_footprints')
|
||||
.eq('user_id', userId)
|
||||
.eq('product_id', productId)
|
||||
.delete()
|
||||
.execute()
|
||||
|
||||
if (response.error != null) {
|
||||
console.error('[deleteFootprint] 删除足迹失败:', response.error)
|
||||
return false
|
||||
}
|
||||
|
||||
console.log('[deleteFootprint] 删除足迹成功')
|
||||
return true
|
||||
} catch (e) {
|
||||
console.error('[deleteFootprint] 删除足迹异常:', e)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// 批量删除足迹
|
||||
async deleteFootprints(productIds: string[]): Promise<boolean> {
|
||||
try {
|
||||
const userId = this.getCurrentUserId()
|
||||
if (userId == null) {
|
||||
console.log('[deleteFootprints] 用户未登录')
|
||||
return false
|
||||
}
|
||||
|
||||
const idsAny: any[] = []
|
||||
for (let i = 0; i < productIds.length; i++) {
|
||||
idsAny.push(productIds[i])
|
||||
}
|
||||
|
||||
const response = await supa
|
||||
.from('ml_user_footprints')
|
||||
.eq('user_id', userId)
|
||||
.in('product_id', idsAny)
|
||||
.delete()
|
||||
.execute()
|
||||
|
||||
if (response.error != null) {
|
||||
console.error('[deleteFootprints] 批量删除足迹失败:', response.error)
|
||||
return false
|
||||
}
|
||||
|
||||
console.log('[deleteFootprints] 批量删除足迹成功')
|
||||
return true
|
||||
} catch (e) {
|
||||
console.error('[deleteFootprints] 批量删除足迹异常:', e)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// 清空所有足迹
|
||||
async clearFootprints(): Promise<boolean> {
|
||||
try {
|
||||
const userId = this.getCurrentUserId()
|
||||
if (userId == null) {
|
||||
console.log('[clearFootprints] 用户未登录')
|
||||
return false
|
||||
}
|
||||
|
||||
const response = await supa
|
||||
.from('ml_user_footprints')
|
||||
.eq('user_id', userId)
|
||||
.delete()
|
||||
.execute()
|
||||
|
||||
if (response.error != null) {
|
||||
console.error('[clearFootprints] 清空足迹失败:', response.error)
|
||||
return false
|
||||
}
|
||||
|
||||
console.log('[clearFootprints] 清空足迹成功')
|
||||
return true
|
||||
} catch (e) {
|
||||
console.error('[clearFootprints] 清空足迹异常:', e)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
async getAddressList(): Promise<UserAddress[]> {
|
||||
try {
|
||||
const userId = this.getCurrentUserId()
|
||||
|
||||
Reference in New Issue
Block a user