consumer模块完成度95%,能编译在安卓端运行,在解决数据获取和页面布局问题
This commit is contained in:
@@ -5,35 +5,40 @@ import type { AkReqResponse } from '@/uni_modules/ak-req/index.uts'
|
||||
// const supa = createClient(SUPA_URL, SUPA_KEY)
|
||||
|
||||
// 类型定义
|
||||
export interface Brand {
|
||||
export type Brand = {
|
||||
id: string
|
||||
name: string
|
||||
logo_url: string
|
||||
description: string
|
||||
}
|
||||
|
||||
export interface Category {
|
||||
export type Category = {
|
||||
id: string
|
||||
name: string
|
||||
icon: string
|
||||
description: string
|
||||
color: string
|
||||
parent_id?: string
|
||||
level?: number
|
||||
slug?: string
|
||||
created_at?: string
|
||||
}
|
||||
|
||||
export interface Product {
|
||||
export type Product = {
|
||||
id: string
|
||||
category_id: string
|
||||
merchant_id: string
|
||||
name: string
|
||||
subtitle?: string
|
||||
description?: string
|
||||
base_price: number
|
||||
base_price?: number
|
||||
market_price?: number
|
||||
cost_price?: number
|
||||
main_image_url?: string
|
||||
image_urls?: string // JSON string array
|
||||
video_urls?: string // JSON string array
|
||||
image_url?: string
|
||||
image_urls?: string
|
||||
video_urls?: string
|
||||
images?: string[]
|
||||
sale_count?: number
|
||||
view_count?: number
|
||||
total_stock?: number
|
||||
@@ -44,25 +49,26 @@ export interface Product {
|
||||
status?: number
|
||||
rating_avg?: number
|
||||
rating_count?: number
|
||||
tags?: string // array string in DB
|
||||
attributes?: string // JSON string
|
||||
rating?: number
|
||||
review_count?: number
|
||||
brand_id?: string
|
||||
shop_id?: string
|
||||
tags?: string
|
||||
attributes?: string
|
||||
created_at?: string
|
||||
updated_at?: string
|
||||
// Alias fields for compatibility
|
||||
price?: number
|
||||
original_price?: number
|
||||
stock?: number
|
||||
sales?: number
|
||||
images?: string
|
||||
cover?: string
|
||||
// View fields
|
||||
brand_name?: string
|
||||
category_name?: string
|
||||
shop_name?: string
|
||||
merchant_name?: string
|
||||
}
|
||||
|
||||
export interface Shop {
|
||||
export type Shop = {
|
||||
id: string
|
||||
merchant_id: string
|
||||
shop_name: string
|
||||
@@ -96,7 +102,7 @@ export type CartItem = {
|
||||
updated_at?: string
|
||||
}
|
||||
|
||||
export interface UserAddress {
|
||||
export type UserAddress = {
|
||||
id: string
|
||||
user_id: string
|
||||
recipient_name: string
|
||||
@@ -143,7 +149,7 @@ export type ChatRoom = {
|
||||
updated_at?: string
|
||||
}
|
||||
|
||||
export interface Notification {
|
||||
export type Notification = {
|
||||
id: string
|
||||
user_id: string
|
||||
type: string
|
||||
@@ -156,7 +162,7 @@ export interface Notification {
|
||||
created_at?: string
|
||||
}
|
||||
|
||||
export interface ChatMessage {
|
||||
export type ChatMessage = {
|
||||
id: string
|
||||
session_id?: string
|
||||
sender_id?: string
|
||||
@@ -169,7 +175,7 @@ export interface ChatMessage {
|
||||
created_at?: string
|
||||
}
|
||||
|
||||
export interface PaginatedResponse<T> {
|
||||
export type PaginatedResponse<T> = {
|
||||
data: T[]
|
||||
total: number
|
||||
page: number
|
||||
@@ -177,7 +183,7 @@ export interface PaginatedResponse<T> {
|
||||
hasmore: boolean
|
||||
}
|
||||
|
||||
export interface ProductSku {
|
||||
export type ProductSku = {
|
||||
id: string
|
||||
product_id: string
|
||||
sku_code: string
|
||||
@@ -306,13 +312,154 @@ class SupabaseService {
|
||||
return []
|
||||
}
|
||||
|
||||
return response.data as Category[]
|
||||
const rawData = response.data
|
||||
if (rawData == null) {
|
||||
return []
|
||||
}
|
||||
|
||||
const categories: Category[] = []
|
||||
const rawList = rawData as any[]
|
||||
for (let i: number = 0; i < rawList.length; i++) {
|
||||
const item = rawList[i]
|
||||
const catObj = item as UTSJSONObject
|
||||
const idVal = catObj.get('id')
|
||||
const nameVal = catObj.get('name')
|
||||
const iconVal = catObj.get('icon')
|
||||
const iconUrlVal = catObj.get('icon_url')
|
||||
const descVal = catObj.get('description')
|
||||
const colorVal = catObj.get('color')
|
||||
const parentIdVal = catObj.get('parent_id')
|
||||
const levelVal = catObj.get('level')
|
||||
|
||||
const cat: Category = {
|
||||
id: (typeof idVal == 'string') ? (idVal as string) : '',
|
||||
name: (typeof nameVal == 'string') ? (nameVal as string) : '',
|
||||
icon: (typeof iconVal == 'string') ? (iconVal as string) : ((typeof iconUrlVal == 'string') ? (iconUrlVal as string) : ''),
|
||||
description: (typeof descVal == 'string') ? (descVal as string) : '',
|
||||
color: (typeof colorVal == 'string') ? (colorVal as string) : '#4CAF50',
|
||||
parent_id: (typeof parentIdVal == 'string') ? (parentIdVal as string) : null,
|
||||
level: (typeof levelVal == 'number') ? (levelVal as number) : 0
|
||||
} as Category
|
||||
categories.push(cat)
|
||||
}
|
||||
return categories
|
||||
} catch (error) {
|
||||
console.error('获取分类异常:', error)
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
// 获取一级分类
|
||||
async getParentCategories(): Promise<Category[]> {
|
||||
try {
|
||||
const response = await supa
|
||||
.from('ml_categories')
|
||||
.select('*')
|
||||
.is('parent_id', null)
|
||||
.order('sort_order', { ascending: true })
|
||||
.execute()
|
||||
|
||||
if (response.error != null) {
|
||||
console.error('获取一级分类失败:', response.error)
|
||||
return []
|
||||
}
|
||||
|
||||
const rawData = response.data
|
||||
if (rawData == null) {
|
||||
return []
|
||||
}
|
||||
|
||||
const categories: Category[] = []
|
||||
const rawList = rawData as Array<UTSJSONObject>
|
||||
for (let i = 0; i < rawList.length; i++) {
|
||||
const item = rawList[i]
|
||||
const icon = this.getCategoryIcon(item)
|
||||
const cat: Category = {
|
||||
id: item['id'] as string,
|
||||
name: item['name'] as string,
|
||||
icon: icon,
|
||||
description: (item['description'] as string) ?? '',
|
||||
color: (item['color'] as string) ?? '#4CAF50',
|
||||
level: 1,
|
||||
slug: item['slug'] as string
|
||||
}
|
||||
categories.push(cat)
|
||||
}
|
||||
return categories
|
||||
} catch (error) {
|
||||
console.error('获取一级分类异常:', error)
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
// 获取子分类
|
||||
async getSubCategories(parentId: string): Promise<Category[]> {
|
||||
try {
|
||||
const response = await supa
|
||||
.from('ml_categories')
|
||||
.select('*')
|
||||
.eq('parent_id', parentId)
|
||||
.order('sort_order', { ascending: true })
|
||||
.execute()
|
||||
|
||||
if (response.error != null) {
|
||||
console.error('获取子分类失败:', response.error)
|
||||
return []
|
||||
}
|
||||
|
||||
const rawData = response.data
|
||||
if (rawData == null) {
|
||||
return []
|
||||
}
|
||||
|
||||
const categories: Category[] = []
|
||||
const rawList = rawData as Array<UTSJSONObject>
|
||||
for (let i = 0; i < rawList.length; i++) {
|
||||
const item = rawList[i]
|
||||
const icon = this.getCategoryIcon(item)
|
||||
const cat: Category = {
|
||||
id: item['id'] as string,
|
||||
name: item['name'] as string,
|
||||
icon: icon,
|
||||
description: (item['description'] as string) ?? '',
|
||||
color: (item['color'] as string) ?? '#4CAF50',
|
||||
level: 2,
|
||||
parent_id: item['parent_id'] as string,
|
||||
slug: item['slug'] as string
|
||||
}
|
||||
categories.push(cat)
|
||||
}
|
||||
return categories
|
||||
} catch (error) {
|
||||
console.error('获取子分类异常:', error)
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
// 获取分类图标的辅助方法
|
||||
getCategoryIcon(item: UTSJSONObject): string {
|
||||
const icon = item['icon'] as string | null
|
||||
if (icon != null && icon.length > 0) {
|
||||
return icon
|
||||
}
|
||||
const iconUrl = item['icon_url'] as string | null
|
||||
if (iconUrl != null && iconUrl.length > 0) {
|
||||
return iconUrl
|
||||
}
|
||||
// 根据分类名称返回默认图标
|
||||
const name = (item['name'] as string) ?? ''
|
||||
if (name.includes('数码') || name.includes('电器') || name.includes('手机')) return '📱'
|
||||
if (name.includes('服装') || name.includes('衣服') || name.includes('鞋')) return '👕'
|
||||
if (name.includes('食品') || name.includes('水果') || name.includes('零食')) return '🍎'
|
||||
if (name.includes('美妆') || name.includes('护肤') || name.includes('化妆')) return '💄'
|
||||
if (name.includes('母婴') || name.includes('婴儿') || name.includes('儿童')) return '👶'
|
||||
if (name.includes('家居') || name.includes('家具') || name.includes('装饰')) return '🏠'
|
||||
if (name.includes('图书') || name.includes('文具')) return '📚'
|
||||
if (name.includes('运动') || name.includes('户外') || name.includes('健身')) return '⚽'
|
||||
if (name.includes('医药') || name.includes('保健') || name.includes('健康')) return '💊'
|
||||
return '📦'
|
||||
}
|
||||
|
||||
// 获取所有品牌
|
||||
async getBrands(): Promise<Brand[]> {
|
||||
try {
|
||||
@@ -328,7 +475,30 @@ class SupabaseService {
|
||||
return []
|
||||
}
|
||||
|
||||
return response.data as Brand[]
|
||||
const rawData = response.data
|
||||
if (rawData == null) {
|
||||
return []
|
||||
}
|
||||
|
||||
const brands: Brand[] = []
|
||||
const rawList = rawData as any[]
|
||||
for (let i: number = 0; i < rawList.length; i++) {
|
||||
const item = rawList[i]
|
||||
const brandObj = item as UTSJSONObject
|
||||
const idVal = brandObj.get('id')
|
||||
const nameVal = brandObj.get('name')
|
||||
const logoVal = brandObj.get('logo_url')
|
||||
const descVal = brandObj.get('description')
|
||||
|
||||
const brand: Brand = {
|
||||
id: (typeof idVal == 'string') ? (idVal as string) : '',
|
||||
name: (typeof nameVal == 'string') ? (nameVal as string) : '',
|
||||
logo_url: (typeof logoVal == 'string') ? (logoVal as string) : '',
|
||||
description: (typeof descVal == 'string') ? (descVal as string) : ''
|
||||
} as Brand
|
||||
brands.push(brand)
|
||||
}
|
||||
return brands
|
||||
} catch (error) {
|
||||
console.error('获取品牌异常:', error)
|
||||
return []
|
||||
@@ -816,9 +986,40 @@ class SupabaseService {
|
||||
return []
|
||||
}
|
||||
|
||||
console.log('推荐商品查询结果条数:', (response.data as any[])?.length ?? 0)
|
||||
const data = response.data as Product[]
|
||||
return data ?? []
|
||||
const rawData = response.data
|
||||
if (rawData == null) {
|
||||
return []
|
||||
}
|
||||
|
||||
const products: Product[] = []
|
||||
const rawList = rawData as any[]
|
||||
for (let i: number = 0; i < rawList.length; i++) {
|
||||
const item = rawList[i]
|
||||
const prodObj = item as UTSJSONObject
|
||||
const imagesRaw = prodObj.getArray('images')
|
||||
const product: Product = {
|
||||
id: prodObj.getString('id') ?? '',
|
||||
name: prodObj.getString('name') ?? '',
|
||||
description: prodObj.getString('description') ?? '',
|
||||
price: prodObj.getNumber('price') ?? 0,
|
||||
original_price: prodObj.getNumber('original_price') ?? 0,
|
||||
image_url: prodObj.getString('image_url') ?? '',
|
||||
images: imagesRaw != null ? (imagesRaw as string[]) : [] as string[],
|
||||
category_id: prodObj.getString('category_id') ?? '',
|
||||
brand_id: prodObj.getString('brand_id') ?? '',
|
||||
shop_id: prodObj.getString('shop_id') ?? '',
|
||||
stock: prodObj.getNumber('stock') ?? 0,
|
||||
sale_count: prodObj.getNumber('sale_count') ?? 0,
|
||||
status: prodObj.getNumber('status') ?? 1,
|
||||
is_featured: prodObj.getBoolean('is_featured') ?? false,
|
||||
is_new: prodObj.getBoolean('is_new') ?? false,
|
||||
rating: prodObj.getNumber('rating') ?? 0,
|
||||
review_count: prodObj.getNumber('review_count') ?? 0,
|
||||
merchant_id: ''
|
||||
} as Product
|
||||
products.push(product)
|
||||
}
|
||||
return products
|
||||
} catch (error) {
|
||||
console.error('获取推荐商品异常:', error)
|
||||
return []
|
||||
@@ -2059,16 +2260,16 @@ class SupabaseService {
|
||||
console.log('[CreateOrder] 插入订单项数量:', orderItems.length)
|
||||
console.log('[CreateOrder] 订单项数据:', JSON.stringify(orderItems))
|
||||
|
||||
const itemsResponse = await supa
|
||||
.from('ml_order_items')
|
||||
.insert(orderItems)
|
||||
.execute()
|
||||
|
||||
if (itemsResponse.error != null) {
|
||||
console.error('[CreateOrder] 创建订单项失败:', itemsResponse.error)
|
||||
console.error('[CreateOrder] 错误详情:', JSON.stringify(itemsResponse.error))
|
||||
console.log('[CreateOrder] 订单主表已创建,但订单项插入失败,返回订单ID')
|
||||
return orderId
|
||||
for (let j: number = 0; j < orderItems.length; j++) {
|
||||
const itemJson = orderItems[j]
|
||||
const itemsResponse = await supa
|
||||
.from('ml_order_items')
|
||||
.insert(itemJson)
|
||||
.execute()
|
||||
|
||||
if (itemsResponse.error != null) {
|
||||
console.error('[CreateOrder] 创建订单项失败:', itemsResponse.error)
|
||||
}
|
||||
}
|
||||
|
||||
console.log('[CreateOrder] 订单项创建成功')
|
||||
@@ -2482,7 +2683,26 @@ class SupabaseService {
|
||||
}
|
||||
}
|
||||
|
||||
// 获取用户钱包余额
|
||||
async deleteRefund(refundId: string): Promise<boolean> {
|
||||
try {
|
||||
const response = await supa
|
||||
.from('ml_refunds')
|
||||
.delete()
|
||||
.eq('id', refundId)
|
||||
.execute()
|
||||
|
||||
if (response.error != null) {
|
||||
console.error('删除退款记录失败:', response.error)
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
} catch (e) {
|
||||
console.error('删除退款记录异常:', e)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
async getUserBalance(): Promise<number> {
|
||||
try {
|
||||
const userId = this.getCurrentUserId()
|
||||
@@ -3735,6 +3955,58 @@ class SupabaseService {
|
||||
} catch (e) { return false }
|
||||
return true
|
||||
}
|
||||
|
||||
// 提交商品评价
|
||||
async submitProductReviews(reviews: Array<UTSJSONObject>): Promise<boolean> {
|
||||
try {
|
||||
for (let i: number = 0; i < reviews.length; i++) {
|
||||
const review = reviews[i]
|
||||
const response = await supa
|
||||
.from('ml_product_reviews')
|
||||
.insert(review)
|
||||
.execute()
|
||||
if (response.error != null) {
|
||||
console.error('提交商品评价失败:', response.error)
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
} catch (e) {
|
||||
console.error('提交商品评价失败:', e)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// 提交店铺评价
|
||||
async submitShopReview(review: UTSJSONObject): Promise<boolean> {
|
||||
try {
|
||||
const response = await supa
|
||||
.from('ml_shop_reviews')
|
||||
.insert(review)
|
||||
.execute()
|
||||
return response.error == null
|
||||
} catch (e) {
|
||||
console.error('提交店铺评价失败:', e)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// 更新订单状态
|
||||
async updateOrderStatus(orderId: string, status: number): Promise<boolean> {
|
||||
try {
|
||||
const updateData = new UTSJSONObject()
|
||||
updateData.set('order_status', status)
|
||||
const response = await supa
|
||||
.from('ml_orders')
|
||||
.update(updateData)
|
||||
.eq('id', orderId)
|
||||
.execute()
|
||||
return response.error == null
|
||||
} catch (e) {
|
||||
console.error('更新订单状态失败:', e)
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 导出单例实例
|
||||
|
||||
Reference in New Issue
Block a user