HomeLease/pages/myOrder/myOrder.vue
2025-08-26 09:11:00 +08:00

375 lines
8.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="container">
<!-- 加载状态 -->
<view v-if="loading && list.length === 0" class="loading-container">
<text class="loading-text">正在加载...</text>
</view>
<!-- 空数据状态 -->
<view v-else-if="isEmpty" class="empty-container">
<view class="empty-icon">📋</view>
<text class="empty-text">暂无订单数据</text>
</view>
<!-- 订单列表 -->
<view v-else>
<view v-for="item in list" :key="item.id" class="order-item" @click="onClick(item)">
<view class="order-header">
<view class="order-title">
<text class="title-text">{{ item.typeName || '订单详情' }}</text>
<text :class="getStatusClass(item.status)" class="status-text">
{{ mapOrderStatus('status', item.status) }}
</text>
</view>
<text class="order-time">{{ formatTime(item.createTime) }}</text>
</view>
<view class="order-content">
<view class="order-info">
<text class="order-id">订单号:{{ item.orderNumber || item.id }}</text>
<text class="order-amount">¥{{ item.amount || '0.00' }}</text>
</view>
<view class="order-details">
<view class="detail-item">
<text class="label">租赁套餐:</text>
<text class="value">{{ item.suitName }}</text>
</view>
<view class="detail-item">
<text class="label">租赁时间:</text>
<text class="value">{{ formatTime(item.leaseTime) }}</text>
</view>
<view class="detail-item">
<text class="label">到期时间:</text>
<text class="value">{{ formatTime(item.expirationTime) }}</text>
</view>
<view class="detail-item">
<text class="label">物流状态:</text>
<text :class="getLogisticClass(item.logisticStatus)" class="value">
{{ mapOrderStatus('logistic', item.logisticStatus) }}
</text>
</view>
</view>
</view>
</view>
</view>
<!-- 分页组件 -->
<pagination
:current-page="pagination.currentPage"
:list="list"
:loading="loading"
:mode="'loadMore'"
:no-more="noMore"
:page-size="pagination.pageSize"
:total="pagination.total"
@page-change="handlePageChange"
/>
</view>
</template>
<script setup>
import { onMounted } from 'vue'
import { onReachBottom } from '@dcloudio/uni-app'
import { usePagination } from '@/composables/usePagination.js'
import { getMyOrder } from '@/api/order/myOrder.js'
import Pagination from '@/components/pagination/pagination.vue'
// 使用分页组合式函数
const { list, loading, noMore, pagination, getList, loadMore } = usePagination({
fetchData: getMyOrder,
defaultParams: {
orderByColumn: 'createTime',
isAsc: 'descending',
},
mode: 'loadMore',
pageSize: 6,
})
// 页面加载时获取数据
onMounted(() => {
getList()
})
// 上拉加载更多
onReachBottom(() => {
loadMore()
})
// 处理页码变化
const handlePageChange = page => {
console.log('页码变化:', page)
}
/**
* 订单状态/物流状态映射工具
* @param {string} type - 'status'(订单状态) 或 'logistic'(物流状态)
* @param {string|number} value - 状态值(数字或中文)
* @returns {string|number} 转换后的值
*/
function mapOrderStatus(type, value) {
const maps = {
status: {
1: '未支付',
2: '支付成功',
3: '退款',
未支付: '1',
支付成功: '2',
退款: '3',
},
logistic: {
1: '未签收',
2: '已签收',
3: '已归还',
未签收: '1',
已签收: '2',
已归还: '3',
},
}
return maps[type]?.[value] || '未知状态'
}
/**
* 获取订单状态样式类
* @param {string} status - 状态值
* @returns {string} 样式类名
*/
function getStatusClass(status) {
const statusMap = {
1: 'status-pending',
2: 'status-success',
3: 'status-refund',
}
return statusMap[status] || 'status-unknown'
}
/**
* 获取物流状态样式类
* @param {string} status - 状态值
* @returns {string} 样式类名
*/
function getLogisticClass(status) {
const statusMap = {
1: 'logistic-pending',
2: 'logistic-success',
3: 'logistic-returned',
}
return statusMap[status] || 'logistic-unknown'
}
/**
* 格式化时间
* @param {string} timeStr - 时间字符串
* @returns {string} 格式化后的时间
*/
function formatTime(timeStr) {
if (!timeStr) return '--'
try {
// 处理iOS兼容性问题将 "yyyy-MM-dd HH:mm:ss" 转换为 "yyyy/MM/dd HH:mm:ss"
let normalizedTimeStr = timeStr
if (typeof timeStr === 'string' && timeStr.includes('-') && timeStr.includes(' ')) {
// 将 "2027-08-22 17:17:01" 转换为 "2027/08/22 17:17:01"
normalizedTimeStr = timeStr.replace(/-/g, '/')
}
const date = new Date(normalizedTimeStr)
// 检查日期是否有效
if (isNaN(date.getTime())) {
return timeStr
}
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
const hours = String(date.getHours()).padStart(2, '0')
const minutes = String(date.getMinutes()).padStart(2, '0')
return `${year}-${month}-${day} ${hours}:${minutes}`
} catch (error) {
console.error('时间格式化错误:', error, '原始时间:', timeStr)
return timeStr
}
}
// 点击订单卡片
const onClick = item => {
console.log('点击订单:', item)
// 跳转到订单详情页
uni.navigateTo({
url: `/pages/myOrder/orderDetail?id=${item.id}`,
})
}
</script>
<style lang="scss" scoped>
.container {
overflow: hidden;
padding: 20rpx;
min-height: 100vh;
background-color: #f5f5f5;
}
.loading-container {
display: flex;
justify-content: center;
align-items: center;
height: 200rpx;
.loading-text {
font-size: 28rpx;
color: #666;
}
}
.empty-container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 400rpx;
.empty-icon {
font-size: 80rpx;
margin-bottom: 20rpx;
}
.empty-text {
font-size: 28rpx;
color: #999;
}
}
.order-item {
background-color: #fff;
border-radius: 16rpx;
margin-bottom: 20rpx;
padding: 30rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
&:active {
background-color: #f8f8f8;
}
}
.order-header {
margin-bottom: 20rpx;
.order-title {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10rpx;
.title-text {
font-size: 32rpx;
font-weight: 600;
color: #333;
}
.status-text {
font-size: 24rpx;
padding: 6rpx 12rpx;
border-radius: 20rpx;
font-weight: 500;
&.status-pending {
background-color: #fff7e6;
color: #fa8c16;
}
&.status-success {
background-color: #f6ffed;
color: #52c41a;
}
&.status-refund {
background-color: #fff2f0;
color: #ff4d4f;
}
&.status-unknown {
background-color: #f5f5f5;
color: #999;
}
}
}
.order-time {
font-size: 24rpx;
color: #999;
}
}
.order-content {
.order-info {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20rpx;
padding-bottom: 15rpx;
border-bottom: 1rpx solid #f0f0f0;
.order-id {
font-size: 26rpx;
color: #666;
}
.order-amount {
font-size: 32rpx;
color: #f15a04;
font-weight: bold;
}
}
.order-details {
.detail-item {
display: flex;
justify-content: space-between;
margin-bottom: 12rpx;
.label {
font-size: 26rpx;
color: #666;
min-width: 140rpx;
}
.value {
font-size: 26rpx;
color: #333;
flex: 1;
text-align: right;
&.logistic-pending {
color: #fa8c16;
}
&.logistic-success {
color: #52c41a;
}
&.logistic-returned {
color: #1890ff;
}
&.logistic-unknown {
color: #999;
}
}
}
}
}
.load-more {
margin-top: 20rpx;
text-align: center;
.no-more-text {
font-size: 24rpx;
color: #999;
}
}
</style>