consumer模块完成度95%,准备部署消费者端测试

This commit is contained in:
cyh666666
2026-03-05 08:45:00 +08:00
parent cceb556c62
commit 7f7f723d93
1043 changed files with 53958 additions and 3445 deletions

View File

@@ -1,23 +1,23 @@
<!-- pages/mall/consumer/orders.uvue -->
<!-- pages/mall/consumer/orders.uvue -->
<template>
<view class="orders-page">
<!-- 顶部标题栏 -->
<!-- 椤堕儴鏍囬鏍?-->
<view class="orders-header">
<view class="header-search full-width">
<input
class="search-input"
type="text"
placeholder="搜索订单号或商品名称"
placeholder="鎼滅储璁㈠崟鍙锋垨鍟嗗搧鍚嶇О"
:value="searchKeyword"
@input="onSearchInput"
@confirm="onSearchConfirm"
/>
<text v-if="searchKeyword" class="search-clear" @click="clearSearch">×</text>
<text v-else class="search-icon">🔍</text>
<text v-if="searchKeyword" class="search-clear" @click="clearSearch"></text>
<text v-else class="search-icon">馃攳</text>
</view>
</view>
<!-- 订单状态筛选 -->
<!-- 璁㈠崟鐘舵€佺瓫閫?-->
<view class="order-tabs">
<scroll-view scroll-x class="tab-scroll" :show-scrollbar="false">
<view class="tab-container">
@@ -35,7 +35,7 @@
</scroll-view>
</view>
<!-- 订单列表 -->
<!-- 璁㈠崟鍒楄〃 -->
<scroll-view
scroll-y
class="orders-content"
@@ -44,15 +44,15 @@
@refresherrefresh="onRefresh"
@scrolltolower="loadMore"
>
<!-- 空状态 -->
<!-- 绌虹姸鎬?-->
<view v-if="!loading && orders.length === 0" class="empty-orders">
<text class="empty-icon">📦</text>
<text class="empty-title">暂无订单</text>
<text class="empty-desc">去逛逛,发现心仪的商品</text>
<button class="go-shopping-btn" @click="goShopping">去逛逛</button>
<text class="empty-icon">馃摝</text>
<text class="empty-title">鏆傛棤璁㈠崟</text>
<text class="empty-desc">鍘婚€涢€涳紝鍙戠幇蹇冧华鐨勫晢鍝?/text>
<button class="go-shopping-btn" @click="goShopping">鍘婚€涢€?/button>
</view>
<!-- 订单列表 -->
<!-- 璁㈠崟鍒楄〃 -->
<view v-else class="order-list">
<view
v-for="order in orders"
@@ -60,19 +60,19 @@
class="order-card"
@click="viewOrderDetail(order.id)"
>
<!-- 订单头部:显示店铺名称 -->
<!-- 璁㈠崟澶撮儴锛氭樉绀哄簵閾哄悕绉?-->
<view class="order-card-header">
<view class="shop-info">
<text class="shop-icon">🏪</text>
<text class="shop-name">{{ order.shop_name != null && order.shop_name != '' ? order.shop_name : '自营店铺' }}</text>
<text class="arrow-right"></text>
<text class="shop-icon">馃彧</text>
<text class="shop-name">{{ order.shop_name != null && order.shop_name != '' ? order.shop_name : '鑷惀搴楅摵' }}</text>
<text class="arrow-right">鈥?/text>
</view>
<text :class="['order-status', getStatusClass(order.status)]">
{{ getStatusText(order.status) }}
</text>
</view>
<!-- 订单商品 -->
<!-- 璁㈠崟鍟嗗搧 -->
<view class="order-products">
<view
v-for="product in order.products"
@@ -91,68 +91,68 @@
<text class="product-spec">{{ product.spec }}</text>
</view>
<view class="product-footer">
<text class="product-price">¥{{ product.price }}</text>
<text class="product-price">{{ product.price }}</text>
<text class="product-quantity">x{{ product.quantity }}</text>
</view>
</view>
</view>
</view>
<!-- 订单汇总信息 -->
<!-- 璁㈠崟姹囨€讳俊鎭?-->
<view class="order-summary">
<text class="order-time">{{ formatDate(order.create_time) }}</text>
<view class="summary-right">
<text class="summary-label">共{{ order.products.length }}件商品 实付:</text>
<text class="summary-price">¥{{ order.total_amount }}</text>
<text class="summary-label">鍏眥{ order.products.length }}浠跺晢鍝?瀹炰粯:</text>
<text class="summary-price">{{ order.total_amount }}</text>
</view>
</view>
<!-- 订单操作 -->
<!-- 璁㈠崟鎿嶄綔 -->
<view class="order-actions" @click.stop="">
<view v-if="order.status === 1" class="action-buttons">
<button class="action-btn cancel" @click="cancelOrder(order.id)">取消订单</button>
<button class="action-btn pay" @click="payOrder(order.id)">立即支付</button>
<button class="action-btn cancel" @click="cancelOrder(order.id)">鍙栨秷璁㈠崟</button>
<button class="action-btn pay" @click="payOrder(order.id)">绔嬪嵆鏀粯</button>
</view>
<view v-if="order.status === 2" class="action-buttons">
<button class="action-btn remind" @click="remindShipping(order.id)">提醒发货</button>
<button class="action-btn refund" @click.stop="onApplyRefund(order)">申请售后</button>
<button class="action-btn remind" @click="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 refund" @click.stop="onApplyRefund(order)">申请售后</button>
<button class="action-btn view" @click="viewLogistics(order.id)">鏌ョ湅鐗╂祦</button>
<button class="action-btn confirm" @click="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 refund" @click.stop="onApplyRefund(order)">申请售后</button>
<button class="action-btn repurchase" @click="repurchase(order)">再次购买</button>
<button class="action-btn review" @click="goReview(order)">璇勪环</button>
<button class="action-btn refund" @click.stop="onApplyRefund(order)">鐢宠鍞悗</button>
<button class="action-btn repurchase" @click="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="viewOrderDetail(order.id)">鏌ョ湅璇︽儏</button>
</view>
</view>
</view>
</view>
<!-- 加载更多 -->
<!-- 鍔犺浇鏇村 -->
<view v-if="loadingMore" class="loading-more">
<view class="loading-spinner"></view>
<text>加载中...</text>
<text>鍔犺浇涓?..</text>
</view>
<view v-if="!hasMore && orders.length > 0" class="no-more">
<text>没有更多订单了</text>
<text>娌℃湁鏇村璁㈠崟浜?/text>
</view>
<!-- 安全区域 -->
<!-- 瀹夊叏鍖哄煙 -->
<view class="safe-area"></view>
</scroll-view>
<!-- 底部导航 -->
<!-- 搴曢儴瀵艰埅 -->
<view class="tabbar-placeholder"></view>
</view>
</template>
@@ -162,14 +162,14 @@ import { ref, reactive, onMounted, computed } from 'vue'
import { onShow, onLoad, onBackPress } from '@dcloudio/uni-app'
import { supabaseService } from '@/utils/supabaseService.uts'
// 定义标签页类型
// 瀹氫箟鏍囩椤电被鍨?
type OrderTabItem = {
id: string,
name: string,
count: number
}
// 定义订单产品类型
// 瀹氫箟璁㈠崟浜у搧绫诲瀷
type OrderProduct = {
id: string,
name: string,
@@ -179,7 +179,7 @@ type OrderProduct = {
quantity: number
}
// 定义订单类型
// 瀹氫箟璁㈠崟绫诲瀷
type OrderItem = {
id: string,
order_no: string,
@@ -193,7 +193,7 @@ type OrderItem = {
products: OrderProduct[]
}
// 响应式数据
// 鍝嶅簲寮忔暟鎹?
const orders = ref<OrderItem[]>([])
const allOrdersList = ref<OrderItem[]>([]) // Store all fetched orders for client-side filtering
const loading = ref<boolean>(false)
@@ -204,20 +204,20 @@ const page = ref<number>(1)
const activeTab = ref<string>('all')
const searchKeyword = ref<string>('')
// 订单标签页 - 使用 ref 以便整体替换
// 璁㈠崟鏍囩椤?- 浣跨敤 ref 浠ヤ究鏁翠綋鏇挎崲
const orderTabs = ref<OrderTabItem[]>([
{ id: 'all', name: '全部', count: 0 },
{ id: 'pending', name: '待付款', count: 0 },
{ id: 'shipping', name: '待发货', count: 0 },
{ id: 'delivering', name: '待收货', count: 0 },
{ id: 'completed', name: '已完成', count: 0 },
{ id: 'cancelled', name: '已取消', count: 0 }
{ id: 'all', name: '鍏ㄩ儴', count: 0 },
{ id: 'pending', name: '寰呬粯娆?, count: 0 },
{ id: 'shipping', name: '寰呭彂璐?, count: 0 },
{ id: 'delivering', name: '寰呮敹璐?, count: 0 },
{ id: 'completed', name: '宸插畬鎴?, count: 0 },
{ id: 'cancelled', name: '宸插彇娑?, count: 0 }
])
// Removed Mock Data
// 辅助函数:获取状态码
// 杈呭姪鍑芥暟锛氳幏鍙栫姸鎬佺爜
const getStatusByTab = (tabId: string): number => {
if (tabId == 'pending') return 1
if (tabId == 'shipping') return 2
@@ -227,11 +227,11 @@ const getStatusByTab = (tabId: string): number => {
return 0
}
// 格式化规格对象为友好的文本 - 必须在 parseSpecText 之前定义
// 鏍煎紡鍖栬鏍煎璞′负鍙嬪ソ鐨勬枃鏈?- 蹇呴』鍦?parseSpecText 涔嬪墠瀹氫箟
function formatSpecObj(obj: any): string {
if (obj == null) return ''
if (typeof obj !== 'object') {
// 非对象类型直接返回字符串形式
// 闈炲璞$被鍨嬬洿鎺ヨ繑鍥炲瓧绗︿覆褰㈠紡
if (typeof obj === 'string') return obj
if (typeof obj === 'number') return obj.toString()
return ''
@@ -244,14 +244,14 @@ function formatSpecObj(obj: any): string {
const specObj = objParsed as UTSJSONObject
// 使用 JSON.stringify 获取所有键
// 浣跨敤 JSON.stringify 鑾峰彇鎵€鏈夐敭
const specObjStr = JSON.stringify(specObj)
const specObjForKeys = JSON.parse(specObjStr) as UTSJSONObject
// 手动提取键值对
// 鎵嬪姩鎻愬彇閿€煎
const parts: string[] = []
// 尝试获取已知字段
// 灏濊瘯鑾峰彇宸茬煡瀛楁
const colorVal = specObjForKeys.getString('Color')
if (colorVal != null && colorVal != '') {
parts.push('Color: ' + colorVal)
@@ -262,14 +262,14 @@ function formatSpecObj(obj: any): string {
parts.push('Size: ' + sizeVal)
}
const defaultVal = specObjForKeys.getString('默认')
const defaultVal = specObjForKeys.getString('榛樿')
if (defaultVal != null && defaultVal != '') {
parts.push('默认: ' + defaultVal)
parts.push('榛樿: ' + defaultVal)
}
// 如果没有匹配到已知字段,尝试直接显示 JSON
// 濡傛灉娌℃湁鍖归厤鍒板凡鐭ュ瓧娈碉紝灏濊瘯鐩存帴鏄剧ず JSON
if (parts.length === 0) {
// 尝试遍历对象
// 灏濊瘯閬嶅巻瀵硅薄
const objAny = specObjForKeys as any
if (objAny != null) {
return specObjStr.replace(/[{}"]/g, '').replace(/:/g, ': ').replace(/,/g, ' | ')
@@ -282,11 +282,11 @@ function formatSpecObj(obj: any): string {
}
}
// 辅助函数:解析规格文本
// 杈呭姪鍑芥暟锛氳В鏋愯鏍兼枃鏈?
function parseSpecText(specs: any): string {
if (specs == null) return ''
if (typeof specs === 'string') {
// 如果是 JSON 字符串,尝试解析
// 濡傛灉鏄?JSON 瀛楃涓诧紝灏濊瘯瑙f瀽
if (specs.startsWith('{') || specs.startsWith('[')) {
try {
const parsed = JSON.parse(specs)
@@ -298,13 +298,13 @@ function parseSpecText(specs: any): string {
}
return specs
}
// 对于对象类型,格式化显示
// 瀵逛簬瀵硅薄绫诲瀷锛屾牸寮忓寲鏄剧ず
return formatSpecObj(specs)
}
// 辅助函数:更新标签计数
// 杈呭姪鍑芥暟锛氭洿鏂版爣绛捐鏁?
const updateTabsCounts = (allOrders: OrderItem[]) => {
// 计算各状态数量
// 璁$畻鍚勭姸鎬佹暟閲?
const countAll = allOrders.length
const countPending = allOrders.filter((o: OrderItem) => o.status === 1).length
const countShipping = allOrders.filter((o: OrderItem) => o.status === 2).length
@@ -312,7 +312,7 @@ const updateTabsCounts = (allOrders: OrderItem[]) => {
const countCompleted = allOrders.filter((o: OrderItem) => o.status === 4).length
const countCancelled = allOrders.filter((o: OrderItem) => o.status === 5).length
// 更新数组元素
// 鏇存柊鏁扮粍鍏冪礌
orderTabs.value[0].count = countAll
orderTabs.value[1].count = countPending
orderTabs.value[2].count = countShipping
@@ -321,7 +321,7 @@ const updateTabsCounts = (allOrders: OrderItem[]) => {
orderTabs.value[5].count = countCancelled
}
// 辅助函数:按标签筛选订单
// 杈呭姪鍑芥暟锛氭寜鏍囩绛涢€夎鍗?
const filterOrdersByTab = () => {
if (activeTab.value === 'all') {
orders.value = allOrdersList.value
@@ -333,20 +333,20 @@ const filterOrdersByTab = () => {
}
}
// 加载订单数据
// 鍔犺浇璁㈠崟鏁版嵁
const loadOrders = async () => {
loading.value = true
try {
// Fetch all orders from Supabase (status=0)
const fetchedOrders = await supabaseService.getOrders(0)
console.log('[loadOrders] 获取到订单数量:', fetchedOrders.length)
console.log('[loadOrders] 鑾峰彇鍒拌鍗曟暟閲?', fetchedOrders.length)
// Map to View Model
const mappedOrders: OrderItem[] = []
for (let i = 0; i < fetchedOrders.length; i++) {
const order = fetchedOrders[i]
// 使用 JSON 序列化转换
// 浣跨敤 JSON 搴忓垪鍖栬浆鎹?
const orderStr = JSON.stringify(order)
const orderParsed = JSON.parse(orderStr)
if (orderParsed == null) continue
@@ -355,13 +355,13 @@ const loadOrders = async () => {
const itemsRaw = orderObj.get('ml_order_items')
const productsList: OrderProduct[] = []
console.log('[loadOrders] 订单商品数据:', itemsRaw)
console.log('[loadOrders] 璁㈠崟鍟嗗搧鏁版嵁:', itemsRaw)
if (itemsRaw != null) {
// 先检查是否为数组
// 鍏堟鏌ユ槸鍚︿负鏁扮粍
if (Array.isArray(itemsRaw)) {
const items = itemsRaw as any[]
console.log('[loadOrders] 商品数量:', items.length)
console.log('[loadOrders] 鍟嗗搧鏁伴噺:', items.length)
for (let j = 0; j < items.length; j++) {
const item = items[j]
const itemStr = JSON.stringify(item)
@@ -378,11 +378,11 @@ const loadOrders = async () => {
const imageUrl = itemObj.getString('image_url')
const quantity = itemObj.getNumber('quantity')
console.log('[loadOrders] 商品:', productName, '图片:', imageUrl, '规格:', specText)
console.log('[loadOrders] 鍟嗗搧:', productName, '鍥剧墖:', imageUrl, '瑙勬牸:', specText)
const productItem: OrderProduct = {
id: productId ?? '',
name: productName ?? '未知商品',
name: productName ?? '鏈煡鍟嗗搧',
price: price ?? 0,
image: imageUrl ?? '/static/default-product.png',
spec: specText,
@@ -403,8 +403,8 @@ const loadOrders = async () => {
const paidAmount = orderObj.getNumber('paid_amount')
const merchantId = orderObj.getString('merchant_id')
// 从关联查询的 ml_shops 表获取店铺名称
let shopName = '自营店铺'
// 浠庡叧鑱旀煡璇㈢殑 ml_shops 琛ㄨ幏鍙栧簵閾哄悕绉?
let shopName = '鑷惀搴楅摵'
const shopsRaw = orderObj.get('ml_shops')
if (shopsRaw != null) {
const shopStr = JSON.stringify(shopsRaw)
@@ -417,16 +417,16 @@ const loadOrders = async () => {
}
}
} else if (merchantId != null && merchantId != '') {
shopName = '商家店铺'
shopName = '鍟嗗搴楅摵'
}
console.log('[loadOrders] 订单号:', orderNo, '店铺:', shopName, '商品数:', productsList.length)
console.log('[loadOrders] 璁㈠崟鍙?', orderNo, '搴楅摵:', shopName, '鍟嗗搧鏁?', productsList.length)
// 如果没有商品数据,添加一个占位商品
// 濡傛灉娌℃湁鍟嗗搧鏁版嵁锛屾坊鍔犱竴涓崰浣嶅晢鍝?
if (productsList.length === 0) {
const placeholderProduct: OrderProduct = {
id: 'placeholder',
name: '订单商品',
name: '璁㈠崟鍟嗗搧',
price: totalAmount ?? paidAmount ?? 0,
image: '/static/default-product.png',
spec: '',
@@ -450,7 +450,7 @@ const loadOrders = async () => {
mappedOrders.push(mappedOrder)
}
// Sort by created_at desc - 直接使用 OrderItem 类型访问属性
// Sort by created_at desc - 鐩存帴浣跨敤 OrderItem 绫诲瀷璁块棶灞炴€?
mappedOrders.sort((a: OrderItem, b: OrderItem) => {
const timeA = new Date(a.create_time).getTime()
const timeB = new Date(b.create_time).getTime()
@@ -466,14 +466,14 @@ const loadOrders = async () => {
filterOrdersByTab()
} catch (err) {
console.error('加载订单异常:', err)
uni.showToast({ title: '加载订单失败', icon: 'none' })
console.error('鍔犺浇璁㈠崟寮傚父:', err)
uni.showToast({ title: '鍔犺浇璁㈠崟澶辫触', icon: 'none' })
} finally {
loading.value = false
}
}
// 生命周期
// 鐢熷懡鍛ㄦ湡
onLoad((options) => {
if (options == null) return
const statusVal = options['status']
@@ -487,9 +487,9 @@ onLoad((options) => {
if (typeVal != null) {
const type = typeVal as string
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 === 'shipped') activeTab.value = 'delivering' // 鏄犲皠鍒板緟鏀惰揣
else if (type === 'review') activeTab.value = 'completed' // 鏄犲皠鍒板凡瀹屾垚
else if (type === 'refund') activeTab.value = 'all' // 鐢宠鍞悗榛樿鏄剧ず鍏ㄩ儴
}
})
@@ -503,12 +503,12 @@ const formatDate = (isoString: string): string => {
return `${date.getFullYear()}-${(date.getMonth()+1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')} ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`
}
// 辅助函数:获取当前订单数据(必须在 performSearch 之前定义)
// 杈呭姪鍑芥暟锛氳幏鍙栧綋鍓嶈鍗曟暟鎹紙蹇呴』鍦?performSearch 涔嬪墠瀹氫箟锛?
function getCurrentOrderData(): OrderItem[] {
return allOrdersList.value
}
// 搜索执行函数(必须在 onSearchInput 等之前定义)
// 鎼滅储鎵ц鍑芥暟锛堝繀椤诲湪 onSearchInput 绛変箣鍓嶅畾涔夛級
const performSearch = () => {
const keyword = searchKeyword.value.trim().toLowerCase()
if (keyword == '') {
@@ -516,17 +516,17 @@ const performSearch = () => {
return
}
// 在当前订单数据中搜索
// 鍦ㄥ綋鍓嶈鍗曟暟鎹腑鎼滅储
const allOrders = getCurrentOrderData()
const filtered = allOrders.filter((order: any) => {
const orderObj = order as Record<string, any>
// 搜索订单号
// 鎼滅储璁㈠崟鍙?
const orderNo = orderObj['order_no'] as string
if (orderNo != null && orderNo.toLowerCase().includes(keyword)) {
return true
}
// 搜索商品名称
// 鎼滅储鍟嗗搧鍚嶇О
const products = orderObj['products']
if (products != null && Array.isArray(products)) {
return products.some((product: any) => {
@@ -542,7 +542,7 @@ const performSearch = () => {
orders.value = filtered
}
// 搜索相关函数
// 鎼滅储鐩稿叧鍑芥暟
const onSearchInput = (e: any) => {
const eObj = e as Record<string, any>
const detail = eObj['detail'] as Record<string, any>
@@ -568,23 +568,23 @@ const formatSpec = (specs: any): string => {
return ''
}
// 切换标签
// 鍒囨崲鏍囩
const switchTab = (tabId: string) => {
activeTab.value = tabId
filterOrdersByTab()
}
// 获取状态文本
// 鑾峰彇鐘舵€佹枃鏈?
const getStatusText = (status: number): string => {
if (status == 1) return '待付款'
if (status == 2) return '待发货'
if (status == 3) return '待收货'
if (status == 4) return '已完成'
if (status == 5) return '已取消'
return '未知状态'
if (status == 1) return '寰呬粯娆?
if (status == 2) return '寰呭彂璐?
if (status == 3) return '寰呮敹璐?
if (status == 4) return '宸插畬鎴?
if (status == 5) return '宸插彇娑?
return '鏈煡鐘舵€?
}
// 获取状态类名
// 鑾峰彇鐘舵€佺被鍚?
const getStatusClass = (status: number): string => {
if (status == 1) return 'status-pending'
if (status == 2) return 'status-shipping'
@@ -594,41 +594,41 @@ const getStatusClass = (status: number): string => {
return 'status-unknown'
}
// 下拉刷新
// 涓嬫媺鍒锋柊
const onRefresh = () => {
refreshing.value = true
setTimeout(() => {
loadOrders()
refreshing.value = false
uni.showToast({
title: '刷新成功',
title: '鍒锋柊鎴愬姛',
icon: 'success'
})
}, 1000)
}
// 上拉加载更多
// 涓婃媺鍔犺浇鏇村
const loadMore = () => {
if (loadingMore.value || !hasMore.value) return
// 暂未实现分页,直接返回
// 鏆傛湭瀹炵幇鍒嗛〉锛岀洿鎺ヨ繑鍥?
hasMore.value = false
}
// 订单操作函数
// 璁㈠崟鎿嶄綔鍑芥暟
const cancelOrder = (orderId: string) => {
uni.showModal({
title: '确认取消',
content: '确定要取消此订单吗?',
title: '纭鍙栨秷',
content: '纭畾瑕佸彇娑堟璁㈠崟鍚楋紵',
success: (res) => {
if (res.confirm) {
// 这里应该是实际的API调用
// 杩欓噷搴旇鏄疄闄呯殑API璋冪敤
uni.showToast({
title: '订单已取消',
title: '璁㈠崟宸插彇娑?,
icon: 'success'
})
// 更新订单状态
// 鏇存柊璁㈠崟鐘舵€?
const index = orders.value.findIndex((o: any) => {
const obj = o as Record<string, any>
return obj['id'] === orderId
@@ -651,7 +651,7 @@ const payOrder = (orderId: string) => {
const remindShipping = (orderId: string) => {
uni.showToast({
title: '已提醒卖家发货',
title: '宸叉彁閱掑崠瀹跺彂璐?,
icon: 'success'
})
}
@@ -662,7 +662,7 @@ const viewLogistics = (orderId: string) => {
})
}
// goReview 必须在 doConfirmReceipt 之前定义,因为 doConfirmReceipt 会调用它
// goReview 蹇呴』鍦?doConfirmReceipt 涔嬪墠瀹氫箟锛屽洜涓?doConfirmReceipt 浼氳皟鐢ㄥ畠
const goReview = (order: any) => {
const orderObj = order as Record<string, any>
const products = orderObj['products'] as any[]
@@ -678,18 +678,18 @@ const goReview = (order: any) => {
}
const doConfirmReceipt = async (orderId: string) => {
uni.showLoading({ title: '处理中...' })
uni.showLoading({ title: '澶勭悊涓?..' })
try {
const result = await supabaseService.confirmReceipt(orderId)
uni.hideLoading()
if (result.success) {
uni.showToast({
title: '收货成功',
title: '鏀惰揣鎴愬姛',
icon: 'success'
})
// 更新本地状态
// 鏇存柊鏈湴鐘舵€?
const index = orders.value.findIndex((o: any) => {
const obj = o as Record<string, any>
return obj['id'] === orderId
@@ -700,7 +700,7 @@ const doConfirmReceipt = async (orderId: string) => {
orders.value = [...orders.value]
}
// 跳转到评价页面
// 璺宠浆鍒拌瘎浠烽〉闈?
setTimeout(() => {
const order = orders.value.find((o: any) => {
const obj = o as Record<string, any>
@@ -712,14 +712,14 @@ const doConfirmReceipt = async (orderId: string) => {
}, 1000)
} else {
uni.showToast({
title: result.error ?? '确认收货失败',
title: result.error ?? '纭鏀惰揣澶辫触',
icon: 'none'
})
}
} catch (e) {
uni.hideLoading()
uni.showToast({
title: '系统异常',
title: '绯荤粺寮傚父',
icon: 'none'
})
}
@@ -727,8 +727,8 @@ const doConfirmReceipt = async (orderId: string) => {
const confirmReceipt = (orderId: string) => {
uni.showModal({
title: '确认收货',
content: '请确认您已收到商品,且商品无误',
title: '纭鏀惰揣',
content: '璇风‘璁ゆ偍宸叉敹鍒板晢鍝侊紝涓斿晢鍝佹棤璇?,
success: (res) => {
if (res.confirm) {
doConfirmReceipt(orderId)
@@ -739,13 +739,13 @@ const confirmReceipt = (orderId: string) => {
const repurchase = (order: any) => {
uni.showModal({
title: '再次购买',
content: '确定要将这些商品加入购物车吗?',
title: '鍐嶆璐拱',
content: '纭畾瑕佸皢杩欎簺鍟嗗搧鍔犲叆璐墿杞﹀悧锛?,
success: (res) => {
if (res.confirm) {
// 这里应该是实际的API调用
// 杩欓噷搴旇鏄疄闄呯殑API璋冪敤
uni.showToast({
title: '已加入购物车',
title: '宸插姞鍏ヨ喘鐗╄溅',
icon: 'success'
})
}
@@ -767,7 +767,7 @@ const onApplyRefund = (order: any) => {
})
}
// 导航函数
// 瀵艰埅鍑芥暟
const navigateToSearch = () => {
uni.navigateTo({ url: '/pages/mall/consumer/search' })
}
@@ -794,7 +794,7 @@ const goShopping = () => {
overflow: hidden;
}
/* 头部 */
/* 澶撮儴 */
.orders-header {
background-color: white;
padding: 15px;
@@ -856,7 +856,7 @@ const goShopping = () => {
/* cursor: pointer; removed */
}
/* 标签页 */
/* 鏍囩椤?*/
.order-tabs {
background-color: #ffffff;
border-bottom: 1px solid #e5e5e5;
@@ -879,15 +879,15 @@ const goShopping = () => {
}
.tab-item {
/* 移除 flex: 1,改为自适应宽度或固定最小宽度 */
padding: 15px 15px; /* 增加水平内边距 */
/* 绉婚櫎 flex: 1锛屾敼涓鸿嚜閫傚簲瀹藉害鎴栧浐瀹氭渶灏忓搴?*/
padding: 15px 15px; /* 澧炲姞姘村钩鍐呰竟璺?*/
text-align: center;
position: relative;
display: flex;
justify-content: center;
align-items: center;
white-space: nowrap; /* 防止文字换行 */
flex-shrink: 0; /* 防止被压缩 */
white-space: nowrap; /* 闃叉鏂囧瓧鎹㈣ */
flex-shrink: 0; /* 闃叉琚帇缂?*/
}
.tab-item.active {
@@ -930,14 +930,14 @@ const goShopping = () => {
text-align: center;
}
/* 内容区 */
/* 鍐呭鍖?*/
.orders-content {
flex: 1;
height: 0;
width: 100%;
}
/* 空状态 */
/* 绌虹姸鎬?*/
.empty-orders {
display: flex;
flex-direction: column;
@@ -973,7 +973,7 @@ const goShopping = () => {
font-size: 16px;
}
/* 订单列表 */
/* 璁㈠崟鍒楄〃 */
.order-list {
padding: 10px;
}
@@ -986,7 +986,7 @@ const goShopping = () => {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}
/* 订单头部 */
/* 璁㈠崟澶撮儴 */
.order-header {
display: flex;
justify-content: space-between;
@@ -1025,14 +1025,14 @@ const goShopping = () => {
color: #999;
}
/* 订单商品 */
/* 璁㈠崟鍟嗗搧 */
.order-products {
padding: 15px;
}
.order-product {
display: flex;
flex-direction: row; /* 显式声明横向排列 */
flex-direction: row; /* 鏄惧紡澹版槑妯悜鎺掑垪 */
margin-bottom: 15px;
width: 100%;
}
@@ -1046,16 +1046,16 @@ const goShopping = () => {
height: 80px;
border-radius: 8px;
margin-right: 12px;
flex-shrink: 0; /* 防止图片被压缩 */
flex-shrink: 0; /* 闃叉鍥剧墖琚帇缂?*/
}
.product-info {
flex: 1; /* 占据右侧剩余所有空间 */
flex: 1; /* 鍗犳嵁鍙充晶鍓╀綑鎵€鏈夌┖闂?*/
display: flex;
flex-direction: column;
justify-content: space-between;
height: 80px;
overflow: hidden; /* 防止文字溢出 */
overflow: hidden; /* 闃叉鏂囧瓧婧㈠嚭 */
}
.product-top-info {
@@ -1098,7 +1098,7 @@ const goShopping = () => {
color: #999;
}
/* 订单信息 */
/* 璁㈠崟淇℃伅 */
.order-info {
padding: 15px;
border-top: 1px solid #f5f5f5;
@@ -1138,7 +1138,7 @@ const goShopping = () => {
font-weight: bold;
}
/* 订单操作 */
/* 璁㈠崟鎿嶄綔 */
.order-actions {
padding: 15px;
}
@@ -1193,7 +1193,7 @@ const goShopping = () => {
border-color: #ff5000;
}
/* 加载更多 */
/* 鍔犺浇鏇村 */
.loading-more {
padding: 20px;
display: flex;
@@ -1218,18 +1218,18 @@ const goShopping = () => {
padding: 20px 0;
}
/* 安全区域 */
/* 瀹夊叏鍖哄煙 */
.safe-area {
height: 20px;
}
/* 底部导航占位 */
/* 搴曢儴瀵艰埅鍗犱綅 */
.tabbar-placeholder {
height: 50px;
background-color: #f5f5f5;
}
/* 响应式适配 */
/* 鍝嶅簲寮忛€傞厤 */
@media screen and (min-width: 768px) {
.order-list {
display: flex;
@@ -1254,7 +1254,7 @@ const goShopping = () => {
}
}
/* 订单卡片新样式 */
/* 璁㈠崟鍗$墖鏂版牱寮?*/
.order-card-header {
padding: 12px 15px;
display: flex;
@@ -1356,3 +1356,5 @@ const goShopping = () => {
}
}
</style>