完成consumer端同步
This commit is contained in:
@@ -88,17 +88,40 @@
|
||||
<view class="product-image-wrapper">
|
||||
<image
|
||||
class="product-image"
|
||||
:src="product.main_image_url"
|
||||
:src="getProductCover(product)"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
</view>
|
||||
<text class="product-name" :lines="2">{{ product.name }}</text>
|
||||
<view v-if="getProductCardTags(product).length > 0" class="product-card-tags">
|
||||
<text
|
||||
v-for="(tag, index) in getProductCardTags(product)"
|
||||
:key="product.id + '-tag-' + index"
|
||||
class="product-card-tag"
|
||||
>
|
||||
{{ tag }}
|
||||
</text>
|
||||
</view>
|
||||
<text class="product-name" :lines="2">{{ getProductTitle(product) }}</text>
|
||||
<text v-if="getProductHighlight(product) !== ''" class="product-highlight">{{ getProductHighlight(product) }}</text>
|
||||
<view v-if="getProductServiceTags(product).length > 0" class="product-service-tags">
|
||||
<text
|
||||
v-for="(tag, index) in getProductServiceTags(product)"
|
||||
:key="product.id + '-service-' + index"
|
||||
class="product-service-tag"
|
||||
>
|
||||
{{ tag }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="product-bottom">
|
||||
<text class="product-price">¥{{ product.base_price ?? product.price ?? 0 }}</text>
|
||||
<view class="price-stack">
|
||||
<text class="product-price">¥{{ formatProductPrice(product) }}</text>
|
||||
<text v-if="showMarketPrice(product)" class="product-market-price">¥{{ formatMarketPrice(product) }}</text>
|
||||
</view>
|
||||
<view class="product-add-btn" @click.stop="addToCart(product)">
|
||||
<text class="add-icon">+</text>
|
||||
</view>
|
||||
</view>
|
||||
<text v-if="getProductSalesText(product) !== ''" class="product-sales-text">{{ getProductSalesText(product) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -110,7 +133,7 @@
|
||||
|
||||
<!-- 空状态 - 仅在非加载状态且无商品时显示 -->
|
||||
<view v-else class="empty-state">
|
||||
<text class="empty-icon"><EFBFBD></text>
|
||||
<text class="empty-icon">🛍️</text>
|
||||
<text class="empty-text">暂无相关商品</text>
|
||||
<text class="empty-desc">该分类下暂无商品,敬请期待</text>
|
||||
</view>
|
||||
@@ -129,6 +152,7 @@ import { ref, onMounted } from 'vue'
|
||||
import { onLoad, onShow } from '@dcloudio/uni-app'
|
||||
import supabaseService from '@/utils/supabaseService.uts'
|
||||
import type { Product } from '@/utils/supabaseService.uts'
|
||||
import { goToLogin } from '@/utils/utils.uts'
|
||||
|
||||
type LocalCategory = {
|
||||
id: string
|
||||
@@ -177,6 +201,66 @@ const currentCategoryDesc = ref('')
|
||||
// 页面参数
|
||||
const pageParams = ref<any>({})
|
||||
|
||||
function getProductCover(product: Product): string {
|
||||
if (product.main_image_url != null && product.main_image_url !== '') return product.main_image_url
|
||||
if (product.images != null && product.images.length > 0 && product.images[0] !== '') return product.images[0]
|
||||
if (product.image_url != null && product.image_url !== '') return product.image_url
|
||||
return '/static/images/default.png'
|
||||
}
|
||||
|
||||
function getProductTitle(product: Product): string {
|
||||
if (product.short_title != null && product.short_title !== '') return product.short_title
|
||||
if (product.name != null && product.name !== '') return product.name
|
||||
return product.id ?? ''
|
||||
}
|
||||
|
||||
function getProductCardTags(product: Product): string[] {
|
||||
if (product.card_tags != null && product.card_tags.length > 0) return product.card_tags.slice(0, 2)
|
||||
const fallback: string[] = []
|
||||
if (product.is_hot === true) fallback.push('热卖')
|
||||
if (product.is_new === true && fallback.length < 2) fallback.push('新品')
|
||||
if (product.is_featured === true && fallback.length < 2) fallback.push('精选')
|
||||
return fallback
|
||||
}
|
||||
|
||||
function getProductServiceTags(product: Product): string[] {
|
||||
if (product.service_tags != null && product.service_tags.length > 0) return product.service_tags.slice(0, 3)
|
||||
return [] as string[]
|
||||
}
|
||||
|
||||
function getProductHighlight(product: Product): string {
|
||||
if (product.selling_points != null && product.selling_points.length > 0 && product.selling_points[0] !== '') {
|
||||
return product.selling_points[0]
|
||||
}
|
||||
if (product.subtitle != null && product.subtitle !== '') return product.subtitle
|
||||
return ''
|
||||
}
|
||||
|
||||
function getProductSalesText(product: Product): string {
|
||||
if (product.display_sales_text != null && product.display_sales_text !== '') return product.display_sales_text
|
||||
const sales = product.sale_count ?? 0
|
||||
if (sales >= 100000) return '已售10万+'
|
||||
if (sales >= 10000) return '已售' + (sales / 10000).toFixed(1) + '万件'
|
||||
if (sales > 0) return '已售' + sales.toString() + '件'
|
||||
return ''
|
||||
}
|
||||
|
||||
function formatProductPrice(product: Product): string {
|
||||
const price = product.base_price ?? product.price ?? 0
|
||||
return parseFloat(price.toString()).toFixed(2)
|
||||
}
|
||||
|
||||
function formatMarketPrice(product: Product): string {
|
||||
const price = product.market_price ?? product.original_price ?? 0
|
||||
return parseFloat(price.toString()).toFixed(2)
|
||||
}
|
||||
|
||||
function showMarketPrice(product: Product): boolean {
|
||||
const marketPrice = product.market_price ?? product.original_price ?? 0
|
||||
const salePrice = product.base_price ?? product.price ?? 0
|
||||
return marketPrice > 0 && marketPrice > salePrice
|
||||
}
|
||||
|
||||
// 加载商品数据
|
||||
async function loadProducts(): Promise<void> {
|
||||
if (loading.value) return
|
||||
@@ -648,6 +732,11 @@ onLoad((options: any) => {
|
||||
|
||||
// 添加到购物车
|
||||
async function addToCart(product: Product): Promise<void> {
|
||||
const userId = supabaseService.getCurrentUserId()
|
||||
if (userId == null || userId === '') {
|
||||
goToLogin('/pages/main/category')
|
||||
return
|
||||
}
|
||||
uni.showLoading({ title: '检查商品...' })
|
||||
try {
|
||||
const pid = (product.id ?? '').toString()
|
||||
@@ -700,7 +789,7 @@ async function addToCart(product: Product): Promise<void> {
|
||||
|
||||
// 导航函数
|
||||
function navigateToSearch(): void { uni.navigateTo({ url: '/pages/mall/consumer/search' }) }
|
||||
function navigateToCart(): void { uni.navigateTo({ url: '/pages/main/cart' }) }
|
||||
function navigateToCart(): void { uni.switchTab({ url: '/pages/main/cart' }) }
|
||||
function navigateToProduct(product: Product): void {
|
||||
const id = (product.id ?? '').toString()
|
||||
if (id === '') return
|
||||
@@ -719,7 +808,7 @@ function onCamera(): void {
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
sourceType: ['camera'],
|
||||
success: (res) => {
|
||||
success: (res: ChooseImageSuccess) => {
|
||||
console.log('相机拍摄成功:', res.tempFilePaths[0])
|
||||
uni.showToast({
|
||||
title: '已拍摄,正在识别...',
|
||||
@@ -742,7 +831,7 @@ function onCamera(): void {
|
||||
// 扫码功能
|
||||
function onScan(): void {
|
||||
uni.scanCode({
|
||||
success: (res) => {
|
||||
success: (res: ScanCodeSuccess) => {
|
||||
console.log('扫码成功:', res)
|
||||
uni.showToast({
|
||||
title: '扫码成功: ' + res.result,
|
||||
@@ -1084,6 +1173,58 @@ function onScan(): void {
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
.product-card-tags {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
padding: 8px 8px 0;
|
||||
}
|
||||
|
||||
.product-card-tag {
|
||||
height: 28rpx;
|
||||
line-height: 28rpx;
|
||||
padding: 0 8rpx;
|
||||
border-radius: 8rpx;
|
||||
font-size: 18rpx;
|
||||
font-weight: 700;
|
||||
color: #fff7d1;
|
||||
background: #e1251b;
|
||||
margin-right: 6rpx;
|
||||
margin-bottom: 4rpx;
|
||||
}
|
||||
|
||||
.product-highlight {
|
||||
font-size: 20rpx;
|
||||
line-height: 28rpx;
|
||||
color: #7a7a7a;
|
||||
padding: 0 8px;
|
||||
margin-bottom: 6rpx;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.product-service-tags {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
padding: 0 8px;
|
||||
margin-bottom: 6rpx;
|
||||
}
|
||||
|
||||
.product-service-tag {
|
||||
height: 28rpx;
|
||||
line-height: 28rpx;
|
||||
padding: 0 8rpx;
|
||||
border-radius: 8rpx;
|
||||
font-size: 18rpx;
|
||||
font-weight: 600;
|
||||
color: #12b76a;
|
||||
background: #ecfdf3;
|
||||
margin-right: 6rpx;
|
||||
margin-bottom: 4rpx;
|
||||
}
|
||||
|
||||
.product-bottom {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
@@ -1092,12 +1233,33 @@ function onScan(): void {
|
||||
padding: 0 8px 8px;
|
||||
}
|
||||
|
||||
.price-stack {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.product-price {
|
||||
font-size: 15px;
|
||||
color: #ff5000;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.product-market-price {
|
||||
font-size: 20rpx;
|
||||
line-height: 1.2;
|
||||
color: #9a9a9a;
|
||||
text-decoration: line-through;
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
|
||||
.product-sales-text {
|
||||
font-size: 20rpx;
|
||||
line-height: 28rpx;
|
||||
color: #8f8f8f;
|
||||
padding: 0 8px 12px;
|
||||
}
|
||||
|
||||
.product-add-btn {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
@@ -1550,4 +1712,3 @@ function onScan(): void {
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user