peixue-dev/peidu/uniapp/manager-package/pages/manager/work-order-detail.vue

336 lines
8.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="container">
<view class="detail-card">
<view class="card-header">
<text class="order-no">工单号{{ detail.id }}</text>
<view class="status" :class="'status-' + detail.status">
{{ getStatusText(detail.status) }}
</view>
</view>
<!-- 订单信息 -->
<view class="section">
<view class="section-title">订单信息</view>
<view class="info-row">
<text class="label">订单号</text>
<text class="value">{{ detail.orderNo }}</text>
</view>
<view class="info-row">
<text class="label">服务名称</text>
<text class="value">{{ detail.serviceName }}</text>
</view>
<view class="info-row">
<text class="label">订单金额</text>
<text class="value price">¥{{ detail.totalAmount }}</text>
</view>
</view>
<!-- 陪伴员信息 -->
<view class="section">
<view class="section-title">陪伴员信息</view>
<view class="teacher-info">
<image :src="detail.teacherAvatar || '/static/images/avatar.png'" mode="aspectFill" />
<view class="teacher-detail">
<text class="teacher-name">{{ detail.teacherName }}</text>
<text class="teacher-phone">{{ detail.teacherPhone }}</text>
</view>
</view>
</view>
<!-- 服务信息 -->
<view class="section">
<view class="section-title">服务信息</view>
<view class="info-row">
<text class="label">服务时间</text>
<text class="value">{{ detail.serviceDate }} {{ detail.timeSlot }}</text>
</view>
<view class="info-row">
<text class="label">服务地址</text>
<text class="value">{{ detail.serviceAddress }}</text>
</view>
<view class="info-row" v-if="detail.serviceRequirement">
<text class="label">服务要求</text>
<text class="value">{{ detail.serviceRequirement }}</text>
</view>
</view>
<!-- 签到记录 -->
<view class="section" v-if="detail.checkInTime">
<view class="section-title">签到记录</view>
<view class="info-row">
<text class="label">签到时间</text>
<text class="value">{{ formatTime(detail.checkInTime) }}</text>
</view>
<view class="info-row" v-if="detail.checkOutTime">
<text class="label">签退时间</text>
<text class="value">{{ formatTime(detail.checkOutTime) }}</text>
</view>
<view class="info-row" v-if="detail.actualDuration">
<text class="label">实际时长</text>
<text class="value">{{ detail.actualDuration }}小时</text>
</view>
</view>
<!-- 反馈信息 -->
<view class="section" v-if="detail.teacherFeedback || detail.managerRemark">
<view class="section-title">反馈信息</view>
<view class="info-row" v-if="detail.teacherFeedback">
<text class="label">陪伴员反馈:</text>
<text class="value">{{ detail.teacherFeedback }}</text>
</view>
<view class="info-row" v-if="detail.managerRemark">
<text class="label">管理师备注:</text>
<text class="value">{{ detail.managerRemark }}</text>
</view>
</view>
<!-- 时间信息 -->
<view class="section">
<view class="section-title">时间信息</view>
<view class="info-row">
<text class="label">创建时间:</text>
<text class="value">{{ formatTime(detail.createTime) }}</text>
</view>
<view class="info-row" v-if="detail.completeTime">
<text class="label">完成时间:</text>
<text class="value">{{ formatTime(detail.completeTime) }}</text>
</view>
</view>
</view>
<!-- 底部操作按钮 -->
<view class="bottom-bar" v-if="detail.status === 0 || detail.status === 1">
<button v-if="detail.status === 0" class="btn-action" @click="reassign">重新派单</button>
<button v-if="detail.status === 1" class="btn-action primary" @click="complete">完成工单</button>
</view>
</view>
</template>
<script>
import { managerApi } from '@/api/index.js'
export default {
data() {
return {
workOrderId: null,
detail: {}
}
},
onLoad(options) {
this.workOrderId = options.id
this.loadDetail()
},
methods: {
async loadDetail() {
try {
const res = await managerApi.getWorkOrderDetail(this.workOrderId)
this.detail = res
} catch (error) {
uni.showToast({ title: '加载失败', icon: 'none' })
}
},
reassign() {
uni.navigateTo({
url: `/pages/manager/assign?orderId=${this.detail.orderId}&workOrderId=${this.workOrderId}`
})
},
complete() {
const self = this
uni.showModal({
title: '确认完成',
content: '确认完成该工单吗?',
success: (res) => {
if (res.confirm) {
managerApi.updateWorkOrderStatus({
workOrderId: self.workOrderId,
status: 2,
remark: '工单已完成'
}).then(() => {
uni.showToast({ title: '操作成功', icon: 'success' })
setTimeout(() => {
uni.navigateBack()
}, 1500)
}).catch(error => {
uni.showToast({ title: '操作失败', icon: 'none' })
})
}
}
})
},
formatTime(time) {
if (!time) return ''
return time.replace('T', ' ').substring(0, 16)
},
getStatusText(status) {
const statusMap = {
0: '待派单',
1: '已派单',
2: '待服务',
3: '服务中',
4: '已完成',
'-1': '已取消',
'-2': '已退款'
}
return statusMap[status] || '未知'
}
}
}
</script>
<style lang="scss" scoped>
.container {
min-height: 100vh;
background: #f8f8f8;
padding: 20rpx 30rpx 120rpx;
}
.detail-card {
background: #fff;
border-radius: 16rpx;
padding: 30rpx;
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 30rpx;
padding-bottom: 30rpx;
border-bottom: 1rpx solid #f0f0f0;
.order-no {
font-size: 28rpx;
color: #666;
}
.status {
padding: 8rpx 20rpx;
border-radius: 20rpx;
font-size: 24rpx;
&.status-0 {
background: #fff7e6;
color: #fa8c16;
}
&.status-1 {
background: #e6f7ff;
color: #1890ff;
}
&.status-2 {
background: #f6ffed;
color: #52c41a;
}
&.status-3 {
background: #f5f5f5;
color: #999;
}
}
}
}
.section {
margin-bottom: 30rpx;
&:last-child {
margin-bottom: 0;
}
.section-title {
font-size: 30rpx;
font-weight: bold;
color: #333;
margin-bottom: 20rpx;
padding-left: 20rpx;
border-left: 6rpx solid #667eea;
}
.info-row {
display: flex;
margin-bottom: 16rpx;
font-size: 28rpx;
line-height: 1.6;
&:last-child {
margin-bottom: 0;
}
.label {
color: #999;
min-width: 180rpx;
}
.value {
flex: 1;
color: #333;
&.price {
color: #ff6b6b;
font-weight: bold;
}
}
}
}
.teacher-info {
display: flex;
align-items: center;
image {
width: 100rpx;
height: 100rpx;
border-radius: 50rpx;
margin-right: 20rpx;
}
.teacher-detail {
flex: 1;
.teacher-name {
display: block;
font-size: 30rpx;
font-weight: bold;
color: #333;
margin-bottom: 12rpx;
}
.teacher-phone {
font-size: 26rpx;
color: #666;
}
}
}
.bottom-bar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding: 20rpx 30rpx;
background: #fff;
border-top: 1rpx solid #eee;
display: flex;
gap: 20rpx;
.btn-action {
flex: 1;
height: 88rpx;
background: #f0f0f0;
color: #666;
border: none;
border-radius: 44rpx;
font-size: 32rpx;
&.primary {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: #fff;
}
}
}
</style>