HomeLease/pages/myOrder/myOrder.vue

402 lines
9.0 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" class="loading-container">
<text class="loading-text">正在加载...</text>
</view>
<!-- 空数据状态 -->
<view v-else-if="list.length === 0 && !loading" 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="status-text" :class="getStatusClass(item.status)">
{{ 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="value" :class="getLogisticClass(item.logisticStatus)">
{{ mapOrderStatus('logistic', item.logisticStatus) }}
</text>
</view>
</view>
</view>
</view>
<!-- 加载更多状态 -->
<view v-if="noData && list.length > 0" class="load-more">
<text class="no-more-text">没有更多数据了</text>
</view>
</view>
</view>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { getMyOrder } from '@/api/order/myOrder.js'
import { onUnload, onReachBottom } from '@dcloudio/uni-app'
const list = ref([])
const noData = ref(false)
const loading = ref(false)
/**
* 订单状态/物流状态映射工具
* @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
}
}
//定义data参数
const queryParams = {
pageNum: 1,
pageSize: 6,
}
// 页面加载时获取数据
onMounted(() => {
getList()
})
onReachBottom(() => {
if (noData.value || loading.value) return
queryParams.pageNum++
getList()
})
// 获取列表
const getList = async () => {
if (loading.value) return
try {
loading.value = true
let res = await getMyOrder(queryParams)
// 确保 res.data 存在且是数组
const newData = res?.rows || []
// 如果是第一页,直接替换数据
if (queryParams.pageNum === 1) {
list.value = newData
} else {
list.value = [...list.value, ...newData]
}
if (newData.length < queryParams.pageSize) {
noData.value = true
}
console.log('订单列表:', list.value)
} catch (error) {
console.error('获取订单列表失败:', error)
uni.showToast({
title: '获取订单列表失败',
icon: 'none',
})
} finally {
loading.value = false
}
}
// 点击订单卡片
const onClick = (item) => {
console.log('点击订单:', item)
// 跳转到订单详情页
uni.navigateTo({
url: `/pages/myOrder/orderDetail?id=${item.id}`
})
}
onUnload(() => {
// 清理数据
list.value = []
noData.value = false
loading.value = false
})
</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>