320 lines
7.7 KiB
Vue
320 lines
7.7 KiB
Vue
|
|
<template>
|
|||
|
|
<view class="dispatch-list-page">
|
|||
|
|
<!-- 页面标题 -->
|
|||
|
|
<view class="page-header">
|
|||
|
|
<text class="page-title">待派单订单</text>
|
|||
|
|
<text class="page-subtitle">选择合适的陪伴员</text>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<!-- 订单列表 -->
|
|||
|
|
<view v-if="orderList.length === 0" class="empty-state">
|
|||
|
|
<text class="empty-icon">📋</text>
|
|||
|
|
<text class="empty-text">暂无待派单订单</text>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<scroll-view v-else class="order-list" scroll-y>
|
|||
|
|
<view
|
|||
|
|
v-for="order in orderList"
|
|||
|
|
:key="order.id"
|
|||
|
|
class="order-card"
|
|||
|
|
>
|
|||
|
|
<view class="order-header">
|
|||
|
|
<text class="order-title">{{ order.serviceName }}</text>
|
|||
|
|
<text class="order-status">待派单</text>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<view class="order-info">
|
|||
|
|
<view class="info-item">
|
|||
|
|
<text class="info-label">服务时间:</text>
|
|||
|
|
<text class="info-value">{{ order.serviceTime }}</text>
|
|||
|
|
</view>
|
|||
|
|
<view class="info-item">
|
|||
|
|
<text class="info-label">服务地址:</text>
|
|||
|
|
<text class="info-value">{{ order.address }}</text>
|
|||
|
|
</view>
|
|||
|
|
<view class="info-item">
|
|||
|
|
<text class="info-label">孩子信息:</text>
|
|||
|
|
<text class="info-value">{{ order.childInfo }}</text>
|
|||
|
|
</view>
|
|||
|
|
<view class="info-item">
|
|||
|
|
<text class="info-label">家长需求:</text>
|
|||
|
|
<text class="info-value">{{ order.requirement }}</text>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<view class="order-footer">
|
|||
|
|
<button class="btn-assign" @click="assignOrder(order)">派单</button>
|
|||
|
|
<button class="btn-detail" @click="viewDetail(order)">详情</button>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</scroll-view>
|
|||
|
|
</view>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script>
|
|||
|
|
import { useUserStore } from '@/store/user'
|
|||
|
|
import { managerApi } from '@/api/index.js'
|
|||
|
|
|
|||
|
|
export default {
|
|||
|
|
data() {
|
|||
|
|
return {
|
|||
|
|
userStore: useUserStore(),
|
|||
|
|
managerId: null,
|
|||
|
|
orderList: [],
|
|||
|
|
loading: false
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
onLoad() {
|
|||
|
|
console.log('[派单管理] 页面加载')
|
|||
|
|
this.initManagerId()
|
|||
|
|
this.loadPendingOrders()
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
onShow() {
|
|||
|
|
console.log('[派单管理] 页面显示,重新加载数据')
|
|||
|
|
this.loadPendingOrders()
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
methods: {
|
|||
|
|
initManagerId() {
|
|||
|
|
const userInfo = this.userStore.userInfo || uni.getStorageSync('userInfo')
|
|||
|
|
if (userInfo) {
|
|||
|
|
this.managerId = userInfo.id || userInfo.userId || userInfo.user_id
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!this.managerId) {
|
|||
|
|
console.warn('[派单管理] 使用默认 managerId: 1')
|
|||
|
|
this.managerId = 1
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
async loadPendingOrders() {
|
|||
|
|
if (this.loading) return
|
|||
|
|
|
|||
|
|
this.loading = true
|
|||
|
|
try {
|
|||
|
|
const params = {
|
|||
|
|
page: 1,
|
|||
|
|
size: 1000,
|
|||
|
|
dispatchStatus: 'pending'
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
console.log('[派单管理] 请求参数:', params)
|
|||
|
|
const res = await managerApi.getWorkOrders(params)
|
|||
|
|
console.log('[派单管理] API响应:', res)
|
|||
|
|
|
|||
|
|
let records = []
|
|||
|
|
if (res) {
|
|||
|
|
if (res.code === 200 && res.data) {
|
|||
|
|
records = res.data.records || []
|
|||
|
|
} else if (res.records) {
|
|||
|
|
records = res.records
|
|||
|
|
} else if (Array.isArray(res)) {
|
|||
|
|
records = res
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
console.log('[派单管理] 解析后的记录数:', records.length)
|
|||
|
|
|
|||
|
|
// 过滤待派单订单
|
|||
|
|
const pendingRecords = records.filter(item => {
|
|||
|
|
return item.status === 0 && item.payStatus === 1 && !item.teacherId
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
console.log('[派单管理] 待派单订单数:', pendingRecords.length)
|
|||
|
|
|
|||
|
|
this.orderList = pendingRecords.map(order => ({
|
|||
|
|
id: order.id,
|
|||
|
|
serviceName: order.title || order.serviceName || '服务订单',
|
|||
|
|
serviceTime: this.formatServiceTime(order),
|
|||
|
|
address: order.serviceAddress || '待确认',
|
|||
|
|
childInfo: this.formatChildInfo(order),
|
|||
|
|
requirement: order.content || order.requirement || '无特殊要求'
|
|||
|
|
}))
|
|||
|
|
|
|||
|
|
console.log('[派单管理] 订单列表加载完成:', this.orderList.length)
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('[派单管理] 加载失败:', error)
|
|||
|
|
uni.showToast({ title: '加载订单失败', icon: 'none' })
|
|||
|
|
} finally {
|
|||
|
|
this.loading = false
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
formatServiceTime(order) {
|
|||
|
|
if (order.serviceDate && order.timeSlot) {
|
|||
|
|
return `${order.serviceDate} ${order.timeSlot}`
|
|||
|
|
}
|
|||
|
|
if (order.createTime) {
|
|||
|
|
return order.createTime
|
|||
|
|
}
|
|||
|
|
return '待确认'
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
formatChildInfo(order) {
|
|||
|
|
if (order.studentName) {
|
|||
|
|
let info = order.studentName
|
|||
|
|
if (order.studentAge) {
|
|||
|
|
info += `,${order.studentAge}岁`
|
|||
|
|
}
|
|||
|
|
if (order.studentGrade) {
|
|||
|
|
info += `,${order.studentGrade}`
|
|||
|
|
}
|
|||
|
|
return info
|
|||
|
|
}
|
|||
|
|
return '待确认'
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
assignOrder(order) {
|
|||
|
|
uni.navigateTo({
|
|||
|
|
url: `/manager-package/pages/manager/assign?orderId=${order.id}`
|
|||
|
|
})
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
viewDetail(order) {
|
|||
|
|
uni.navigateTo({
|
|||
|
|
url: `/manager-package/pages/manager/work-order-detail?id=${order.id}`
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<style lang="scss" scoped>
|
|||
|
|
@import '@/static/css/common.scss';
|
|||
|
|
|
|||
|
|
.dispatch-list-page {
|
|||
|
|
min-height: 100vh;
|
|||
|
|
background: #f8f8f8;
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.page-header {
|
|||
|
|
background: linear-gradient(135deg, $primary-color 0%, $primary-light 100%);
|
|||
|
|
padding: 40rpx 30rpx 30rpx;
|
|||
|
|
text-align: center;
|
|||
|
|
|
|||
|
|
.page-title {
|
|||
|
|
display: block;
|
|||
|
|
font-size: 36rpx;
|
|||
|
|
font-weight: bold;
|
|||
|
|
color: #ffffff;
|
|||
|
|
margin-bottom: 10rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.page-subtitle {
|
|||
|
|
display: block;
|
|||
|
|
font-size: 24rpx;
|
|||
|
|
color: rgba(255, 255, 255, 0.9);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.empty-state {
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
align-items: center;
|
|||
|
|
padding: 120rpx 60rpx;
|
|||
|
|
|
|||
|
|
.empty-icon {
|
|||
|
|
font-size: 120rpx;
|
|||
|
|
margin-bottom: 30rpx;
|
|||
|
|
opacity: 0.3;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.empty-text {
|
|||
|
|
font-size: 30rpx;
|
|||
|
|
color: #999;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.order-list {
|
|||
|
|
flex: 1;
|
|||
|
|
padding: 20rpx 30rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.order-card {
|
|||
|
|
background: #ffffff;
|
|||
|
|
border-radius: 16rpx;
|
|||
|
|
padding: 30rpx;
|
|||
|
|
margin-bottom: 20rpx;
|
|||
|
|
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
|
|||
|
|
|
|||
|
|
.order-header {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
align-items: center;
|
|||
|
|
margin-bottom: 20rpx;
|
|||
|
|
padding-bottom: 20rpx;
|
|||
|
|
border-bottom: 1rpx solid #f0f0f0;
|
|||
|
|
|
|||
|
|
.order-title {
|
|||
|
|
font-size: 32rpx;
|
|||
|
|
font-weight: bold;
|
|||
|
|
color: #333;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.order-status {
|
|||
|
|
padding: 8rpx 20rpx;
|
|||
|
|
background: #fff3cd;
|
|||
|
|
color: #856404;
|
|||
|
|
font-size: 22rpx;
|
|||
|
|
border-radius: 20rpx;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.order-info {
|
|||
|
|
margin-bottom: 20rpx;
|
|||
|
|
|
|||
|
|
.info-item {
|
|||
|
|
display: flex;
|
|||
|
|
margin-bottom: 12rpx;
|
|||
|
|
|
|||
|
|
&:last-child {
|
|||
|
|
margin-bottom: 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.info-label {
|
|||
|
|
width: 160rpx;
|
|||
|
|
font-size: 26rpx;
|
|||
|
|
color: #999;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.info-value {
|
|||
|
|
flex: 1;
|
|||
|
|
font-size: 26rpx;
|
|||
|
|
color: #333;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.order-footer {
|
|||
|
|
display: flex;
|
|||
|
|
gap: 20rpx;
|
|||
|
|
padding-top: 20rpx;
|
|||
|
|
border-top: 1rpx solid #f0f0f0;
|
|||
|
|
|
|||
|
|
.btn-assign {
|
|||
|
|
flex: 1;
|
|||
|
|
height: 70rpx;
|
|||
|
|
background: linear-gradient(135deg, $primary-color 0%, $primary-light 100%);
|
|||
|
|
color: #ffffff;
|
|||
|
|
font-size: 28rpx;
|
|||
|
|
border-radius: 35rpx;
|
|||
|
|
border: none;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.btn-detail {
|
|||
|
|
width: 140rpx;
|
|||
|
|
height: 70rpx;
|
|||
|
|
background: #ffffff;
|
|||
|
|
color: $primary-color;
|
|||
|
|
font-size: 28rpx;
|
|||
|
|
border-radius: 35rpx;
|
|||
|
|
border: 2rpx solid $primary-color;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</style>
|