完成consumer端同步

This commit is contained in:
2026-05-14 15:28:09 +08:00
parent 612fb3d360
commit 0ffbc53902
197 changed files with 92657 additions and 7564 deletions

View File

@@ -6,10 +6,7 @@ export { supa }
import type { OrderOptions } from '@/components/supadb/aksupa.uts'
const OLD_URL = '192.168.1.61:18000'
// const NEW_URL = '119.146.131.237:9126'
// 医疗项目 Supabase 实例地址(与 ak/config.uts 中的 SUPA_URL 保持一致,去掉 http:// 前缀)
const NEW_URL = '119.146.131.237:9127'
const NEW_URL = '119.146.131.237:9126'
function fixImageUrl(url: string | null): string {
if (url == null) return ''
@@ -424,6 +421,16 @@ export type ShopOrderParams = {
discountAmount: number
}
function emptyProductPage(page: number, limit: number): PaginatedResponse<Product> {
return {
data: [] as Product[],
total: 0,
page,
limit,
hasmore: false
}
}
export type ShopOrderResponse = {
success: boolean
orderIds: string[]
@@ -1730,25 +1737,26 @@ class SupabaseService {
}
// 获取按销量排序的商品(所有商品,不限制 is_hot
async getProductsBySales(limit: number = 10): Promise<Product[]> {
async getProductsBySales(page: number = 1, limit: number = 10): Promise<PaginatedResponse<Product>> {
try {
console.log('[getProductsBySales] 开始获取销量排序商品...')
const response = await supa
.from('ml_products_detail_view')
.select('id, name, description, base_price, market_price, main_image_url, image_urls, category_id, brand_id, merchant_id, total_stock, sale_count, status, is_featured, is_new, is_hot')
.select('id, name, description, base_price, market_price, main_image_url, image_urls, category_id, brand_id, merchant_id, total_stock, sale_count, status, is_featured, is_new, is_hot', { count: 'exact' })
.eq('status', '1')
.order('sale_count', { ascending: false })
.page(page)
.limit(limit)
.execute()
if (response.error != null) {
console.error('获取销量排序商品失败:', response.error)
return []
return emptyProductPage(page, limit)
}
const rawData = response.data
if (rawData == null) {
return []
return emptyProductPage(page, limit)
}
const products: Product[] = []
@@ -1758,32 +1766,39 @@ class SupabaseService {
products.push(parseProductFromRaw(item))
}
console.log('[getProductsBySales] 返回商品数:', products.length)
return products
return {
data: products,
total: response.total ?? products.length,
page,
limit,
hasmore: response.hasmore ?? false
}
} catch (error) {
console.error('获取销量排序商品异常:', error)
return []
return emptyProductPage(page, limit)
}
}
// 获取按价格排序的商品(升序:从低到高)
async getProductsByPrice(limit: number = 10, ascending: boolean = true): Promise<Product[]> {
async getProductsByPrice(page: number = 1, limit: number = 10, ascending: boolean = true): Promise<PaginatedResponse<Product>> {
try {
const response = await supa
.from('ml_products_detail_view')
.select('id, name, description, base_price, market_price, main_image_url, image_urls, category_id, brand_id, merchant_id, total_stock, sale_count, status, is_featured, is_new, is_hot')
.select('id, name, description, base_price, market_price, main_image_url, image_urls, category_id, brand_id, merchant_id, total_stock, sale_count, status, is_featured, is_new, is_hot', { count: 'exact' })
.eq('status', '1') // 在数据库层面过滤
.order('base_price', { ascending })
.page(page)
.limit(limit)
.execute()
if (response.error != null) {
console.error('获取价格排序商品失败:', response.error)
return []
return emptyProductPage(page, limit)
}
const rawData = response.data
if (rawData == null) {
return []
return emptyProductPage(page, limit)
}
const products: Product[] = []
@@ -1792,33 +1807,40 @@ class SupabaseService {
const item = rawList[i]
products.push(parseProductFromRaw(item))
}
return products
return {
data: products,
total: response.total ?? products.length,
page,
limit,
hasmore: response.hasmore ?? false
}
} catch (error) {
console.error('获取价格排序商品异常:', error)
return []
return emptyProductPage(page, limit)
}
}
// 获取新品(按创建时间排序,最新的在前)
async getProductsByNewest(limit: number = 10): Promise<Product[]> {
async getProductsByNewest(page: number = 1, limit: number = 10): Promise<PaginatedResponse<Product>> {
try {
console.log('[getProductsByNewest] 开始获取新品...')
const response = await supa
.from('ml_products_detail_view')
.select('id, name, description, base_price, market_price, main_image_url, image_urls, category_id, brand_id, merchant_id, total_stock, sale_count, status, is_featured, is_new, is_hot')
.select('id, name, description, base_price, market_price, main_image_url, image_urls, category_id, brand_id, merchant_id, total_stock, sale_count, status, is_featured, is_new, is_hot', { count: 'exact' })
.eq('status', '1')
.order('created_at', { ascending: false })
.page(page)
.limit(limit * 5)
.execute()
if (response.error != null) {
console.error('获取新品失败:', response.error)
return []
return emptyProductPage(page, limit)
}
const rawData = response.data
if (rawData == null) {
return []
return emptyProductPage(page, limit)
}
const products: Product[] = []
@@ -1864,10 +1886,17 @@ class SupabaseService {
}
console.log('[getProductsByNewest] 返回商品数:', products.length)
return products
const pageData = products.slice(0, limit)
return {
data: pageData,
total: response.total ?? products.length,
page,
limit,
hasmore: products.length > limit || (response.hasmore ?? false)
}
} catch (error) {
console.error('获取新品异常:', error)
return []
return emptyProductPage(page, limit)
}
}
@@ -5821,12 +5850,13 @@ class SupabaseService {
}
// 智能推荐:综合用户搜索历史、浏览历史、热销商品
async getSmartRecommendations(limit: number = 10): Promise<Product[]> {
async getSmartRecommendations(page: number = 1, limit: number = 10): Promise<PaginatedResponse<Product>> {
try {
console.log('[getSmartRecommendations] 开始获取智能推荐...')
const products: Product[] = []
const addedIds = new Set<string>()
const requiredCount = page * limit + 1
// 1. 根据用户搜索历史推荐商品(权重最高)
const searchHistory = await this.getUserSearchHistory(5)
@@ -5834,7 +5864,7 @@ class SupabaseService {
if (searchHistory.length > 0) {
// 根据搜索关键词查找商品
const keywordProducts = await this.searchProductsByKeywords(searchHistory, limit)
const keywordProducts = await this.searchProductsByKeywords(searchHistory, requiredCount)
for (let i = 0; i < keywordProducts.length; i++) {
const prod = keywordProducts[i]
if (!addedIds.has(prod.id)) {
@@ -5845,53 +5875,63 @@ class SupabaseService {
}
// 2. 根据用户浏览历史推荐相似分类商品
if (products.length < limit) {
if (products.length < requiredCount) {
const browseCategories = await this.getUserBrowseCategories(3)
console.log('[getSmartRecommendations] 用户浏览分类:', browseCategories)
if (browseCategories.length > 0) {
const categoryProducts = await this.getProductsByCategories(browseCategories, limit - products.length)
const categoryProducts = await this.getProductsByCategories(browseCategories, requiredCount - products.length)
for (let i = 0; i < categoryProducts.length; i++) {
const prod = categoryProducts[i]
if (!addedIds.has(prod.id)) {
products.push(prod)
addedIds.add(prod.id)
if (products.length >= requiredCount) break
}
}
}
}
// 3. 补充热销商品
if (products.length < limit) {
const hotProducts = await this.getHotProducts(limit - products.length + 5)
if (products.length < requiredCount) {
const hotProducts = await this.getHotProducts(requiredCount - products.length + 5)
for (let i = 0; i < hotProducts.length; i++) {
const prod = hotProducts[i]
if (!addedIds.has(prod.id)) {
products.push(prod)
addedIds.add(prod.id)
if (products.length >= limit) break
if (products.length >= requiredCount) break
}
}
}
// 4. 如果还不够,用普通商品补充
if (products.length < limit) {
const moreProducts = await this.getProductsByPrice(limit - products.length + 5, false)
for (let i = 0; i < moreProducts.length; i++) {
const prod = moreProducts[i]
if (products.length < requiredCount) {
const moreProducts = await this.getProductsByPrice(1, requiredCount - products.length + 5, false)
for (let i = 0; i < moreProducts.data.length; i++) {
const prod = moreProducts.data[i]
if (!addedIds.has(prod.id)) {
products.push(prod)
addedIds.add(prod.id)
if (products.length >= limit) break
if (products.length >= requiredCount) break
}
}
}
console.log('[getSmartRecommendations] 返回商品数量:', products.length)
return products.slice(0, limit)
const startIndex = (page - 1) * limit
const endIndex = startIndex + limit
const pageData = products.slice(startIndex, endIndex)
console.log('[getSmartRecommendations] 返回商品数量:', pageData.length)
return {
data: pageData,
total: products.length,
page,
limit,
hasmore: products.length > endIndex
}
} catch (e) {
console.error('获取智能推荐失败:', e)
return [] as Product[]
return emptyProductPage(page, limit)
}
}