336 lines
8.3 KiB
Vue
336 lines
8.3 KiB
Vue
<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>
|