Browse Source

’优化包邮城市,主页跳转首页,查看质检详情,订单逻辑优化,关于页面下拉刷新等‘

v1
Lj 2 months ago
parent
commit
fecaae63de
9 changed files with 339 additions and 129 deletions
  1. +5
    -1
      pages/baoyou-city/baoyou-city.vue
  2. +4
    -1
      pages/index/index.vue
  3. +4
    -1
      pages/manager/inspect-result.vue
  4. +6
    -0
      pages/manager/order-detail.vue
  5. +125
    -24
      pages/manager/order.vue
  6. +32
    -18
      pages/subcomponent/about.vue
  7. +35
    -19
      pages/subcomponent/detail.vue
  8. +102
    -49
      pages/subcomponent/order.vue
  9. +26
    -16
      pages/subcomponent/wallet.vue

+ 5
- 1
pages/baoyou-city/baoyou-city.vue View File

@ -12,7 +12,7 @@
</view>
<!-- 蓝色banner卡片 -->
<view class="byc-banner">
<image class="byc-banner-img" src="https://oss.budingxiaoshuo.com/upload/已开通包邮服务的城市-banner_1748252607736.png" mode="widthFix" />
<image class="byc-banner-img" :src="myCityImage" mode="widthFix" />
</view>
<!-- 主内容卡片 -->
<view class="byc-main-card">
@ -76,6 +76,10 @@
const item = getApp().globalData.configData.find(i => i.keyName === 'city_desc')
return item ? item.keyContent : ''
},
myCityImage() {
const item = getApp().globalData.configData.find(i => i.keyName === 'city_banner')
return item ? item.keyContent : ''
},
},
methods: {
goBack() {


+ 4
- 1
pages/index/index.vue View File

@ -115,7 +115,10 @@
// }, 1500);
},
handleCancel() {
uni.navigateBack();
//
uni.reLaunch({
url: '/pages/component/home'
});
},
handleAgreementChange(e) {


+ 4
- 1
pages/manager/inspect-result.vue View File

@ -335,7 +335,10 @@ export default {
this.$api('submitQualityInfo', this.inspectData , res => {
if (res && res.code === 200) {
uni.showToast({ title: '质检完成', icon: 'success' })
uni.navigateBack()
//
uni.reLaunch({
url: '/pages/component/home'
})
}
})


+ 6
- 0
pages/manager/order-detail.vue View File

@ -320,6 +320,12 @@ export default {
}
})
},
goToInspection() {
if (!this.order.id) return;
uni.navigateTo({
url: `/pages/subcomponent/inspection-report?orderId=${this.order.orderId}`
})
},
}
}
</script>


+ 125
- 24
pages/manager/order.vue View File

@ -119,6 +119,28 @@
</view>
</view>
</view>
<!-- 加载状态 -->
<view v-if="isLoading && orderList.length === 0" class="loading-container">
<uni-icons type="spinner-cycle" size="24" color="#999" class="loading-icon" />
<text class="loading-text">加载中...</text>
</view>
<!-- 加载更多状态 -->
<view v-if="loadingMore" class="load-more-container">
<uni-icons type="spinner-cycle" size="20" color="#999" class="loading-icon" />
<text class="load-more-text">加载更多...</text>
</view>
<!-- 到底提示 -->
<view v-if="!hasMore && orderList.length > 0" class="no-more-container">
<text class="no-more-text">已加载全部订单</text>
</view>
<!-- 空状态 -->
<view v-if="!isLoading && orderList.length === 0" class="empty-container">
<text class="empty-text">暂无订单数据</text>
</view>
</view>
</view>
</template>
@ -147,10 +169,12 @@ export default {
searchText: '',
historyOrderMode: false,
pageNo: 1,
pageSize: 3,
pageSize: 10,
hasMore: true,
isLoading: false,
userId: ''
loadingMore: false,
userId: '',
reachBottomTimer: null
}
},
onLoad(options) {
@ -181,23 +205,7 @@ export default {
(order.phone && order.phone.toLowerCase().includes(text))
);
}
const tabValue = this.tabs[this.currentTab].value;
// console.log('tab:', tabValue, 'orderList:', this.orderList);
if (tabValue === -1) return this.orderList;
if (tabValue === 0) {
// status == 1
// console.log(this.orderList.filter(order => order.status == 1),'this.orderList')
return this.orderList.filter(order => order.status == 1);
} else if (tabValue === 1) {
// state == 1
return this.orderList.filter(order => order.status == 2);
} else if (tabValue === 2) {
// status == 3
return this.orderList.filter(order => order.status == 3);
} else if (tabValue === 3) {
// status == 1 && state == 3
return this.orderList.filter(order => order.status == 4);
}
// Tab
return this.orderList;
}
},
@ -211,6 +219,7 @@ export default {
this.hasMore = true
this.orderList = []
this.isLoading = false
this.loadingMore = false
this.fetchOrderList()
},
onSearchIconClick() {
@ -241,11 +250,38 @@ export default {
if (this.isLoading) return
if (isLoadMore && !this.hasMore) return
console.log(isLoadMore,'isLoadMore')
this.isLoading = true
if (isLoadMore) {
this.loadingMore = true
} else {
this.isLoading = true
}
// Tabstatus
const tabValue = this.tabs[this.currentTab].value
let statusParam = 0 //
if (tabValue === -1) {
// status = 0
statusParam = 0
} else if (tabValue === 0) {
// status = 0
statusParam = 1
} else if (tabValue === 1) {
// status = 1
statusParam = 2
} else if (tabValue === 2) {
// status = 2
statusParam = 3
} else if (tabValue === 3) {
// status = 3
statusParam = 4
}
const params = {
pageNo: isLoadMore ? this.pageNo + 1 : 1,
pageSize: this.pageSize,
status: 0
status: statusParam
}
console.log(params,'params')
if (this.userId) {
@ -254,7 +290,16 @@ export default {
this.$api && this.$api('getOrderList', params, res => {
if (res && res.code === 200 && res.result && res.result.records) {
console.log(res.result,'res.result.records')
const newOrders = res.result.records.map(order => {
// state3 status=3state1
const filteredRecords = res.result.records.filter(order => {
// state3
if (order.state === 3) return false
// status=3state1
// if (order.status === 3 && order.state === 1) return false
return true
})
const newOrders = filteredRecords.map(order => {
const statusInfo = this.getOrderStatusInfo(order.status, order.state)
return {
id: order.id,
@ -289,6 +334,16 @@ export default {
this.hasMore = false
}
this.isLoading = false
this.loadingMore = false
}, err => {
console.error('获取订单列表失败:', err)
this.isLoading = false
this.loadingMore = false
this.hasMore = false
uni.showToast({
title: '加载失败,请重试',
icon: 'none'
})
})
},
getOrderStatusInfo(status, state) {
@ -334,7 +389,7 @@ export default {
return actions
},
onLoadMore() {
if (this.hasMore && !this.isLoading) {
if (this.hasMore && !this.isLoading && !this.loadingMore) {
this.fetchOrderList(true)
}
},
@ -366,11 +421,18 @@ export default {
this.hasMore = true;
this.orderList = [];
this.isLoading = false;
this.loadingMore = false;
this.fetchOrderList();
uni.stopPullDownRefresh();
},
onReachBottom() {
this.onLoadMore()
//
if (this.reachBottomTimer) {
clearTimeout(this.reachBottomTimer)
}
this.reachBottomTimer = setTimeout(() => {
this.onLoadMore()
}, 100)
}
}
</script>
@ -613,4 +675,43 @@ export default {
}
}
}
/* 加载状态样式 */
.loading-container, .load-more-container, .no-more-container, .empty-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 40rpx 0;
color: #999;
}
.loading-icon {
animation: spin 1s linear infinite;
margin-bottom: 16rpx;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.loading-text, .load-more-text {
font-size: 28rpx;
color: #999;
}
.no-more-text {
font-size: 26rpx;
color: #ccc;
}
.empty-container {
padding: 120rpx 0;
}
.empty-text {
font-size: 30rpx;
color: #ccc;
}
</style>

+ 32
- 18
pages/subcomponent/about.vue View File

@ -1,14 +1,17 @@
<template>
<view class="about-container">
<!-- 顶部导航栏 -->
<view class="nav-bar" :style="{height: (statusBarHeight + 88) + 'rpx', paddingTop: statusBarHeight + 'px'}">
<view class="nav-bar" :style="{paddingTop: statusBarHeight + 'px'}">
<view class="back" @tap="goBack">
<uni-icons type="left" size="20"></uni-icons>
</view>
<text class="title">关于我们</text>
<text class="nav-title">关于我们</text>
<view class="nav-icons">
<!-- 占位元素保持布局对称 -->
</view>
</view>
<!-- 主卡片 -->
<view class="main-card" :style="{marginTop: (statusBarHeight + 88) + 'rpx'}">
<view class="main-card" :style="{marginTop: 'calc(200rpx )'}">
<!-- 富文本内容 -->
<rich-text :nodes="memberTextContent" class="rich-text-content"></rich-text>
</view>
@ -16,10 +19,7 @@
</template>
<script>
import pullRefreshMixin from '@/pages/mixins/pullRefreshMixin.js'
export default {
mixins: [pullRefreshMixin],
data() {
return {
statusBarHeight: 0
@ -35,14 +35,20 @@ export default {
onLoad() {
this.statusBarHeight = uni.getSystemInfoSync().statusBarHeight
},
onPullDownRefresh() {
//
setTimeout(() => {
uni.stopPullDownRefresh()
uni.showToast({
title: '刷新成功',
icon: 'success',
duration: 2000
})
}, 1000)
},
methods: {
goBack() {
uni.navigateBack();
},
async onRefresh() {
//
await new Promise(resolve => setTimeout(resolve, 1000))
this.stopPullRefresh()
}
}
}
@ -55,20 +61,23 @@ export default {
padding-bottom: 40rpx;
}
.nav-bar {
display: flex;
align-items: center;
height: calc(150rpx + var(--status-bar-height));
padding: 0 32rpx;
background: #fffbe6;
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 999;
display: flex;
align-items: center;
background: #fffbe6;
padding: 0 30rpx;
box-sizing: border-box;
box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.03);
.back {
padding: 20rpx;
margin-left: -20rpx;
}
.title {
.nav-title {
flex: 1;
text-align: center;
font-family: PingFang SC;
@ -81,13 +90,18 @@ export default {
font-weight: 500;
color: #222;
}
.nav-icons {
display: flex;
align-items: center;
gap: 12px;
}
}
.main-card {
background: #ffffff;
border-radius: 36rpx;
box-shadow: 0 8rpx 32rpx rgba(255, 156, 0, 0.08);
margin: 32rpx 24rpx 0 24rpx;
padding: 40rpx 32rpx 32rpx 32rpx;
margin: 0 24rpx 0 24rpx;
padding: 20rpx 32rpx 32rpx 32rpx;
display: flex;
flex-direction: column;
align-items: stretch;


+ 35
- 19
pages/subcomponent/detail.vue View File

@ -18,14 +18,14 @@
v-for="(step, index) in processSteps"
:key="index"
class="step-item"
:class="{ cancel: currentStep === 0 && index === 1 }"
:class="{ cancel: state === 3 && index === status }"
>
<image :src="step.icon" mode="aspectFit" class="step-icon"></image>
<view
class="step-label"
:class="{
active: currentStep === index + 1,
cancel: currentStep === 0 && index === 1
active: status === index && state !== 3,
cancel: state === 3 && index === status
}"
>
<view class="step-label-inner">
@ -41,25 +41,25 @@
<view class="status-info" v-if="currentStatus">
<image class="status-icon" :src="currentStatus.icon" mode="aspectFit"></image>
<view class="status-detail">
<text class="status-text" v-if="currentStep === 0">已取消本次预约</text>
<text class="status-text" v-if="state === 3">已取消本次预约</text>
<text class="status-text" v-else>{{ currentStatus.text }}</text>
<text class="status-time">{{ currentStatus.time }}</text>
</view>
</view>
<!-- 取消后提示语 -->
<view v-if="currentStep === 0" class="cancel-tip">期待您下次的支持共同为地球减少碳排放出一份力</view>
<!-- 物流公司currentStep为12时显示 -->
<view class="express-info" v-if="currentStep !== 0 && currentStep < 3">
<view v-if="state === 3" class="cancel-tip">期待您下次的支持共同为地球减少碳排放出一份力</view>
<!-- 物流公司status为01时显示 -->
<view class="express-info" v-if="state !== 3 && status <= 1">
<text class="express-label">物流公司</text>
<view class="express-row">
<text class="express-value">{{ expressCompany }}{{ expressNo }}</text>
<text class="express-copy" @tap="copyExpressNo">复制</text>
</view>
</view>
<view class="info-divider" v-if="currentStep !== 0 && currentStep < 4"></view>
<view class="info-divider" v-if="state !== 3 && status < 3"></view>
<!-- 地址信息仅非取消和非结款时显示 -->
<view class="pickup-info" v-if="currentStep !== 0 && currentStep < 4">
<view class="pickup-info" v-if="state !== 3 && status < 3">
<view class="info-item" @tap="viewAddress">
<text class="label">取件地址</text>
<view class="value">
@ -86,13 +86,13 @@
<text class="order-value">{{ orderDetail && orderDetail.ordeNo ? orderDetail.ordeNo : orderId }}</text>
</view>
<view class="order-divider"></view>
<template v-if="currentStep < 3">
<template v-if="status < 2">
<view class="order-row">
<text class="order-label">预估回收</text>
<text class="order-value order-highlight">¥ {{ estimatePrice }}</text>
</view>
</template>
<template v-else-if="currentStep === 4">
<template v-else-if="status === 3">
<view class="order-row">
<text class="order-label">合格结算</text>
<text class="order-value order-highlight">¥ {{ finalPrice }}</text>
@ -125,7 +125,7 @@
</view>
<!-- 质检结果卡片仅结款状态显示 -->
<view class="order-detail-card" v-if="currentStep === 4">
<view class="order-detail-card" v-if="status === 3">
<text class="order-title">质检结果</text>
<view class="order-row"><text class="order-label">质检数量</text><text class="order-value">9 </text></view>
<view class="order-row"><text class="order-label">质检合格</text><text class="order-value">7 </text></view>
@ -137,7 +137,7 @@
</view>
<!-- 详细信息卡片仅结款状态显示 -->
<view class="order-detail-card detail-info-card" v-if="currentStep === 4">
<view class="order-detail-card detail-info-card" v-if="status === 3">
<text class="order-title">详细信息</text>
<view class="order-row">
<text class="order-label">预约时间</text>
@ -150,8 +150,8 @@
</view>
</view>
<!-- 底部按钮待取件时显示 -->
<view class="bottom-btns" v-if="currentStatus.text === '【待取件】快递员正在赶来'">
<!-- 底部按钮在线预约时显示 -->
<view class="bottom-btns" v-if="status === 0 && state !== 3">
<button class="btn cancel-btn" @tap="showCancelModal = true">取消订单</button>
<button class="btn contact-btn" @tap="contactCourier">联系快递员</button>
</view>
@ -199,22 +199,24 @@ export default {
expressNo: '',
showCancelModal: false,
statusBarHeight: 0,
orderDetail: null
orderDetail: null,
status: null, // 0:线 1: 2: 3:
state: null // 0 1 2 3
}
},
computed: {
timeLabel() {
//
if (this.currentStep === 4) {
if (this.status === 3) {
return '回收到账时间'
} else if (this.currentStep === 3) {
} else if (this.status === 2) {
return '质检完成时间'
} else {
return '上门时间'
}
},
showEstimate() {
return this.currentStep < 3
return this.status < 2
}
},
methods: {
@ -328,6 +330,10 @@ export default {
if (res && res.code === 200) {
console.log('res', res)
uni.showToast({ title: '订单已取消', icon: 'none' });
//
this.fetchOrderDetail(this.orderId);
//
uni.$emit('orderStatusChanged');
}
})
// uni.showToast({ title: '', icon: 'none' });
@ -355,6 +361,9 @@ export default {
this.$api && this.$api('getOrderDetail', { orderId }, res => {
if (res && res.code === 200 && res.result) {
this.orderDetail = res.result
//
this.status = res.result.status
this.state = res.result.state
//
this.address = res.result.address + (res.result.addressDetail || '')
this.appointmentTime = res.result.goTime || ''
@ -634,15 +643,22 @@ letter-spacing: 0%;
height: 60rpx;
margin-right: 16rpx;
}
.status-detail {
display: flex;
flex-direction: column;
flex: 1;
}
.status-text {
font-size: 28rpx;
color: #222;
font-weight: bold;
display: block;
}
.status-time {
font-size: 24rpx;
color: #999;
margin-top: 4rpx;
display: block;
}
.pickup-info .info-item {
display: flex;


+ 102
- 49
pages/subcomponent/order.vue View File

@ -34,6 +34,9 @@
scroll-y
class="order-list"
@scrolltolower="loadMore"
refresher-enabled
:refresher-triggered="refresherTriggered"
@refresherrefresh="onRefresherRefresh"
>
<view
v-for="order in orderList"
@ -86,10 +89,7 @@
</template>
<script>
import pullRefreshMixin from '@/pages/mixins/pullRefreshMixin.js'
export default {
mixins: [pullRefreshMixin],
data() {
return {
tabs: [
@ -102,63 +102,82 @@ export default {
loading: false,
page: 1,
pageSize: 10,
hasMore: true
hasMore: true,
refresherTriggered: false
}
},
created() {
this.fetchOrderList()
//
uni.$on('orderStatusChanged', this.handleOrderStatusChanged)
},
onShow() {
this.fetchOrderList()
},
onPullDownRefresh() {
//
this.refreshData()
},
onUnload() {
//
uni.$off('orderStatusChanged', this.handleOrderStatusChanged)
},
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) {
try {
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', { status, pageSize: this.pageSize, current: this.page }, res => {
this.$api('getOrderListPage', { 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)
allOrders = res.result.records
if (isLoadMore) {
this.orderList = this.orderList.concat(allOrders)
} else {
this.orderList = allOrders
}
this.hasMore = allOrders.length === this.pageSize
}
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
//
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.hasMore = allOrders.length === this.pageSize
} catch (error) {
console.error('获取订单列表失败:', error)
} finally {
this.loading = false
}
this.loading = false
},
switchTab(index) {
if (this.currentTab === index) return
@ -179,11 +198,7 @@ export default {
if (status == 3 && state == 2) return '【已结款】平台已结款至账户'
return ''
},
async onRefresh() {
//
await new Promise(resolve => setTimeout(resolve, 1000))
uni.stopPullRefresh()
},
goBack() {
uni.navigateBack()
},
@ -206,7 +221,45 @@ export default {
uni.navigateTo({
url: `/pages/subcomponent/detail?id=${order.id}`
})
}
},
//
handleOrderStatusChanged() {
//
this.page = 1
this.hasMore = true
this.orderList = []
this.fetchOrderList()
},
// scroll-view
onRefresherRefresh() {
this.refreshData()
},
//
async refreshData() {
this.refresherTriggered = true
this.page = 1
this.hasMore = true
this.orderList = []
try {
await this.fetchOrderList()
uni.showToast({
title: '刷新成功',
icon: 'success',
duration: 1000
})
} catch (error) {
uni.showToast({
title: '刷新失败',
icon: 'none'
})
} finally {
setTimeout(() => {
this.refresherTriggered = false
uni.stopPullDownRefresh()
}, 1000)
}
}
}
}
</script>


+ 26
- 16
pages/subcomponent/wallet.vue View File

@ -10,10 +10,15 @@
<!-- banner -->
<view class="banner"
:style="{ marginTop: (statusBarHeight + 88) + 'rpx', height: (bannerBaseHeight + statusBarHeight + 88) + 'rpx' }">
<image class="banner-bg" :src="image" mode="aspectFill"></image>
<!-- <view class="banner-content">
<image class="wallet-icon" src="/static/wallet/wallet-3d.png" mode="aspectFit"></image>
</view> -->
<swiper :indicator-dots="false" :autoplay="true" :interval="3000" :duration="500" circular
style="width: 100%; height: 100%;">
<swiper-item v-for="(item, index) in bannerList" :key="item.id || index">
<video v-if="item.type == 1" :src="item.voUrl" autoplay muted loop :controls="false"
:show-play-btn="false" :show-center-play-btn="false" object-fit="cover"
style="width: 100%; height: 100%;"></video>
<image v-else :src="item.image" mode="aspectFill" style="width: 100%; height: 100%;" />
</swiper-item>
</swiper>
</view>
<!-- 账户余额 -->
@ -118,15 +123,11 @@ export default {
loadingMore: false,
noMore: false,
refreshing: false,
isInitialized: false
isInitialized: false,
bannerList: []
}
},
computed: {
image() {
// console.log(getApp().globalData.bannerList,'getApp().globalData.bannerList')
const item = getApp().globalData.bannerList.find(i => i.title === '我的-轮播图')
return item ? item.image : ''
},
},
onLoad() {
this.statusBarHeight = uni.getSystemInfoSync().statusBarHeight
@ -138,12 +139,26 @@ export default {
onReachBottom(){
this.loadMore()
},
onUnload() {
uni.$off('bannerListUpdated')
},
methods: {
async initData() {
this.getBannerList()
await this.getUserInfo()
await this.loadRecords()
},
getBannerList() {
//
this.bannerList = getApp().globalData.bannerList || []
//
uni.$on('bannerListUpdated', () => {
this.bannerList = getApp().globalData.bannerList || []
})
},
async getUserInfo() {
try {
const res = await api('getUserByToken')
@ -382,12 +397,7 @@ export default {
margin-top: 0;
}
.banner-bg {
position: absolute;
width: 100%;
height: 100%;
// opacity: 0.8;
}
.banner-content {
position: relative;


Loading…
Cancel
Save