consumer模块完成度95%,能编译在安卓端运行,在解决数据获取和页面布局问题
This commit is contained in:
@@ -5,23 +5,26 @@ 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
|
||||
level?: number
|
||||
parent_id?: string
|
||||
slug?: string
|
||||
created_at?: string
|
||||
}
|
||||
|
||||
export interface Product {
|
||||
export type Product = {
|
||||
id: string
|
||||
category_id: string
|
||||
merchant_id: string
|
||||
@@ -62,7 +65,7 @@ export interface Product {
|
||||
merchant_name?: string
|
||||
}
|
||||
|
||||
export interface Shop {
|
||||
export type Shop = {
|
||||
id: string
|
||||
merchant_id: string
|
||||
shop_name: string
|
||||
@@ -96,7 +99,7 @@ export type CartItem = {
|
||||
updated_at?: string
|
||||
}
|
||||
|
||||
export interface UserAddress {
|
||||
export type UserAddress = {
|
||||
id: string
|
||||
user_id: string
|
||||
recipient_name: string
|
||||
@@ -143,7 +146,7 @@ export type ChatRoom = {
|
||||
updated_at?: string
|
||||
}
|
||||
|
||||
export interface Notification {
|
||||
export type Notification = {
|
||||
id: string
|
||||
user_id: string
|
||||
type: string
|
||||
@@ -156,7 +159,7 @@ export interface Notification {
|
||||
created_at?: string
|
||||
}
|
||||
|
||||
export interface ChatMessage {
|
||||
export type ChatMessage = {
|
||||
id: string
|
||||
session_id?: string
|
||||
sender_id?: string
|
||||
@@ -169,7 +172,7 @@ export interface ChatMessage {
|
||||
created_at?: string
|
||||
}
|
||||
|
||||
export interface PaginatedResponse<T> {
|
||||
export type PaginatedResponse<T> = {
|
||||
data: T[]
|
||||
total: number
|
||||
page: number
|
||||
@@ -177,7 +180,7 @@ export interface PaginatedResponse<T> {
|
||||
hasmore: boolean
|
||||
}
|
||||
|
||||
export interface ProductSku {
|
||||
export type ProductSku = {
|
||||
id: string
|
||||
product_id: string
|
||||
sku_code: string
|
||||
@@ -313,6 +316,134 @@ class SupabaseService {
|
||||
}
|
||||
}
|
||||
|
||||
// 获取一级分类
|
||||
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 iconUrl = (item['icon_url'] as string) ?? ''
|
||||
const slug = (item['slug'] as string) ?? ''
|
||||
|
||||
// 如果 icon_url 已经是 emoji,直接返回
|
||||
if (iconUrl.length > 0 && iconUrl.length <= 4) {
|
||||
return iconUrl
|
||||
}
|
||||
|
||||
// slug 映射到 emoji
|
||||
if (slug === 'digital') return '📱'
|
||||
if (slug === 'fashion') return '👕'
|
||||
if (slug === 'home') return '🏠'
|
||||
if (slug === 'food') return '🍎'
|
||||
if (slug === 'beauty') return '💄'
|
||||
if (slug === 'sports') return '⚽'
|
||||
if (slug === 'books') return '📚'
|
||||
if (slug === 'baby') return '👶'
|
||||
if (slug === 'health') return '💊'
|
||||
// 二级分类
|
||||
if (slug === 'mobile') return '📱'
|
||||
if (slug === 'computer') return '💻'
|
||||
if (slug === 'appliance') return '🎥'
|
||||
if (slug === 'accessories') return '🔌'
|
||||
if (slug === 'mens-wear') return '👔'
|
||||
if (slug === 'womens-wear') return '👗'
|
||||
if (slug === 'mens-shoes') return '👞'
|
||||
if (slug === 'womens-shoes') return '👠'
|
||||
if (slug === 'furniture') return '🛋️'
|
||||
if (slug === 'decoration') return '🖼️'
|
||||
if (slug === 'kitchen') return '🍳'
|
||||
if (slug === 'daily') return '🧹'
|
||||
if (slug === 'fruits') return '🍊'
|
||||
if (slug === 'meat') return '🥩'
|
||||
if (slug === 'snacks') return '🍪'
|
||||
if (slug === 'drinks') return '🍺'
|
||||
|
||||
return '📂'
|
||||
}
|
||||
|
||||
// 获取所有品牌
|
||||
async getBrands(): Promise<Brand[]> {
|
||||
try {
|
||||
@@ -968,6 +1099,7 @@ class SupabaseService {
|
||||
let selected: boolean = false
|
||||
let createdAt: string = ''
|
||||
let updatedAt: string = ''
|
||||
let cartMerchantId: string = ''
|
||||
|
||||
if (item instanceof UTSJSONObject) {
|
||||
itemId = item.getString('id') ?? ''
|
||||
@@ -978,6 +1110,7 @@ class SupabaseService {
|
||||
selected = item.getBoolean('selected') ?? false
|
||||
createdAt = item.getString('created_at') ?? ''
|
||||
updatedAt = item.getString('updated_at') ?? ''
|
||||
cartMerchantId = item.getString('merchant_id') ?? ''
|
||||
} else {
|
||||
const iObj = JSON.parse(JSON.stringify(item)) as UTSJSONObject
|
||||
itemId = iObj.getString('id') ?? ''
|
||||
@@ -988,12 +1121,13 @@ class SupabaseService {
|
||||
selected = iObj.getBoolean('selected') ?? false
|
||||
createdAt = iObj.getString('created_at') ?? ''
|
||||
updatedAt = iObj.getString('updated_at') ?? ''
|
||||
cartMerchantId = iObj.getString('merchant_id') ?? ''
|
||||
}
|
||||
|
||||
const product = productMap.get(productId)
|
||||
const sku = (skuId !== '' && skuMap.has(skuId)) ? skuMap.get(skuId) : null
|
||||
|
||||
let merchantId: string = ''
|
||||
let merchantId: string = cartMerchantId
|
||||
let productName: string = ''
|
||||
let productImage: string = ''
|
||||
let productPrice: number = 0
|
||||
@@ -1002,7 +1136,10 @@ class SupabaseService {
|
||||
|
||||
if (product != null) {
|
||||
if (product instanceof UTSJSONObject) {
|
||||
merchantId = product.getString('merchant_id') ?? ''
|
||||
// 优先使用购物车中的 merchant_id,如果没有则使用商品中的
|
||||
if (merchantId == '') {
|
||||
merchantId = product.getString('merchant_id') ?? ''
|
||||
}
|
||||
productName = product.getString('name') ?? ''
|
||||
productImage = product.getString('main_image_url') ?? ''
|
||||
productPrice = product.getNumber('base_price') ?? 0
|
||||
@@ -1330,7 +1467,7 @@ class SupabaseService {
|
||||
}
|
||||
|
||||
// 添加商品到购物车
|
||||
async addToCart(productId: string, quantity: number = 1, skuId?: string): Promise<boolean> {
|
||||
async addToCart(productId: string, quantity: number = 1, skuId?: string, merchantId?: string): Promise<boolean> {
|
||||
try {
|
||||
const userId = this.getCurrentUserId()
|
||||
if (userId == null) {
|
||||
@@ -1339,6 +1476,7 @@ class SupabaseService {
|
||||
}
|
||||
|
||||
const realSkuId = (skuId != null && skuId.length > 0) ? skuId : null
|
||||
const realMerchantId = (merchantId != null && merchantId.length > 0) ? merchantId : null
|
||||
|
||||
// 检查商品是否已在购物车中
|
||||
// 注意:必须处理 sku_id 为空的情况,使用 is.null 过滤器
|
||||
@@ -1401,6 +1539,7 @@ class SupabaseService {
|
||||
.from('ml_shopping_cart')
|
||||
.update({
|
||||
quantity: newQty,
|
||||
merchant_id: realMerchantId,
|
||||
updated_at: new Date().toISOString()
|
||||
})
|
||||
.eq('id', itemId)
|
||||
@@ -1411,17 +1550,21 @@ class SupabaseService {
|
||||
}
|
||||
} else {
|
||||
// 商品不存在,添加新记录
|
||||
const cartPayload = new UTSJSONObject()
|
||||
cartPayload.set('user_id', userId)
|
||||
cartPayload.set('product_id', productId)
|
||||
cartPayload.set('sku_id', realSkuId)
|
||||
cartPayload.set('quantity', quantity)
|
||||
cartPayload.set('selected', true)
|
||||
cartPayload.set('created_at', new Date().toISOString())
|
||||
cartPayload.set('updated_at', new Date().toISOString())
|
||||
if (realMerchantId != null) {
|
||||
cartPayload.set('merchant_id', realMerchantId)
|
||||
}
|
||||
|
||||
response = await supa
|
||||
.from('ml_shopping_cart')
|
||||
.insert({
|
||||
user_id: userId,
|
||||
product_id: productId,
|
||||
sku_id: realSkuId,
|
||||
quantity: quantity,
|
||||
selected: true,
|
||||
created_at: new Date().toISOString(),
|
||||
updated_at: new Date().toISOString()
|
||||
})
|
||||
.insert(cartPayload)
|
||||
.execute()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user