consumer模块完成度95%,优化安卓端界面和小程序测试
This commit is contained in:
@@ -18,8 +18,13 @@ function fixImageUrls(urls: any): string[] {
|
||||
const result: string[] = []
|
||||
const arr = urls as any[]
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
const fixed = fixImageUrl(arr[i] as string)
|
||||
if (fixed !== '') result.push(fixed)
|
||||
try {
|
||||
const urlStr = JSON.stringify(arr[i])
|
||||
if (urlStr != null && urlStr.startsWith('"') && urlStr.endsWith('"')) {
|
||||
const fixed = fixImageUrl(urlStr.substring(1, urlStr.length - 1))
|
||||
if (fixed !== '') result.push(fixed)
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -34,10 +39,12 @@ function safeGetString(obj: UTSJSONObject, key: string): string {
|
||||
try {
|
||||
const rawVal = obj.get(key)
|
||||
if (rawVal == null) return ''
|
||||
if (typeof rawVal == 'string') return rawVal as string
|
||||
if (typeof rawVal == 'number') return (rawVal as number).toString()
|
||||
if (typeof rawVal == 'boolean') return (rawVal as boolean) ? 'true' : 'false'
|
||||
return ''
|
||||
const strVal = JSON.stringify(rawVal)
|
||||
if (strVal == null) return ''
|
||||
if (strVal.startsWith('"') && strVal.endsWith('"')) {
|
||||
return strVal.substring(1, strVal.length - 1)
|
||||
}
|
||||
return strVal
|
||||
} catch (e) {
|
||||
console.error('safeGetString error for key:', key, e)
|
||||
return ''
|
||||
@@ -49,11 +56,10 @@ function safeGetNumber(obj: UTSJSONObject, key: string): number {
|
||||
try {
|
||||
const rawVal = obj.get(key)
|
||||
if (rawVal == null) return 0
|
||||
if (typeof rawVal == 'number') return rawVal as number
|
||||
if (typeof rawVal == 'string') {
|
||||
const parsed = parseFloat(rawVal as string)
|
||||
return isNaN(parsed) ? 0 : parsed
|
||||
}
|
||||
try {
|
||||
const numVal = rawVal as number
|
||||
if (!isNaN(numVal)) return numVal
|
||||
} catch (e) {}
|
||||
return 0
|
||||
} catch (e) {
|
||||
console.error('safeGetNumber error for key:', key, e)
|
||||
@@ -66,9 +72,10 @@ function safeGetBoolean(obj: UTSJSONObject, key: string): boolean {
|
||||
try {
|
||||
const rawVal = obj.get(key)
|
||||
if (rawVal == null) return false
|
||||
if (typeof rawVal == 'boolean') return rawVal as boolean
|
||||
if (typeof rawVal == 'string') return (rawVal as string) === 'true'
|
||||
if (typeof rawVal == 'number') return (rawVal as number) !== 0
|
||||
try {
|
||||
const boolVal = rawVal as boolean
|
||||
return boolVal
|
||||
} catch (e) {}
|
||||
return false
|
||||
} catch (e) {
|
||||
console.error('safeGetBoolean error for key:', key, e)
|
||||
@@ -93,78 +100,46 @@ function safeGetStringArray(obj: UTSJSONObject, key: string): string[] {
|
||||
// 辅助函数:从原始数据解析商品
|
||||
function parseProductFromRaw(item: any): Product {
|
||||
try {
|
||||
console.log('[parseProductFromRaw] 开始解析商品')
|
||||
const itemObj = JSON.parse(JSON.stringify(item)) as UTSJSONObject
|
||||
console.log('[parseProductFromRaw] JSON转换成功')
|
||||
|
||||
const getSafeString = (key: string): string => {
|
||||
const val = itemObj.get(key)
|
||||
if (val == null) return ''
|
||||
if (typeof val === 'string') return val
|
||||
if (typeof val === 'number') return val.toString()
|
||||
if (typeof val === 'boolean') return val ? 'true' : 'false'
|
||||
return ''
|
||||
}
|
||||
const mainImageUrl = fixImageUrl(safeGetString(itemObj, 'main_image_url'))
|
||||
const imageUrls = fixImageUrls(safeGetStringArray(itemObj, 'image_urls'))
|
||||
console.log('[parseProductFromRaw] 图片处理完成')
|
||||
|
||||
const getSafeNumber = (key: string): number => {
|
||||
const val = itemObj.get(key)
|
||||
if (val == null) return 0
|
||||
if (typeof val === 'number') return val
|
||||
if (typeof val === 'string') {
|
||||
const parsed = parseFloat(val)
|
||||
return isNaN(parsed) ? 0 : parsed
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
const getSafeBoolean = (key: string): boolean => {
|
||||
const val = itemObj.get(key)
|
||||
if (val == null) return false
|
||||
if (typeof val === 'boolean') return val
|
||||
if (typeof val === 'string') return val === 'true'
|
||||
if (typeof val === 'number') return val !== 0
|
||||
return false
|
||||
}
|
||||
|
||||
const getSafeStringArray = (key: string): string[] => {
|
||||
const val = itemObj.get(key)
|
||||
if (val != null && Array.isArray(val)) {
|
||||
return val as string[]
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
const mainImageUrl = fixImageUrl(getSafeString('main_image_url'))
|
||||
const imageUrls = fixImageUrls(getSafeStringArray('image_urls'))
|
||||
|
||||
return {
|
||||
id: getSafeString('id'),
|
||||
name: getSafeString('name'),
|
||||
description: getSafeString('description'),
|
||||
base_price: getSafeNumber('base_price'),
|
||||
price: getSafeNumber('base_price'),
|
||||
original_price: getSafeNumber('market_price'),
|
||||
market_price: getSafeNumber('market_price'),
|
||||
const result: Product = {
|
||||
id: safeGetString(itemObj, 'id'),
|
||||
name: safeGetString(itemObj, 'name'),
|
||||
description: safeGetString(itemObj, 'description'),
|
||||
base_price: safeGetNumber(itemObj, 'base_price'),
|
||||
price: safeGetNumber(itemObj, 'base_price'),
|
||||
original_price: safeGetNumber(itemObj, 'market_price'),
|
||||
market_price: safeGetNumber(itemObj, 'market_price'),
|
||||
main_image_url: mainImageUrl,
|
||||
image_url: mainImageUrl,
|
||||
images: imageUrls,
|
||||
category_id: getSafeString('category_id'),
|
||||
brand_id: getSafeString('brand_id'),
|
||||
merchant_id: getSafeString('merchant_id'),
|
||||
total_stock: getSafeNumber('total_stock'),
|
||||
stock: getSafeNumber('total_stock'),
|
||||
sale_count: getSafeNumber('sale_count'),
|
||||
status: getSafeNumber('status'),
|
||||
is_featured: getSafeBoolean('is_featured'),
|
||||
is_new: getSafeBoolean('is_new'),
|
||||
is_hot: getSafeBoolean('is_hot'),
|
||||
specification: getSafeString('specification'),
|
||||
usage: getSafeString('usage'),
|
||||
side_effects: getSafeString('side_effects'),
|
||||
precautions: getSafeString('precautions'),
|
||||
expiry_date: getSafeString('expiry_date'),
|
||||
storage_conditions: getSafeString('storage_conditions'),
|
||||
approval_number: getSafeString('approval_number'),
|
||||
created_at: getSafeString('created_at')
|
||||
} as Product
|
||||
category_id: safeGetString(itemObj, 'category_id'),
|
||||
brand_id: safeGetString(itemObj, 'brand_id'),
|
||||
merchant_id: safeGetString(itemObj, 'merchant_id'),
|
||||
total_stock: safeGetNumber(itemObj, 'total_stock'),
|
||||
stock: safeGetNumber(itemObj, 'total_stock'),
|
||||
sale_count: safeGetNumber(itemObj, 'sale_count'),
|
||||
status: safeGetNumber(itemObj, 'status'),
|
||||
is_featured: safeGetBoolean(itemObj, 'is_featured'),
|
||||
is_new: safeGetBoolean(itemObj, 'is_new'),
|
||||
is_hot: safeGetBoolean(itemObj, 'is_hot'),
|
||||
specification: safeGetString(itemObj, 'specification'),
|
||||
usage: safeGetString(itemObj, 'usage'),
|
||||
side_effects: safeGetString(itemObj, 'side_effects'),
|
||||
precautions: safeGetString(itemObj, 'precautions'),
|
||||
expiry_date: safeGetString(itemObj, 'expiry_date'),
|
||||
storage_conditions: safeGetString(itemObj, 'storage_conditions'),
|
||||
approval_number: safeGetString(itemObj, 'approval_number'),
|
||||
created_at: safeGetString(itemObj, 'created_at')
|
||||
}
|
||||
console.log('[parseProductFromRaw] 商品解析成功:', result.name)
|
||||
return result
|
||||
} catch (e) {
|
||||
console.error('parseProductFromRaw error:', e)
|
||||
return {
|
||||
@@ -949,17 +924,23 @@ class SupabaseService {
|
||||
ascending: boolean = false
|
||||
): Promise<PaginatedResponse<Product>> {
|
||||
try {
|
||||
const keywordLower = keyword.toLowerCase()
|
||||
const encodedKeyword = encodeURIComponent(keywordLower)
|
||||
const orString = `name.ilike.%${encodedKeyword}%,description.ilike.%${encodedKeyword}%,subtitle.ilike.%${encodedKeyword}%,brand_name.ilike.%${encodedKeyword}%`
|
||||
console.log('[searchProducts] 搜索关键词:', keyword, '编码后:', encodedKeyword)
|
||||
console.log('[searchProducts] or条件:', orString)
|
||||
|
||||
let query = supa
|
||||
.from('ml_products_detail_view')
|
||||
.select('*', { count: 'exact' })
|
||||
.eq('status', 1)
|
||||
.or(orString)
|
||||
|
||||
// 根据sortBy和ascending设置排序
|
||||
if (sortBy === 'price') {
|
||||
query = query.order('base_price', { ascending })
|
||||
} else if (sortBy === 'sales' || sortBy === 'sale_count') {
|
||||
query = query.order('sale_count', { ascending: false }) // 销量总是降序
|
||||
query = query.order('sale_count', { ascending: false })
|
||||
} else {
|
||||
// 默认按销量降序
|
||||
query = query.order('sale_count', { ascending: false })
|
||||
}
|
||||
|
||||
@@ -968,8 +949,27 @@ class SupabaseService {
|
||||
.limit(limit)
|
||||
.execute()
|
||||
|
||||
if (response.error != null) {
|
||||
console.error('搜索商品失败:', response.error)
|
||||
let dataLength = 0
|
||||
try {
|
||||
const respData = response.data
|
||||
if (respData != null && Array.isArray(respData)) {
|
||||
dataLength = (respData as any[]).length
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('[searchProducts] 获取数据长度失败:', e)
|
||||
}
|
||||
let statusNum = 0
|
||||
try {
|
||||
statusNum = response.status as number
|
||||
} catch (e) {}
|
||||
console.log('[searchProducts] 响应状态:', statusNum, '数据条数:', dataLength)
|
||||
|
||||
let hasError = false
|
||||
try {
|
||||
hasError = response.error != null
|
||||
} catch (e) {}
|
||||
if (hasError) {
|
||||
console.error('[searchProducts] 搜索商品失败:', response.error)
|
||||
return {
|
||||
data: [] as Product[],
|
||||
total: 0,
|
||||
@@ -980,6 +980,7 @@ class SupabaseService {
|
||||
}
|
||||
|
||||
const rawData = response.data
|
||||
console.log('[searchProducts] rawData:', rawData != null ? 'not null' : 'null')
|
||||
if (rawData == null) {
|
||||
return {
|
||||
data: [] as Product[],
|
||||
@@ -991,43 +992,42 @@ class SupabaseService {
|
||||
}
|
||||
|
||||
const products: Product[] = []
|
||||
const rawList = rawData as any[]
|
||||
const keywordLower = keyword.toLowerCase()
|
||||
let rawList: any[] = []
|
||||
try {
|
||||
rawList = rawData as any[]
|
||||
console.log('[searchProducts] rawList长度:', rawList.length)
|
||||
} catch (e) {
|
||||
console.error('[searchProducts] 转换rawList失败:', e)
|
||||
return {
|
||||
data: [] as Product[],
|
||||
total: 0,
|
||||
page,
|
||||
limit,
|
||||
hasmore: false
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < rawList.length; i++) {
|
||||
const item = rawList[i]
|
||||
const prodObj = JSON.parse(JSON.stringify(item)) as UTSJSONObject
|
||||
|
||||
// 手动过滤 status
|
||||
const rawStatus = prodObj.get('status')
|
||||
let statusNum: number = 0
|
||||
if (typeof rawStatus == 'number') {
|
||||
statusNum = rawStatus as number
|
||||
}
|
||||
if (statusNum !== 1) continue
|
||||
|
||||
// 手动过滤关键词
|
||||
const name = safeGetString(prodObj, 'name').toLowerCase()
|
||||
const desc = safeGetString(prodObj, 'description').toLowerCase()
|
||||
const subtitle = safeGetString(prodObj, 'subtitle').toLowerCase()
|
||||
const brandName = safeGetString(prodObj, 'brand_name').toLowerCase()
|
||||
|
||||
if (name.indexOf(keywordLower) === -1 &&
|
||||
desc.indexOf(keywordLower) === -1 &&
|
||||
subtitle.indexOf(keywordLower) === -1 &&
|
||||
brandName.indexOf(keywordLower) === -1) {
|
||||
continue
|
||||
}
|
||||
|
||||
console.log('[searchProducts] 处理第', i + 1, '个商品')
|
||||
products.push(parseProductFromRaw(item))
|
||||
}
|
||||
|
||||
let totalNum = 0
|
||||
try {
|
||||
totalNum = response.total as number
|
||||
} catch (e) {}
|
||||
let hasmoreVal = false
|
||||
try {
|
||||
hasmoreVal = response.hasmore as boolean
|
||||
} catch (e) {}
|
||||
|
||||
return {
|
||||
data: products,
|
||||
total: response.total ?? products.length,
|
||||
total: totalNum > 0 ? totalNum : products.length,
|
||||
page,
|
||||
limit,
|
||||
hasmore: response.hasmore ?? false
|
||||
hasmore: hasmoreVal
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('搜索商品异常:', error)
|
||||
@@ -1048,10 +1048,11 @@ class SupabaseService {
|
||||
limit: number = 20
|
||||
): Promise<PaginatedResponse<Shop>> {
|
||||
try {
|
||||
const encodedKeyword = encodeURIComponent(keyword)
|
||||
const response = await supa
|
||||
.from('ml_shops')
|
||||
.select('*', { count: 'exact' })
|
||||
.ilike('shop_name', `%${keyword}%`)
|
||||
.ilike('shop_name', `%${encodedKeyword}%`)
|
||||
.order('product_count', { ascending: false })
|
||||
.page(page)
|
||||
.limit(limit)
|
||||
@@ -1984,24 +1985,31 @@ class SupabaseService {
|
||||
}
|
||||
|
||||
const productRes = await supa
|
||||
.from('ml_products_detail_view')
|
||||
.select('id,name,main_image_url,base_price,attributes,merchant_id,shop_name')
|
||||
.from('ml_products')
|
||||
.select('*')
|
||||
.in('id', productIdsAny)
|
||||
.execute()
|
||||
|
||||
console.log('[getCartItems] 商品查询结果:', productRes.error != null ? 'error' : 'success', productRes.error)
|
||||
if (productRes.error == null && productRes.data != null) {
|
||||
const products = productRes.data as any[]
|
||||
console.log('[getCartItems] 商品数量:', products.length)
|
||||
for (let i = 0; i < products.length; i++) {
|
||||
let p = products[i]
|
||||
let pid: string = ''
|
||||
let pname: string = ''
|
||||
|
||||
if (p instanceof UTSJSONObject) {
|
||||
pid = p.getString('id') ?? ''
|
||||
pname = p.getString('name') ?? ''
|
||||
} else {
|
||||
const pObj = JSON.parse(JSON.stringify(p)) as UTSJSONObject
|
||||
pid = pObj.getString('id') ?? ''
|
||||
pname = pObj.getString('name') ?? ''
|
||||
}
|
||||
|
||||
console.log('[getCartItems] 商品:', pid, pname)
|
||||
|
||||
if (pid !== '') {
|
||||
productMap.set(pid, p)
|
||||
}
|
||||
@@ -2009,6 +2017,55 @@ class SupabaseService {
|
||||
}
|
||||
}
|
||||
|
||||
// 批量查询店铺信息
|
||||
const shopMap = new Map<string, string>()
|
||||
const merchantIds: string[] = []
|
||||
// 遍历 productMap 获取 merchant_id
|
||||
productMap.forEach((p: any, pid: string) => {
|
||||
let mid: string = ''
|
||||
if (p instanceof UTSJSONObject) {
|
||||
mid = p.getString('merchant_id') ?? ''
|
||||
} else {
|
||||
const pObj = JSON.parse(JSON.stringify(p)) as UTSJSONObject
|
||||
mid = pObj.getString('merchant_id') ?? ''
|
||||
}
|
||||
if (mid !== '' && !merchantIds.includes(mid)) {
|
||||
merchantIds.push(mid)
|
||||
}
|
||||
})
|
||||
|
||||
if (merchantIds.length > 0) {
|
||||
const merchantIdsAny: any[] = []
|
||||
for(let i=0; i<merchantIds.length; i++) {
|
||||
merchantIdsAny.push(merchantIds[i])
|
||||
}
|
||||
const shopRes = await supa
|
||||
.from('ml_shops')
|
||||
.select('merchant_id,shop_name')
|
||||
.in('merchant_id', merchantIdsAny)
|
||||
.execute()
|
||||
|
||||
if (shopRes.error == null && shopRes.data != null) {
|
||||
const shops = shopRes.data as any[]
|
||||
for (let i = 0; i < shops.length; i++) {
|
||||
let s = shops[i]
|
||||
let mid: string = ''
|
||||
let sname: string = ''
|
||||
if (s instanceof UTSJSONObject) {
|
||||
mid = s.getString('merchant_id') ?? ''
|
||||
sname = s.getString('shop_name') ?? ''
|
||||
} else {
|
||||
const sObj = JSON.parse(JSON.stringify(s)) as UTSJSONObject
|
||||
mid = sObj.getString('merchant_id') ?? ''
|
||||
sname = sObj.getString('shop_name') ?? ''
|
||||
}
|
||||
if (mid !== '') {
|
||||
shopMap.set(mid, sname)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 批量查询 SKU 详情
|
||||
const skuMap = new Map<string, any>()
|
||||
if (skuIds.length > 0) {
|
||||
@@ -2018,7 +2075,7 @@ class SupabaseService {
|
||||
}
|
||||
const skuRes = await supa
|
||||
.from('ml_product_skus')
|
||||
.select('id, specifications, price, image_url')
|
||||
.select('*')
|
||||
.in('id', skuIdsAny)
|
||||
.execute()
|
||||
|
||||
@@ -2083,6 +2140,8 @@ class SupabaseService {
|
||||
const product = productMap.get(productId)
|
||||
const sku = (skuId !== '' && skuMap.has(skuId)) ? skuMap.get(skuId) : null
|
||||
|
||||
console.log('[getCartItems] 处理购物车项:', itemId, 'productId:', productId, 'product存在:', product != null, 'sku存在:', sku != null)
|
||||
|
||||
let merchantId: string = cartMerchantId
|
||||
let productName: string = ''
|
||||
let productImage: string = ''
|
||||
@@ -2091,6 +2150,7 @@ class SupabaseService {
|
||||
let shopNameStr: string = '未知店铺'
|
||||
|
||||
if (product != null) {
|
||||
console.log('[getCartItems] product类型:', typeof product, 'instanceof UTSJSONObject:', product instanceof UTSJSONObject)
|
||||
if (product instanceof UTSJSONObject) {
|
||||
// 优先使用购物车中的 merchant_id,如果没有则使用商品中的
|
||||
if (merchantId == '') {
|
||||
@@ -2099,170 +2159,114 @@ class SupabaseService {
|
||||
productName = product.getString('name') ?? ''
|
||||
productImage = product.getString('main_image_url') ?? ''
|
||||
productPrice = product.getNumber('base_price') ?? 0
|
||||
shopNameStr = product.getString('shop_name') ?? '未知店铺'
|
||||
|
||||
// 只有当没有sku信息时,才尝试使用商品的attributes(作为降级显示)
|
||||
// 修改策略:不使用 product.attributes 作为规格显示,因为那通常包含品牌、风格等静态属性,非用户选择的规格
|
||||
// 如果 sku 为空,则让前端显示默认"标准规格"
|
||||
/*
|
||||
if (sku == null) {
|
||||
const specRaw = product.get('attributes')
|
||||
if (specRaw != null) {
|
||||
if (typeof specRaw === 'string') {
|
||||
productSpec = specRaw
|
||||
} else if (specRaw instanceof UTSJSONObject) {
|
||||
const keys = UTSJSONObject.keys(specRaw)
|
||||
const parts: string[] = []
|
||||
for(let k = 0; k < keys.length; k++) {
|
||||
let val = specRaw.get(keys[k])
|
||||
if (val != null) {
|
||||
parts.push(`${keys[k]}: ${val}`)
|
||||
}
|
||||
}
|
||||
productSpec = parts.join('; ')
|
||||
} else {
|
||||
try {
|
||||
let jsonStr = JSON.stringify(specRaw)
|
||||
productSpec = jsonStr.replace(/["{}]/g, '').replace(/,/g, '; ')
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
console.log('[getCartItems] 从UTSJSONObject获取: name=', productName, 'price=', productPrice)
|
||||
} else {
|
||||
const pObj = JSON.parse(JSON.stringify(product)) as UTSJSONObject
|
||||
merchantId = pObj.getString('merchant_id') ?? ''
|
||||
if (merchantId == '') {
|
||||
merchantId = pObj.getString('merchant_id') ?? ''
|
||||
}
|
||||
productName = pObj.getString('name') ?? ''
|
||||
productImage = pObj.getString('main_image_url') ?? ''
|
||||
productPrice = pObj.getNumber('base_price') ?? 0
|
||||
shopNameStr = pObj.getString('shop_name') ?? '未知店铺'
|
||||
|
||||
// Same here: disable fallback to attributes
|
||||
/*
|
||||
if (sku == null) {
|
||||
const specRaw = product['attributes']
|
||||
if (specRaw != null) {
|
||||
if (typeof specRaw === 'string') {
|
||||
productSpec = specRaw
|
||||
} else if (specRaw instanceof UTSJSONObject) {
|
||||
const keys = UTSJSONObject.keys(specRaw)
|
||||
const parts: string[] = []
|
||||
for(let k = 0; k < keys.length; k++) {
|
||||
let val = specRaw.get(keys[k])
|
||||
if (val != null) {
|
||||
parts.push(`${keys[k]}: ${val}`)
|
||||
}
|
||||
}
|
||||
productSpec = parts.join('; ')
|
||||
} else {
|
||||
try {
|
||||
let jsonStr = JSON.stringify(specRaw)
|
||||
productSpec = jsonStr.replace(/["{}]/g, '').replace(/,/g, '; ')
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
console.log('[getCartItems] 从普通对象获取: name=', productName, 'price=', productPrice)
|
||||
}
|
||||
// 从 shopMap 获取店铺名称
|
||||
if (merchantId !== '' && shopMap.has(merchantId)) {
|
||||
shopNameStr = shopMap.get(merchantId) ?? '未知店铺'
|
||||
}
|
||||
}
|
||||
|
||||
// 如果有SKU信息,覆盖价格、图片和规格
|
||||
if (sku != null) {
|
||||
if (sku instanceof UTSJSONObject) {
|
||||
const skuPrice = sku.getNumber('price')
|
||||
if (skuPrice != null && skuPrice > 0) {
|
||||
productPrice = skuPrice
|
||||
}
|
||||
const skuImg = sku.getString('image_url')
|
||||
if (skuImg != null && skuImg !== '') {
|
||||
productImage = skuImg
|
||||
}
|
||||
|
||||
const specRaw = sku.get('specifications')
|
||||
if (specRaw != null) {
|
||||
// 优先使用SKU的规格
|
||||
if (typeof specRaw === 'string') {
|
||||
productSpec = specRaw
|
||||
} else if (specRaw instanceof UTSJSONObject) {
|
||||
const keys = ['规格', '颜色', '尺码', '容量', '版本', '型号']
|
||||
const result: string[] = []
|
||||
for (let k = 0; k < keys.length; k++) {
|
||||
const key = keys[k]
|
||||
const val = specRaw.get(key)
|
||||
if (val != null && val !== '') {
|
||||
result.push(`${val}`)
|
||||
}
|
||||
}
|
||||
if (result.length > 0) {
|
||||
productSpec = result.join(' ')
|
||||
} else {
|
||||
// Fallback for other keys
|
||||
const allKeys = UTSJSONObject.keys(specRaw)
|
||||
const parts: string[] = []
|
||||
for(let k = 0; k < allKeys.length; k++) {
|
||||
let val = specRaw.get(allKeys[k])
|
||||
if (val != null) {
|
||||
parts.push(`${val}`)
|
||||
}
|
||||
}
|
||||
productSpec = parts.join(' ')
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
let jsonStr = JSON.stringify(specRaw)
|
||||
productSpec = jsonStr.replace(/["{}]/g, '').replace(/,/g, ' ').replace(/:/g, ' ')
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const sObj = JSON.parse(JSON.stringify(sku)) as UTSJSONObject
|
||||
const skuPrice = sObj.getNumber('price') ?? 0
|
||||
if (skuPrice > 0) productPrice = skuPrice
|
||||
if (sku instanceof UTSJSONObject) {
|
||||
const skuPrice = sku.getNumber('price')
|
||||
if (skuPrice != null && skuPrice > 0) {
|
||||
productPrice = skuPrice
|
||||
}
|
||||
const skuImg = sku.getString('image_url')
|
||||
if (skuImg != null && skuImg !== '') {
|
||||
productImage = skuImg
|
||||
}
|
||||
|
||||
const specRaw = sku.get('specifications')
|
||||
if (specRaw != null) {
|
||||
if (typeof specRaw === 'string') {
|
||||
productSpec = specRaw
|
||||
} else if (specRaw instanceof UTSJSONObject) {
|
||||
const keys = ['规格', '颜色', '尺码', '容量', '版本', '型号']
|
||||
const result: string[] = []
|
||||
for (let k = 0; k < keys.length; k++) {
|
||||
const key = keys[k]
|
||||
const val = specRaw.get(key)
|
||||
if (val != null && val !== '') {
|
||||
result.push(`${val}`)
|
||||
}
|
||||
}
|
||||
if (result.length > 0) {
|
||||
productSpec = result.join(' ')
|
||||
} else {
|
||||
const allKeys = UTSJSONObject.keys(specRaw)
|
||||
const parts: string[] = []
|
||||
for(let k = 0; k < allKeys.length; k++) {
|
||||
let val = specRaw.get(allKeys[k])
|
||||
if (val != null) {
|
||||
parts.push(`${val}`)
|
||||
}
|
||||
}
|
||||
productSpec = parts.join(' ')
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
let jsonStr = JSON.stringify(specRaw)
|
||||
productSpec = jsonStr.replace(/["{}]/g, '').replace(/,/g, ' ').replace(/:/g, ' ')
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const sObj = JSON.parse(JSON.stringify(sku)) as UTSJSONObject
|
||||
const skuPrice = sObj.getNumber('price') ?? 0
|
||||
if (skuPrice > 0) productPrice = skuPrice
|
||||
|
||||
const skuImg = sObj.getString('image_url') ?? ''
|
||||
if (skuImg !== '') productImage = skuImg
|
||||
const skuImg = sObj.getString('image_url') ?? ''
|
||||
if (skuImg !== '') productImage = skuImg
|
||||
|
||||
const specRaw = sObj.get('specifications')
|
||||
if (specRaw != null) {
|
||||
// 优先使用SKU的规格
|
||||
if (typeof specRaw === 'string') {
|
||||
productSpec = specRaw
|
||||
} else if (specRaw instanceof UTSJSONObject) {
|
||||
const keys = ['规格', '颜色', '尺码', '容量', '版本', '型号']
|
||||
const result: string[] = []
|
||||
for (let k = 0; k < keys.length; k++) {
|
||||
const key = keys[k]
|
||||
const val = specRaw.get(key)
|
||||
if (val != null && val !== '') {
|
||||
result.push(`${val}`)
|
||||
}
|
||||
}
|
||||
if (result.length > 0) {
|
||||
productSpec = result.join(' ')
|
||||
} else {
|
||||
// Fallback for other keys
|
||||
const allKeys = UTSJSONObject.keys(specRaw)
|
||||
const parts: string[] = []
|
||||
for(let k = 0; k < allKeys.length; k++) {
|
||||
let val = specRaw.get(allKeys[k])
|
||||
if (val != null) {
|
||||
parts.push(`${val}`)
|
||||
}
|
||||
}
|
||||
productSpec = parts.join(' ')
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
let jsonStr = JSON.stringify(specRaw)
|
||||
productSpec = jsonStr.replace(/["{}]/g, '').replace(/,/g, ' ').replace(/:/g, ' ')
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
const specRaw = sObj.get('specifications')
|
||||
if (specRaw != null) {
|
||||
if (typeof specRaw === 'string') {
|
||||
productSpec = specRaw
|
||||
} else if (specRaw instanceof UTSJSONObject) {
|
||||
const keys = ['规格', '颜色', '尺码', '容量', '版本', '型号']
|
||||
const result: string[] = []
|
||||
for (let k = 0; k < keys.length; k++) {
|
||||
const key = keys[k]
|
||||
const val = specRaw.get(key)
|
||||
if (val != null && val !== '') {
|
||||
result.push(`${val}`)
|
||||
}
|
||||
}
|
||||
if (result.length > 0) {
|
||||
productSpec = result.join(' ')
|
||||
} else {
|
||||
const allKeys = UTSJSONObject.keys(specRaw)
|
||||
const parts: string[] = []
|
||||
for(let k = 0; k < allKeys.length; k++) {
|
||||
let val = specRaw.get(allKeys[k])
|
||||
if (val != null) {
|
||||
parts.push(`${val}`)
|
||||
}
|
||||
}
|
||||
productSpec = parts.join(' ')
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
let jsonStr = JSON.stringify(specRaw)
|
||||
productSpec = jsonStr.replace(/["{}]/g, '').replace(/,/g, ' ').replace(/:/g, ' ')
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
let shopIdStr = merchantId != '' ? merchantId : 'unknown_shop'
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user