|
|
@@ -3,25 +3,21 @@
|
|
|
<!-- 统计banner:圆角浮动卡,左右30rpx边距 -->
|
|
|
<view class="stats-banner">
|
|
|
<view class="banner-item">
|
|
|
- <text class="banner-num">2546</text>
|
|
|
+ <text class="banner-num">{{ stats.total }}</text>
|
|
|
<text class="banner-label">累计接单</text>
|
|
|
</view>
|
|
|
<view class="banner-item">
|
|
|
- <text class="banner-num">10</text>
|
|
|
+ <text class="banner-num">{{ stats.reject }}</text>
|
|
|
<text class="banner-label">累计拒单</text>
|
|
|
</view>
|
|
|
<view class="banner-item">
|
|
|
- <text class="banner-num">10</text>
|
|
|
+ <text class="banner-num">{{ stats.reward }}</text>
|
|
|
<text class="banner-label">奖励单量</text>
|
|
|
</view>
|
|
|
<view class="banner-item">
|
|
|
- <text class="banner-num">10</text>
|
|
|
+ <text class="banner-num">{{ stats.punish }}</text>
|
|
|
<text class="banner-label">惩罚单量</text>
|
|
|
</view>
|
|
|
- <view class="banner-item">
|
|
|
- <text class="banner-num">158<text class="banner-unit">天</text></text>
|
|
|
- <text class="banner-label">服务时长</text>
|
|
|
- </view>
|
|
|
</view>
|
|
|
|
|
|
<!-- 标签页(全宽,无圆角,紧贴屏幕宽度) -->
|
|
|
@@ -39,7 +35,7 @@
|
|
|
</view>
|
|
|
|
|
|
<!-- 订单列表:每张卡片用margin左右各30rpx,与banner宽度对齐 -->
|
|
|
- <scroll-view scroll-y class="order-scroll">
|
|
|
+ <scroll-view scroll-y class="order-scroll" @scrolltolower="onReachBottom">
|
|
|
<view style="height: 16rpx;"></view>
|
|
|
|
|
|
<view
|
|
|
@@ -108,64 +104,146 @@
|
|
|
</view>
|
|
|
|
|
|
<!-- 空状态 -->
|
|
|
- <view class="empty-state" v-if="filteredOrders.length === 0">
|
|
|
+ <view class="empty-state" v-if="filteredOrders.length === 0 && !loading">
|
|
|
<text class="empty-text">暂无相关订单</text>
|
|
|
</view>
|
|
|
+
|
|
|
+ <view class="loading-more" v-if="loading">
|
|
|
+ <text>加载中...</text>
|
|
|
+ </view>
|
|
|
+
|
|
|
<view style="height: 40rpx;"></view>
|
|
|
</scroll-view>
|
|
|
</view>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
+import { getOrderStats, getStatisticOrders } from '@/api/fulfiller';
|
|
|
+import { getServiceList } from '@/api/service';
|
|
|
+
|
|
|
export default {
|
|
|
data() {
|
|
|
return {
|
|
|
tabs: ['全部', '已完成', '已拒绝'],
|
|
|
activeTab: 0,
|
|
|
- orders: [
|
|
|
- {
|
|
|
- orderType: 1,
|
|
|
- typeName: '接送', typeIcon: '/static/icons/car.svg',
|
|
|
- status: '完成', finishTime: '2026/02/03 14:30', serviceTime: '2026/02/10 10:00',
|
|
|
- petName: '哈士奇宝宝', petBreed: '哈士奇', petAvatar: '/static/dog.png', price: '20.00',
|
|
|
- startName: '武汉大学宠物店', startAddr: '武汉市洪山区珞喻路458号',
|
|
|
- endName: '张** 189****8451', endAddr: '武汉市武昌区新区大道凤凰广场A座', serviceNote: ''
|
|
|
- },
|
|
|
- {
|
|
|
- orderType: 2,
|
|
|
- typeName: '喂遛', typeIcon: '/static/icons/walk.svg',
|
|
|
- status: '完成', finishTime: '2026/02/03 15:00', serviceTime: '2026/02/11 14:00',
|
|
|
- petName: '金毛', petBreed: '金毛寻回犬', petAvatar: '/static/dog.png', price: '35.00',
|
|
|
- startName: '', startAddr: '',
|
|
|
- endName: '王女士 138****1234', endAddr: '武汉市江汉区泛海国际居住区', serviceNote: '需自带牵引绳,遛弯30分钟。'
|
|
|
- },
|
|
|
- {
|
|
|
- orderType: 3,
|
|
|
- typeName: '洗护', typeIcon: '/static/icons/wash.svg',
|
|
|
- status: '拒绝', finishTime: '2026/02/03 09:30', serviceTime: '2026/02/12 09:30',
|
|
|
- petName: 'Mimi', petBreed: '布偶猫', petAvatar: '/static/dog.png', price: '50.00',
|
|
|
- startName: '', startAddr: '',
|
|
|
- endName: '赵先生 159****9876', endAddr: '武汉市汉阳区钟家村', serviceNote: '上门洗澡,剪指甲。'
|
|
|
- }
|
|
|
- ]
|
|
|
+ stats: {
|
|
|
+ total: 0,
|
|
|
+ reject: 0,
|
|
|
+ reward: 0,
|
|
|
+ punish: 0
|
|
|
+ },
|
|
|
+ orders: [],
|
|
|
+ serviceList: [],
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ total: 0,
|
|
|
+ loading: false
|
|
|
};
|
|
|
},
|
|
|
computed: {
|
|
|
filteredOrders() {
|
|
|
- if (this.activeTab === 0) return this.orders;
|
|
|
- if (this.activeTab === 1) return this.orders.filter(o => o.status === '完成');
|
|
|
- return this.orders.filter(o => o.status === '拒绝');
|
|
|
+ return this.orders;
|
|
|
}
|
|
|
},
|
|
|
+ async onLoad() {
|
|
|
+ await this.loadServiceList();
|
|
|
+ this.fetchStats();
|
|
|
+ this.fetchOrders(true);
|
|
|
+ },
|
|
|
methods: {
|
|
|
- switchTab(idx) { this.activeTab = idx; }
|
|
|
+ async loadServiceList() {
|
|
|
+ try {
|
|
|
+ const res = await getServiceList();
|
|
|
+ this.serviceList = res.data || [];
|
|
|
+ } catch (err) {
|
|
|
+ console.error('获取服务类型失败:', err);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ async fetchStats() {
|
|
|
+ try {
|
|
|
+ const res = await getOrderStats();
|
|
|
+ if (res.code === 200 && res.data) {
|
|
|
+ this.stats = {
|
|
|
+ ...this.stats,
|
|
|
+ ...res.data
|
|
|
+ };
|
|
|
+ }
|
|
|
+ } catch (err) {
|
|
|
+ console.error('获取统计值失败:', err);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ async fetchOrders(reset = false) {
|
|
|
+ if (reset) {
|
|
|
+ this.pageNum = 1;
|
|
|
+ this.orders = [];
|
|
|
+ }
|
|
|
+ if (this.loading) return;
|
|
|
+ if (!reset && this.orders.length >= this.total && this.total !== 0) return;
|
|
|
+
|
|
|
+ this.loading = true;
|
|
|
+ try {
|
|
|
+ const statusMap = { 0: undefined, 1: 4, 2: 5 };
|
|
|
+ const params = {
|
|
|
+ status: statusMap[this.activeTab],
|
|
|
+ pageNum: this.pageNum,
|
|
|
+ pageSize: this.pageSize
|
|
|
+ };
|
|
|
+ const res = await getStatisticOrders(params);
|
|
|
+ if (res.code === 200) {
|
|
|
+ this.total = res.total || 0;
|
|
|
+ const rows = res.rows || [];
|
|
|
+ const mapped = rows.map(item => this.transformOrder(item));
|
|
|
+ this.orders = this.orders.concat(mapped);
|
|
|
+ this.pageNum++;
|
|
|
+ }
|
|
|
+ } catch (err) {
|
|
|
+ console.error('获取订单列表失败:', err);
|
|
|
+ } finally {
|
|
|
+ this.loading = false;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ transformOrder(order) {
|
|
|
+ const service = this.serviceList.find(s => s.id === order.service);
|
|
|
+ const mode = service?.mode || 0;
|
|
|
+ const isRoundTrip = mode === 1;
|
|
|
+ const isSuccess = order.status === 4;
|
|
|
+
|
|
|
+ return {
|
|
|
+ id: order.id,
|
|
|
+ orderType: isRoundTrip ? 1 : 2,
|
|
|
+ typeName: service?.name || '未知',
|
|
|
+ typeIcon: service?.iconUrl || '',
|
|
|
+ status: isSuccess ? '完成' : '拒绝',
|
|
|
+ finishTime: order.serviceTime || '',
|
|
|
+ serviceTime: order.serviceTime || '',
|
|
|
+ petName: order.petName || '未知',
|
|
|
+ petBreed: order.breed || '未知',
|
|
|
+ petAvatar: order.petAvatarUrl || '/static/dog.png',
|
|
|
+ price: (order.price / 100).toFixed(2),
|
|
|
+ startName: order.fromAddress || '',
|
|
|
+ startAddr: order.fromAddress || '',
|
|
|
+ endName: (order.customerName || '') + ' ' + (order.customerPhone || ''),
|
|
|
+ endAddr: order.toAddress || '',
|
|
|
+ serviceNote: order.remark || ''
|
|
|
+ };
|
|
|
+ },
|
|
|
+ switchTab(idx) {
|
|
|
+ this.activeTab = idx;
|
|
|
+ this.fetchOrders(true);
|
|
|
+ },
|
|
|
+ onReachBottom() {
|
|
|
+ this.fetchOrders();
|
|
|
+ },
|
|
|
+ navBack() {
|
|
|
+ uni.navigateBack();
|
|
|
+ }
|
|
|
}
|
|
|
};
|
|
|
</script>
|
|
|
|
|
|
<style>
|
|
|
page { background-color: #F7F8FA; }
|
|
|
-.container { min-height: 100vh; background-color: #F7F8FA; padding: 20rpx 0 0; }
|
|
|
+.container { min-height: 100vh; background-color: #F7F8FA; padding: 20rpx 0 0; display: flex; flex-direction: column; }
|
|
|
|
|
|
/* ===== 统计banner:圆角浮动卡,左右30rpx边距 ===== */
|
|
|
.stats-banner {
|
|
|
@@ -176,6 +254,7 @@ page { background-color: #F7F8FA; }
|
|
|
margin: 0 30rpx 20rpx;
|
|
|
border-radius: 20rpx;
|
|
|
box-shadow: 0 6rpx 20rpx rgba(255, 87, 34, 0.25);
|
|
|
+ flex-shrink: 0;
|
|
|
}
|
|
|
|
|
|
.banner-item { display: flex; flex-direction: column; align-items: center; }
|
|
|
@@ -190,6 +269,7 @@ page { background-color: #F7F8FA; }
|
|
|
padding: 0 30rpx;
|
|
|
border-bottom: 1rpx solid #f0f0f0;
|
|
|
margin-bottom: 0;
|
|
|
+ flex-shrink: 0;
|
|
|
}
|
|
|
|
|
|
.tab-item {
|
|
|
@@ -216,14 +296,13 @@ page { background-color: #F7F8FA; }
|
|
|
}
|
|
|
|
|
|
/* ===== 订单列表:scroll-view 全宽,每张card用margin左右30rpx ===== */
|
|
|
-.order-scroll { width: 100%; }
|
|
|
+.order-scroll { flex: 1; height: 0; width: 100%; }
|
|
|
|
|
|
-/* 关键:order-card 用 margin: 0 30rpx 实现与banner对齐 */
|
|
|
.order-card {
|
|
|
background-color: #fff;
|
|
|
border-radius: 16rpx;
|
|
|
padding: 24rpx;
|
|
|
- margin: 0 30rpx 16rpx; /* ← 与banner的 margin: 0 30rpx 完全一致 */
|
|
|
+ margin: 0 30rpx 16rpx;
|
|
|
box-sizing: border-box;
|
|
|
}
|
|
|
|
|
|
@@ -237,7 +316,6 @@ page { background-color: #F7F8FA; }
|
|
|
|
|
|
.type-badge { display: flex; align-items: center; }
|
|
|
|
|
|
-/* 订单类型图标:与my-orders列表一致,直接使用带色彩的SVG图标 */
|
|
|
.type-icon {
|
|
|
width: 44rpx;
|
|
|
height: 44rpx;
|
|
|
@@ -327,4 +405,6 @@ page { background-color: #F7F8FA; }
|
|
|
/* 空状态 */
|
|
|
.empty-state { text-align: center; padding: 80rpx 0; }
|
|
|
.empty-text { font-size: 28rpx; color: #ccc; }
|
|
|
+
|
|
|
+.loading-more { text-align: center; padding: 20rpx; font-size: 24rpx; color: #999; }
|
|
|
</style>
|