314 lines
7.7 KiB
Plaintext
314 lines
7.7 KiB
Plaintext
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 PaginatedResponse<T> {
|
||
data: T[]
|
||
total: number
|
||
page: number
|
||
limit: number
|
||
hasmore: boolean
|
||
}
|
||
|
||
class SupabaseService {
|
||
// 获取所有分类
|
||
async getCategories(): Promise<Category[]> {
|
||
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<PaginatedResponse<Product>> {
|
||
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<PaginatedResponse<Product>> {
|
||
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<Product | null> {
|
||
try {
|
||
const response = await supa
|
||
.from('products')
|
||
.select('*')
|
||
.eq('id', productId)
|
||
.single()
|
||
.execute()
|
||
|
||
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<Product[]> {
|
||
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<Product[]> {
|
||
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<Product[]> {
|
||
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<Product[]> {
|
||
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<Product[]> {
|
||
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 []
|
||
}
|
||
}
|
||
}
|
||
|
||
// 导出单例实例
|
||
export const supabaseService = new SupabaseService()
|
||
|
||
// 默认导出
|
||
export default supabaseService
|