feat: 初次提交我的项目代码
This commit is contained in:
908
pages/mall/consumer/orders.uvue
Normal file
908
pages/mall/consumer/orders.uvue
Normal file
@@ -0,0 +1,908 @@
|
||||
<!-- 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>
|
||||
|
||||
<!-- 订单状态筛选 -->
|
||||
<view class="order-tabs">
|
||||
<scroll-view scroll-x class="tab-scroll" :show-scrollbar="false">
|
||||
<view class="tab-container">
|
||||
<view
|
||||
v-for="tab in orderTabs"
|
||||
:key="tab.id"
|
||||
:class="['tab-item', { active: activeTab === tab.id }]"
|
||||
@click="switchTab(tab.id)"
|
||||
>
|
||||
<text class="tab-name">{{ tab.name }}</text>
|
||||
<text v-if="tab.count > 0" class="tab-count">{{ tab.count }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
<!-- 订单列表 -->
|
||||
<scroll-view
|
||||
scroll-y
|
||||
class="orders-content"
|
||||
refresher-enabled
|
||||
:refresher-triggered="refreshing"
|
||||
@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>
|
||||
</view>
|
||||
|
||||
<!-- 订单列表 -->
|
||||
<view v-else class="order-list">
|
||||
<view
|
||||
v-for="order in orders"
|
||||
:key="order.id"
|
||||
class="order-card"
|
||||
>
|
||||
<!-- 订单头部 -->
|
||||
<view class="order-header">
|
||||
<text class="order-no">订单号:{{ order.order_no }}</text>
|
||||
<text :class="['order-status', getStatusClass(order.status)]">
|
||||
{{ getStatusText(order.status) }}
|
||||
</text>
|
||||
</view>
|
||||
|
||||
<!-- 订单商品 -->
|
||||
<view class="order-products">
|
||||
<view
|
||||
v-for="product in order.products"
|
||||
:key="product.id"
|
||||
class="order-product"
|
||||
@click="navigateToProduct(product)"
|
||||
>
|
||||
<image
|
||||
class="product-image"
|
||||
:src="product.image"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
<view class="product-info">
|
||||
<text class="product-name">{{ product.name }}</text>
|
||||
<text class="product-spec">{{ product.spec }}</text>
|
||||
<view class="product-footer">
|
||||
<text class="product-price">¥{{ product.price }}</text>
|
||||
<text class="product-quantity">×{{ product.quantity }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 订单信息 -->
|
||||
<view class="order-info">
|
||||
<view class="info-row">
|
||||
<text class="info-label">商品合计</text>
|
||||
<text class="info-value">¥{{ order.product_amount }}</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="info-label">运费</text>
|
||||
<text class="info-value">¥{{ order.shipping_fee }}</text>
|
||||
</view>
|
||||
<view class="info-row total">
|
||||
<text class="info-label">实付款</text>
|
||||
<text class="info-value total-price">¥{{ order.total_amount }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 订单操作 -->
|
||||
<view class="order-actions">
|
||||
<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>
|
||||
</view>
|
||||
|
||||
<view v-if="order.status === 2" class="action-buttons">
|
||||
<button class="action-btn remind" @click="remindShipping(order.id)">提醒发货</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>
|
||||
</view>
|
||||
|
||||
<view v-if="order.status === 4" class="action-buttons">
|
||||
<button class="action-btn review" @click="goReview(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>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载更多 -->
|
||||
<view v-if="loadingMore" class="loading-more">
|
||||
<view class="loading-spinner"></view>
|
||||
<text>加载中...</text>
|
||||
</view>
|
||||
|
||||
<view v-if="!hasMore && orders.length > 0" class="no-more">
|
||||
<text>没有更多订单了</text>
|
||||
</view>
|
||||
|
||||
<!-- 安全区域 -->
|
||||
<view class="safe-area"></view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 底部导航 -->
|
||||
<view class="tabbar-placeholder"></view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref, reactive, onMounted, computed } from 'vue'
|
||||
|
||||
// 响应式数据
|
||||
const orders = ref<any[]>([])
|
||||
const loading = ref<boolean>(false)
|
||||
const loadingMore = ref<boolean>(false)
|
||||
const hasMore = ref<boolean>(true)
|
||||
const refreshing = ref<boolean>(false)
|
||||
const page = ref<number>(1)
|
||||
const activeTab = ref<string>('all')
|
||||
|
||||
// 订单标签页
|
||||
const orderTabs = reactive([
|
||||
{ id: 'all', name: '全部', count: 12 },
|
||||
{ id: 'pending', name: '待付款', count: 2 },
|
||||
{ id: 'shipping', name: '待发货', count: 1 },
|
||||
{ id: 'delivering', name: '待收货', count: 3 },
|
||||
{ id: 'completed', name: '已完成', count: 5 },
|
||||
{ id: 'cancelled', name: '已取消', count: 1 }
|
||||
])
|
||||
|
||||
// Mock 订单数据
|
||||
const mockOrders = [
|
||||
{
|
||||
id: '202311230001',
|
||||
order_no: '202311230001',
|
||||
status: 1, // 1:待付款 2:待发货 3:待收货 4:已完成 5:已取消
|
||||
create_time: '2023-11-23 14:30:22',
|
||||
product_amount: 378.00,
|
||||
shipping_fee: 0.00,
|
||||
total_amount: 378.00,
|
||||
products: [
|
||||
{
|
||||
id: '1001',
|
||||
name: '无线蓝牙耳机 降噪版',
|
||||
price: 299.00,
|
||||
image: 'https://picsum.photos/80/80?random=1',
|
||||
spec: '白色',
|
||||
quantity: 1
|
||||
},
|
||||
{
|
||||
id: '1002',
|
||||
name: '耳机保护套',
|
||||
price: 29.00,
|
||||
image: 'https://picsum.photos/80/80?random=2',
|
||||
spec: '黑色',
|
||||
quantity: 1
|
||||
},
|
||||
{
|
||||
id: '1003',
|
||||
name: '数据线',
|
||||
price: 19.00,
|
||||
image: 'https://picsum.photos/80/80?random=3',
|
||||
spec: '1米',
|
||||
quantity: 2
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: '202311220001',
|
||||
order_no: '202311220001',
|
||||
status: 2,
|
||||
create_time: '2023-11-22 10:15:33',
|
||||
product_amount: 199.00,
|
||||
shipping_fee: 10.00,
|
||||
total_amount: 209.00,
|
||||
products: [
|
||||
{
|
||||
id: '2001',
|
||||
name: '运动T恤 速干面料',
|
||||
price: 79.00,
|
||||
image: 'https://picsum.photos/80/80?random=4',
|
||||
spec: '黑色 L',
|
||||
quantity: 2
|
||||
},
|
||||
{
|
||||
id: '2002',
|
||||
name: '运动短裤',
|
||||
price: 59.00,
|
||||
image: 'https://picsum.photos/80/80?random=5',
|
||||
spec: '黑色 M',
|
||||
quantity: 1
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: '202311210001',
|
||||
order_no: '202311210001',
|
||||
status: 3,
|
||||
create_time: '2023-11-21 16:45:12',
|
||||
product_amount: 299.00,
|
||||
shipping_fee: 0.00,
|
||||
total_amount: 299.00,
|
||||
products: [
|
||||
{
|
||||
id: '3001',
|
||||
name: '智能手环 心率监测',
|
||||
price: 199.00,
|
||||
image: 'https://picsum.photos/80/80?random=6',
|
||||
spec: '黑色',
|
||||
quantity: 1
|
||||
},
|
||||
{
|
||||
id: '3002',
|
||||
name: '手环腕带',
|
||||
price: 29.00,
|
||||
image: 'https://picsum.photos/80/80?random=7',
|
||||
spec: '蓝色',
|
||||
quantity: 2
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: '202311200001',
|
||||
order_no: '202311200001',
|
||||
status: 4,
|
||||
create_time: '2023-11-20 09:30:45',
|
||||
product_amount: 99.00,
|
||||
shipping_fee: 0.00,
|
||||
total_amount: 99.00,
|
||||
products: [
|
||||
{
|
||||
id: '4001',
|
||||
name: '保温杯 500ml',
|
||||
price: 49.00,
|
||||
image: 'https://picsum.photos/80/80?random=8',
|
||||
spec: '白色',
|
||||
quantity: 2
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: '202311190001',
|
||||
order_no: '202311190001',
|
||||
status: 5,
|
||||
create_time: '2023-11-19 14:20:18',
|
||||
product_amount: 599.00,
|
||||
shipping_fee: 0.00,
|
||||
total_amount: 599.00,
|
||||
products: [
|
||||
{
|
||||
id: '5001',
|
||||
name: '蓝牙音箱 便携式',
|
||||
price: 199.00,
|
||||
image: 'https://picsum.photos/80/80?random=9',
|
||||
spec: '黑色',
|
||||
quantity: 3
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
// 计算属性:根据当前标签筛选订单
|
||||
const filteredOrders = computed(() => {
|
||||
if (activeTab.value === 'all') {
|
||||
return orders.value
|
||||
}
|
||||
|
||||
const statusMap: Record<string, number> = {
|
||||
'pending': 1,
|
||||
'shipping': 2,
|
||||
'delivering': 3,
|
||||
'completed': 4,
|
||||
'cancelled': 5
|
||||
}
|
||||
|
||||
const targetStatus = statusMap[activeTab.value]
|
||||
return orders.value.filter(order => order.status === targetStatus)
|
||||
})
|
||||
|
||||
// 生命周期
|
||||
onMounted(() => {
|
||||
loadOrders()
|
||||
})
|
||||
|
||||
// 加载订单数据
|
||||
const loadOrders = () => {
|
||||
loading.value = true
|
||||
|
||||
// 模拟API请求延迟
|
||||
setTimeout(() => {
|
||||
orders.value = [...mockOrders]
|
||||
loading.value = false
|
||||
}, 800)
|
||||
}
|
||||
|
||||
// 切换标签
|
||||
const switchTab = (tabId: string) => {
|
||||
activeTab.value = tabId
|
||||
page.value = 1
|
||||
orders.value = []
|
||||
loadOrders()
|
||||
}
|
||||
|
||||
// 获取状态文本
|
||||
const getStatusText = (status: number): string => {
|
||||
const statusMap: Record<number, string> = {
|
||||
1: '待付款',
|
||||
2: '待发货',
|
||||
3: '待收货',
|
||||
4: '已完成',
|
||||
5: '已取消'
|
||||
}
|
||||
return statusMap[status] || '未知状态'
|
||||
}
|
||||
|
||||
// 获取状态类名
|
||||
const getStatusClass = (status: number): string => {
|
||||
const classMap: Record<number, string> = {
|
||||
1: 'status-pending',
|
||||
2: 'status-shipping',
|
||||
3: 'status-delivering',
|
||||
4: 'status-completed',
|
||||
5: 'status-cancelled'
|
||||
}
|
||||
return classMap[status] || 'status-unknown'
|
||||
}
|
||||
|
||||
// 下拉刷新
|
||||
const onRefresh = () => {
|
||||
refreshing.value = true
|
||||
setTimeout(() => {
|
||||
loadOrders()
|
||||
refreshing.value = false
|
||||
uni.showToast({
|
||||
title: '刷新成功',
|
||||
icon: 'success'
|
||||
})
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
// 上拉加载更多
|
||||
const loadMore = () => {
|
||||
if (loadingMore.value || !hasMore.value) return
|
||||
|
||||
loadingMore.value = true
|
||||
|
||||
// 模拟加载更多数据
|
||||
setTimeout(() => {
|
||||
const newOrders = [...mockOrders].map((order, index) => ({
|
||||
...order,
|
||||
id: `${order.id}_${page.value}${index}`,
|
||||
order_no: `${order.order_no}_${page.value}${index}`
|
||||
}))
|
||||
|
||||
orders.value = [...orders.value, ...newOrders]
|
||||
loadingMore.value = false
|
||||
page.value++
|
||||
hasMore.value = orders.value.length < 20
|
||||
}, 1200)
|
||||
}
|
||||
|
||||
// 订单操作函数
|
||||
const cancelOrder = (orderId: string) => {
|
||||
uni.showModal({
|
||||
title: '确认取消',
|
||||
content: '确定要取消此订单吗?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
// 这里应该是实际的API调用
|
||||
uni.showToast({
|
||||
title: '订单已取消',
|
||||
icon: 'success'
|
||||
})
|
||||
|
||||
// 更新订单状态
|
||||
const index = orders.value.findIndex(order => order.id === orderId)
|
||||
if (index !== -1) {
|
||||
orders.value[index].status = 5
|
||||
orders.value = [...orders.value]
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const payOrder = (orderId: string) => {
|
||||
uni.navigateTo({
|
||||
url: `/pages/mall/consumer/payment?orderId=${orderId}`
|
||||
})
|
||||
}
|
||||
|
||||
const remindShipping = (orderId: string) => {
|
||||
uni.showToast({
|
||||
title: '已提醒卖家发货',
|
||||
icon: 'success'
|
||||
})
|
||||
}
|
||||
|
||||
const viewLogistics = (orderId: string) => {
|
||||
uni.navigateTo({
|
||||
url: `/pages/mall/consumer/logistics?orderId=${orderId}`
|
||||
})
|
||||
}
|
||||
|
||||
const confirmReceipt = (orderId: string) => {
|
||||
uni.showModal({
|
||||
title: '确认收货',
|
||||
content: '请确认您已收到商品,且商品无误',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
// 这里应该是实际的API调用
|
||||
uni.showToast({
|
||||
title: '收货成功',
|
||||
icon: 'success'
|
||||
})
|
||||
|
||||
// 更新订单状态
|
||||
const index = orders.value.findIndex(order => order.id === orderId)
|
||||
if (index !== -1) {
|
||||
orders.value[index].status = 4
|
||||
orders.value = [...orders.value]
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const goReview = (order: any) => {
|
||||
const productIds = order.products.map((p: any) => p.id).join(',')
|
||||
uni.navigateTo({
|
||||
url: `/pages/mall/consumer/review?orderId=${order.id}&productIds=${productIds}`
|
||||
})
|
||||
}
|
||||
|
||||
const repurchase = (order: any) => {
|
||||
uni.showModal({
|
||||
title: '再次购买',
|
||||
content: '确定要将这些商品加入购物车吗?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
// 这里应该是实际的API调用
|
||||
uni.showToast({
|
||||
title: '已加入购物车',
|
||||
icon: 'success'
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const viewOrderDetail = (orderId: string) => {
|
||||
uni.navigateTo({
|
||||
url: `/pages/mall/consumer/order-detail?id=${orderId}`
|
||||
})
|
||||
}
|
||||
|
||||
// 导航函数
|
||||
const navigateToSearch = () => {
|
||||
uni.navigateTo({ url: '/pages/mall/consumer/search' })
|
||||
}
|
||||
|
||||
const navigateToProduct = (product: any) => {
|
||||
uni.navigateTo({ url: `/pages/mall/consumer/product-detail?id=${product.id}` })
|
||||
}
|
||||
|
||||
const goShopping = () => {
|
||||
uni.switchTab({ url: '/pages/mall/consumer/index' })
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.orders-page {
|
||||
width: 100%;
|
||||
min-height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
/* 头部 */
|
||||
.orders-header {
|
||||
background-color: white;
|
||||
padding: 15px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid #eee;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.header-actions .search-icon {
|
||||
font-size: 20px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* 标签页 */
|
||||
.order-tabs {
|
||||
background-color: white;
|
||||
border-bottom: 1px solid #eee;
|
||||
position: sticky;
|
||||
top: 50px;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.tab-scroll {
|
||||
white-space: nowrap;
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.tab-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 0 15px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
flex-shrink: 0;
|
||||
padding: 0 15px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.tab-item.active {
|
||||
color: #ff5000;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.tab-item.active::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 2px;
|
||||
background-color: #ff5000;
|
||||
}
|
||||
|
||||
.tab-name {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.tab-count {
|
||||
margin-left: 4px;
|
||||
background-color: #ff5000;
|
||||
color: white;
|
||||
font-size: 10px;
|
||||
padding: 1px 4px;
|
||||
border-radius: 8px;
|
||||
min-width: 12px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* 内容区 */
|
||||
.orders-content {
|
||||
height: calc(100vh - 100px);
|
||||
}
|
||||
|
||||
/* 空状态 */
|
||||
.empty-orders {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 80px 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
font-size: 80px;
|
||||
color: #ddd;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.empty-title {
|
||||
font-size: 18px;
|
||||
color: #666;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.empty-desc {
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.go-shopping-btn {
|
||||
background-color: #ff5000;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 25px;
|
||||
padding: 10px 40px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
/* 订单列表 */
|
||||
.order-list {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.order-card {
|
||||
background-color: white;
|
||||
border-radius: 10px;
|
||||
margin-bottom: 10px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
/* 订单头部 */
|
||||
.order-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 15px;
|
||||
border-bottom: 1px solid #f5f5f5;
|
||||
}
|
||||
|
||||
.order-no {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.order-status {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.status-pending {
|
||||
color: #ff5000;
|
||||
}
|
||||
|
||||
.status-shipping {
|
||||
color: #ff9500;
|
||||
}
|
||||
|
||||
.status-delivering {
|
||||
color: #007aff;
|
||||
}
|
||||
|
||||
.status-completed {
|
||||
color: #34c759;
|
||||
}
|
||||
|
||||
.status-cancelled {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* 订单商品 */
|
||||
.order-products {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.order-product {
|
||||
display: flex;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.order-product:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.product-image {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
border-radius: 8px;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.product-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.product-name {
|
||||
font-size: 15px;
|
||||
color: #333;
|
||||
margin-bottom: 5px;
|
||||
display: block;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.product-spec {
|
||||
font-size: 13px;
|
||||
color: #999;
|
||||
margin-bottom: 10px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.product-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.product-price {
|
||||
font-size: 16px;
|
||||
color: #ff5000;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.product-quantity {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* 订单信息 */
|
||||
.order-info {
|
||||
padding: 15px;
|
||||
border-top: 1px solid #f5f5f5;
|
||||
border-bottom: 1px solid #f5f5f5;
|
||||
}
|
||||
|
||||
.info-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.info-row:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.info-row.total {
|
||||
margin-top: 8px;
|
||||
padding-top: 8px;
|
||||
border-top: 1px solid #f5f5f5;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.total-price {
|
||||
font-size: 18px;
|
||||
color: #ff5000;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* 订单操作 */
|
||||
.order-actions {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
padding: 6px 15px;
|
||||
border-radius: 15px;
|
||||
font-size: 13px;
|
||||
border: 1px solid;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.action-btn.cancel {
|
||||
color: #666;
|
||||
border-color: #ccc;
|
||||
}
|
||||
|
||||
.action-btn.pay {
|
||||
color: #ff5000;
|
||||
border-color: #ff5000;
|
||||
}
|
||||
|
||||
.action-btn.remind {
|
||||
color: #666;
|
||||
border-color: #ccc;
|
||||
}
|
||||
|
||||
.action-btn.view {
|
||||
color: #666;
|
||||
border-color: #ccc;
|
||||
}
|
||||
|
||||
.action-btn.confirm {
|
||||
color: #34c759;
|
||||
border-color: #34c759;
|
||||
}
|
||||
|
||||
.action-btn.review {
|
||||
color: #ff9500;
|
||||
border-color: #ff9500;
|
||||
}
|
||||
|
||||
.action-btn.repurchase {
|
||||
color: #ff5000;
|
||||
border-color: #ff5000;
|
||||
}
|
||||
|
||||
/* 加载更多 */
|
||||
.loading-more {
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.loading-spinner {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border: 2px solid #f0f5ff;
|
||||
border-top-color: #ff5000;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
.no-more {
|
||||
text-align: center;
|
||||
color: #999;
|
||||
font-size: 13px;
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
/* 安全区域 */
|
||||
.safe-area {
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
/* 底部导航占位 */
|
||||
.tabbar-placeholder {
|
||||
height: 50px;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
/* 响应式适配 */
|
||||
@media screen and (max-width: 320px) {
|
||||
.tab-item {
|
||||
padding: 0 10px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
padding: 6px 10px;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 415px) {
|
||||
.order-card {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user