完成consumer端同步

This commit is contained in:
2026-05-14 15:28:09 +08:00
parent 612fb3d360
commit 0ffbc53902
197 changed files with 92657 additions and 7564 deletions

View File

@@ -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>