继续完善购物逻辑闭环,consumer模块完成度80%

This commit is contained in:
2026-01-27 17:33:39 +08:00
parent f2f208f258
commit 4ab722a118
22 changed files with 5290 additions and 515 deletions

View File

@@ -1,13 +1,21 @@
<!-- pages/mall/consumer/orders.uvue -->
<template>
<view class="orders-page">
<!-- 顶部标题栏 -->
<view class="orders-header">
<text class="header-title">我的订单</text>
<view class="header-actions">
<text class="search-icon" @click="navigateToSearch">🔍</text>
</view>
<!-- 顶部标题栏 -->
<view class="orders-header">
<view class="header-search full-width">
<input
class="search-input"
type="text"
placeholder="搜索订单号或商品名称"
:value="searchKeyword"
@input="onSearchInput"
@confirm="onSearchConfirm"
/>
<text v-if="searchKeyword" class="search-clear" @click="clearSearch">×</text>
<text v-else class="search-icon">🔍</text>
</view>
</view>
<!-- 订单状态筛选 -->
<view class="order-tabs">
@@ -158,6 +166,7 @@ const hasMore = ref<boolean>(true)
const refreshing = ref<boolean>(false)
const page = ref<number>(1)
const activeTab = ref<string>('all')
const searchKeyword = ref<string>('')
// 订单标签页
const orderTabs = reactive([
@@ -350,45 +359,66 @@ const loadOrders = async () => {
}
try {
// Mock Data Loading
await new Promise(resolve => setTimeout(resolve, 500)) // Simulate network delay
// Use filtered mock orders based on user ID logic if needed, but for now just return all mock orders
// In a real app we'd filter by userId
/* const { data, error } = await supa
.from('orders')
.select('*, order_items(*)')
.eq('user_id', userId)
.order('created_at', { ascending: false })
if (error != null) {
console.error('加载订单失败:', error)
return
// 从本地存储获取订单
const ordersStr = uni.getStorageSync('orders')
let localOrders: any[] = []
if (ordersStr) {
localOrders = JSON.parse(ordersStr as string) as any[]
}
if (data != null) {
orders.value = data.map((order: any) => ({
id: order.id,
order_no: order.order_no,
status: order.status,
create_time: formatDate(order.created_at),
product_amount: order.total_amount,
shipping_fee: order.delivery_fee,
total_amount: order.actual_amount,
products: (order.order_items as any[]).map((item: any) => ({
id: item.product_id,
name: item.product_name,
price: item.price,
image: '/static/products/1.jpg', // 默认图片
spec: formatSpec(item.sku_specifications),
quantity: item.quantity
}))
}))
} */
// 过滤当前用户的订单
// const userOrders = localOrders.filter((o: any) => o.user_id === userId)
// 暂时显示所有订单用于测试
let userOrders = localOrders
// Using Mock Data
orders.value = mockOrders
// 根据标签页过滤
let filtered = userOrders
const statusMap: Record<string, number> = {
'pending': 1,
'shipping': 2,
'delivering': 3,
'completed': 4,
'cancelled': 5
}
if (activeTab.value !== 'all') {
const targetStatus = statusMap[activeTab.value]
filtered = userOrders.filter((o: any) => o.status === targetStatus)
}
// 按时间倒序
filtered.sort((a: any, b: any) => {
const timeA = new Date(a.created_at || a.create_time).getTime()
const timeB = new Date(b.created_at || b.create_time).getTime()
return timeB - timeA
})
// 处理数据格式以适配当前页面
orders.value = filtered.map((order: any) => ({
id: order.id,
order_no: order.order_no,
status: order.status,
create_time: order.created_at || order.create_time,
product_amount: order.total_amount,
shipping_fee: order.delivery_fee,
total_amount: order.actual_amount,
products: (order.items || order.products || []).map((item: any) => ({
id: item.product_id || item.id,
name: item.product_name || item.name,
price: item.price,
image: item.product_image || item.image || '/static/default-product.png',
spec: item.sku_specifications ? formatSpec(item.sku_specifications) : (item.spec || ''),
quantity: item.quantity
}))
}))
// 更新统计数据
orderTabs[0].count = userOrders.length
orderTabs[1].count = userOrders.filter((o: any) => o.status === 1).length
orderTabs[2].count = userOrders.filter((o: any) => o.status === 2).length
orderTabs[3].count = userOrders.filter((o: any) => o.status === 3).length
orderTabs[4].count = userOrders.filter((o: any) => o.status === 4).length
orderTabs[5].count = userOrders.filter((o: any) => o.status === 5).length
} catch (err) {
console.error('加载订单异常:', err)
@@ -403,6 +433,55 @@ 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')}`
}
// 搜索相关函数
const onSearchInput = (e: any) => {
searchKeyword.value = e.detail.value
performSearch()
}
const onSearchConfirm = () => {
performSearch()
}
const clearSearch = () => {
searchKeyword.value = ''
performSearch()
}
const performSearch = () => {
const keyword = searchKeyword.value.trim().toLowerCase()
if (!keyword) {
loadOrders()
return
}
// 在当前订单数据中搜索
const allOrders = getCurrentOrderData() // 这里需要获取完整的订单数据
const filtered = allOrders.filter((order: any) => {
// 搜索订单号
if (order.order_no && order.order_no.toLowerCase().includes(keyword)) {
return true
}
// 搜索商品名称
if (order.products && Array.isArray(order.products)) {
return order.products.some((product: any) => {
return product.name && product.name.toLowerCase().includes(keyword)
})
}
return false
})
orders.value = filtered
}
const getCurrentOrderData = () => {
// 这里应该从本地存储或API获取完整订单数据
// 暂时返回当前orders.value
return orders.value
}
const formatSpec = (specs: any): string => {
if (!specs) return ''
if (typeof specs === 'object') {
@@ -586,54 +665,95 @@ const goShopping = () => {
padding: 15px;
display: flex;
align-items: center;
justify-content: space-between;
justify-content: center;
border-bottom: 1px solid #eee;
position: sticky;
top: 0;
z-index: 10;
}
.header-title {
font-size: 18px;
font-weight: bold;
color: #333;
.header-search.full-width {
display: flex;
align-items: center;
position: relative;
width: 100%;
}
.header-actions .search-icon {
.search-input {
flex: 1;
height: 36px;
border: 1px solid #ddd;
border-radius: 18px;
padding: 0 40px 0 16px;
font-size: 14px;
background-color: #f5f5f5;
color: #333;
width: 100%;
}
.search-input::placeholder {
color: #999;
font-size: 12px;
}
.search-input:focus {
outline: none;
border-color: #ff5000;
background-color: white;
}
.search-icon {
position: absolute;
right: 12px;
font-size: 18px;
color: #999;
}
.search-clear {
position: absolute;
right: 12px;
font-size: 20px;
color: #666;
color: #999;
width: 20px;
height: 20px;
line-height: 18px;
text-align: center;
border-radius: 50%;
background-color: #ddd;
cursor: pointer;
}
/* 标签页 */
.order-tabs {
background-color: white;
border-bottom: 1px solid #eee;
background-color: #ffffff;
border-bottom: 1px solid #e5e5e5;
position: sticky;
top: 50px;
z-index: 10;
}
.tab-scroll {
white-space: nowrap;
width: 100%;
height: 50px;
white-space: nowrap;
}
.tab-container {
display: flex;
flex-direction: row;
padding: 0 15px;
height: 100%;
padding: 0 10px;
min-width: 100%;
}
.tab-item {
flex-shrink: 0;
padding: 0 15px;
display: flex;
align-items: center;
/* 移除 flex: 1改为自适应宽度或固定最小宽度 */
padding: 15px 15px; /* 增加水平内边距 */
text-align: center;
position: relative;
height: 100%;
margin-right: 10px;
display: flex;
justify-content: center;
align-items: center;
white-space: nowrap; /* 防止文字换行 */
flex-shrink: 0; /* 防止被压缩 */
}
.tab-item.active {
@@ -971,4 +1091,4 @@ const goShopping = () => {
margin-bottom: 15px;
}
}
</style>
</style>