consumer模块完成度95%,优化安卓端界面和小程序测试2

This commit is contained in:
cyh666666
2026-03-12 15:20:45 +08:00
parent 77f9968d18
commit b2a6e5a142
633 changed files with 4405 additions and 1651 deletions

View File

@@ -1,4 +1,4 @@
<!-- pages/main/cart.uvue -->
<!-- pages/main/cart.uvue -->
<template>
<view class="cart-page">
<!-- 智能顶部导航栏 - 与消息页保持一致 -->
@@ -103,6 +103,7 @@
<view v-if="!isManageMode" class="total-info">
<text class="total-text">合计:</text>
<text class="total-price">¥{{ totalPrice }}</text>
<text v-if="parseFloat(memberSavedAmount) > 0" class="member-saved">会员已省¥{{ memberSavedAmount }}</text>
</view>
<button v-if="!isManageMode" class="checkout-btn" @click="goToCheckout">
去结算({{ selectedCount }})
@@ -188,6 +189,8 @@ type LocalCartItem = {
shopName: string
name: string
price: number
originalPrice: number // 原价
memberPrice: number // 会员价
image: string
spec: string
quantity: number
@@ -284,7 +287,19 @@ const selectedCount = computed(() => {
const totalPrice = computed(() => {
return cartItems.value
.filter((item: LocalCartItem) => item.selected)
.reduce((sum: number, item: LocalCartItem) => sum + item.price * item.quantity, 0)
.reduce((sum: number, item: LocalCartItem) => {
// 优先使用会员价,如果没有会员价则使用原价
const finalPrice = item.memberPrice > 0 && item.memberPrice < item.price ? item.memberPrice : item.price
return sum + finalPrice * item.quantity
}, 0)
.toFixed(2)
})
// 计算会员节省金额
const memberSavedAmount = computed(() => {
return cartItems.value
.filter((item: LocalCartItem) => item.selected && item.memberPrice > 0 && item.memberPrice < item.price)
.reduce((sum: number, item: LocalCartItem) => sum + (item.price - item.memberPrice) * item.quantity, 0)
.toFixed(2)
})
@@ -393,6 +408,18 @@ const loadCartData = async () => {
loading.value = true
try {
// 获取会员折扣信息
let memberDiscount = 1.0
try {
const memberInfo = await supabaseService.getUserMemberInfo()
const discountRaw = memberInfo.get('discount')
if (discountRaw != null) {
memberDiscount = discountRaw as number
}
} catch (e) {
console.log('获取会员信息失败,使用默认折扣:', e)
}
// 从Supabase加载购物车数据
const supabaseCartItems = await supabaseService.getCartItems()
@@ -405,12 +432,21 @@ const loadCartData = async () => {
const shopId = (item.shop_id != null && item.shop_id !== '') ? item.shop_id : 'default_shop'
const shopName = (item.shop_name != null && item.shop_name !== '') ? item.shop_name : '商城优选'
// 计算会员价
const originalPrice = item.product_price != null ? item.product_price : 0
let memberPrice = 0
if (memberDiscount > 0 && memberDiscount < 1 && originalPrice > 0) {
memberPrice = Math.round(originalPrice * memberDiscount * 100) / 100
}
return {
id: item.id,
shopId: shopId,
shopName: shopName,
name: item.product_name ?? '未知商品',
price: item.product_price != null ? item.product_price : 0,
price: originalPrice,
originalPrice: originalPrice,
memberPrice: memberPrice,
image: item.product_image ?? '/static/images/default-product.png',
spec: item.product_specification ?? '标准规格',
quantity: item.quantity ?? 1,
@@ -534,6 +570,8 @@ const toggleShopSelect = async (shopId: string) => {
shopName: item.shopName,
name: item.name,
price: item.price,
originalPrice: item.originalPrice,
memberPrice: item.memberPrice,
image: item.image,
spec: item.spec,
quantity: item.quantity,

View File

@@ -1,11 +1,11 @@
<template>
<template>
<view class="category-page">
<!-- 顶部搜索栏 -->
<view class="search-bar" :style="{ paddingTop: statusBarHeight + 'px' }">
<view class="search-container">
<view class="search-box" @click="navigateToSearch" :style="{ height: '30px' }">
<!-- 模拟输入框 -->
<text class="search-placeholder">请输入品名称、症状或品牌</text>
<text class="search-placeholder">请输入品名称、店铺</text>
<!-- 扫码图标 -->
<view class="nav-icon-btn" @click.stop="onScan">
@@ -100,10 +100,16 @@
</view>
</view>
<!-- 状态 -->
<!-- 加载中状态 -->
<view v-else-if="loading" class="loading-state">
<view class="loading-spinner"></view>
<text class="loading-text">加载中...</text>
</view>
<!-- 空状态 - 仅在非加载状态且无商品时显示 -->
<view v-else class="empty-state">
<text class="empty-icon">💊</text>
<text class="empty-text">暂无相关品</text>
<text class="empty-icon"><EFBFBD></text>
<text class="empty-text">暂无相关品</text>
<text class="empty-desc">该分类下暂无商品,敬请期待</text>
</view>
@@ -1095,6 +1101,37 @@ function onScan(): void {
margin-right: 6px; /* gap replacement */
}
/* 加载中状态 */
.loading-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 60px 20px;
text-align: center;
}
.loading-spinner {
width: 40px;
height: 40px;
border: 3px solid #f0f0f0;
border-top-color: #ff5000;
border-radius: 50%;
animation: spin 1s linear infinite;
margin-bottom: 15px;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
.loading-text {
font-size: 14px;
color: #999;
}
/* 空状态 */
.empty-state {
display: flex;

View File

@@ -1,4 +1,4 @@
<!-- pages/main/index.uvue -->
<!-- pages/main/index.uvue -->
<template>
<view class="medic-home">
<!-- 智能顶部导航栏 - 添加滚动隐藏效果 -->
@@ -12,7 +12,7 @@
<view class="search-container">
<view class="search-box" @click="navigateToSearch" :style="{ height: '30px' }">
<!-- 模拟输入框 -->
<text class="search-placeholder">请输入品名称、症状或品牌</text>
<text class="search-placeholder">请输入品名称、店铺</text>
<!-- 扫码图标 -->
<view class="nav-icon-btn" @click.stop="onScan">
@@ -681,37 +681,43 @@ onShow(() => {
// 处理滚动事件
const handleScroll = (event: any) => {
const eventObj = event as UTSJSONObject
const detail = eventObj.get('detail') as UTSJSONObject
const scrollTop = detail.getNumber('scrollTop') ?? 0
const currentTime = Date.now()
// 判断滚动方向
if (scrollTop > lastScrollTop.value) {
// 向下滚动
scrollingUp.value = false
// 向下滚动超过阈值时隐藏导航栏
if (scrollTop > scrollThreshold && showNavbar.value) {
showNavbar.value = false
try {
const eventObj = event as UTSJSONObject
const detailRaw = eventObj.get('detail')
if (detailRaw == null) return
const detail = detailRaw as UTSJSONObject
const scrollTop = detail.getNumber('scrollTop') ?? 0
const currentTime = Date.now()
// 判断滚动方向
if (scrollTop > lastScrollTop.value) {
// 向下滚动
scrollingUp.value = false
// 向下滚动超过阈值时隐藏导航栏
if (scrollTop > scrollThreshold && showNavbar.value) {
showNavbar.value = false
}
} else if (scrollTop < lastScrollTop.value) {
// 向上滚动
scrollingUp.value = true
// 向上滚动时显示导航栏
if (!showNavbar.value) {
showNavbar.value = true
}
}
} else if (scrollTop < lastScrollTop.value) {
// 向上滚动
scrollingUp.value = true
// 向上滚动时显示导航栏
if (!showNavbar.value) {
// 滚动到顶部时强制显示导航栏
if (scrollTop <= 10) {
showNavbar.value = true
}
lastScrollTop.value = scrollTop
// 调试信息(开发时可启用)
// console.log(`Scroll: ${scrollTop}, ShowNavbar: ${showNavbar.value}, ScrollingUp: ${scrollingUp.value}`)
} catch (e) {
// 忽略滚动事件处理错误
}
// 滚动到顶部时强制显示导航栏
if (scrollTop <= 10) {
showNavbar.value = true
}
lastScrollTop.value = scrollTop
// 调试信息(开发时可启用)
// console.log(`Scroll: ${scrollTop}, ShowNavbar: ${showNavbar.value}, ScrollingUp: ${scrollingUp.value}`)
}
// 重置导航栏显示状态(例如点击回到顶部时)