consumer模块完成度95%,完成部署消费者端(外网可访问consumer.meitizs.com),消费者小程序能正常运行在微信开发者工具上

This commit is contained in:
cyh666666
2026-03-05 16:54:00 +08:00
parent 7f7f723d93
commit 3b0e397714
728 changed files with 1495 additions and 985 deletions

View File

@@ -2,7 +2,7 @@
<template>
<view class="orders-page">
<!-- 顶部标题栏 -->
<view class="orders-header">
<view class="orders-header" :style="{ paddingTop: statusBarHeight + 'px' }">
<view class="header-search full-width">
<input
class="search-input"
@@ -44,7 +44,7 @@
<!-- 订单列表 -->
<scroll-view
scroll-y
direction="vertical"
class="orders-content"
refresher-enabled
:refresher-triggered="refreshing"
@@ -125,29 +125,30 @@
</view>
<view v-if="order.status === 2" class="action-buttons">
<button class="action-btn remind" @click="remindShipping(order.id)">提醒发货</button>
<button class="action-btn remind" @click.stop="remindShipping(order.id)">提醒发货</button>
<button class="action-btn refund" @click.stop="onApplyRefund(order)">申请售后</button>
</view>
<view v-if="order.status === 3" class="action-buttons">
<button class="action-btn view" @click="viewLogistics(order.id)">查看物流</button>
<button class="action-btn confirm" @click="confirmReceipt(order.id)">确认收货</button>
<button class="action-btn view" @click.stop="viewLogistics(order.id)">查看物流</button>
<button class="action-btn confirm" @click.stop="confirmReceipt(order.id)">确认收货</button>
<button class="action-btn refund" @click.stop="onApplyRefund(order)">申请售后</button>
</view>
<view v-if="order.status === 4" class="action-buttons">
<button class="action-btn review" @click="goReview(order)">评价</button>
<button class="action-btn review" @click.stop="goReview(order)">评价</button>
<button class="action-btn refund" @click.stop="onApplyRefund(order)">申请售后</button>
<button class="action-btn repurchase" @click="repurchase(order)">再次购买</button>
<button class="action-btn repurchase" @click.stop="repurchase(order)">再次购买</button>
</view>
<view v-if="order.status === 5" class="action-buttons">
<button class="action-btn view" @click="viewOrderDetail(order.id)">查看详情</button>
<button class="action-btn view" @click.stop="viewOrderDetail(order.id)">查看详情</button>
</view>
<view v-if="order.status === 6" class="action-buttons">
<button class="action-btn view" @click="viewOrderDetail(order.id)">查看详情</button>
<button class="action-btn refund" @click="viewRefundProgress(order.id)">退款进度</button>
<button class="action-btn view" @click.stop="viewOrderDetail(order.id)">查看详情</button>
<button class="action-btn cancel" @click.stop="cancelRefund(order.id)">取消退款</button>
<button class="action-btn refund" @click.stop="viewRefundProgress(order.id)">退款进度</button>
</view>
<view v-if="order.status === 7" class="action-buttons">
@@ -222,6 +223,7 @@ const hasMore = ref<boolean>(true)
const refreshing = ref<boolean>(false)
const page = ref<number>(1)
const activeTab = ref<string>('all')
const statusBarHeight = ref<number>(0)
const searchKeyword = ref<string>('')
// 订单标签页 - 使用 ref 以便整体替换
@@ -504,6 +506,10 @@ const loadOrders = async () => {
// 生命周期
onLoad((options) => {
// 初始化状态栏高度
const systemInfo = uni.getSystemInfoSync()
statusBarHeight.value = systemInfo.statusBarHeight ?? 0
if (options == null) return
const statusVal = options['status']
if (statusVal != null) {
@@ -518,7 +524,7 @@ onLoad((options) => {
if (type === 'pending') activeTab.value = 'pending'
else if (type === 'shipped') activeTab.value = 'delivering' // 映射到待收货
else if (type === 'review') activeTab.value = 'completed' // 映射到已完成
else if (type === 'refund') activeTab.value = 'all' // 申请售后默认显示全部
else if (type === 'refund') activeTab.value = 'aftersale' // 退款/售后跳转到售后标签页
}
})
@@ -771,15 +777,11 @@ const viewLogistics = (orderId: string) => {
}
// goReview 必须在 doConfirmReceipt 之前定义,因为 doConfirmReceipt 会调用它
const goReview = (order: any) => {
const orderObj = order as Record<string, any>
const products = orderObj['products'] as any[]
const productIds = products.map((p: any) => {
const pObj = p as Record<string, any>
const pid = pObj['id']
return pid != null ? pid as string : ''
const goReview = (order: OrderItem) => {
const productIds = order.products.map((p: OrderProduct): string => {
return p.id
}).join(',')
const orderId = orderObj['id'] as string
const orderId = order.id
uni.navigateTo({
url: `/pages/mall/consumer/review?orderId=${orderId}&productIds=${productIds}`
})
@@ -798,22 +800,15 @@ const doConfirmReceipt = async (orderId: string) => {
})
// 更新本地状态
const index = orders.value.findIndex((o: any) => {
const obj = o as Record<string, any>
return obj['id'] === orderId
})
const index = orders.value.findIndex((o: OrderItem): boolean => o.id === orderId)
if (index !== -1) {
const orderObj = orders.value[index] as Record<string, any>
orderObj['status'] = 4
orders.value[index].status = 4
orders.value = [...orders.value]
}
// 跳转到评价页面
setTimeout(() => {
const order = orders.value.find((o: any) => {
const obj = o as Record<string, any>
return obj['id'] === orderId
})
const order = orders.value.find((o: OrderItem): boolean => o.id === orderId)
if (order != null) {
goReview(order)
}
@@ -845,11 +840,10 @@ const confirmReceipt = (orderId: string) => {
})
}
const repurchase = (order: any) => {
const orderObj = order as Record<string, any>
const products = orderObj['products'] as any[]
const repurchase = (order: OrderItem) => {
const products = order.products
if (products == null || products.length === 0) {
if (products.length === 0) {
uni.showToast({
title: '订单无商品',
icon: 'none'
@@ -864,12 +858,12 @@ const repurchase = (order: any) => {
let successCount = 0
for (let i = 0; i < products.length; i++) {
const pObj = products[i] as Record<string, any>
const productId = pObj['id'] as string
const merchantId = orderObj['merchant_id'] as string
const product = products[i]
const productId = product.id
const merchantId = order.merchant_id
if (productId != null && productId !== '') {
supabaseService.addToCart(productId, 1, '', merchantId ?? '').then((success) => {
supabaseService.addToCart(productId, 1, '', merchantId ?? '').then((success: boolean) => {
completed++
if (success) successCount++
if (completed === total) {
@@ -929,9 +923,8 @@ const viewOrderDetail = (orderId: string) => {
})
}
const onApplyRefund = (order: any) => {
const orderObj = order as Record<string, any>
const orderId = orderObj['id']
const onApplyRefund = (order: OrderItem) => {
const orderId = order.id
uni.navigateTo({
url: `/pages/mall/consumer/apply-refund?orderId=${orderId}`
})
@@ -943,6 +936,32 @@ const viewRefundProgress = (orderId: string) => {
})
}
const doCancelRefund = async (orderId: string) => {
uni.showLoading({ title: '处理中...' })
const result = await supabaseService.cancelRefund(orderId)
uni.hideLoading()
if (result.success) {
uni.showToast({ title: '已取消退款', icon: 'success' })
loadOrders()
} else {
uni.showToast({ title: result.message, icon: 'none' })
}
}
// 取消退款申请
const cancelRefund = (orderId: string) => {
uni.showModal({
title: '确认取消',
content: '确定要取消退款申请吗?',
success: (res) => {
if (res.confirm) {
doCancelRefund(orderId)
}
}
})
}
// 处理订单操作
const handleOrderAction = (order: OrderItem, action: string) => {
if (action === '取消订单') {
@@ -963,6 +982,8 @@ const handleOrderAction = (order: OrderItem, action: string) => {
deleteOrder(order.id)
} else if (action === '退款进度') {
viewRefundProgress(order.id)
} else if (action === '取消退款') {
cancelRefund(order.id)
}
}
@@ -982,7 +1003,7 @@ const showOrderMenu = (order: OrderItem) => {
} else if (status === 5) {
actions = ['删除订单', '再次购买', '联系卖家']
} else if (status === 6) {
actions = ['退款进度', '联系卖家']
actions = ['取消退款', '退款进度', '联系卖家']
} else if (status === 7) {
actions = ['再次购买', '联系卖家']
}
@@ -1001,59 +1022,75 @@ const navigateToSearch = () => {
uni.navigateTo({ url: '/pages/mall/consumer/search' })
}
const navigateToProduct = (product: any) => {
const productObj = product as Record<string, any>
const productId = productObj['id']
const navigateToProduct = (product: OrderProduct) => {
const productId = product.id
uni.navigateTo({ url: `/pages/mall/consumer/product-detail?id=${productId}` })
}
const goShopping = () => {
uni.switchTab({ url: '/pages/mall/consumer/index' })
uni.switchTab({ url: '/pages/main/index' })
}
</script>
<style>
.orders-page {
position: absolute;
display: flex;
flex-direction: column;
/* 采用相对于窗口的 100% 方案 */
width: 100%;
height: 100%;
/* App/小程序通过 fixed 解决根容器撑满问题H5/电脑端建议使用 flex 1 */
/* #ifdef APP-PLUS || MP-WEIXIN */
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
flex-direction: column;
/* #endif */
/* #ifdef H5 */
position: relative;
/* #endif */
background-color: #f5f5f5;
overflow: hidden;
}
/* 头部 */
/* 头部:确保显式可见且不被遮挡 */
.orders-header {
background-color: white;
padding: 15px;
background-color: #ffffff;
padding: 10px 15px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
border-bottom: 1px solid #eee;
z-index: 10;
width: 100%;
border-bottom: 1px solid #eeeeee;
z-index: 999;
position: relative;
box-sizing: border-box;
flex-shrink: 0;
}
.header-search.full-width {
display: flex;
flex-direction: row;
align-items: center;
position: relative;
width: 100%;
flex: 1;
}
.search-input {
flex: 1;
height: 36px;
border: 1px solid #ddd;
line-height: normal;
border: 1px solid #dddddd;
border-radius: 18px;
padding: 0 40px 0 16px;
font-size: 14px;
background-color: #f5f5f5;
color: #333;
color: #333333;
width: 100%;
display: flex;
align-items: center;
}
.search-input::placeholder {
@@ -1086,7 +1123,7 @@ const goShopping = () => {
/* cursor: pointer; removed */
}
/* 标签页 */
/* 标签页容器:确保在安卓下层级正确且不随内容滚动 */
.order-tabs-fixed-container {
background-color: #ffffff;
border-bottom: 1px solid #f0f0f0;
@@ -1094,26 +1131,25 @@ const goShopping = () => {
flex-direction: row;
align-items: center;
width: 100%;
z-index: 10;
height: 50px;
z-index: 100 !important;
flex-shrink: 0;
position: relative;
}
/* 安卓端滚动修复 */
/* 安卓端滚动修复:关键容器 */
.orders-content {
flex: 1;
width: 100%;
height: 0; /* 关键:强制 flex: 1 生效 */
/* 极致方案:不再设置 height: 0改用 flex: 1 填满,并显式设置 scroll-y 的表现 */
min-height: 0;
flex-shrink: 1;
background-color: #f5f5f5;
}
.orders-header {
background-color: white;
padding: 15px;
display: flex;
align-items: center;
justify-content: center;
border-bottom: 1px solid #eee;
/* 顶部内容区域必须显式不可伸缩,防止撑占滚动空间 */
.orders-header, .order-tabs-fixed-container {
flex-shrink: 0;
width: 100%;
}
.tab-item-fixed {
@@ -1456,6 +1492,16 @@ const goShopping = () => {
border-color: #34c759;
}
.action-btn.refund {
color: #666;
border-color: #ccc;
}
.action-btn.cancel {
color: #ff6b6b;
border-color: #ff6b6b;
}
.action-btn.review {
color: #ff9500;
border-color: #ff9500;