consumer模块完成度85%,连接服务器supabase,新建相关表

This commit is contained in:
2026-01-29 17:28:47 +08:00
parent a4fa00c935
commit ab038ec029
15 changed files with 4475 additions and 4793 deletions

View File

@@ -244,85 +244,7 @@
</view>
</view>
<!-- 智能推荐 -->
<view class="smart-recommend">
<view class="section-header">
<view class="title-section">
<text class="section-icon">✨</text>
<text class="section-title">智能推荐</text>
</view>
<view class="recommend-filters">
<text
v-for="filter in recommendFilters"
:key="filter.id"
:class="['filter-item', { active: activeFilter === filter.id }]"
@click="switchFilter(filter.id)"
>
{{ filter.name }}
</text>
</view>
</view>
<view class="recommend-grid">
<view
v-for="product in recommendedProducts"
:key="product.id"
class="recommend-product"
@click="navigateToProduct(product)"
>
<view class="product-image-container">
<image
class="product-image"
:src="product.image"
mode="aspectFill"
/>
<view class="product-tags">
<text v-if="product.tag" class="product-tag">{{ product.tag }}</text>
<text v-if="product.featured" class="featured-tag">{{ product.featured }}</text>
</view>
</view>
<view class="product-details">
<text class="product-title">{{ product.name }}</text>
<text class="product-specification">{{ product.specification }}</text>
<view class="product-rating">
<view class="rating-stars">
<text class="star-icon">⭐</text>
<text class="rating-value">{{ product.rating }}</text>
</view>
<text class="reviews-count">{{ product.reviews }}条评价</text>
</view>
<view class="price-section">
<view class="current-price">
<text class="price-symbol">¥</text>
<text class="price-value">{{ product.price }}</text>
</view>
<text class="original-price" v-if="product.originalPrice > product.price">
¥{{ product.originalPrice }}
</text>
</view>
<view class="product-actions">
<view class="add-to-cart" @click.stop="addToCart(product)">
<text class="cart-icon">🛒</text>
</view>
</view>
</view>
</view>
</view>
<!-- 加载状态 -->
<view v-if="loading" class="loading-state">
<view class="loading-spinner"></view>
<text class="loading-text">加载中...</text>
</view>
<view v-if="!hasMore && recommendedProducts.length > 0" class="no-more">
<text class="no-more-text">--- 已加载全部内容 ---</text>
</view>
</view>
<!-- 智能推荐模块已隐藏 -->
<!-- 健康提醒 -->
<view class="health-reminder">
@@ -347,6 +269,8 @@
<script setup lang="uts">
import { ref, reactive, onMounted } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import supabaseService from '@/utils/supabaseService.uts'
import type { Product, Category } from '@/utils/supabaseService.uts'
// 响应式数据
const statusBarHeight = ref(0)
@@ -359,9 +283,8 @@ const activeFilter = ref('recommend')
const currentPage = ref(1)
// 数据源
const allProducts = ref<any[]>([])
const hotProducts = ref<any[]>([])
const recommendedProducts = ref<any[]>([])
const hotProducts = ref<Product[]>([])
const recommendedProducts = ref<Product[]>([])
// 屏幕尺寸检测
const isMobile = ref(false)
@@ -372,35 +295,18 @@ const lastScrollTop = ref(0)
const scrollThreshold = 30 // 降低滚动阈值,使其更灵敏
const scrollingUp = ref(false)
// 分类数据
const categories = [
{ id: 'cold', name: '感冒发烧', icon: '🤧', desc: '解热镇痛', color: '#2196F3' },
{ id: 'stomach', name: '肠胃用药', icon: '🤢', desc: '消化系统', color: '#4CAF50' },
{ id: 'pain', name: '止痛消炎', icon: '💊', desc: '镇痛消炎', color: '#F44336' },
{ id: 'skin', name: '皮肤用药', icon: '🤕', desc: '皮肤护理', color: '#9C27B0' },
{ id: 'vitamin', name: '维生素', icon: '🍊', desc: '营养补充', color: '#FF9800' },
{ id: 'chronic', name: '慢性病', icon: '🫀', desc: '长期管理', color: '#795548' },
{ id: 'child', name: '儿童用药', icon: '👶', desc: '儿童专用', color: '#00BCD4' },
{ id: 'external', name: '外用药品', icon: '🧴', desc: '外用制剂', color: '#8BC34A' },
{ id: 'device', name: '医疗器械', icon: '🩺', desc: '医疗设备', color: '#607D8B' },
{ id: 'health', name: '健康食品', icon: '🥗', desc: '保健食品', color: '#FFC107' }
]
// 分类数据 - 从Supabase获取
const categories = ref<Category[]>([])
// 排序标签
const sortTabs = [
{ id: 'recommend', name: '智能推荐' },
{ id: 'sales', name: '销量' },
{ id: 'price', name: '价格' },
{ id: 'new', name: '新品' },
{ id: 'recommend', name: '推荐' }
{ id: 'discount', name: '特价' }
]
// 推荐筛选器
const recommendFilters = [
{ id: 'recommend', name: '智能推荐' },
{ id: 'hot', name: '热门商品' },
{ id: 'discount', name: '限时优惠' },
{ id: 'quality', name: '品质优选' }
]
// 健康资讯
const healthNews = [
@@ -424,100 +330,89 @@ const healthNews = [
}
]
// 获取分类数据
const loadCategories = async () => {
try {
const categoriesData = await supabaseService.getCategories()
// 映射字段将description映射为desc保持与原有结构兼容
categories.value = categoriesData.map((cat: any) => ({
id: cat.id,
name: cat.name,
icon: cat.icon || '📦',
desc: cat.description || cat.desc || '',
color: cat.color || '#4CAF50'
}))
} catch (error) {
console.error('加载分类数据失败:', error)
// 如果加载失败,使用默认分类作为后备
categories.value = [
{ id: 'cold', name: '感冒发烧', icon: '🤧', desc: '解热镇痛', color: '#2196F3' },
{ id: 'stomach', name: '肠胃用药', icon: '🤢', desc: '消化系统', color: '#4CAF50' },
{ id: 'pain', name: '止痛消炎', icon: '💊', desc: '镇痛消炎', color: '#F44336' },
{ id: 'skin', name: '皮肤用药', icon: '🤕', desc: '皮肤护理', color: '#9C27B0' },
{ id: 'vitamin', name: '维生素', icon: '🍊', desc: '营养补充', color: '#FF9800' }
]
}
}
// 获取热销商品(根据当前排序方式)
const loadHotProducts = async () => {
try {
let products: Product[] = []
const limit = 6
console.log('加载热销商品,当前排序方式:', activeSort.value)
switch (activeSort.value) {
case 'sales':
console.log('调用 getHotProducts')
products = await supabaseService.getHotProducts(limit)
break
case 'price':
console.log('调用 getProductsByPrice')
// 按价格升序(从低到高)
products = await supabaseService.getProductsByPrice(limit, true)
break
case 'new':
console.log('调用 getProductsByNewest')
// 按创建时间,最新的在前
products = await supabaseService.getProductsByNewest(limit)
break
case 'recommend':
console.log('调用 getRecommendedProducts')
// 推荐商品带badge的商品
products = await supabaseService.getRecommendedProducts(limit)
break
case 'discount':
console.log('调用 getDiscountProducts')
// 特价商品badge为'特价'
products = await supabaseService.getDiscountProducts(limit)
break
default:
console.log('调用默认 getHotProducts')
products = await supabaseService.getHotProducts(limit)
}
console.log('加载到的商品数量:', products.length)
hotProducts.value = products
} catch (error) {
console.error('加载热销商品失败:', error)
hotProducts.value = []
}
}
// 获取推荐商品
const loadRecommendedProducts = async (limit: number = 6) => {
recommendedProducts.value = await supabaseService.getRecommendedProducts(limit)
}
// 初始化数据
const initData = () => {
const manufacturers = ['修正药业', '白云山', '养生堂', '三九医药', '同仁堂', '云南白药', '拜耳', '辉瑞']
const names = ['布洛芬', '板蓝根', '维生素C', '胃康灵', '阿莫西林', '连花清瘟', '氨溴索', '氯雷他定', '感冒灵', '健胃消食片', '阿司匹林', '蒙脱石散']
const tags = ['处方药', '中成药', '止咳化痰', '抗过敏', '感冒发烧', '肠胃用药', '消炎镇痛']
const featureds = ['医生推荐', '热销爆款', '家庭必备', '季节必备', '店长推荐']
const products = [] as any[]
for (let i = 0; i < 50; i++) {
const nameIdx = Math.floor(Math.random() * names.length)
const name = names[nameIdx]
const price = parseFloat((10 + Math.random() * 100).toFixed(1))
const originalPrice = parseFloat((price * (1.1 + Math.random() * 0.5)).toFixed(1))
const sales = Math.floor(Math.random() * 5000)
// 随机店铺ID避免全部是同一家
const randomShopSuffix = Math.floor(Math.random() * 20) + 1
products.push({
id: `prod_${i}`,
shopId: `shop_${randomShopSuffix}`,
shopName: manufacturers[Math.floor(Math.random() * manufacturers.length)] + '官方旗舰店',
name: name + (Math.random() > 0.5 ? '胶囊' : '颗粒'),
specification: Math.random() > 0.5 ? '0.3g*24粒' : '10g*10袋',
price: price,
originalPrice: originalPrice,
image: '/static/images/default-product.png',
manufacturer: manufacturers[Math.floor(Math.random() * manufacturers.length)],
sales: sales,
rating: (3.5 + Math.random() * 1.5).toFixed(1),
reviews: Math.floor(Math.random() * 500),
tag: tags[Math.floor(Math.random() * tags.length)],
featured: Math.random() > 0.7 ? featureds[Math.floor(Math.random() * featureds.length)] : '',
badge: sales > 3000 ? '热销' : (price < 20 ? '特价' : (Math.random() > 0.8 ? '新品' : '')),
// Attributes for filtering
isNew: Math.random() > 0.8,
isRecommend: Math.random() > 0.6,
isHot: sales > 2000,
isDiscount: (originalPrice - price) > 15,
isQuality: price > 60
})
}
allProducts.value = products
filterHotProducts()
filterRecommendedProducts()
const initData = async () => {
await loadCategories()
await loadHotProducts()
await loadRecommendedProducts()
}
// 筛选热销商品
const filterHotProducts = () => {
let list = [...allProducts.value]
if (activeSort.value === 'sales') {
list.sort((a, b) => b.sales - a.sales)
} else if (activeSort.value === 'price') {
list.sort((a, b) => a.price - b.price)
} else if (activeSort.value === 'new') {
list = list.filter(p => p.isNew)
} else if (activeSort.value === 'recommend') {
list = list.filter(p => p.isRecommend)
}
// 如果筛选后数量不足4个补足
if (list.length < 4) {
const remaining = allProducts.value.filter(p => !list.includes(p))
list = [...list, ...remaining]
}
hotProducts.value = list.slice(0, 4)
}
// 筛选推荐商品
const filterRecommendedProducts = () => {
let list = [...allProducts.value]
if (activeFilter.value === 'hot') {
list = list.filter(p => p.isHot)
} else if (activeFilter.value === 'discount') {
list = list.filter(p => p.isDiscount)
} else if (activeFilter.value === 'quality') {
list = list.filter(p => p.isQuality)
} else {
// 默认随机排序
list.sort(() => Math.random() - 0.5)
}
// 如果筛选后数量不足4个补足
if (list.length < 4) {
const remaining = allProducts.value.filter(p => !list.includes(p))
list = [...list, ...remaining]
}
recommendedProducts.value = list.slice(0, 4)
}
// 家庭常备药
const familyItems = [
@@ -572,9 +467,9 @@ const familyItems = [
]
// 生命周期
onMounted(() => {
onMounted(async () => {
initPage()
initData()
await initData()
})
// 页面显示时重置状态
@@ -689,13 +584,15 @@ const switchCategory = (category: any) => {
// 切换排序
const switchSort = (sortId: string) => {
activeSort.value = sortId
filterHotProducts()
// 重新加载热销商品,排序由 Supabase 服务处理
loadHotProducts()
}
// 切换筛选器
const switchFilter = (filterId: string) => {
activeFilter.value = filterId
filterRecommendedProducts()
// 重新加载推荐商品,筛选由 Supabase 服务处理
loadRecommendedProducts()
}
// 查看新闻详情
@@ -718,27 +615,33 @@ const onRefresh = () => {
}
// 加载更多
const loadMore = () => {
const loadMore = async () => {
if (loading.value || !hasMore.value) return
loading.value = true
setTimeout(() => {
// 模拟加载更多数据
const newProducts = [...recommendedProducts].map((item, index) => ({
...item,
id: `new${index}`,
price: Math.floor(item.price * 0.9 + Math.random() * 10)
}))
try {
// 增加限制以加载更多推荐商品
const currentLimit = recommendedProducts.value.length + 6
await loadRecommendedProducts(currentLimit)
// 实际项目中应该合并数据
loading.value = false
hasMore.value = recommendedProducts.length < 20
// 假设如果返回的商品数量小于请求的限制,则没有更多数据
if (recommendedProducts.value.length < currentLimit) {
hasMore.value = false
}
uni.showToast({
title: '加载完成',
icon: 'success'
})
}, 2000)
} catch (error) {
console.error('加载更多失败:', error)
uni.showToast({
title: '加载失败',
icon: 'none'
})
} finally {
loading.value = false
}
}
// 添加到购物车