import { createClient } from '@/components/supadb/aksupa.uts' import { SUPA_URL, SUPA_KEY } from '@/ak/config.uts' import type { AkReqResponse } from '@/uni_modules/ak-req/index.uts' // 创建 Supabase 客户端 const supa = createClient(SUPA_URL, SUPA_KEY) // 类型定义 export interface Category { id: string name: string icon: string description: string color: string created_at?: string } export interface Product { id: string category_id: string name: string description?: string specification: string price: number original_price?: number image?: string manufacturer: string sales?: number stock?: number badge?: string shop_id?: string shop_name?: string created_at?: string } export interface CartItem { id: string user_id: string product_id: string sku_id?: string quantity: number selected: boolean product_name?: string product_image?: string product_price?: number product_specification?: string shop_id?: string shop_name?: string created_at?: string updated_at?: string } export interface UserAddress { id: string user_id: string recipient_name: string phone: string province: string city: string district: string detail_address: string postal_code?: string is_default: boolean created_at?: string updated_at?: string } export interface PaginatedResponse { data: T[] total: number page: number limit: number hasmore: boolean } class SupabaseService { // 获取当前用户ID private getCurrentUserId(): string | null { try { const userId = uni.getStorageSync('user_id') return userId ? userId as string : null } catch (e) { console.error('获取用户ID失败:', e) return null } } // 获取所有分类 async getCategories(): Promise { try { const response = await supa .from('categories') .select('*') .order('name', { ascending: true }) .execute() if (response.error) { console.error('获取分类失败:', response.error) return [] } return response.data as Category[] } catch (error) { console.error('获取分类异常:', error) return [] } } // 获取指定分类的商品 async getProductsByCategory( categoryId: string, page: number = 1, limit: number = 20 ): Promise> { try { const response = await supa .from('products') .select('*', { count: 'exact' }) .eq('category_id', categoryId) .order('sales', { 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 searchProducts( keyword: string, page: number = 1, limit: number = 20, sortBy: string = 'sales', ascending: boolean = false ): Promise> { try { let query = supa .from('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 }) // 销量总是降序 } else { // 默认按销量降序 query = query.order('sales', { ascending: false }) } const response = await query .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 getProductById(productId: string): Promise { try { const response = await supa .from('products') .select('*') .eq('id', productId) .single() .executeAs() if (response.error) { console.error('获取商品详情失败:', response.error) return null } return response.data as Product } catch (error) { console.error('获取商品详情异常:', error) return null } } // 获取热销商品(按销量排序) async getHotProducts(limit: number = 10): Promise { try { const response = await supa .from('products') .select('*') .order('sales', { ascending: false }) .limit(limit) .execute() if (response.error) { console.error('获取热销商品失败:', response.error) return [] } return response.data as Product[] } catch (error) { console.error('获取热销商品异常:', error) return [] } } // 获取按价格排序的商品(升序:从低到高) async getProductsByPrice(limit: number = 10, ascending: boolean = true): Promise { try { const response = await supa .from('products') .select('*') .order('price', { ascending }) .limit(limit) .execute() if (response.error) { console.error('获取价格排序商品失败:', response.error) return [] } return response.data as Product[] } catch (error) { console.error('获取价格排序商品异常:', error) return [] } } // 获取新品(按创建时间排序,最新的在前) async getProductsByNewest(limit: number = 10): Promise { try { const response = await supa .from('products') .select('*') .order('created_at', { ascending: false }) .limit(limit) .execute() if (response.error) { console.error('获取新品失败:', response.error) return [] } return response.data as Product[] } catch (error) { console.error('获取新品异常:', error) return [] } } // 获取推荐商品(带badge的商品) async getRecommendedProducts(limit: number = 10): Promise { try { // 直接使用 neq 空字符串查询,忽略 null 值(null 表示没有 badge,不应被推荐) const response = await supa .from('products') .select('*') .neq('badge', '') .order('sales', { ascending: false }) .limit(limit) .execute() if (response.error) { console.error('获取推荐商品失败:', response.error) return [] } console.log('推荐商品查询结果条数:', response.data?.length || 0) return response.data as Product[] || [] } catch (error) { console.error('获取推荐商品异常:', error) return [] } } // 获取特价商品(badge为'特价') async getDiscountProducts(limit: number = 10): Promise { try { const response = await supa .from('products') .select('*') .eq('badge', '特价') .order('sales', { ascending: false }) .limit(limit) .execute() if (response.error) { console.error('获取特价商品失败:', response.error) return [] } console.log('特价商品查询结果条数:', response.data?.length || 0) return response.data as Product[] || [] } catch (error) { console.error('获取特价商品异常:', error) return [] } } // 获取当前用户的购物车商品(关联商品和店铺信息) async getCartItems(): Promise { try { const userId = this.getCurrentUserId() if (!userId) { console.warn('用户未登录,无法获取购物车') return [] } // 查询购物车表,并关联商品表(使用内联关联) const response = await supa .from('ml_shopping_cart') .select(` id, user_id, product_id, sku_id, quantity, selected, created_at, updated_at, products!inner ( id, name, image, price, specification, shop_id, shop_name ) `) .eq('user_id', userId) .order('created_at', { ascending: false }) .execute() if (response.error) { console.error('获取购物车失败:', response.error) return [] } // 处理返回数据,构建CartItem数组 const cartItems: CartItem[] = [] if (response.data && Array.isArray(response.data)) { for (const item of response.data) { const product = item.products as any cartItems.push({ id: item.id as string, user_id: item.user_id as string, product_id: item.product_id as string, sku_id: item.sku_id as string, quantity: item.quantity as number, selected: item.selected as boolean, product_name: product?.name as string, 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, created_at: item.created_at as string, updated_at: item.updated_at as string }) } } return cartItems } catch (error) { console.error('获取购物车异常:', error) return [] } } // 添加商品到购物车 async addToCart(productId: string, quantity: number = 1, skuId?: string): Promise { try { const userId = this.getCurrentUserId() if (!userId) { console.error('用户未登录,无法添加商品到购物车') return false } // 检查商品是否已在购物车中 const existingResponse = await supa .from('ml_shopping_cart') .select('*') .eq('user_id', userId) .eq('product_id', productId) .eq('sku_id', skuId || '') .single() .execute() let response if (existingResponse.data) { // 商品已存在,更新数量 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() } else { // 商品不存在,添加新记录 response = await supa .from('ml_shopping_cart') .insert({ user_id: userId, product_id: productId, sku_id: skuId || null, quantity: quantity, selected: true, created_at: new Date().toISOString(), updated_at: new Date().toISOString() }) .execute() } if (response.error) { console.error('添加商品到购物车失败:', response.error) return false } return true } catch (error) { console.error('添加商品到购物车异常:', error) return false } } // 更新购物车商品数量 async updateCartItemQuantity(cartItemId: string, quantity: number): Promise { try { const userId = this.getCurrentUserId() if (!userId) { console.error('用户未登录,无法更新购物车') return false } if (quantity < 1) { // 数量小于1时删除商品 return await this.deleteCartItem(cartItemId) } const response = await supa .from('ml_shopping_cart') .update({ quantity: quantity, updated_at: new Date().toISOString() }) .eq('id', cartItemId) .eq('user_id', userId) .execute() if (response.error) { console.error('更新购物车商品数量失败:', response.error) return false } return true } catch (error) { console.error('更新购物车商品数量异常:', error) return false } } // 更新购物车商品选中状态 async updateCartItemSelection(cartItemId: string, selected: boolean): Promise { try { const userId = this.getCurrentUserId() if (!userId) { console.error('用户未登录,无法更新购物车') return false } const response = await supa .from('ml_shopping_cart') .update({ selected: selected, updated_at: new Date().toISOString() }) .eq('id', cartItemId) .eq('user_id', userId) .execute() if (response.error) { console.error('更新购物车商品选中状态失败:', response.error) return false } return true } catch (error) { console.error('更新购物车商品选中状态异常:', error) return false } } // 批量更新购物车商品选中状态 async batchUpdateCartItemSelection(cartItemIds: string[], selected: boolean): Promise { try { const userId = this.getCurrentUserId() if (!userId) { console.error('用户未登录,无法更新购物车') return false } const response = await supa .from('ml_shopping_cart') .update({ selected: selected, updated_at: new Date().toISOString() }) .eq('user_id', userId) .in('id', cartItemIds) .execute() if (response.error) { console.error('批量更新购物车商品选中状态失败:', response.error) return false } return true } catch (error) { console.error('批量更新购物车商品选中状态异常:', error) return false } } // 删除购物车商品 async deleteCartItem(cartItemId: string): Promise { try { const userId = this.getCurrentUserId() if (!userId) { console.error('用户未登录,无法删除购物车商品') return false } const response = await supa .from('ml_shopping_cart') .delete() .eq('id', cartItemId) .eq('user_id', userId) .execute() if (response.error) { console.error('删除购物车商品失败:', response.error) return false } return true } catch (error) { console.error('删除购物车商品异常:', error) return false } } // 批量删除购物车商品 async batchDeleteCartItems(cartItemIds: string[]): Promise { try { const userId = this.getCurrentUserId() if (!userId) { console.error('用户未登录,无法删除购物车商品') return false } const response = await supa .from('ml_shopping_cart') .delete() .eq('user_id', userId) .in('id', cartItemIds) .execute() if (response.error) { console.error('批量删除购物车商品失败:', response.error) return false } return true } catch (error) { console.error('批量删除购物车商品异常:', error) return false } } // 清空购物车 async clearCart(): Promise { try { const userId = this.getCurrentUserId() if (!userId) { console.error('用户未登录,无法清空购物车') return false } const response = await supa .from('ml_shopping_cart') .delete() .eq('user_id', userId) .execute() if (response.error) { console.error('清空购物车失败:', response.error) return false } return true } catch (error) { console.error('清空购物车异常:', error) return false } } // 获取当前用户的所有地址 async getAddresses(): Promise { try { const userId = this.getCurrentUserId() if (!userId) { console.warn('用户未登录,无法获取地址') return [] } const response = await supa .from('ml_user_addresses') .select('*') .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 (error) { console.error('获取地址异常:', error) return [] } } // 根据ID获取地址详情 async getAddressById(addressId: string): Promise { try { const userId = this.getCurrentUserId() if (!userId) { console.warn('用户未登录,无法获取地址') return null } const response = await supa .from('ml_user_addresses') .select('*') .eq('id', addressId) .eq('user_id', userId) .single() .execute() if (response.error) { console.error('获取地址详情失败:', response.error) return null } return response.data as UserAddress } catch (error) { console.error('获取地址详情异常:', error) return null } } // 添加新地址 async addAddress(address: { recipient_name: string phone: string province: string city: string district: string detail_address: string postal_code?: string is_default?: boolean }): Promise { try { const userId = this.getCurrentUserId() if (!userId) { console.error('用户未登录,无法添加地址') return false } // 如果设置为默认地址,需要先取消其他默认地址 if (address.is_default) { await this.clearDefaultAddress(userId) } const response = await supa .from('ml_user_addresses') .insert({ user_id: userId, recipient_name: address.recipient_name, phone: address.phone, province: address.province, city: address.city, district: address.district, detail_address: address.detail_address, postal_code: address.postal_code || null, is_default: address.is_default || false, created_at: new Date().toISOString(), updated_at: new Date().toISOString() }) .execute() if (response.error) { console.error('添加地址失败:', response.error) return false } return true } catch (error) { console.error('添加地址异常:', error) return false } } // 更新地址 async updateAddress(addressId: string, address: { recipient_name?: string phone?: string province?: string city?: string district?: string detail_address?: string postal_code?: string is_default?: boolean }): Promise { try { const userId = this.getCurrentUserId() if (!userId) { console.error('用户未登录,无法更新地址') return false } // 如果设置为默认地址,需要先取消其他默认地址 if (address.is_default) { await this.clearDefaultAddress(userId) } const response = await supa .from('ml_user_addresses') .update({ ...address, updated_at: new Date().toISOString() }) .eq('id', addressId) .eq('user_id', userId) .execute() if (response.error) { console.error('更新地址失败:', response.error) return false } return true } catch (error) { console.error('更新地址异常:', error) return false } } // 删除地址 async deleteAddress(addressId: string): Promise { try { const userId = this.getCurrentUserId() if (!userId) { console.error('用户未登录,无法删除地址') return false } const response = await supa .from('ml_user_addresses') .delete() .eq('id', addressId) .eq('user_id', userId) .execute() if (response.error) { console.error('删除地址失败:', response.error) return false } return true } catch (error) { console.error('删除地址异常:', error) return false } } // 设置默认地址 async setDefaultAddress(addressId: string): Promise { try { const userId = this.getCurrentUserId() if (!userId) { console.error('用户未登录,无法设置默认地址') return false } // 先取消所有默认地址 await this.clearDefaultAddress(userId) // 设置新的默认地址 const response = await supa .from('ml_user_addresses') .update({ is_default: true, updated_at: new Date().toISOString() }) .eq('id', addressId) .eq('user_id', userId) .execute() if (response.error) { console.error('设置默认地址失败:', response.error) return false } return true } catch (error) { console.error('设置默认地址异常:', error) return false } } // 清除用户的默认地址(内部方法) private async clearDefaultAddress(userId: string): Promise { 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 } } } // 导出单例实例 export const supabaseService = new SupabaseService() // 默认导出 export default supabaseService