consumer模块完成度95%,准备部署消费者端测试
This commit is contained in:
@@ -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>
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user