解决登录显示、首页显示bug
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import supa from '@/components/supadb/aksupainstance.uts'
|
||||
import type { AkReqResponse } from '@/uni_modules/ak-req/index.uts'
|
||||
import { APP_ROLE, CURRENT_CLIENT, SUPA_KEY, SUPA_URL } from '@/ak/config.uts'
|
||||
|
||||
// 导出 supa 实例,供 services 层统一使用
|
||||
export { supa }
|
||||
@@ -35,6 +36,65 @@ function fixImageUrls(urls: any): string[] {
|
||||
return []
|
||||
}
|
||||
|
||||
function canUseConsumerData(): boolean {
|
||||
return CURRENT_CLIENT === 'consumer' || CURRENT_CLIENT === 'full'
|
||||
}
|
||||
|
||||
function maskConsumerKey(key: string): string {
|
||||
const keyLen = key.length
|
||||
if (keyLen <= 20) {
|
||||
return '(too short)'
|
||||
}
|
||||
return key.substring(0, 10) + '...' + key.substring(keyLen - 8)
|
||||
}
|
||||
|
||||
function logConsumerQueryStart(action: string, tableName: string, fieldList: string = '*'): boolean {
|
||||
if (!canUseConsumerData()) {
|
||||
console.error('[consumer-db] 已阻止非 consumer 数据请求')
|
||||
console.error('[consumer-db] 当前端类型:', CURRENT_CLIENT)
|
||||
console.error('[consumer-db] 当前应用角色:', APP_ROLE)
|
||||
console.error('[consumer-db] 查询表:', tableName)
|
||||
console.error('[consumer-db] 查询动作:', action)
|
||||
return false
|
||||
}
|
||||
console.log('[consumer-db] 当前端类型:', CURRENT_CLIENT)
|
||||
console.log('[consumer-db] 当前应用角色:', APP_ROLE)
|
||||
console.log('[consumer-db] supabaseUrl 已加载:', SUPA_URL)
|
||||
console.log('[consumer-db] supabaseKey 已加载:', maskConsumerKey(SUPA_KEY))
|
||||
console.log('[consumer-db] 首页开始加载数据')
|
||||
console.log('[consumer-db] 查询表:', tableName)
|
||||
console.log('[consumer-db] 查询字段:', fieldList)
|
||||
console.log('[consumer-db] 查询动作:', action)
|
||||
return true
|
||||
}
|
||||
|
||||
function logConsumerQuerySuccess(action: string, tableName: string, count: number): void {
|
||||
console.log('[consumer-db] 查询成功,动作:', action)
|
||||
console.log('[consumer-db] 查询成功,表:', tableName)
|
||||
console.log('[consumer-db] 查询成功,数量:', count)
|
||||
}
|
||||
|
||||
function logConsumerQueryFailure(action: string, tableName: string, error: any): void {
|
||||
console.error('[consumer-db] 查询失败')
|
||||
console.error('[consumer-db] 查询动作:', action)
|
||||
console.error('[consumer-db] 查询表:', tableName)
|
||||
if (error != null) {
|
||||
try {
|
||||
console.error('[consumer-db] error.message:', error.message)
|
||||
} catch (e) {}
|
||||
try {
|
||||
console.error('[consumer-db] error.code:', error.code)
|
||||
} catch (e) {}
|
||||
try {
|
||||
console.error('[consumer-db] error.details:', error.details)
|
||||
} catch (e) {}
|
||||
try {
|
||||
console.error('[consumer-db] error.hint:', error.hint)
|
||||
} catch (e) {}
|
||||
}
|
||||
console.error('[consumer-db] error.raw:', error)
|
||||
}
|
||||
|
||||
// 使用单例 Supabase 客户端
|
||||
// const supa = createClient(SUPA_URL, SUPA_KEY)
|
||||
|
||||
@@ -602,14 +662,18 @@ class SupabaseService {
|
||||
// 获取一级分类
|
||||
async getParentCategories(): Promise<Category[]> {
|
||||
try {
|
||||
if (!logConsumerQueryStart('getParentCategories', 'ml_categories', '*')) {
|
||||
return []
|
||||
}
|
||||
const response = await supa
|
||||
.from('ml_categories')
|
||||
.select('*')
|
||||
.is('parent_id', null)
|
||||
.eq('level', 1)
|
||||
.order('sort_order', { ascending: true })
|
||||
.execute()
|
||||
|
||||
if (response.error != null) {
|
||||
logConsumerQueryFailure('getParentCategories', 'ml_categories', response.error)
|
||||
console.error('获取一级分类失败:', response.error)
|
||||
return []
|
||||
}
|
||||
@@ -643,8 +707,10 @@ class SupabaseService {
|
||||
}
|
||||
categories.push(cat)
|
||||
}
|
||||
logConsumerQuerySuccess('getParentCategories', 'ml_categories', categories.length)
|
||||
return categories
|
||||
} catch (error) {
|
||||
logConsumerQueryFailure('getParentCategories', 'ml_categories', error)
|
||||
console.error('获取一级分类异常:', error)
|
||||
return []
|
||||
}
|
||||
@@ -653,16 +719,22 @@ class SupabaseService {
|
||||
// 获取子分类
|
||||
async getSubCategories(parentId: string): Promise<Category[]> {
|
||||
try {
|
||||
if (!logConsumerQueryStart('getSubCategories', 'ml_categories', '*')) {
|
||||
return []
|
||||
}
|
||||
console.log('[getSubCategories] 开始获取子分类, parentId:', parentId)
|
||||
const response = await supa
|
||||
.from('ml_categories')
|
||||
.select('*')
|
||||
.eq('level', 2)
|
||||
.eq('parent_id', parentId)
|
||||
.order('sort_order', { ascending: true })
|
||||
.execute()
|
||||
|
||||
console.log('[getSubCategories] 查询完成')
|
||||
|
||||
if (response.error != null) {
|
||||
logConsumerQueryFailure('getSubCategories', 'ml_categories', response.error)
|
||||
console.error('获取子分类失败:', response.error)
|
||||
return []
|
||||
}
|
||||
@@ -674,20 +746,13 @@ class SupabaseService {
|
||||
}
|
||||
|
||||
const categories: Category[] = []
|
||||
const rawList = rawData as any[]
|
||||
const rawList = rawData as UTSJSONObject[]
|
||||
console.log('[getSubCategories] 原始数据条数:', rawList.length)
|
||||
|
||||
for (let i = 0; i < rawList.length; i++) {
|
||||
const item = rawList[i]
|
||||
const itemObj = JSON.parse(JSON.stringify(item)) as UTSJSONObject
|
||||
|
||||
// 手动过滤 parent_id
|
||||
const itemParentId = safeGetString(itemObj, 'parent_id')
|
||||
const isMatch = (itemParentId.length > 0 && itemParentId == parentId)
|
||||
if (!isMatch) {
|
||||
continue
|
||||
}
|
||||
|
||||
const icon = this.getCategoryIcon(itemObj)
|
||||
const cat: Category = {
|
||||
id: safeGetString(itemObj, 'id'),
|
||||
@@ -702,8 +767,10 @@ class SupabaseService {
|
||||
categories.push(cat)
|
||||
}
|
||||
console.log('[getSubCategories] 返回分类数量:', categories.length)
|
||||
logConsumerQuerySuccess('getSubCategories', 'ml_categories', categories.length)
|
||||
return categories
|
||||
} catch (error) {
|
||||
logConsumerQueryFailure('getSubCategories', 'ml_categories', error)
|
||||
console.error('获取子分类异常:', error)
|
||||
return []
|
||||
}
|
||||
@@ -736,6 +803,9 @@ class SupabaseService {
|
||||
// 获取所有品牌
|
||||
async getBrands(): Promise<Brand[]> {
|
||||
try {
|
||||
if (!logConsumerQueryStart('getBrands', 'ml_brands', 'id, name, logo_url, description, is_active')) {
|
||||
return []
|
||||
}
|
||||
console.log('[getBrands] 开始获取品牌数据...')
|
||||
const response = await supa
|
||||
.from('ml_brands')
|
||||
@@ -744,6 +814,7 @@ class SupabaseService {
|
||||
.execute()
|
||||
|
||||
if (response.error != null) {
|
||||
logConsumerQueryFailure('getBrands', 'ml_brands', response.error)
|
||||
console.error('获取品牌失败:', response.error)
|
||||
return []
|
||||
}
|
||||
@@ -788,8 +859,10 @@ class SupabaseService {
|
||||
brands.push(brand)
|
||||
}
|
||||
console.log('[getBrands] 返回品牌数量:', brands.length)
|
||||
logConsumerQuerySuccess('getBrands', 'ml_brands', brands.length)
|
||||
return brands
|
||||
} catch (error) {
|
||||
logConsumerQueryFailure('getBrands', 'ml_brands', error)
|
||||
console.error('获取品牌异常:', error)
|
||||
return []
|
||||
}
|
||||
@@ -802,6 +875,9 @@ class SupabaseService {
|
||||
limit: number = 20
|
||||
): Promise<PaginatedResponse<Product>> {
|
||||
try {
|
||||
if (!logConsumerQueryStart('getProductsByCategory', 'ml_products_detail_view', '*')) {
|
||||
return emptyProductPage(page, limit)
|
||||
}
|
||||
console.log('[getProductsByCategory] 开始查询,分类ID:', categoryId, '页码:', page)
|
||||
|
||||
// 在数据库层面进行分类过滤
|
||||
@@ -818,6 +894,7 @@ class SupabaseService {
|
||||
console.log('[getProductsByCategory] 查询完成,total:', response.total)
|
||||
|
||||
if (response.error != null) {
|
||||
logConsumerQueryFailure('getProductsByCategory', 'ml_products_detail_view', response.error)
|
||||
console.error('获取商品失败:', response.error)
|
||||
return {
|
||||
data: [] as Product[],
|
||||
@@ -847,6 +924,7 @@ class SupabaseService {
|
||||
const item = rawList[i]
|
||||
products.push(parseProductFromRaw(item))
|
||||
}
|
||||
logConsumerQuerySuccess('getProductsByCategory', 'ml_products_detail_view', products.length)
|
||||
|
||||
return {
|
||||
data: products,
|
||||
@@ -856,6 +934,7 @@ class SupabaseService {
|
||||
hasmore: response.hasmore ?? false
|
||||
}
|
||||
} catch (error) {
|
||||
logConsumerQueryFailure('getProductsByCategory', 'ml_products_detail_view', error)
|
||||
console.error('获取商品异常:', error)
|
||||
return {
|
||||
data: [] as Product[],
|
||||
@@ -1689,7 +1768,7 @@ class SupabaseService {
|
||||
// 在数据库层面过滤 status,获取更多数据以便手动过滤 is_hot
|
||||
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('*')
|
||||
.eq('status', '1') // 使用字符串 '1'
|
||||
.order('sale_count', { ascending: false })
|
||||
.limit(limit * 5) // 获取更多数据以便过滤
|
||||
@@ -1739,10 +1818,13 @@ class SupabaseService {
|
||||
// 获取按销量排序的商品(所有商品,不限制 is_hot)
|
||||
async getProductsBySales(page: number = 1, limit: number = 10): Promise<PaginatedResponse<Product>> {
|
||||
try {
|
||||
if (!logConsumerQueryStart('getProductsBySales', 'ml_products_detail_view', '*')) {
|
||||
return emptyProductPage(page, limit)
|
||||
}
|
||||
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', { count: 'exact' })
|
||||
.select('*', { count: 'exact' })
|
||||
.eq('status', '1')
|
||||
.order('sale_count', { ascending: false })
|
||||
.page(page)
|
||||
@@ -1750,6 +1832,7 @@ class SupabaseService {
|
||||
.execute()
|
||||
|
||||
if (response.error != null) {
|
||||
logConsumerQueryFailure('getProductsBySales', 'ml_products_detail_view', response.error)
|
||||
console.error('获取销量排序商品失败:', response.error)
|
||||
return emptyProductPage(page, limit)
|
||||
}
|
||||
@@ -1766,6 +1849,7 @@ class SupabaseService {
|
||||
products.push(parseProductFromRaw(item))
|
||||
}
|
||||
console.log('[getProductsBySales] 返回商品数:', products.length)
|
||||
logConsumerQuerySuccess('getProductsBySales', 'ml_products_detail_view', products.length)
|
||||
return {
|
||||
data: products,
|
||||
total: response.total ?? products.length,
|
||||
@@ -1774,6 +1858,7 @@ class SupabaseService {
|
||||
hasmore: response.hasmore ?? false
|
||||
}
|
||||
} catch (error) {
|
||||
logConsumerQueryFailure('getProductsBySales', 'ml_products_detail_view', error)
|
||||
console.error('获取销量排序商品异常:', error)
|
||||
return emptyProductPage(page, limit)
|
||||
}
|
||||
@@ -1782,9 +1867,12 @@ class SupabaseService {
|
||||
// 获取按价格排序的商品(升序:从低到高)
|
||||
async getProductsByPrice(page: number = 1, limit: number = 10, ascending: boolean = true): Promise<PaginatedResponse<Product>> {
|
||||
try {
|
||||
if (!logConsumerQueryStart('getProductsByPrice', 'ml_products_detail_view', '*')) {
|
||||
return emptyProductPage(page, limit)
|
||||
}
|
||||
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', { count: 'exact' })
|
||||
.select('*', { count: 'exact' })
|
||||
.eq('status', '1') // 在数据库层面过滤
|
||||
.order('base_price', { ascending })
|
||||
.page(page)
|
||||
@@ -1792,6 +1880,7 @@ class SupabaseService {
|
||||
.execute()
|
||||
|
||||
if (response.error != null) {
|
||||
logConsumerQueryFailure('getProductsByPrice', 'ml_products_detail_view', response.error)
|
||||
console.error('获取价格排序商品失败:', response.error)
|
||||
return emptyProductPage(page, limit)
|
||||
}
|
||||
@@ -1807,6 +1896,7 @@ class SupabaseService {
|
||||
const item = rawList[i]
|
||||
products.push(parseProductFromRaw(item))
|
||||
}
|
||||
logConsumerQuerySuccess('getProductsByPrice', 'ml_products_detail_view', products.length)
|
||||
return {
|
||||
data: products,
|
||||
total: response.total ?? products.length,
|
||||
@@ -1815,6 +1905,7 @@ class SupabaseService {
|
||||
hasmore: response.hasmore ?? false
|
||||
}
|
||||
} catch (error) {
|
||||
logConsumerQueryFailure('getProductsByPrice', 'ml_products_detail_view', error)
|
||||
console.error('获取价格排序商品异常:', error)
|
||||
return emptyProductPage(page, limit)
|
||||
}
|
||||
@@ -1823,17 +1914,22 @@ class SupabaseService {
|
||||
// 获取新品(按创建时间排序,最新的在前)
|
||||
async getProductsByNewest(page: number = 1, limit: number = 10): Promise<PaginatedResponse<Product>> {
|
||||
try {
|
||||
if (!logConsumerQueryStart('getProductsByNewest', 'ml_products_detail_view', '*')) {
|
||||
return emptyProductPage(page, limit)
|
||||
}
|
||||
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', { count: 'exact' })
|
||||
.select('*', { count: 'exact' })
|
||||
.eq('status', '1')
|
||||
.order('is_new', { ascending: false })
|
||||
.order('created_at', { ascending: false })
|
||||
.page(page)
|
||||
.limit(limit * 5)
|
||||
.limit(limit)
|
||||
.execute()
|
||||
|
||||
if (response.error != null) {
|
||||
logConsumerQueryFailure('getProductsByNewest', 'ml_products_detail_view', response.error)
|
||||
console.error('获取新品失败:', response.error)
|
||||
return emptyProductPage(page, limit)
|
||||
}
|
||||
@@ -1847,54 +1943,20 @@ class SupabaseService {
|
||||
const rawList = rawData as any[]
|
||||
for (let i: number = 0; i < rawList.length; i++) {
|
||||
const item = rawList[i]
|
||||
const prodObj = JSON.parse(JSON.stringify(item)) as UTSJSONObject
|
||||
|
||||
// 手动过滤 is_new
|
||||
const rawIsNew = prodObj.get('is_new')
|
||||
let isNewBool: boolean = false
|
||||
if (typeof rawIsNew == 'boolean') {
|
||||
isNewBool = rawIsNew as boolean
|
||||
} else if (typeof rawIsNew == 'number') {
|
||||
isNewBool = (rawIsNew as number) == 1
|
||||
}
|
||||
if (!isNewBool) continue
|
||||
|
||||
products.push(parseProductFromRaw(item))
|
||||
if (products.length >= limit) break
|
||||
}
|
||||
|
||||
// 如果 is_new 商品不足,补充普通商品
|
||||
if (products.length < limit) {
|
||||
console.log('[getProductsByNewest] is_new商品不足,补充普通商品')
|
||||
const addedIds = new Set<string>()
|
||||
for (let i = 0; i < products.length; i++) {
|
||||
addedIds.add(products[i].id)
|
||||
}
|
||||
|
||||
for (let i: number = 0; i < rawList.length; i++) {
|
||||
const item = rawList[i]
|
||||
const prodObj = JSON.parse(JSON.stringify(item)) as UTSJSONObject
|
||||
const rawId = prodObj.get('id')
|
||||
const itemId = (typeof rawId == 'string') ? (rawId as string) : ''
|
||||
|
||||
if (!addedIds.has(itemId)) {
|
||||
products.push(parseProductFromRaw(item))
|
||||
addedIds.add(itemId)
|
||||
if (products.length >= limit) break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log('[getProductsByNewest] 返回商品数:', products.length)
|
||||
const pageData = products.slice(0, limit)
|
||||
logConsumerQuerySuccess('getProductsByNewest', 'ml_products_detail_view', products.length)
|
||||
return {
|
||||
data: pageData,
|
||||
data: products,
|
||||
total: response.total ?? products.length,
|
||||
page,
|
||||
limit,
|
||||
hasmore: products.length > limit || (response.hasmore ?? false)
|
||||
hasmore: response.hasmore ?? false
|
||||
}
|
||||
} catch (error) {
|
||||
logConsumerQueryFailure('getProductsByNewest', 'ml_products_detail_view', error)
|
||||
console.error('获取新品异常:', error)
|
||||
return emptyProductPage(page, limit)
|
||||
}
|
||||
@@ -1903,6 +1965,9 @@ class SupabaseService {
|
||||
// 获取推荐商品(is_featured=true)
|
||||
async getRecommendedProducts(limit: number = 10): Promise<Product[]> {
|
||||
try {
|
||||
if (!logConsumerQueryStart('getRecommendedProducts', 'ml_products_detail_view', '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')) {
|
||||
return []
|
||||
}
|
||||
console.log('[getRecommendedProducts] 开始获取推荐商品...')
|
||||
const response = await supa
|
||||
.from('ml_products_detail_view')
|
||||
@@ -1915,6 +1980,7 @@ class SupabaseService {
|
||||
console.log('[getRecommendedProducts] 查询完成')
|
||||
|
||||
if (response.error != null) {
|
||||
logConsumerQueryFailure('getRecommendedProducts', 'ml_products_detail_view', response.error)
|
||||
console.error('获取推荐商品失败:', response.error)
|
||||
return []
|
||||
}
|
||||
@@ -1947,8 +2013,10 @@ class SupabaseService {
|
||||
products.push(parseProductFromRaw(item))
|
||||
if (products.length >= limit) break
|
||||
}
|
||||
logConsumerQuerySuccess('getRecommendedProducts', 'ml_products_detail_view', products.length)
|
||||
return products
|
||||
} catch (error) {
|
||||
logConsumerQueryFailure('getRecommendedProducts', 'ml_products_detail_view', error)
|
||||
console.error('获取推荐商品异常:', error)
|
||||
return []
|
||||
}
|
||||
@@ -1957,6 +2025,10 @@ class SupabaseService {
|
||||
// 获取特价商品(这里假设没有specific flag, just use logic or tag if exists, defaulting to hot for now or just skip)
|
||||
// Modify to use compatible logic if badge column doesn't exist
|
||||
async getDiscountProducts(limit: number = 10): Promise<Product[]> {
|
||||
if (!logConsumerQueryStart('getDiscountProducts', 'ml_products_detail_view', '(none)')) {
|
||||
return [] as Product[]
|
||||
}
|
||||
logConsumerQuerySuccess('getDiscountProducts', 'ml_products_detail_view', 0)
|
||||
return [] as Product[] // 暂无特价字段
|
||||
}
|
||||
|
||||
@@ -5660,6 +5732,9 @@ class SupabaseService {
|
||||
// 获取热搜词(全站搜索频率最高的关键词)
|
||||
async getHotKeywords(limit: number = 10): Promise<string[]> {
|
||||
try {
|
||||
if (!logConsumerQueryStart('getHotKeywords', 'ml_search_history', 'keyword')) {
|
||||
return [] as string[]
|
||||
}
|
||||
const response = await supa
|
||||
.from('ml_search_history')
|
||||
.select('keyword')
|
||||
@@ -5668,6 +5743,7 @@ class SupabaseService {
|
||||
.execute()
|
||||
|
||||
if (response.error != null || response.data == null) {
|
||||
logConsumerQueryFailure('getHotKeywords', 'ml_search_history', response.error)
|
||||
return [] as string[]
|
||||
}
|
||||
|
||||
@@ -5712,8 +5788,10 @@ class SupabaseService {
|
||||
sortedKeywords.push(entryArray[i].keyword)
|
||||
}
|
||||
|
||||
logConsumerQuerySuccess('getHotKeywords', 'ml_search_history', sortedKeywords.length)
|
||||
return sortedKeywords
|
||||
} catch (e) {
|
||||
logConsumerQueryFailure('getHotKeywords', 'ml_search_history', e)
|
||||
console.error('获取热搜词失败:', e)
|
||||
return [] as string[]
|
||||
}
|
||||
@@ -5809,8 +5887,8 @@ class SupabaseService {
|
||||
|
||||
// 查询这些商品的分类
|
||||
const prodResponse = await supa
|
||||
.from('ml_products')
|
||||
.select('category_id')
|
||||
.from('ml_products_detail_view')
|
||||
.select('id, category_id')
|
||||
.limit(50)
|
||||
.execute()
|
||||
|
||||
@@ -5852,6 +5930,9 @@ class SupabaseService {
|
||||
// 智能推荐:综合用户搜索历史、浏览历史、热销商品
|
||||
async getSmartRecommendations(page: number = 1, limit: number = 10): Promise<PaginatedResponse<Product>> {
|
||||
try {
|
||||
if (!logConsumerQueryStart('getSmartRecommendations', 'ml_products_detail_view', 'composed: search_history + browse_history + products_detail_view')) {
|
||||
return emptyProductPage(page, limit)
|
||||
}
|
||||
console.log('[getSmartRecommendations] 开始获取智能推荐...')
|
||||
|
||||
const products: Product[] = []
|
||||
@@ -5922,6 +6003,7 @@ class SupabaseService {
|
||||
const endIndex = startIndex + limit
|
||||
const pageData = products.slice(startIndex, endIndex)
|
||||
console.log('[getSmartRecommendations] 返回商品数量:', pageData.length)
|
||||
logConsumerQuerySuccess('getSmartRecommendations', 'ml_products_detail_view', pageData.length)
|
||||
return {
|
||||
data: pageData,
|
||||
total: products.length,
|
||||
@@ -5930,6 +6012,7 @@ class SupabaseService {
|
||||
hasmore: products.length > endIndex
|
||||
}
|
||||
} catch (e) {
|
||||
logConsumerQueryFailure('getSmartRecommendations', 'ml_products_detail_view', e)
|
||||
console.error('获取智能推荐失败:', e)
|
||||
return emptyProductPage(page, limit)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user