consumer模块完成度95%,准备部署消费者端测试
This commit is contained in:
@@ -1,28 +1,28 @@
|
||||
<!-- 消费者端 - 个人中心 -->
|
||||
<!-- 消费者端 - 个人中心 -->
|
||||
<template>
|
||||
<view class="consumer-profile">
|
||||
<!-- 智能顶部导航栏 - 与消息页保持一致 -->
|
||||
<view class="smart-navbar" :style="{ paddingTop: statusBarHeight + 'px' }">
|
||||
<view class="nav-container">
|
||||
<!-- 头像 -->
|
||||
<image
|
||||
:src="userInfo.avatar_url != '' ? userInfo.avatar_url : '/static/default-avatar.png'"
|
||||
class="nav-avatar"
|
||||
@click="editProfile"
|
||||
/>
|
||||
|
||||
<!-- 用户信息横向排列 (名字、积分、余额、优惠券) -->
|
||||
<view class="nav-user-stats">
|
||||
<!-- 基础用户信息:头像和昵称 -->
|
||||
<view class="nav-user-basic" @click="editProfile">
|
||||
<image
|
||||
:src="userInfo.avatar_url != '' ? userInfo.avatar_url : '/static/default-avatar.png'"
|
||||
class="nav-avatar"
|
||||
/>
|
||||
<text class="nav-user-name">{{ userInfo.nickname != '' ? userInfo.nickname : userInfo.phone }}</text>
|
||||
|
||||
</view>
|
||||
|
||||
<!-- 用户资产横向排列 (积分、余额、优惠券) -->
|
||||
<view class="nav-user-stats">
|
||||
<view class="nav-stat-item" @click="goToPoints">
|
||||
<text class="nav-stat-label">积分</text>
|
||||
<text class="nav-stat-value">{{ userStats.points }}</text>
|
||||
</view>
|
||||
|
||||
<view class="nav-stat-item">
|
||||
<view class="nav-stat-item" @click="goToWallet">
|
||||
<text class="nav-stat-label">余额</text>
|
||||
<text class="nav-stat-value" @click="goToWallet">¥{{ userStats.balance }}</text>
|
||||
<text class="nav-stat-value">¥{{ userStats.balance }}</text>
|
||||
</view>
|
||||
|
||||
<view class="nav-stat-item" @click="goToCoupons">
|
||||
@@ -31,7 +31,7 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 设置按钮 (右侧) -->
|
||||
<!-- 设置按钮 (最右侧) -->
|
||||
<view class="nav-actions">
|
||||
<view class="action-btn" @click="goToSettings">
|
||||
<text class="action-icon">⚙️</text>
|
||||
@@ -88,7 +88,10 @@
|
||||
|
||||
<!-- 订单状态快捷入口 -->
|
||||
<view class="order-shortcuts">
|
||||
<view class="section-title">我的订单</view>
|
||||
<view class="section-header-row">
|
||||
<text class="section-title">我的订单</text>
|
||||
<text class="view-all" @click="goToOrders(currentOrderTab)">查看更多 ></text>
|
||||
</view>
|
||||
<view class="order-tabs">
|
||||
<view class="order-tab" :class="{ active: currentOrderTab === 'all' }" @click="switchOrderTab('all')">
|
||||
<text class="tab-icon">📋</text>
|
||||
@@ -117,7 +120,6 @@
|
||||
<view class="recent-orders">
|
||||
<view class="section-header">
|
||||
<text class="section-title">{{ getOrderSectionTitle() }}</text>
|
||||
<text class="view-all" @click="goToOrders(currentOrderTab)">查看更多 ></text>
|
||||
</view>
|
||||
|
||||
<view v-if="filteredOrders.length === 0" class="empty-orders">
|
||||
@@ -126,22 +128,36 @@
|
||||
</view>
|
||||
|
||||
<view v-for="order in filteredOrders" :key="order.id" class="order-item" @click="viewOrderDetail(order)">
|
||||
<view class="order-header">
|
||||
<text class="order-no">订单号: {{ order.order_no }}</text>
|
||||
<text class="order-status" :class="getOrderStatusClass(order.status)">{{ getOrderStatusText(order.status) }}</text>
|
||||
</view>
|
||||
<view class="order-content">
|
||||
<image :src="getOrderMainImage(order)" class="order-image" mode="aspectFill" />
|
||||
<view class="order-info">
|
||||
<text class="order-title">{{ getOrderTitle(order) }}</text>
|
||||
<text class="order-amount">¥{{ order.actual_amount }}</text>
|
||||
<text class="order-time">{{ formatTime(order.created_at) }}</text>
|
||||
<view class="order-item-header">
|
||||
<view class="order-shop">
|
||||
<text class="shop-icon">🏪</text>
|
||||
<text class="shop-name">{{ getOrderShopName(order) }}</text>
|
||||
<text class="shop-arrow">›</text>
|
||||
</view>
|
||||
<view class="status-row">
|
||||
<text class="order-status-text" :class="getOrderStatusClass(order.status)">{{ getOrderStatusText(order.status) }}</text>
|
||||
<text class="more-btn" @click.stop="showOrderMenu(order)">⋯</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="order-actions">
|
||||
<button v-if="order.status === 1" class="action-btn pay" @click.stop="payOrder(order)">立即支付</button>
|
||||
<button v-if="order.status === 3" class="action-btn confirm" @click.stop="confirmReceive(order)">确认收货</button>
|
||||
<button v-if="order.status === 4" class="action-btn review" @click.stop="reviewOrder(order)">评价</button>
|
||||
<view class="order-item-content">
|
||||
<image :src="getOrderMainImage(order)" class="order-item-image" mode="aspectFill" />
|
||||
<view class="order-item-info">
|
||||
<view class="order-title-row">
|
||||
<text class="order-item-title">{{ getOrderTitle(order) }}</text>
|
||||
<text class="order-item-price">¥{{ order.actual_amount }}</text>
|
||||
</view>
|
||||
<view class="order-spec-row">
|
||||
<text class="order-item-spec">{{ getOrderSpec(order) }}</text>
|
||||
<text class="order-item-num">x{{ getOrderItemCount(order) }}</text>
|
||||
</view>
|
||||
<text class="order-item-time">{{ formatDateTime(order.created_at) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="order-item-actions">
|
||||
<button v-if="order.status === 1" class="order-action-btn pay" @click.stop="payOrder(order)">立即支付</button>
|
||||
<button v-if="order.status === 3" class="order-action-btn confirm" @click.stop="confirmReceive(order)">确认收货</button>
|
||||
<button v-if="order.status === 4" class="order-action-btn review" @click.stop="reviewOrder(order)">评价</button>
|
||||
<button v-if="order.status === 2 || order.status === 3" class="order-action-btn secondary" @click.stop="viewOrderDetail(order)">查看物流</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -290,6 +306,8 @@ type OrderItemType = {
|
||||
actual_amount: number
|
||||
created_at: string
|
||||
ml_order_items: any | null
|
||||
ml_shops: any | null
|
||||
items_count: number
|
||||
}
|
||||
|
||||
export default {
|
||||
@@ -407,13 +425,22 @@ export default {
|
||||
actualAmount = totalAmount != null ? totalAmount : 0
|
||||
}
|
||||
|
||||
const mlOrderItems = o.get('ml_order_items')
|
||||
|
||||
let itemsCount = 0
|
||||
if (mlOrderItems != null && Array.isArray(mlOrderItems)) {
|
||||
itemsCount = (mlOrderItems as any[]).length
|
||||
}
|
||||
|
||||
const orderItem: OrderItemType = {
|
||||
id: o.getString('id') ?? '',
|
||||
order_no: o.getString('order_no') ?? '',
|
||||
status: status,
|
||||
actual_amount: actualAmount,
|
||||
created_at: o.getString('created_at') ?? '',
|
||||
ml_order_items: o.get('ml_order_items')
|
||||
ml_order_items: mlOrderItems,
|
||||
ml_shops: o.get('ml_shops'),
|
||||
items_count: itemsCount
|
||||
}
|
||||
|
||||
mappedOrders.push(orderItem)
|
||||
@@ -629,6 +656,8 @@ export default {
|
||||
},
|
||||
|
||||
getOrderStatusText(status: number): string {
|
||||
if (status === 6) return '退款中'
|
||||
if (status === 7) return '已退款'
|
||||
const statusTexts = ['异常', '待支付', '待发货', '待收货', '已完成', '已取消']
|
||||
if (status >= 0 && status < statusTexts.length) {
|
||||
return statusTexts[status]
|
||||
@@ -637,6 +666,8 @@ export default {
|
||||
},
|
||||
|
||||
getOrderStatusClass(status: number): string {
|
||||
if (status === 6) return 'refunding'
|
||||
if (status === 7) return 'refunded'
|
||||
const statusClasses = ['error', 'pending', 'processing', 'shipping', 'completed', 'cancelled']
|
||||
if (status >= 0 && status < statusClasses.length) {
|
||||
return statusClasses[status]
|
||||
@@ -644,6 +675,242 @@ export default {
|
||||
return 'error'
|
||||
},
|
||||
|
||||
showOrderMenu(order: OrderItemType) {
|
||||
const status = order.status
|
||||
let actions: string[] = []
|
||||
|
||||
if (status === 1) {
|
||||
actions = ['取消订单', '联系卖家']
|
||||
} else if (status === 2) {
|
||||
actions = ['提醒发货', '申请退款', '联系卖家']
|
||||
} else if (status === 3) {
|
||||
actions = ['查看物流', '确认收货', '申请退款', '联系卖家']
|
||||
} else if (status === 4) {
|
||||
actions = ['申请售后', '再次购买', '联系卖家']
|
||||
} else if (status === 5) {
|
||||
actions = ['删除订单', '再次购买', '联系卖家']
|
||||
} else if (status === 6) {
|
||||
actions = ['退款进度', '联系卖家']
|
||||
} else if (status === 7) {
|
||||
actions = ['再次购买', '联系卖家']
|
||||
}
|
||||
|
||||
uni.showActionSheet({
|
||||
itemList: actions,
|
||||
success: (res) => {
|
||||
const action = actions[res.tapIndex]
|
||||
this.handleOrderAction(order, action)
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
handleOrderAction(order: OrderItemType, action: string) {
|
||||
if (action === '取消订单') {
|
||||
this.cancelOrderAction(order)
|
||||
} else if (action === '联系卖家') {
|
||||
this.contactSeller(order)
|
||||
} else if (action === '提醒发货') {
|
||||
this.remindShipping(order)
|
||||
} else if (action === '申请退款' || action === '申请售后') {
|
||||
this.applyRefund(order)
|
||||
} else if (action === '查看物流') {
|
||||
this.viewLogistics(order.id)
|
||||
} else if (action === '确认收货') {
|
||||
this.confirmReceive(order)
|
||||
} else if (action === '再次购买') {
|
||||
this.repurchase(order)
|
||||
} else if (action === '删除订单') {
|
||||
this.deleteOrder(order.id)
|
||||
} else if (action === '退款进度') {
|
||||
this.viewRefundProgress(order.id)
|
||||
}
|
||||
},
|
||||
|
||||
cancelOrderAction(order: OrderItemType) {
|
||||
uni.showModal({
|
||||
title: '确认取消',
|
||||
content: '确定要取消此订单吗?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
uni.showLoading({ title: '取消中...' })
|
||||
supabaseService.cancelOrder(order.id).then(() => {
|
||||
uni.hideLoading()
|
||||
uni.showToast({ title: '订单已取消', icon: 'success' })
|
||||
this.loadOrders()
|
||||
}).catch(() => {
|
||||
uni.hideLoading()
|
||||
uni.showToast({ title: '取消失败', icon: 'none' })
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
contactSeller(order: OrderItemType) {
|
||||
const merchantId = order.ml_shops != null ? this.getMerchantIdFromOrder(order) : ''
|
||||
if (merchantId !== '') {
|
||||
uni.navigateTo({
|
||||
url: `/pages/mall/consumer/chat?merchantId=${merchantId}`
|
||||
})
|
||||
} else {
|
||||
uni.showToast({ title: '暂无卖家联系方式', icon: 'none' })
|
||||
}
|
||||
},
|
||||
|
||||
getMerchantIdFromOrder(order: OrderItemType): string {
|
||||
const shopsRaw = order.ml_shops
|
||||
if (shopsRaw != null) {
|
||||
const shopStr = JSON.stringify(shopsRaw)
|
||||
const shopParsed = JSON.parse(shopStr)
|
||||
if (shopParsed != null) {
|
||||
const shopObj = shopParsed as UTSJSONObject
|
||||
return shopObj.getString('merchant_id') ?? ''
|
||||
}
|
||||
}
|
||||
return ''
|
||||
},
|
||||
|
||||
remindShipping(order: OrderItemType) {
|
||||
uni.showLoading({ title: '提醒中...' })
|
||||
const merchantId = order.ml_shops != null ? this.getMerchantIdFromOrder(order) : ''
|
||||
if (merchantId !== '') {
|
||||
const message = `你好,我的订单[${order.order_no}]还没有发货,请尽快安排,谢谢。`
|
||||
supabaseService.sendChatMessage(message, merchantId).then(() => {
|
||||
uni.hideLoading()
|
||||
uni.showToast({ title: '已提醒卖家发货', icon: 'success' })
|
||||
}).catch(() => {
|
||||
uni.hideLoading()
|
||||
uni.showToast({ title: '提醒失败', icon: 'none' })
|
||||
})
|
||||
} else {
|
||||
uni.hideLoading()
|
||||
uni.showToast({ title: '无法联系卖家', icon: 'none' })
|
||||
}
|
||||
},
|
||||
|
||||
applyRefund(order: OrderItemType) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/mall/consumer/apply-refund?orderId=${order.id}`
|
||||
})
|
||||
},
|
||||
|
||||
viewLogistics(orderId: string) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/mall/consumer/logistics?orderId=${orderId}`
|
||||
})
|
||||
},
|
||||
|
||||
repurchase(order: OrderItemType) {
|
||||
uni.showLoading({ title: '处理中...' })
|
||||
const itemsRaw = order.ml_order_items
|
||||
if (itemsRaw == null || (itemsRaw as any[]).length === 0) {
|
||||
uni.hideLoading()
|
||||
uni.showToast({ title: '订单无商品', icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
const items = itemsRaw as any[]
|
||||
let completed = 0
|
||||
const total = items.length
|
||||
let successCount = 0
|
||||
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
const itemStr = JSON.stringify(items[i])
|
||||
const itemParsed = JSON.parse(itemStr)
|
||||
if (itemParsed == null) {
|
||||
completed++
|
||||
if (completed === total) {
|
||||
uni.hideLoading()
|
||||
if (successCount > 0) {
|
||||
uni.showToast({ title: `已添加${successCount}件商品`, icon: 'success' })
|
||||
} else {
|
||||
uni.showToast({ title: '添加失败', icon: 'none' })
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
const itemObj = itemParsed as UTSJSONObject
|
||||
const productId = itemObj.getString('product_id') ?? ''
|
||||
const merchantId = order.ml_shops != null ? this.getMerchantIdFromOrder(order) : ''
|
||||
|
||||
if (productId !== '') {
|
||||
supabaseService.addToCart(productId, 1, '', merchantId).then((success) => {
|
||||
completed++
|
||||
if (success) successCount++
|
||||
if (completed === total) {
|
||||
uni.hideLoading()
|
||||
if (successCount > 0) {
|
||||
uni.showToast({ title: `已添加${successCount}件商品`, icon: 'success' })
|
||||
} else {
|
||||
uni.showToast({ title: '添加失败', icon: 'none' })
|
||||
}
|
||||
}
|
||||
}).catch(() => {
|
||||
completed++
|
||||
if (completed === total) {
|
||||
uni.hideLoading()
|
||||
if (successCount > 0) {
|
||||
uni.showToast({ title: `已添加${successCount}件商品`, icon: 'success' })
|
||||
} else {
|
||||
uni.showToast({ title: '添加失败', icon: 'none' })
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
completed++
|
||||
if (completed === total) {
|
||||
uni.hideLoading()
|
||||
if (successCount > 0) {
|
||||
uni.showToast({ title: `已添加${successCount}件商品`, icon: 'success' })
|
||||
} else {
|
||||
uni.showToast({ title: '添加失败', icon: 'none' })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
deleteOrder(orderId: string) {
|
||||
uni.showModal({
|
||||
title: '删除订单',
|
||||
content: '确定要删除此订单吗?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
uni.showLoading({ title: '删除中...' })
|
||||
supabaseService.deleteOrder(orderId).then(() => {
|
||||
uni.hideLoading()
|
||||
uni.showToast({ title: '订单已删除', icon: 'success' })
|
||||
this.loadOrders()
|
||||
}).catch(() => {
|
||||
uni.hideLoading()
|
||||
uni.showToast({ title: '删除失败', icon: 'none' })
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
viewRefundProgress(orderId: string) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/mall/consumer/refund?orderId=${orderId}`
|
||||
})
|
||||
},
|
||||
|
||||
getOrderShopName(order: OrderItemType): string {
|
||||
const shopsRaw = order.ml_shops
|
||||
if (shopsRaw != null) {
|
||||
const shopStr = JSON.stringify(shopsRaw)
|
||||
const shopParsed = JSON.parse(shopStr)
|
||||
if (shopParsed != null) {
|
||||
const shopObj = shopParsed as UTSJSONObject
|
||||
const name = shopObj.getString('shop_name')
|
||||
if (name != null && name !== '') return name
|
||||
}
|
||||
}
|
||||
return '自营店铺'
|
||||
},
|
||||
|
||||
getOrderMainImage(order: OrderItemType): string {
|
||||
const itemsRaw = order.ml_order_items
|
||||
if (itemsRaw == null) return '/static/product1.jpg'
|
||||
@@ -675,14 +942,80 @@ export default {
|
||||
const pName = itemObj.getString('product_name')
|
||||
const name = (pName != null && pName !== '') ? pName : '商品'
|
||||
|
||||
if (items.length > 1) {
|
||||
return name + ' 等' + items.length + '件商品'
|
||||
}
|
||||
return name
|
||||
}
|
||||
return '精选商品'
|
||||
},
|
||||
|
||||
getOrderSpec(order: OrderItemType): string {
|
||||
const itemsRaw = order.ml_order_items
|
||||
if (itemsRaw == null) return ''
|
||||
const items = itemsRaw as any[]
|
||||
if (items.length > 0) {
|
||||
const firstItem = items[0]
|
||||
const itemStr = JSON.stringify(firstItem)
|
||||
const itemParsed = JSON.parse(itemStr)
|
||||
if (itemParsed == null) return ''
|
||||
const itemObj = itemParsed as UTSJSONObject
|
||||
const specRaw = itemObj.get('specifications')
|
||||
if (specRaw == null) return ''
|
||||
|
||||
if (typeof specRaw === 'string') {
|
||||
const specStr = specRaw as string
|
||||
if (specStr.startsWith('{')) {
|
||||
try {
|
||||
const specObj = JSON.parse(specStr) as UTSJSONObject
|
||||
const parts: string[] = []
|
||||
const color = specObj.get('Color')
|
||||
if (color != null) parts.push('颜色: ' + color)
|
||||
const size = specObj.get('Size')
|
||||
if (size != null) parts.push('尺码: ' + size)
|
||||
|
||||
if (parts.length > 0) return parts.join(' ')
|
||||
return specStr.replace(/[{}"]/g, '')
|
||||
} catch (e) {
|
||||
return specStr
|
||||
}
|
||||
}
|
||||
return specStr
|
||||
}
|
||||
return JSON.stringify(specRaw).replace(/[{}"]/g, '')
|
||||
}
|
||||
return ''
|
||||
},
|
||||
|
||||
getOrderItemCount(order: OrderItemType): number {
|
||||
if (order.items_count != null && order.items_count > 0) {
|
||||
return order.items_count
|
||||
}
|
||||
return 1
|
||||
},
|
||||
|
||||
getOrderShopName(order: OrderItemType): string {
|
||||
const shopsRaw = order.ml_shops
|
||||
if (shopsRaw != null) {
|
||||
const shopStr = JSON.stringify(shopsRaw)
|
||||
const shopParsed = JSON.parse(shopStr)
|
||||
if (shopParsed != null) {
|
||||
const shopObj = shopParsed as UTSJSONObject
|
||||
const name = shopObj.getString('shop_name')
|
||||
if (name != null && name !== '') return name
|
||||
}
|
||||
}
|
||||
return '自营店铺'
|
||||
},
|
||||
|
||||
formatDateTime(timeStr: string): string {
|
||||
if (timeStr == null || timeStr === '') return ''
|
||||
const date = new Date(timeStr)
|
||||
const y = date.getFullYear()
|
||||
const m = (date.getMonth() + 1).toString().padStart(2, '0')
|
||||
const d = date.getDate().toString().padStart(2, '0')
|
||||
const h = date.getHours().toString().padStart(2, '0')
|
||||
const i = date.getMinutes().toString().padStart(2, '0')
|
||||
return `${y}-${m}-${d} ${h}:${i}`
|
||||
},
|
||||
|
||||
formatTime(timeStr: string): string {
|
||||
const date = new Date(timeStr)
|
||||
const now = new Date()
|
||||
@@ -753,11 +1086,21 @@ export default {
|
||||
content: '确认已收到商品吗?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
uni.showToast({
|
||||
title: '确认收货成功',
|
||||
icon: 'success'
|
||||
uni.showLoading({ title: '处理中...' })
|
||||
supabaseService.confirmOrderReceived(order.id).then(() => {
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: '确认收货成功',
|
||||
icon: 'success'
|
||||
})
|
||||
this.loadOrders()
|
||||
}).catch(() => {
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: '操作失败',
|
||||
icon: 'none'
|
||||
})
|
||||
})
|
||||
this.refreshData()
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -891,9 +1234,9 @@ export default {
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: #4CAF50;
|
||||
background-color: #ff5000;
|
||||
z-index: 1000;
|
||||
box-shadow: 0 2px 12px rgba(76, 175, 80, 0.15);
|
||||
box-shadow: 0 2px 12px rgba(255, 80, 0, 0.15);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
@@ -912,23 +1255,28 @@ export default {
|
||||
}
|
||||
|
||||
/* 导航栏用户信息区域 */
|
||||
.nav-user-basic {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.nav-user-stats {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-start; /* 靠左对齐,紧跟头像 */
|
||||
margin-right: 12px;
|
||||
overflow: hidden; /* 防止溢出 */
|
||||
justify-content: flex-end; /* 将积分、余额、券推向右侧,但在设置按钮之前 */
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.nav-user-name {
|
||||
font-size: 16px;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
margin-right: 12px;
|
||||
/* max-width: 30%; REMOVED */
|
||||
width: 100px; /* Use fixed width approx */
|
||||
width: 70px; /* 进一步压缩名字宽度 */
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
@@ -938,31 +1286,31 @@ export default {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border-radius: 12px;
|
||||
padding: 2px 8px;
|
||||
margin-right: 8px;
|
||||
flex-shrink: 0; /* 防止被压缩 */
|
||||
background: rgba(255, 255, 255, 0.15); /* 降低透明度更清爽 */
|
||||
border-radius: 10px;
|
||||
padding: 2px 6px;
|
||||
margin-right: 4px; /* 减小间距 */
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.nav-stat-label {
|
||||
font-size: 11px;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
margin-right: 4px;
|
||||
font-size: 10px; /* 调小字体 */
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
.nav-stat-value {
|
||||
font-size: 12px;
|
||||
font-size: 11px; /* 调小字体 */
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.nav-avatar {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 18px;
|
||||
border: 2px solid rgba(255, 255, 255, 0.8);
|
||||
margin-right: 12px;
|
||||
width: 32px; /* 缩小头像 */
|
||||
height: 32px;
|
||||
border-radius: 16px;
|
||||
border: 1.5px solid rgba(255, 255, 255, 0.8);
|
||||
margin-right: 6px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
@@ -1010,6 +1358,23 @@ export default {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.section-header-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.section-header-row .section-title {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.view-all {
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.order-tabs {
|
||||
display: flex;
|
||||
flex-direction: row; /* 显式横向排列 */
|
||||
@@ -1041,12 +1406,12 @@ export default {
|
||||
/* 选中状态的Tab */
|
||||
.order-tab.active .tab-icon,
|
||||
.order-tab.active .tab-text {
|
||||
color: #4CAF50;
|
||||
color: #ff5000;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.order-tab.active {
|
||||
background-color: #f0f9f0;
|
||||
background-color: #fff8f5;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
@@ -1054,7 +1419,7 @@ export default {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 10%; /* 调整位置 */
|
||||
background-color: #ff4444;
|
||||
background-color: #ff5000;
|
||||
color: #fff;
|
||||
font-size: 10px;
|
||||
padding: 1px 5px;
|
||||
@@ -1085,114 +1450,200 @@ export default {
|
||||
}
|
||||
|
||||
.order-item {
|
||||
padding: 25rpx 0;
|
||||
border-bottom: 1rpx solid #f5f5f5;
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 24rpx;
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.order-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.order-header {
|
||||
.order-item-header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 15rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.order-no {
|
||||
font-size: 26rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.order-status {
|
||||
font-size: 24rpx;
|
||||
padding: 6rpx 12rpx;
|
||||
border-radius: 10rpx;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.order-status.pending {
|
||||
background-color: #ffa726;
|
||||
}
|
||||
|
||||
.order-status.processing {
|
||||
background-color: #2196f3;
|
||||
}
|
||||
|
||||
.order-status.shipping {
|
||||
background-color: #9c27b0;
|
||||
}
|
||||
|
||||
.order-status.completed {
|
||||
background-color: #4caf50;
|
||||
}
|
||||
|
||||
.order-content {
|
||||
.status-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
margin-bottom: 15rpx;
|
||||
}
|
||||
|
||||
.order-image {
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
border-radius: 8rpx;
|
||||
margin-right: 20rpx;
|
||||
.more-btn {
|
||||
font-size: 18px;
|
||||
color: #999;
|
||||
margin-left: 8px;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.order-info {
|
||||
flex: 1;
|
||||
.order-shop {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.order-title {
|
||||
font-size: 26rpx;
|
||||
color: #333;
|
||||
margin-bottom: 8rpx;
|
||||
.shop-icon {
|
||||
font-size: 32rpx;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
.order-amount {
|
||||
.shop-name {
|
||||
font-size: 28rpx;
|
||||
color: #ff4444;
|
||||
font-weight: bold;
|
||||
margin-bottom: 5rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.order-time {
|
||||
font-size: 22rpx;
|
||||
.shop-arrow {
|
||||
font-size: 28rpx;
|
||||
color: #ccc;
|
||||
margin-left: 4rpx;
|
||||
}
|
||||
|
||||
.order-status-text {
|
||||
font-size: 26rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.order-status-text.pending {
|
||||
color: #ff5000;
|
||||
}
|
||||
|
||||
.order-status-text.processing {
|
||||
color: #ff9500;
|
||||
}
|
||||
|
||||
.order-status-text.shipping {
|
||||
color: #007aff;
|
||||
}
|
||||
|
||||
.order-status-text.completed {
|
||||
color: #34c759;
|
||||
}
|
||||
|
||||
.order-status-text.refunding {
|
||||
color: #ff9500;
|
||||
}
|
||||
|
||||
.order-status-text.refunded {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.order-actions {
|
||||
.order-status-text.cancelled {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.order-item-content {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
/* gap: 15rpx; REMOVED */
|
||||
flex-direction: row;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.order-actions .action-btn {
|
||||
margin-left: 15px; /* Replace gap */
|
||||
.order-item-image {
|
||||
width: 140rpx;
|
||||
height: 140rpx;
|
||||
border-radius: 12rpx;
|
||||
margin-right: 20rpx;
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
padding: 12rpx 25rpx;
|
||||
border-radius: 20rpx;
|
||||
.order-item-info {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.order-title-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.order-item-title {
|
||||
flex: 1;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
line-height: 1.4;
|
||||
margin-right: 20rpx;
|
||||
lines: 2;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.order-item-price {
|
||||
font-size: 32rpx;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.order-spec-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: 4rpx;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.order-item-spec {
|
||||
flex: 1;
|
||||
font-size: 24rpx;
|
||||
border: none;
|
||||
color: #999;
|
||||
margin-right: 12rpx;
|
||||
lines: 1;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.action-btn.pay {
|
||||
background-color: #ff4444;
|
||||
color: #fff;
|
||||
.order-item-time {
|
||||
font-size: 22rpx;
|
||||
color: #999;
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
.action-btn.confirm {
|
||||
background-color: #4caf50;
|
||||
color: #fff;
|
||||
.order-item-num {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.action-btn.review {
|
||||
background-color: #ffa726;
|
||||
.order-item-actions {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.order-action-btn {
|
||||
margin-left: 16rpx;
|
||||
padding: 10rpx 28rpx;
|
||||
border-radius: 30rpx;
|
||||
font-size: 24rpx;
|
||||
border: 1px solid #ddd;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.order-action-btn.pay {
|
||||
background-color: #ff5000;
|
||||
color: #fff;
|
||||
border-color: #ff5000;
|
||||
}
|
||||
|
||||
.order-action-btn.confirm {
|
||||
background-color: #ff5000;
|
||||
color: #fff;
|
||||
border-color: #ff5000;
|
||||
}
|
||||
|
||||
.order-action-btn.review {
|
||||
color: #ff5000;
|
||||
border-color: #ff5000;
|
||||
}
|
||||
|
||||
.order-action-btn.secondary {
|
||||
color: #666;
|
||||
border-color: #ddd;
|
||||
}
|
||||
|
||||
.service-grid {
|
||||
@@ -1227,7 +1678,7 @@ export default {
|
||||
position: absolute;
|
||||
top: -5rpx;
|
||||
right: 10rpx;
|
||||
background-color: #ff4444;
|
||||
background-color: #ff5000;
|
||||
color: #fff;
|
||||
font-size: 18rpx;
|
||||
padding: 4rpx 6rpx;
|
||||
@@ -1332,3 +1783,4 @@ export default {
|
||||
color: #999;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user