433 lines
9.7 KiB
Plaintext
433 lines
9.7 KiB
Plaintext
<template>
|
|
<view class="tasks-container">
|
|
<!-- 顶部导航栏 -->
|
|
<view class="page-header">
|
|
<!-- 左上角:返回主页按钮 -->
|
|
<view class="nav-left" @click="goBackToHome">
|
|
<text class="nav-icon">←</text>
|
|
<text class="nav-title">返回</text>
|
|
</view>
|
|
|
|
<!-- 页面标题居中 -->
|
|
<text class="page-title">{{ getTitle() }}</text>
|
|
|
|
<!-- 右上角留空 -->
|
|
<view class="nav-right"></view>
|
|
</view>
|
|
|
|
<!-- 任务列表 -->
|
|
<view class="tasks-list">
|
|
<view v-if="taskList.length > 0" class="task-item" v-for="task in taskList" :key="task.id" @click="viewTaskDetail(task.id)">
|
|
<view class="task-header">
|
|
<text class="task-id">订单: {{ task.order_id.slice(-6) }}</text>
|
|
<text class="task-status" :class="'status-' + task.status">{{ getTaskStatusText(task.status) }}</text>
|
|
</view>
|
|
<view class="task-info">
|
|
<text class="info-item">取货: {{ getAddressText(task.pickup_address) }}</text>
|
|
<text class="info-item">距离: {{ task.distance }}km</text>
|
|
</view>
|
|
<view class="task-actions">
|
|
<button class="action-btn" @click.stop="contactCustomer(task)">联系客户</button>
|
|
<button class="action-btn primary" @click.stop="viewTaskDetail(task.id)">查看详情</button>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 无数据时显示 -->
|
|
<view v-else class="no-data">
|
|
<text class="no-data-text">暂无{{ getTitle() }}任务</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 加载更多按钮 -->
|
|
<view v-if="hasMore" class="load-more">
|
|
<button @click="loadMoreTasks" class="load-more-btn">加载更多</button>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script setup lang="uts">
|
|
import { ref, onMounted, computed } from 'vue'
|
|
import type { DeliveryTaskType } from '@/types/mall-types'
|
|
|
|
// 响应式数据
|
|
const taskList = ref([] as Array<DeliveryTaskType>)
|
|
const currentPage = ref(1)
|
|
const pageSize = ref(10)
|
|
const hasMore = ref(true)
|
|
const currentType = ref('all') // 默认全部任务
|
|
|
|
// 生命周期
|
|
onMounted(() => {
|
|
// 获取 URL 参数
|
|
const query = uni.getLaunchOptionsSync().query
|
|
currentType.value = query.type || 'all'
|
|
|
|
loadTasks()
|
|
})
|
|
|
|
// 方法
|
|
function loadTasks() {
|
|
// 模拟加载任务数据
|
|
const mockTasks = [
|
|
{
|
|
id: 'task001',
|
|
order_id: 'ORD20250122001',
|
|
driver_id: 'driver001',
|
|
pickup_address: { address: '深圳市南山区科技园南区深圳湾科技生态园' },
|
|
delivery_address: { address: '深圳市南山区蛇口海上世界广场' },
|
|
distance: 8.2,
|
|
estimated_time: 25,
|
|
delivery_fee: 12.0,
|
|
status: 3, // 配送中
|
|
pickup_time: '2025-01-22 14:30:00',
|
|
delivered_time: null,
|
|
delivery_code: 'DEL001',
|
|
remark: '联系电话: 13800138000',
|
|
created_at: '2025-01-22 14:00:00',
|
|
updated_at: '2025-01-22 14:35:00'
|
|
},
|
|
{
|
|
id: 'task002',
|
|
order_id: 'ORD20250122002',
|
|
driver_id: 'driver001',
|
|
pickup_address: { address: '深圳市南山区海岸城' },
|
|
delivery_address: { address: '深圳市南山区欢乐颂广场' },
|
|
distance: 3.5,
|
|
estimated_time: 12,
|
|
delivery_fee: 8.0,
|
|
status: 4, // 已完成
|
|
pickup_time: '2025-01-22 13:00:00',
|
|
delivered_time: '2025-01-22 13:15:00',
|
|
delivery_code: 'DEL002',
|
|
remark: '',
|
|
created_at: '2025-01-22 12:45:00',
|
|
updated_at: '2025-01-22 13:15:00'
|
|
},
|
|
{
|
|
id: 'task003',
|
|
order_id: 'ORD20250122003',
|
|
driver_id: 'driver001',
|
|
pickup_address: { address: '深圳市南山区世界之窗' },
|
|
delivery_address: { address: '深圳市南山区欢乐谷' },
|
|
distance: 2.1,
|
|
estimated_time: 8,
|
|
delivery_fee: 6.5,
|
|
status: 4, // 已完成
|
|
pickup_time: '2025-01-22 11:30:00',
|
|
delivered_time: '2025-01-22 11:40:00',
|
|
delivery_code: 'DEL003',
|
|
remark: '',
|
|
created_at: '2025-01-22 11:15:00',
|
|
updated_at: '2025-01-22 11:40:00'
|
|
},
|
|
{
|
|
id: 'task004',
|
|
order_id: 'ORD20250122004',
|
|
driver_id: 'driver001',
|
|
pickup_address: { address: '深圳市南山区万象天地' },
|
|
delivery_address: { address: '深圳市南山区深圳湾体育中心' },
|
|
distance: 5.8,
|
|
estimated_time: 18,
|
|
delivery_fee: 9.5,
|
|
status: 4, // 已完成
|
|
pickup_time: '2025-01-22 10:00:00',
|
|
delivered_time: '2025-01-22 10:20:00',
|
|
delivery_code: 'DEL004',
|
|
remark: '',
|
|
created_at: '2025-01-22 09:45:00',
|
|
updated_at: '2025-01-22 10:20:00'
|
|
},
|
|
{
|
|
id: 'task005',
|
|
order_id: 'ORD20250122005',
|
|
driver_id: 'driver001',
|
|
pickup_address: { address: '深圳市南山区科技园' },
|
|
delivery_address: { address: '深圳市南山区腾讯大厦' },
|
|
distance: 1.5,
|
|
estimated_time: 5,
|
|
delivery_fee: 5.0,
|
|
status: 1, // 待接单
|
|
pickup_time: null,
|
|
delivered_time: null,
|
|
delivery_code: 'DEL005',
|
|
remark: '',
|
|
created_at: '2025-01-22 09:00:00',
|
|
updated_at: '2025-01-22 09:00:00'
|
|
}
|
|
]
|
|
|
|
// 根据 type 筛选数据
|
|
let filteredTasks = mockTasks
|
|
|
|
if (currentType.value === 'pending') {
|
|
filteredTasks = mockTasks.filter(task => task.status === 1)
|
|
} else if (currentType.value === 'ongoing') {
|
|
filteredTasks = mockTasks.filter(task => task.status === 3)
|
|
} else if (currentType.value === 'completed') {
|
|
filteredTasks = mockTasks.filter(task => task.status === 4)
|
|
}
|
|
|
|
// 分页
|
|
const start = (currentPage.value - 1) * pageSize.value
|
|
const end = start + pageSize.value
|
|
const newTasks = filteredTasks.slice(start, end)
|
|
|
|
taskList.value.push(...newTasks)
|
|
hasMore.value = newTasks.length === pageSize.value
|
|
}
|
|
|
|
function loadMoreTasks() {
|
|
currentPage.value++
|
|
loadTasks()
|
|
}
|
|
|
|
function getTitle(): string {
|
|
switch (currentType.value) {
|
|
case 'all':
|
|
return '全部任务'
|
|
case 'pending':
|
|
return '待接单'
|
|
case 'ongoing':
|
|
return '配送中'
|
|
case 'completed':
|
|
return '已完成'
|
|
default:
|
|
return '任务列表'
|
|
}
|
|
}
|
|
|
|
function getTaskStatusText(status: number): string {
|
|
const statusMap = {
|
|
1: '待接单',
|
|
2: '已接单',
|
|
3: '配送中',
|
|
4: '已完成',
|
|
5: '已取消'
|
|
}
|
|
return statusMap[status] || '未知'
|
|
}
|
|
|
|
function getAddressText(address: UTSJSONObject): string {
|
|
return address['address'] as string || '地址信息'
|
|
}
|
|
|
|
function contactCustomer(task: DeliveryTaskType) {
|
|
uni.showActionSheet({
|
|
itemList: ['拨打电话', '发送短信'],
|
|
success: (res) => {
|
|
if (res.tapIndex === 0) {
|
|
uni.makePhoneCall({
|
|
phoneNumber: '13800138000'
|
|
})
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
function viewTaskDetail(taskId: string) {
|
|
uni.navigateTo({
|
|
url: `/pages/mall/delivery/task-detail?id=${taskId}`
|
|
})
|
|
}
|
|
|
|
// 返回上一页
|
|
function goBackToHome() {
|
|
uni.reLaunch({
|
|
url: '/pages/mall/delivery/profile'
|
|
})
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.tasks-container {
|
|
background-color: #f5f5f5;
|
|
min-height: 100vh;
|
|
padding: 20rpx 30rpx;
|
|
}
|
|
|
|
/* 导航栏样式 */
|
|
.page-header {
|
|
background-color: #fff;
|
|
padding: 20rpx 30rpx;
|
|
border-bottom: 1rpx solid #e9ecef;
|
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
|
|
position: relative;
|
|
min-height: 80rpx;
|
|
}
|
|
|
|
.nav-left {
|
|
position: absolute;
|
|
top: 20rpx;
|
|
left: 30rpx;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
cursor: pointer;
|
|
padding: 10rpx;
|
|
border-radius: 8rpx;
|
|
transition: background-color 0.2s ease;
|
|
}
|
|
|
|
.nav-left:hover {
|
|
background-color: #f0f0f0;
|
|
}
|
|
|
|
.nav-left:active {
|
|
background-color: #e0e0e0;
|
|
}
|
|
|
|
.nav-icon {
|
|
font-size: 36rpx;
|
|
color: #333;
|
|
margin-bottom: 5rpx;
|
|
}
|
|
|
|
.nav-title {
|
|
font-size: 28rpx;
|
|
color: #333;
|
|
font-weight: 500;
|
|
text-align: center;
|
|
}
|
|
|
|
.page-title {
|
|
font-size: 32rpx;
|
|
font-weight: bold;
|
|
color: #333;
|
|
text-align: center;
|
|
margin-top: 20rpx;
|
|
}
|
|
|
|
.nav-right {
|
|
width: 1rpx;
|
|
height: 1rpx;
|
|
}
|
|
|
|
/* 任务列表 */
|
|
.tasks-list {
|
|
margin-top: 20rpx;
|
|
}
|
|
|
|
.task-item {
|
|
background-color: #fff;
|
|
border-radius: 16rpx;
|
|
padding: 20rpx;
|
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
|
|
border-left: 6rpx solid #74b9ff;
|
|
margin-bottom: 20rpx;
|
|
}
|
|
|
|
.task-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 15rpx;
|
|
}
|
|
|
|
.task-id {
|
|
font-size: 28rpx;
|
|
font-weight: 500;
|
|
color: #333;
|
|
}
|
|
|
|
.task-status {
|
|
font-size: 22rpx;
|
|
padding: 6rpx 12rpx;
|
|
border-radius: 20rpx;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.status-1 {
|
|
background: #ffeb3b;
|
|
color: #333;
|
|
}
|
|
|
|
.status-3 {
|
|
background: #2196f3;
|
|
color: white;
|
|
}
|
|
|
|
.status-4 {
|
|
background: #4caf50;
|
|
color: white;
|
|
}
|
|
|
|
.task-info {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
flex-wrap: wrap;
|
|
gap: 10rpx;
|
|
font-size: 24rpx;
|
|
color: #666;
|
|
margin-bottom: 15rpx;
|
|
padding-bottom: 10rpx;
|
|
border-bottom: 1rpx solid #f0f0f0;
|
|
}
|
|
|
|
.info-item {
|
|
flex: 1 1 45%;
|
|
min-width: 120rpx;
|
|
word-break: break-all;
|
|
}
|
|
|
|
.task-actions {
|
|
display: flex;
|
|
gap: 20rpx;
|
|
}
|
|
|
|
.action-btn {
|
|
flex: 1;
|
|
height: 80rpx;
|
|
border-radius: 8rpx;
|
|
font-size: 28rpx;
|
|
border: none;
|
|
font-weight: bold;
|
|
padding: 0 10rpx;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.action-btn:hover {
|
|
background-color: #45a049; /* 按钮悬停效果 */
|
|
}
|
|
|
|
.action-btn:active {
|
|
background-color: #3d8b40; /* 按钮点击效果 */
|
|
}
|
|
|
|
.no-data {
|
|
text-align: center;
|
|
padding: 80rpx 30rpx;
|
|
border-radius: 16rpx;
|
|
background-color: #fff;
|
|
}
|
|
|
|
.no-data-text {
|
|
font-size: 32rpx;
|
|
color: #999;
|
|
margin-bottom: 15rpx;
|
|
}
|
|
|
|
.load-more {
|
|
text-align: center;
|
|
margin-top: 20rpx;
|
|
}
|
|
|
|
.load-more-btn {
|
|
background-color: #4CAF50;
|
|
color: #fff;
|
|
border: none;
|
|
border-radius: 8rpx;
|
|
padding: 20rpx 40rpx;
|
|
font-size: 28rpx;
|
|
font-weight: bold;
|
|
cursor: pointer;
|
|
transition: background-color 0.2s ease;
|
|
}
|
|
|
|
.load-more-btn:hover {
|
|
background-color: #45a049;
|
|
}
|
|
|
|
.load-more-btn:active {
|
|
background-color: #3d8b40;
|
|
}
|
|
</style> |