爱简收旧衣按件回收前端代码仓库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

473 lines
11 KiB

<template>
<view class="container">
<!-- 顶部导航 -->
<view class="nav-bar">
<view class="back" @tap="goBack">
<uni-icons type="left" size="20"></uni-icons>
</view>
<text class="title">我的订单</text>
</view>
<!-- 页面内容 -->
<view class="content">
<!-- <view class="page-header">
<text class="page-title">我的订单</text>
<text class="view-all" @tap="viewAll">查看全部 ></text>
</view> -->
<!-- 标签页 -->
<view class="tabs">
<view
v-for="(tab, index) in tabs"
:key="index"
class="tab-item"
:class="{ active: currentTab === index }"
@tap="switchTab(index)"
>
<text>{{ tab.name }}</text>
<text v-if="tab.count > 0" class="badge">{{ tab.count }}</text>
</view>
</view>
<!-- 订单列表 -->
<scroll-view
scroll-y
class="order-list"
@scrolltolower="loadMore"
>
<view
v-for="order in orderList"
:key="order.id"
class="order-card"
@tap="goToDetail(order)"
>
<!-- 订单号 -->
<view class="order-header">
<text class="order-id">
订单编号
<text class="order-ids">{{order.ordeNo || order.id}}</text>
</text>
</view>
<!-- 订单内容 -->
<view class="order-content">
<image class="order-image" :src="order.image || '/static/回收/衣物.png'" mode="aspectFill"></image>
<view class="order-arrow">
<text class="iconfont">⇄</text>
</view>
<view class="order-info">
<text class="order-count">{{ order.num || order.count || 1 }} 件</text>
<text class="order-price">¥ {{ order.onePrice || order.priceRange || 0 }} /件</text>
<view class="order-estimate">
<text>预估 ¥{{ order.price || order.estimatePrice }}</text>
</view>
</view>
</view>
<!-- 订单状态 -->
<view class="order-status">
<image class="status-icon" :src="order.statusIcon || '/static/my/【待取件】快递员正在赶来.png'" mode="aspectFill"></image>
<view class="status-info">
<text class="status-text">{{ getOrderStatusText(order) }}</text>
<text class="status-time">{{ order.goTime || order.statusTime }}</text>
</view>
</view>
</view>
<view class="order-loading" v-if="loading">
<uni-loading color="#ffac07" :size="40" />
<text class="loading-text">加载中...</text>
</view>
<view class="order-nomore" v-else-if="!hasMore && orderList.length">
<text class="nomore-text">没有更多订单了</text>
</view>
</scroll-view>
</view>
</view>
</template>
<script>
import pullRefreshMixin from '@/pages/mixins/pullRefreshMixin.js'
export default {
mixins: [pullRefreshMixin],
data() {
return {
tabs: [
{ name: '全部', count: 0 },
{ name: '进行中', count: 0 },
{ name: '已完成', count: 0 }
],
currentTab: 0,
orderList: [], // 当前显示的订单列表
loading: false,
page: 1,
pageSize: 10,
hasMore: true
}
},
created() {
this.fetchOrderList()
},
methods: {
async fetchOrderList(isLoadMore = false) {
this.loading = true
let statusArr = []
if (this.currentTab === 1) statusArr = [0, 1, 2] // 进行中
else if (this.currentTab === 2) statusArr = [3] // 已完成
else statusArr = [] // 全部
let allOrders = []
if (statusArr.length === 0) {
// 全部
await new Promise(resolve => {
this.$api('getOrderListPage', { pageSize: this.pageSize, current: this.page }, res => {
if (res && res.code === 200 && res.result && Array.isArray(res.result.records)) {
allOrders = res.result.records
if (isLoadMore) {
this.orderList = this.orderList.concat(allOrders)
} else {
this.orderList = allOrders
}
this.hasMore = allOrders.length === this.pageSize
}
resolve()
})
})
} else {
// 多状态合并
for (let status of statusArr) {
await new Promise(resolve => {
this.$api('getOrderListPage', { status, pageSize: this.pageSize, current: this.page }, res => {
if (res && res.code === 200 && res.result && Array.isArray(res.result.records)) {
allOrders = allOrders.concat(res.result.records)
}
resolve()
})
})
}
// 去重
const map = {}
allOrders = allOrders.filter(item => {
if (map[item.id]) return false
map[item.id] = 1
return true
})
if (isLoadMore) {
this.orderList = this.orderList.concat(allOrders)
} else {
this.orderList = allOrders
}
this.hasMore = allOrders.length === this.pageSize
}
this.loading = false
},
switchTab(index) {
if (this.currentTab === index) return
this.currentTab = index
this.page = 1 // 重置页码
this.hasMore = true
this.orderList = []
this.fetchOrderList()
},
getOrderStatusText(order) {
const { status, state } = order
if (state == 3) return '已取消'
if (status == 0) return '【在线预约】'
if (status == 1 && state == 0) return '【待取件】快递员正在赶来'
if (status == 1 && state == 1) return '【已取件】快递员正在送至质检'
if (status == 2 && state == 1) return '【质检中】质检员正在质检'
if (status == 3 && state == 1) return '【待结款】待平台确认结款项'
if (status == 3 && state == 2) return '【已结款】平台已结款至账户'
return ''
},
async onRefresh() {
// 模拟刷新数据
await new Promise(resolve => setTimeout(resolve, 1000))
uni.stopPullRefresh()
},
goBack() {
uni.navigateBack()
},
showMore() {
// 显示更多选项
},
onShare() {
// 分享功能
},
viewAll() {
this.switchTab(0) // 切换到全部标签
},
// 加载更多
loadMore() {
if (this.loading || !this.hasMore) return
this.page++
this.fetchOrderList(true)
},
goToDetail(order) {
uni.navigateTo({
url: `/pages/subcomponent/detail?id=${order.id}`
})
}
}
}
</script>
<style lang="scss" scoped>
.container {
background: #f8f8f8;
padding-bottom: calc(140rpx + env(safe-area-inset-bottom));
overflow: hidden;
height: 100vh;
}
.nav-bar {
display: flex;
align-items: center;
height: calc(150rpx + var(--status-bar-height));
padding: 0 32rpx;
padding-top: var(--status-bar-height);
background: #fff;
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 999;
box-sizing: border-box;
.back {
padding: 20rpx;
margin-left: -20rpx;
}
.title {
flex: 1;
text-align: center;
font-size: 34rpx;
font-weight: 500;
color: #222;
}
.right-btns {
display: flex;
align-items: center;
gap: 32rpx;
.more, .target {
font-size: 40rpx;
color: #333;
}
}
}
.content {
padding: 30rpx 0 0 0;
margin-top: calc(150rpx + var(--status-bar-height) + 80rpx);
height: 100%;
display: flex;
flex-direction: column;
overflow: hidden;
box-sizing: border-box;
.page-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 30rpx;
.page-title {
font-size: 34rpx;
font-weight: bold;
}
.view-all {
font-size: 28rpx;
color: #999;
}
}
}
.tabs {
display: flex;
background: #f5f5f5;
border-radius: 8rpx;
margin-bottom: 30rpx;
position: fixed;
top: calc(150rpx + var(--status-bar-height));
left: 0;
width: 100%;
z-index: 998;
box-sizing: border-box;
.tab-item {
flex: 1;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 28rpx;
color: #666;
position: relative;
&.active {
color: #333;
background-color: #e7e7e7;
font-weight: 500;
border-radius: 8rpx;
}
.badge {
position: absolute;
top: 10rpx;
right: 10rpx;
min-width: 32rpx;
height: 32rpx;
line-height: 32rpx;
text-align: center;
background: #ff4d4f;
color: #fff;
border-radius: 16rpx;
font-size: 24rpx;
padding: 0 6rpx;
}
}
}
.order-list {
flex: 1;
min-height: 0;
overflow-y: scroll;
padding-bottom: env(safe-area-inset-bottom);
box-sizing: border-box;
}
.order-card {
background: #fff;
border-radius: 16rpx;
padding: 40rpx;
margin-bottom: 20rpx;
.order-header {
margin-bottom: 20rpx;
.order-id {
font-size: 28rpx;
color: #999;
.order-ids{
font-family: PingFang SC;
font-weight: 600;
font-size: 16px;
line-height: 140%;
letter-spacing: 0%;
color: #333;
}
}
}
.order-content {
display: flex;
align-items: center;
margin-bottom: 20rpx;
flex-direction: row;
justify-content: space-between;
.order-image {
width: 160rpx;
height: 160rpx;
border-radius: 8rpx;
// background-color: #fff8ea;
background: #fffbe6;
padding: 20rpx;
box-sizing: border-box;
display: block;
}
.order-arrow {
padding: 0 30rpx;
color: #999;
}
.order-info {
// flex: 1;
display: flex;
flex-direction: column;
text-align: center;
.order-count {
font-size: 32rpx;
font-weight: 500;
margin-bottom: 10rpx;
background-color: #fffaee;
// display: block;
}
.order-price {
font-size: 28rpx;
color: #666;
margin-bottom: 10rpx;
background-color: #fffaee;
// display: block;
}
.order-estimate {
display: inline-block;
background:#ffac07;
color: #fff;
font-size: 26rpx;
padding: 8rpx 20rpx;
border-radius: 20rpx;
}
}
}
.order-status {
display: flex;
align-items: center;
padding: 20rpx;
background: #f4f4f4;
border-radius: 8rpx;
.status-icon {
width: 80rpx;
height: 80rpx;
margin-right: 20rpx;
}
.status-info {
flex: 1;
.status-text {
font-size: 28rpx;
color: #333;
margin-bottom: 6rpx;
display: block;
}
.status-time {
font-size: 26rpx;
color: #999;
}
}
}
}
.order-loading {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 30rpx 0;
color: #ffac07;
font-size: 28rpx;
}
.loading-text {
margin-top: 10rpx;
color: #ffac07;
font-size: 26rpx;
}
.order-nomore {
text-align: center;
color: #bbb;
font-size: 24rpx;
padding: 20rpx 0 40rpx 0;
}
.nomore-text {
color: #bbb;
font-size: 24rpx;
}
</style>