前端各页面对接数据
This commit is contained in:
@@ -1,9 +1,8 @@
|
||||
import { createClient } from '@/components/supadb/aksupa.uts'
|
||||
import { SUPA_URL, SUPA_KEY } from '@/ak/config.uts'
|
||||
import supa from '@/components/supadb/aksupainstance.uts'
|
||||
import type { AkReqResponse } from '@/uni_modules/ak-req/index.uts'
|
||||
|
||||
// 创建 Supabase 客户端
|
||||
const supa = createClient(SUPA_URL, SUPA_KEY)
|
||||
// 使用单例 Supabase 客户端
|
||||
// const supa = createClient(SUPA_URL, SUPA_KEY)
|
||||
|
||||
// 类型定义
|
||||
export interface Category {
|
||||
@@ -18,18 +17,46 @@ export interface Category {
|
||||
export interface Product {
|
||||
id: string
|
||||
category_id: string
|
||||
merchant_id: string
|
||||
name: string
|
||||
description?: string
|
||||
specification: string
|
||||
specification?: string
|
||||
price: number
|
||||
base_price?: number
|
||||
original_price?: number
|
||||
market_price?: number
|
||||
image?: string
|
||||
manufacturer: string
|
||||
main_image_url?: string
|
||||
image_urls?: string // JSON string
|
||||
manufacturer?: string
|
||||
sales?: number
|
||||
sale_count?: number
|
||||
stock?: number
|
||||
available_stock?: number
|
||||
badge?: string
|
||||
shop_id?: string
|
||||
shop_name?: string
|
||||
attributes?: string // JSON string
|
||||
created_at?: string
|
||||
expiry_date?: string
|
||||
approval_number?: string
|
||||
usage?: string
|
||||
side_effects?: string
|
||||
}
|
||||
|
||||
export interface Shop {
|
||||
id: string
|
||||
merchant_id: string
|
||||
shop_name: string
|
||||
shop_logo?: string
|
||||
shop_banner?: string
|
||||
description?: string
|
||||
contact_name?: string
|
||||
contact_phone?: string
|
||||
rating_avg?: number
|
||||
total_sales?: number
|
||||
product_count?: number
|
||||
total_sales_count?: number
|
||||
created_at?: string
|
||||
}
|
||||
|
||||
@@ -73,10 +100,33 @@ export interface PaginatedResponse<T> {
|
||||
hasmore: boolean
|
||||
}
|
||||
|
||||
export interface ProductSku {
|
||||
id: string
|
||||
product_id: string
|
||||
sku_code: string
|
||||
specifications: string // JSON string
|
||||
price: number
|
||||
market_price?: number
|
||||
cost_price?: number
|
||||
stock?: number
|
||||
warning_stock?: number
|
||||
image_url?: string
|
||||
weight?: number
|
||||
status?: number
|
||||
created_at?: string
|
||||
}
|
||||
|
||||
class SupabaseService {
|
||||
// 获取当前用户ID
|
||||
private getCurrentUserId(): string | null {
|
||||
public getCurrentUserId(): string | null {
|
||||
try {
|
||||
// 优先从 Supabase 会话获取
|
||||
const session = supa.getSession()
|
||||
if (session && session.user) {
|
||||
return session.user.getString('id')
|
||||
}
|
||||
|
||||
// 后备:尝试从本地存储获取 (兼容旧逻辑)
|
||||
const userId = uni.getStorageSync('user_id')
|
||||
return userId ? userId as string : null
|
||||
} catch (e) {
|
||||
@@ -89,7 +139,7 @@ class SupabaseService {
|
||||
async getCategories(): Promise<Category[]> {
|
||||
try {
|
||||
const response = await supa
|
||||
.from('categories')
|
||||
.from('ml_categories')
|
||||
.select('*')
|
||||
.order('name', { ascending: true })
|
||||
.execute()
|
||||
@@ -114,10 +164,10 @@ class SupabaseService {
|
||||
): Promise<PaginatedResponse<Product>> {
|
||||
try {
|
||||
const response = await supa
|
||||
.from('products')
|
||||
.from('ml_products')
|
||||
.select('*', { count: 'exact' })
|
||||
.eq('category_id', categoryId)
|
||||
.order('sales', { ascending: false })
|
||||
.order('sale_count', { ascending: false })
|
||||
.page(page)
|
||||
.limit(limit)
|
||||
.execute()
|
||||
@@ -152,6 +202,28 @@ class SupabaseService {
|
||||
}
|
||||
}
|
||||
|
||||
// 根据商品ID获取SKU列表
|
||||
async getProductSkus(productId: string): Promise<ProductSku[]> {
|
||||
try {
|
||||
const response = await supa
|
||||
.from('ml_product_skus')
|
||||
.select('*')
|
||||
.eq('product_id', productId)
|
||||
.eq('status', 1)
|
||||
.execute()
|
||||
|
||||
if (response.error) {
|
||||
console.error('获取商品SKU失败:', response.error)
|
||||
return []
|
||||
}
|
||||
|
||||
return response.data as ProductSku[]
|
||||
} catch (error) {
|
||||
console.error('获取商品SKU异常:', error)
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
// 搜索商品
|
||||
async searchProducts(
|
||||
keyword: string,
|
||||
@@ -162,18 +234,18 @@ class SupabaseService {
|
||||
): Promise<PaginatedResponse<Product>> {
|
||||
try {
|
||||
let query = supa
|
||||
.from('products')
|
||||
.from('ml_products')
|
||||
.select('*', { count: 'exact' })
|
||||
.or(`name.ilike.%${keyword}%,manufacturer.ilike.%${keyword}%,specification.ilike.%${keyword}%`)
|
||||
|
||||
// 根据sortBy和ascending设置排序
|
||||
if (sortBy === 'price') {
|
||||
query = query.order('price', { ascending })
|
||||
} else if (sortBy === 'sales') {
|
||||
query = query.order('sales', { ascending: false }) // 销量总是降序
|
||||
query = query.order('base_price', { ascending })
|
||||
} else if (sortBy === 'sales' || sortBy === 'sale_count') {
|
||||
query = query.order('sale_count', { ascending: false }) // 销量总是降序
|
||||
} else {
|
||||
// 默认按销量降序
|
||||
query = query.order('sales', { ascending: false })
|
||||
query = query.order('sale_count', { ascending: false })
|
||||
}
|
||||
|
||||
const response = await query
|
||||
@@ -215,7 +287,7 @@ class SupabaseService {
|
||||
async getProductById(productId: string): Promise<Product | null> {
|
||||
try {
|
||||
const response = await supa
|
||||
.from('products')
|
||||
.from('ml_products')
|
||||
.select('*')
|
||||
.eq('id', productId)
|
||||
.single()
|
||||
@@ -233,11 +305,80 @@ class SupabaseService {
|
||||
}
|
||||
}
|
||||
|
||||
// 根据商户ID获取店铺信息
|
||||
async getShopByMerchantId(merchantId: string): Promise<Shop | null> {
|
||||
try {
|
||||
const response = await supa
|
||||
.from('ml_shops')
|
||||
.select('*')
|
||||
.eq('merchant_id', merchantId)
|
||||
.single()
|
||||
.executeAs<Shop>()
|
||||
|
||||
if (response.error) {
|
||||
console.error('获取店铺信息失败:', response.error)
|
||||
return null
|
||||
}
|
||||
|
||||
const data = response.data
|
||||
if (Array.isArray(data)) {
|
||||
if (data.length > 0) return data[0] as Shop
|
||||
return null
|
||||
}
|
||||
return data as Shop
|
||||
} catch (error) {
|
||||
console.error('获取店铺信息异常:', error)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
// 根据商户ID获取商品列表
|
||||
async getProductsByMerchantId(merchantId: string, page: number = 1, limit: number = 20): Promise<PaginatedResponse<Product>> {
|
||||
try {
|
||||
const response = await supa
|
||||
.from('ml_products')
|
||||
.select('*', { count: 'exact' })
|
||||
.eq('merchant_id', merchantId)
|
||||
.order('created_at', { ascending: false })
|
||||
.page(page)
|
||||
.limit(limit)
|
||||
.execute()
|
||||
|
||||
if (response.error) {
|
||||
console.error('获取商户商品失败:', response.error)
|
||||
return {
|
||||
data: [],
|
||||
total: 0,
|
||||
page,
|
||||
limit,
|
||||
hasmore: false
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
data: response.data as Product[],
|
||||
total: response.total || 0,
|
||||
page,
|
||||
limit,
|
||||
hasmore: response.hasmore || false
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取商户商品异常:', error)
|
||||
return {
|
||||
data: [],
|
||||
total: 0,
|
||||
page,
|
||||
limit,
|
||||
hasmore: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取热销商品(按销量排序)
|
||||
async getHotProducts(limit: number = 10): Promise<Product[]> {
|
||||
try {
|
||||
const response = await supa
|
||||
.from('products')
|
||||
.from('ml_products')
|
||||
.select('*')
|
||||
.order('sales', { ascending: false })
|
||||
.limit(limit)
|
||||
@@ -259,7 +400,7 @@ class SupabaseService {
|
||||
async getProductsByPrice(limit: number = 10, ascending: boolean = true): Promise<Product[]> {
|
||||
try {
|
||||
const response = await supa
|
||||
.from('products')
|
||||
.from('ml_products')
|
||||
.select('*')
|
||||
.order('price', { ascending })
|
||||
.limit(limit)
|
||||
@@ -281,7 +422,7 @@ class SupabaseService {
|
||||
async getProductsByNewest(limit: number = 10): Promise<Product[]> {
|
||||
try {
|
||||
const response = await supa
|
||||
.from('products')
|
||||
.from('ml_products')
|
||||
.select('*')
|
||||
.order('created_at', { ascending: false })
|
||||
.limit(limit)
|
||||
@@ -304,7 +445,7 @@ class SupabaseService {
|
||||
try {
|
||||
// 直接使用 neq 空字符串查询,忽略 null 值(null 表示没有 badge,不应被推荐)
|
||||
const response = await supa
|
||||
.from('products')
|
||||
.from('ml_products')
|
||||
.select('*')
|
||||
.neq('badge', '')
|
||||
.order('sales', { ascending: false })
|
||||
@@ -328,7 +469,7 @@ class SupabaseService {
|
||||
async getDiscountProducts(limit: number = 10): Promise<Product[]> {
|
||||
try {
|
||||
const response = await supa
|
||||
.from('products')
|
||||
.from('ml_products')
|
||||
.select('*')
|
||||
.eq('badge', '特价')
|
||||
.order('sales', { ascending: false })
|
||||
@@ -369,14 +510,13 @@ class SupabaseService {
|
||||
selected,
|
||||
created_at,
|
||||
updated_at,
|
||||
products!inner (
|
||||
ml_products!inner (
|
||||
id,
|
||||
name,
|
||||
image,
|
||||
price,
|
||||
specification,
|
||||
shop_id,
|
||||
shop_name
|
||||
merchant_id
|
||||
)
|
||||
`)
|
||||
.eq('user_id', userId)
|
||||
@@ -387,12 +527,59 @@ class SupabaseService {
|
||||
console.error('获取购物车失败:', response.error)
|
||||
return []
|
||||
}
|
||||
|
||||
const cartData = response.data as any[]
|
||||
|
||||
// 调试日子:打印购物车数据第一条结构,确认产品字段名
|
||||
if (cartData && Array.isArray(cartData) && cartData.length > 0) {
|
||||
console.log('Cart Item Structure:', JSON.stringify(cartData[0]))
|
||||
}
|
||||
|
||||
const merchantIds: string[] = []
|
||||
|
||||
if (cartData && Array.isArray(cartData)) {
|
||||
for (const item of cartData) {
|
||||
// PostgREST 返回的关联字段通常与表名一致
|
||||
// 尝试获取ml_products,如果为空则尝试products
|
||||
let product = item['ml_products'] as any
|
||||
if (!product) {
|
||||
product = item['products'] as any
|
||||
}
|
||||
|
||||
if (product && product.merchant_id && !merchantIds.includes(product.merchant_id)) {
|
||||
merchantIds.push(product.merchant_id as string)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 查询店铺信息
|
||||
const shopMap = new Map<string, any>()
|
||||
if (merchantIds.length > 0) {
|
||||
const shopRes = await supa
|
||||
.from('ml_shops')
|
||||
.select('id, merchant_id, shop_name')
|
||||
.in('merchant_id', merchantIds)
|
||||
.execute()
|
||||
|
||||
if (!shopRes.error && shopRes.data != null) {
|
||||
const shops = shopRes.data as any[]
|
||||
for (const shop of shops) {
|
||||
shopMap.set(shop.merchant_id as string, shop)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 处理返回数据,构建CartItem数组
|
||||
const cartItems: CartItem[] = []
|
||||
if (response.data && Array.isArray(response.data)) {
|
||||
for (const item of response.data) {
|
||||
const product = item.products as any
|
||||
if (cartData && Array.isArray(cartData)) {
|
||||
for (const item of cartData) {
|
||||
let product = item['ml_products'] as any
|
||||
if (!product) {
|
||||
product = item['products'] as any
|
||||
}
|
||||
|
||||
const merchantId = product?.merchant_id as string
|
||||
const shopInfo = shopMap.get(merchantId)
|
||||
|
||||
cartItems.push({
|
||||
id: item.id as string,
|
||||
@@ -405,8 +592,8 @@ class SupabaseService {
|
||||
product_image: product?.image as string,
|
||||
product_price: product?.price as number,
|
||||
product_specification: product?.specification as string,
|
||||
shop_id: product?.shop_id as string,
|
||||
shop_name: product?.shop_name as string,
|
||||
shop_id: shopInfo ? (shopInfo['id'] as string) : (merchantId || 'unknown_shop'),
|
||||
shop_name: shopInfo ? (shopInfo['shop_name'] as string) : '未知店铺',
|
||||
created_at: item.created_at as string,
|
||||
updated_at: item.updated_at as string
|
||||
})
|
||||
@@ -430,27 +617,59 @@ class SupabaseService {
|
||||
}
|
||||
|
||||
// 检查商品是否已在购物车中
|
||||
const existingResponse = await supa
|
||||
// 注意:必须处理 sku_id 为空的情况,使用 is.null 过滤器
|
||||
let query = supa
|
||||
.from('ml_shopping_cart')
|
||||
.select('*')
|
||||
.eq('user_id', userId)
|
||||
.eq('product_id', productId)
|
||||
.eq('sku_id', skuId || '')
|
||||
.single()
|
||||
.execute()
|
||||
|
||||
if (skuId && skuId.length > 0) {
|
||||
query = query.eq('sku_id', skuId)
|
||||
} else {
|
||||
query = query.is('sku_id', null)
|
||||
}
|
||||
|
||||
const existingResponse = await query.single().execute()
|
||||
|
||||
let existingItem: any | null = null
|
||||
|
||||
if (existingResponse.data != null) {
|
||||
const rawData = existingResponse.data as any
|
||||
if (Array.isArray(rawData)) {
|
||||
if (rawData.length > 0) {
|
||||
existingItem = rawData[0]
|
||||
}
|
||||
} else {
|
||||
existingItem = rawData
|
||||
}
|
||||
}
|
||||
|
||||
let response
|
||||
if (existingResponse.data) {
|
||||
if (existingItem != null) {
|
||||
// 商品已存在,更新数量
|
||||
const existingItem = existingResponse.data as any
|
||||
response = await supa
|
||||
.from('ml_shopping_cart')
|
||||
.update({
|
||||
quantity: (existingItem.quantity || 0) + quantity,
|
||||
updated_at: new Date().toISOString()
|
||||
})
|
||||
.eq('id', existingItem.id)
|
||||
.execute()
|
||||
console.log('Found existing cart item:', JSON.stringify(existingItem))
|
||||
|
||||
// 确保 existingItem.id 存在
|
||||
const itemId = existingItem['id']
|
||||
const itemQty = existingItem['quantity']
|
||||
|
||||
if (itemId != null) {
|
||||
const currentQty = typeof itemQty === 'number' ? itemQty : parseInt(String(itemQty || 0))
|
||||
const newQty = currentQty + quantity
|
||||
|
||||
response = await supa
|
||||
.from('ml_shopping_cart')
|
||||
.update({
|
||||
quantity: newQty,
|
||||
updated_at: new Date().toISOString()
|
||||
})
|
||||
.eq('id', itemId)
|
||||
.execute()
|
||||
} else {
|
||||
console.error('购物车已有商品但缺少ID,无法更新. Data:', JSON.stringify(existingItem))
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
// 商品不存在,添加新记录
|
||||
response = await supa
|
||||
@@ -671,7 +890,7 @@ class SupabaseService {
|
||||
|
||||
const response = await supa
|
||||
.from('ml_user_addresses')
|
||||
.select('*')
|
||||
.select('*, recipient_name:receiver_name, phone:receiver_phone, detail_address:address_detail')
|
||||
.eq('user_id', userId)
|
||||
.order('is_default', { ascending: false })
|
||||
.order('created_at', { ascending: false })
|
||||
@@ -700,7 +919,7 @@ class SupabaseService {
|
||||
|
||||
const response = await supa
|
||||
.from('ml_user_addresses')
|
||||
.select('*')
|
||||
.select('*, recipient_name:receiver_name, phone:receiver_phone, detail_address:address_detail')
|
||||
.eq('id', addressId)
|
||||
.eq('user_id', userId)
|
||||
.single()
|
||||
@@ -745,12 +964,12 @@ class SupabaseService {
|
||||
.from('ml_user_addresses')
|
||||
.insert({
|
||||
user_id: userId,
|
||||
recipient_name: address.recipient_name,
|
||||
phone: address.phone,
|
||||
receiver_name: address.recipient_name,
|
||||
receiver_phone: address.phone,
|
||||
province: address.province,
|
||||
city: address.city,
|
||||
district: address.district,
|
||||
detail_address: address.detail_address,
|
||||
address_detail: address.detail_address,
|
||||
postal_code: address.postal_code || null,
|
||||
is_default: address.is_default || false,
|
||||
created_at: new Date().toISOString(),
|
||||
@@ -792,13 +1011,22 @@ class SupabaseService {
|
||||
if (address.is_default) {
|
||||
await this.clearDefaultAddress(userId)
|
||||
}
|
||||
|
||||
// 构造更新数据,映射字段名到数据库列名
|
||||
const updateData = {}
|
||||
if (address.recipient_name != null) updateData['receiver_name'] = address.recipient_name
|
||||
if (address.phone != null) updateData['receiver_phone'] = address.phone
|
||||
if (address.province != null) updateData['province'] = address.province
|
||||
if (address.city != null) updateData['city'] = address.city
|
||||
if (address.district != null) updateData['district'] = address.district
|
||||
if (address.detail_address != null) updateData['address_detail'] = address.detail_address
|
||||
if (address.postal_code != null) updateData['postal_code'] = address.postal_code
|
||||
if (address.is_default != null) updateData['is_default'] = address.is_default
|
||||
updateData['updated_at'] = new Date().toISOString()
|
||||
|
||||
const response = await supa
|
||||
.from('ml_user_addresses')
|
||||
.update({
|
||||
...address,
|
||||
updated_at: new Date().toISOString()
|
||||
})
|
||||
.update(updateData)
|
||||
.eq('id', addressId)
|
||||
.eq('user_id', userId)
|
||||
.execute()
|
||||
@@ -843,6 +1071,298 @@ class SupabaseService {
|
||||
}
|
||||
}
|
||||
|
||||
// 清除默认地址(内部使用)
|
||||
private async clearDefaultAddress(userId: string): Promise<void> {
|
||||
try {
|
||||
await supa
|
||||
.from('ml_user_addresses')
|
||||
.update({
|
||||
is_default: false,
|
||||
updated_at: new Date().toISOString()
|
||||
})
|
||||
.eq('user_id', userId)
|
||||
.eq('is_default', true)
|
||||
.execute()
|
||||
} catch (error) {
|
||||
console.error('清除默认地址异常:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 获取用户资料
|
||||
async getUserProfile(): Promise<any | null> {
|
||||
try {
|
||||
const userId = this.getCurrentUserId()
|
||||
if (!userId) return null
|
||||
|
||||
// 联合查询 auth user 和 profile
|
||||
// 由于 Supabase auth table 不可直接访问,这里查询 ml_user_profiles
|
||||
const response = await supa
|
||||
.from('ml_user_profiles')
|
||||
.select('*')
|
||||
.eq('user_id', userId)
|
||||
.single()
|
||||
.execute()
|
||||
|
||||
if (response.error) {
|
||||
// 如果不存在 profile,可能只有 auth user,这里暂时返回空或创建默认
|
||||
return null
|
||||
}
|
||||
return response.data
|
||||
} catch (e) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
// 创建订单
|
||||
async createOrder(orderData: {
|
||||
merchant_id: string,
|
||||
product_amount: number,
|
||||
shipping_fee: number,
|
||||
total_amount: number,
|
||||
shipping_address: any,
|
||||
items: any[]
|
||||
}): Promise<string | null> {
|
||||
try {
|
||||
const userId = this.getCurrentUserId()
|
||||
if (!userId) return null
|
||||
|
||||
// 生成订单号
|
||||
const orderNo = 'ORD' + Date.now() + Math.floor(Math.random() * 1000)
|
||||
|
||||
// 1. 创建主订单
|
||||
const orderResponse = await supa
|
||||
.from('ml_orders')
|
||||
.insert({
|
||||
user_id: userId,
|
||||
merchant_id: orderData.merchant_id,
|
||||
order_no: orderNo,
|
||||
product_amount: orderData.product_amount,
|
||||
shipping_fee: orderData.shipping_fee,
|
||||
total_amount: orderData.total_amount,
|
||||
paid_amount: 0,
|
||||
shipping_address: JSON.stringify(orderData.shipping_address),
|
||||
order_status: 1, // 待付款
|
||||
payment_status: 1, // 未支付
|
||||
shipping_status: 1, // 未发货
|
||||
created_at: new Date().toISOString()
|
||||
})
|
||||
.select()
|
||||
.single()
|
||||
.execute()
|
||||
|
||||
if (orderResponse.error) {
|
||||
console.error('创建订单失败:', orderResponse.error)
|
||||
return null
|
||||
}
|
||||
|
||||
const orderId = orderResponse.data['id'] as string
|
||||
|
||||
// 2. 创建订单项
|
||||
const orderItems = orderData.items.map((item: any) => ({
|
||||
order_id: orderId,
|
||||
product_id: item.product_id,
|
||||
sku_id: item.sku_id || null,
|
||||
product_name: item.product_name,
|
||||
sku_name: item.sku_name || '',
|
||||
specifications: item.specifications ? JSON.stringify(item.specifications) : '{}',
|
||||
image_url: item.image_url,
|
||||
price: item.price,
|
||||
quantity: item.quantity,
|
||||
total_amount: item.price * item.quantity,
|
||||
created_at: new Date().toISOString()
|
||||
}))
|
||||
|
||||
const itemsResponse = await supa
|
||||
.from('ml_order_items')
|
||||
.insert(orderItems)
|
||||
.execute()
|
||||
|
||||
if (itemsResponse.error) {
|
||||
console.error('创建订单项失败:', itemsResponse.error)
|
||||
// 此时应该回滚订单,但这里简化处理
|
||||
return null
|
||||
}
|
||||
|
||||
// 3. 清除购物车中已购买的商品(如果是从购物车购买)
|
||||
// 这一步通常在前端调用 removeCartItem 或在此处根据参数处理
|
||||
|
||||
return orderId
|
||||
} catch (error) {
|
||||
console.error('创建订单异常:', error)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
// 获取订单列表
|
||||
async getOrders(status: number = 0): Promise<any[]> {
|
||||
try {
|
||||
const userId = this.getCurrentUserId()
|
||||
if (!userId) return []
|
||||
|
||||
let query = supa
|
||||
.from('ml_orders')
|
||||
.select(`
|
||||
*,
|
||||
ml_order_items (*)
|
||||
`)
|
||||
.eq('user_id', userId)
|
||||
.order('created_at', { ascending: false })
|
||||
|
||||
if (status > 0) {
|
||||
query = query.eq('order_status', status)
|
||||
}
|
||||
|
||||
const response = await query.execute()
|
||||
|
||||
if (response.error) {
|
||||
console.error('获取订单列表失败:', response.error)
|
||||
return []
|
||||
}
|
||||
|
||||
return response.data || []
|
||||
} catch (error) {
|
||||
console.error('获取订单列表异常:', error)
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
// 获取订单详情
|
||||
async getOrderDetail(orderId: string): Promise<any | null> {
|
||||
try {
|
||||
const userId = this.getCurrentUserId()
|
||||
if (!userId) return null
|
||||
|
||||
const response = await supa
|
||||
.from('ml_orders')
|
||||
.select(`
|
||||
*,
|
||||
ml_order_items (*),
|
||||
ml_shops (shop_name, id)
|
||||
`)
|
||||
.eq('id', orderId)
|
||||
.eq('user_id', userId)
|
||||
.single()
|
||||
.execute()
|
||||
|
||||
if (response.error) {
|
||||
return null
|
||||
}
|
||||
return response.data
|
||||
} catch (e) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
// 收藏相关
|
||||
async checkFavorite(productId: string): Promise<boolean> {
|
||||
try {
|
||||
const userId = this.getCurrentUserId()
|
||||
if (!userId) return false
|
||||
|
||||
const response = await supa
|
||||
.from('ml_user_favorites')
|
||||
.select('id')
|
||||
.eq('user_id', userId)
|
||||
.eq('target_id', productId)
|
||||
.eq('target_type', 1) // 1 for product
|
||||
.single()
|
||||
.execute()
|
||||
|
||||
return !!response.data
|
||||
} catch(e) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
async toggleFavorite(productId: string): Promise<boolean> {
|
||||
try {
|
||||
const userId = this.getCurrentUserId()
|
||||
if (!userId) return false
|
||||
|
||||
// Check if exists
|
||||
const exists = await this.checkFavorite(productId)
|
||||
|
||||
if (exists) {
|
||||
// Delete
|
||||
await supa
|
||||
.from('ml_user_favorites')
|
||||
.delete()
|
||||
.eq('user_id', userId)
|
||||
.eq('target_id', productId)
|
||||
.eq('target_type', 1)
|
||||
.execute()
|
||||
return false // Now not favorite
|
||||
} else {
|
||||
// Add
|
||||
await supa
|
||||
.from('ml_user_favorites')
|
||||
.insert({
|
||||
user_id: userId,
|
||||
target_id: productId,
|
||||
target_type: 1,
|
||||
created_at: new Date().toISOString()
|
||||
})
|
||||
.execute()
|
||||
return true // Now favorite
|
||||
}
|
||||
} catch (e) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
async getFavorites(): Promise<any[]> {
|
||||
try {
|
||||
const userId = this.getCurrentUserId()
|
||||
if (!userId) return []
|
||||
|
||||
// 需要关联查询商品信息
|
||||
const response = await supa
|
||||
.from('ml_user_favorites')
|
||||
.select(`
|
||||
id,
|
||||
target_id,
|
||||
created_at,
|
||||
ml_products!target_id (
|
||||
id, name, image_urls, main_image_url, price, sales
|
||||
)
|
||||
`)
|
||||
.eq('user_id', userId)
|
||||
.eq('target_type', 1)
|
||||
.order('created_at', { ascending: false })
|
||||
.execute()
|
||||
|
||||
if (response.error) return []
|
||||
return response.data || []
|
||||
} catch (e) {
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async getAddressList(): Promise<UserAddress[]> {
|
||||
try {
|
||||
const userId = this.getCurrentUserId()
|
||||
if (!userId) return []
|
||||
|
||||
const response = await supa
|
||||
.from('ml_user_addresses')
|
||||
.select('*, recipient_name:receiver_name, phone:receiver_phone, detail_address:address_detail')
|
||||
.eq('user_id', userId)
|
||||
.order('is_default', { ascending: false })
|
||||
.order('created_at', { ascending: false })
|
||||
.execute()
|
||||
|
||||
if (response.error) {
|
||||
console.error('获取地址列表失败:', response.error)
|
||||
return []
|
||||
}
|
||||
return response.data as UserAddress[]
|
||||
} catch (e) {
|
||||
console.error('获取地址列表异常:', e)
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
// 设置默认地址
|
||||
async setDefaultAddress(addressId: string): Promise<boolean> {
|
||||
try {
|
||||
@@ -877,31 +1397,6 @@ class SupabaseService {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// 清除用户的默认地址(内部方法)
|
||||
private async clearDefaultAddress(userId: string): Promise<boolean> {
|
||||
try {
|
||||
const response = await supa
|
||||
.from('ml_user_addresses')
|
||||
.update({
|
||||
is_default: false,
|
||||
updated_at: new Date().toISOString()
|
||||
})
|
||||
.eq('user_id', userId)
|
||||
.eq('is_default', true)
|
||||
.execute()
|
||||
|
||||
if (response.error) {
|
||||
console.error('清除默认地址失败:', response.error)
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
} catch (error) {
|
||||
console.error('清除默认地址异常:', error)
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 导出单例实例
|
||||
|
||||
Reference in New Issue
Block a user