<template>
|
<view class="task-detail-container">
|
<view class="detail-header">
|
<view class="back-btn" @click="goBack">
|
<uni-icons type="arrowleft" size="20"></uni-icons>
|
</view>
|
<view class="title">任务详情</view>
|
</view>
|
|
<scroll-view class="detail-content" scroll-y="true" v-if="taskDetail">
|
<view class="detail-section">
|
<view class="section-title">基本信息</view>
|
<view class="info-item">
|
<view class="label">任务编号</view>
|
<view class="value">{{ taskDetail.taskCode }}</view>
|
</view>
|
<view class="info-item">
|
<view class="label">任务类型</view>
|
<view class="value">{{ displayTaskType }}</view>
|
</view>
|
<view class="info-item">
|
<view class="label">任务状态</view>
|
<view class="value status" :class="statusClass">
|
{{ displayTaskStatus }}
|
</view>
|
</view>
|
<view class="info-item">
|
<view class="label">执行车辆</view>
|
<view class="value">{{ getVehicleInfo(taskDetail) }}</view>
|
</view>
|
</view>
|
|
<!-- 执行人员列表 -->
|
<view class="detail-section">
|
<view class="section-title">执行人员</view>
|
<view v-if="taskDetail.assignees && taskDetail.assignees.length > 0" class="assignee-list">
|
<view
|
class="assignee-item"
|
v-for="(assignee, index) in taskDetail.assignees"
|
:key="'assignee-' + (assignee.userId || assignee.userName || index)"
|
>
|
<view class="assignee-index">{{ index + 1 }}</view>
|
<view class="assignee-info">
|
<view class="assignee-name">
|
{{ assignee.userName }}
|
<view v-if="assignee.isPrimary === '1'" class="primary-badge">
|
<uni-icons type="star-filled" size="12" color="#ff9500"></uni-icons>
|
<text>负责人</text>
|
</view>
|
</view>
|
<view class="assignee-role">
|
<view
|
class="role-tag"
|
:class="{
|
'role-driver': assignee.userType === 'driver',
|
'role-doctor': assignee.userType === 'doctor',
|
'role-nurse': assignee.userType === 'nurse'
|
}"
|
>
|
{{ getUserTypeLabel(assignee.userType) }}
|
</view>
|
</view>
|
</view>
|
</view>
|
</view>
|
<view v-else class="empty-assignee">
|
<uni-icons type="info" size="40" color="#ccc"></uni-icons>
|
<text>暂无执行人员</text>
|
</view>
|
</view>
|
|
<view class="detail-section">
|
<view class="section-title">时间信息</view>
|
<view class="info-item">
|
<view class="label">预约时间</view>
|
<view class="value">{{ displayPlannedStartTime }}</view>
|
</view>
|
<view class="info-item" v-if="taskDetail.plannedEndTime">
|
<view class="label">计划结束时间</view>
|
<view class="value">{{ displayPlannedEndTime }}</view>
|
</view>
|
<view class="info-item" v-if="taskDetail.actualStartTime">
|
<view class="label">实际开始时间</view>
|
<view class="value">{{ displayActualStartTime }}</view>
|
</view>
|
<view class="info-item" v-if="taskDetail.actualEndTime">
|
<view class="label">实际结束时间</view>
|
<view class="value">{{ displayActualEndTime }}</view>
|
</view>
|
</view>
|
|
<view class="detail-section">
|
<view class="section-title">位置信息</view>
|
<!-- 转运任务:显示转出/转入医院地址 -->
|
<template v-if="taskDetail.taskType === 'EMERGENCY_TRANSFER' && taskDetail.emergencyInfo">
|
<view class="info-item" v-if="taskDetail.emergencyInfo.hospitalOutAddress">
|
<view class="label">转出医院</view>
|
<view class="value">{{ taskDetail.emergencyInfo.hospitalOutAddress }}</view>
|
</view>
|
<view class="info-item" v-if="taskDetail.emergencyInfo.hospitalInAddress">
|
<view class="label">转入医院</view>
|
<view class="value">{{ taskDetail.emergencyInfo.hospitalInAddress }}</view>
|
</view>
|
</template>
|
<!-- 福祉车任务:显示接送/目的地址 -->
|
<template v-else-if="taskDetail.taskType === 'WELFARE' && taskDetail.welfareInfo">
|
<view class="info-item" v-if="taskDetail.welfareInfo.pickupAddress">
|
<view class="label">接送地址</view>
|
<view class="value">{{ taskDetail.welfareInfo.pickupAddress }}</view>
|
</view>
|
<view class="info-item" v-if="taskDetail.welfareInfo.destinationAddress">
|
<view class="label">目的地址</view>
|
<view class="value">{{ taskDetail.welfareInfo.destinationAddress }}</view>
|
</view>
|
</template>
|
<!-- 其他任务类型:显示通用地址 -->
|
<template v-else>
|
<view class="info-item">
|
<view class="label">出发地</view>
|
<view class="value">{{ getDepartureAddress(taskDetail) }}</view>
|
</view>
|
<view class="info-item">
|
<view class="label">目的地</view>
|
<view class="value">{{ getDestinationAddress(taskDetail) }}</view>
|
</view>
|
</template>
|
<!-- 距离信息:根据任务类型显示不同字段 -->
|
<view class="info-item" v-if="getDistanceInfo(taskDetail)">
|
<view class="label">距离</view>
|
<view class="value">{{ getDistanceInfo(taskDetail) }}公里</view>
|
</view>
|
</view>
|
|
<view class="detail-section" v-if="taskDetail.taskDescription && taskDetail.taskType !== 'EMERGENCY_TRANSFER'">
|
<view class="section-title">任务描述</view>
|
<view class="description">{{ taskDetail.taskDescription }}</view>
|
</view>
|
|
<view class="detail-section" v-if="taskDetail.remark && taskDetail.taskType !== 'EMERGENCY_TRANSFER'">
|
<view class="section-title">备注信息</view>
|
<view class="description">{{ taskDetail.remark }}</view>
|
</view>
|
|
<!-- 转运任务特有信息 -->
|
<view class="detail-section" v-if="taskDetail.taskType === 'EMERGENCY_TRANSFER' && taskDetail.emergencyInfo">
|
<view class="section-title">患者信息</view>
|
<view class="info-item">
|
<view class="label">联系人</view>
|
<view class="value">{{ taskDetail.emergencyInfo.patientContact || '未设置' }}</view>
|
</view>
|
<view class="info-item">
|
<view class="label">患者姓名</view>
|
<view class="value">{{ taskDetail.emergencyInfo.patientName || '未设置' }}</view>
|
</view>
|
<view class="info-item">
|
<view class="label">联系电话</view>
|
<view class="value">{{ taskDetail.emergencyInfo.patientPhone || '未设置' }}</view>
|
</view>
|
<view class="info-item" v-if="taskDetail.emergencyInfo.patientGender">
|
<view class="label">性别</view>
|
<view class="value">{{ taskDetail.emergencyInfo.patientGender === 'male' ? '男' : '女' }}</view>
|
</view>
|
<view class="info-item" v-if="taskDetail.emergencyInfo.patientAge">
|
<view class="label">年龄</view>
|
<view class="value">{{ taskDetail.emergencyInfo.patientAge }}岁</view>
|
</view>
|
<view class="info-item" v-if="taskDetail.emergencyInfo.patientIdCard">
|
<view class="label">身份证号</view>
|
<view class="value">{{ taskDetail.emergencyInfo.patientIdCard }}</view>
|
</view>
|
<view class="info-item" v-if="taskDetail.emergencyInfo.patientCondition">
|
<view class="label">病情描述</view>
|
<view class="value" style="white-space: pre-line;">{{ taskDetail.emergencyInfo.patientCondition }}</view>
|
</view>
|
</view>
|
|
<!-- 转运 - 转出医院信息 -->
|
<view class="detail-section" v-if="taskDetail.taskType === 'EMERGENCY_TRANSFER' && taskDetail.emergencyInfo">
|
<view class="section-title">转出医院信息</view>
|
<view class="info-item" v-if="taskDetail.emergencyInfo.hospitalOutName">
|
<view class="label">医院名称</view>
|
<view class="value">{{ taskDetail.emergencyInfo.hospitalOutName }}</view>
|
</view>
|
<view class="info-item" v-if="taskDetail.emergencyInfo.hospitalOutDepartment">
|
<view class="label">科室</view>
|
<view class="value">{{ taskDetail.emergencyInfo.hospitalOutDepartment }}</view>
|
</view>
|
<view class="info-item" v-if="taskDetail.emergencyInfo.hospitalOutBedNumber">
|
<view class="label">床号</view>
|
<view class="value">{{ taskDetail.emergencyInfo.hospitalOutBedNumber }}</view>
|
</view>
|
<view class="info-item" v-if="taskDetail.emergencyInfo.hospitalOutAddress">
|
<view class="label">医院地址</view>
|
<view class="value">{{ taskDetail.emergencyInfo.hospitalOutAddress }}</view>
|
</view>
|
</view>
|
|
<!-- 转运 - 转入医院信息 -->
|
<view class="detail-section" v-if="taskDetail.taskType === 'EMERGENCY_TRANSFER' && taskDetail.emergencyInfo">
|
<view class="section-title">转入医院信息</view>
|
<view class="info-item" v-if="taskDetail.emergencyInfo.hospitalInName">
|
<view class="label">医院名称</view>
|
<view class="value">{{ taskDetail.emergencyInfo.hospitalInName }}</view>
|
</view>
|
<view class="info-item" v-if="taskDetail.emergencyInfo.hospitalInDepartment">
|
<view class="label">科室</view>
|
<view class="value">{{ taskDetail.emergencyInfo.hospitalInDepartment }}</view>
|
</view>
|
<view class="info-item" v-if="taskDetail.emergencyInfo.hospitalInBedNumber">
|
<view class="label">床号</view>
|
<view class="value">{{ taskDetail.emergencyInfo.hospitalInBedNumber }}</view>
|
</view>
|
<view class="info-item" v-if="taskDetail.emergencyInfo.hospitalInAddress">
|
<view class="label">医院地址</view>
|
<view class="value">{{ taskDetail.emergencyInfo.hospitalInAddress }}</view>
|
</view>
|
</view>
|
|
<!-- 转运 - 费用信息 -->
|
<view class="detail-section" v-if="taskDetail.taskType === 'EMERGENCY_TRANSFER' && taskDetail.emergencyInfo">
|
<view class="section-title">费用信息</view>
|
<view class="info-item" v-if="taskDetail.emergencyInfo.transferDistance">
|
<view class="label">转运公里数</view>
|
<view class="value">{{ taskDetail.emergencyInfo.transferDistance }}公里</view>
|
</view>
|
<view class="info-item" v-if="taskDetail.emergencyInfo.transferPrice">
|
<view class="label">基础费用</view>
|
<view class="value">¥{{ taskDetail.emergencyInfo.transferPrice }}</view>
|
</view>
|
<view class="info-item" v-if="paymentInfo">
|
<view class="label">附加费用</view>
|
<view class="value">¥{{ paymentInfo.additionalAmount || 0 }}</view>
|
</view>
|
<view class="info-item" v-if="paymentInfo">
|
<view class="label">总费用</view>
|
<view class="value" style="color: #e54d42; font-weight: bold;">¥{{ paymentInfo.totalAmount || 0 }}</view>
|
</view>
|
<view class="info-item" v-if="paymentInfo && paymentInfo.paidAmount > 0">
|
<view class="label">已支付</view>
|
<view class="value" style="color: #34C759;">¥{{ paymentInfo.paidAmount }}</view>
|
</view>
|
<view class="info-item" v-if="paymentInfo && paymentInfo.paidAmount > 0">
|
<view class="label">剩余未付</view>
|
<view class="value" style="color: #ff9900; font-weight: bold;">¥{{ getRemainingAmount() }}</view>
|
</view>
|
</view>
|
|
<!-- 支付记录明细 -->
|
<view class="detail-section" v-if="paymentInfo && paymentInfo.paidPayments && paymentInfo.paidPayments.length > 0">
|
<view class="section-title">支付记录</view>
|
<view
|
class="payment-record-item"
|
v-for="(payment, index) in paymentInfo.paidPayments"
|
:key="'payment-' + (payment.id || index)"
|
>
|
<view class="payment-header">
|
<view
|
class="payment-method-tag"
|
:class="[
|
payment.paymentMethod === '1' ? 'method-cash' : '',
|
payment.paymentMethod === '2' ? 'method-bank' : '',
|
payment.paymentMethod === '3' ? 'method-wechat' : '',
|
payment.paymentMethod === '4' ? 'method-alipay' : '',
|
payment.paymentMethod === '5' ? 'method-pos' : '',
|
payment.paymentMethod === '6' ? 'method-account' : '',
|
payment.paymentMethod === '7' ? 'method-yyt' : ''
|
]"
|
>
|
{{ getPaymentMethodLabel(payment.paymentMethod) }}
|
</view>
|
<view class="payment-amount">¥{{ payment.settlementAmount }}</view>
|
</view>
|
<view class="payment-time" v-if="payment.payTime">
|
{{ formatPaymentTime(payment.payTime) }}
|
</view>
|
<view class="payment-remark" v-if="payment.remark">
|
备注:{{ payment.remark }}
|
</view>
|
</view>
|
</view>
|
|
<!-- 附件信息 -->
|
<AttachmentUpload
|
:taskId="taskId"
|
title="任务附件"
|
:readonly="isTaskFinished"
|
@uploaded="onAttachmentUploaded"
|
@deleted="onAttachmentDeleted"
|
/>
|
|
<!-- 福祉车任务特有信息 -->
|
<view class="detail-section" v-if="taskDetail.taskType === 'WELFARE' && taskDetail.welfareInfo">
|
<view class="section-title">乘客信息</view>
|
<view class="info-item" v-if="taskDetail.welfareInfo.passengerContact">
|
<view class="label">联系人</view>
|
<view class="value">{{ taskDetail.welfareInfo.passengerContact }}</view>
|
</view>
|
<view class="info-item" v-if="taskDetail.welfareInfo.passengerPhone">
|
<view class="label">联系电话</view>
|
<view class="value">{{ taskDetail.welfareInfo.passengerPhone }}</view>
|
</view>
|
<view class="info-item" v-if="taskDetail.welfareInfo.passengerName">
|
<view class="label">乘客姓名</view>
|
<view class="value">{{ taskDetail.welfareInfo.passengerName }}</view>
|
</view>
|
<view class="info-item" v-if="taskDetail.welfareInfo.passengerAge">
|
<view class="label">年龄</view>
|
<view class="value">{{ taskDetail.welfareInfo.passengerAge }}岁</view>
|
</view>
|
<view class="info-item" v-if="taskDetail.welfareInfo.passengerGender">
|
<view class="label">性别</view>
|
<view class="value">{{ taskDetail.welfareInfo.passengerGender === 'male' ? '男' : '女' }}</view>
|
</view>
|
<view class="info-item" v-if="taskDetail.welfareInfo.passengerIdCard">
|
<view class="label">身份证号</view>
|
<view class="value">{{ taskDetail.welfareInfo.passengerIdCard }}</view>
|
</view>
|
<view class="info-item" v-if="taskDetail.welfareInfo.specialNeeds">
|
<view class="label">特殊需求</view>
|
<view class="value">{{ taskDetail.welfareInfo.specialNeeds }}</view>
|
</view>
|
</view>
|
|
<!-- 福祉车 - 服务信息 -->
|
<view class="detail-section" v-if="taskDetail.taskType === 'WELFARE' && taskDetail.welfareInfo">
|
<view class="section-title">服务信息</view>
|
<view class="info-item" v-if="taskDetail.welfareInfo.serviceType">
|
<view class="label">服务类型</view>
|
<view class="value">{{ taskDetail.welfareInfo.serviceType }}</view>
|
</view>
|
<view class="info-item" v-if="taskDetail.welfareInfo.pickupAddress">
|
<view class="label">接送地址</view>
|
<view class="value">{{ taskDetail.welfareInfo.pickupAddress }}</view>
|
</view>
|
<view class="info-item" v-if="taskDetail.welfareInfo.destinationAddress">
|
<view class="label">目的地址</view>
|
<view class="value">{{ taskDetail.welfareInfo.destinationAddress }}</view>
|
</view>
|
<view class="info-item" v-if="taskDetail.welfareInfo.serviceDistance">
|
<view class="label">服务公里数</view>
|
<view class="value">{{ taskDetail.welfareInfo.serviceDistance }}公里</view>
|
</view>
|
<view class="info-item" v-if="taskDetail.welfareInfo.servicePrice">
|
<view class="label">服务费用</view>
|
<view class="value">¥{{ taskDetail.welfareInfo.servicePrice }}</view>
|
</view>
|
</view>
|
</scroll-view>
|
|
<view class="loading" v-else>
|
<uni-icons type="spinner-cycle" size="40" color="#007AFF"></uni-icons>
|
<text>加载中...</text>
|
</view>
|
|
<!-- 操作按钮区域 -->
|
<view class="action-buttons" v-if="taskDetail">
|
<!-- 待处理状态: 显示编辑、出发、取消 -->
|
<template v-if="taskDetail.taskStatus === 'PENDING'">
|
<button
|
class="action-btn edit"
|
@click="handleEdit"
|
>
|
修改
|
</button>
|
<button
|
class="action-btn primary"
|
@click="handleTaskAction('depart')"
|
>
|
出发
|
</button>
|
<button
|
class="action-btn cancel"
|
@click="handleTaskAction('cancel')"
|
>
|
取消
|
</button>
|
</template>
|
|
<!-- 出发中状态: 显示编辑、已到达、强制结束 -->
|
<template v-else-if="taskDetail.taskStatus === 'DEPARTING'">
|
<button
|
class="action-btn edit"
|
@click="handleEdit"
|
>
|
修改
|
</button>
|
<button
|
class="action-btn primary"
|
@click="handleTaskAction('arrive')"
|
>
|
已到达
|
</button>
|
<button
|
class="action-btn cancel"
|
@click="handleTaskAction('forceCancel')"
|
>
|
强制结束
|
</button>
|
</template>
|
|
<!-- 已到达状态: 显示编辑、已返程 -->
|
<template v-else-if="taskDetail.taskStatus === 'ARRIVED'">
|
<button
|
class="action-btn edit"
|
@click="handleEdit"
|
>
|
修改
|
</button>
|
<button
|
class="action-btn primary"
|
@click="handleTaskAction('return')"
|
>
|
已返程
|
</button>
|
</template>
|
|
<!-- 返程中状态: 显示编辑、已完成 -->
|
<template v-else-if="taskDetail.taskStatus === 'RETURNING'">
|
<button
|
class="action-btn edit"
|
@click="handleEdit"
|
>
|
修改
|
</button>
|
<button
|
class="action-btn primary"
|
@click="handleTaskAction('complete')"
|
>
|
已完成
|
</button>
|
</template>
|
|
<!-- 已完成/已取消: 不显示按钮,但如果是转运任务则显示结算按钮 -->
|
|
<!-- 转运任务的结算按钮:仅完成/取消状态不显示 -->
|
<button
|
v-if="taskDetail.taskType === 'EMERGENCY_TRANSFER' && !isTaskFinished"
|
class="action-btn settlement"
|
@click="handleSettlement"
|
>
|
结算
|
</button>
|
</view>
|
</view>
|
</template>
|
|
<script>
|
import { getTask, changeTaskStatus } from '@/api/task'
|
import { checkVehicleActiveTasks } from '@/api/task'
|
import { getPaymentInfo } from '@/api/payment'
|
import { formatDateTime } from '@/utils/common'
|
import { validateTaskForDepart, validateTaskForSettlement, getTaskVehicleId, checkTaskCanDepart } from '@/utils/taskValidator'
|
import AttachmentUpload from './components/AttachmentUpload.vue'
|
|
export default {
|
components: {
|
AttachmentUpload
|
},
|
data() {
|
return {
|
taskDetail: null,
|
taskId: null,
|
paymentInfo: null // 支付信息
|
}
|
},
|
computed: {
|
// 判断任务是否已结束(已完成或已取消)
|
isTaskFinished() {
|
if (!this.taskDetail || !this.taskDetail.taskStatus) {
|
return false
|
}
|
return ['COMPLETED', 'CANCELLED'].includes(this.taskDetail.taskStatus)
|
},
|
// 显示任务类型
|
displayTaskType() {
|
if (!this.taskDetail || !this.taskDetail.taskType) {
|
return '未设置'
|
}
|
return this.getTaskTypeText(this.taskDetail.taskType)
|
},
|
// 显示任务状态
|
displayTaskStatus() {
|
if (!this.taskDetail || !this.taskDetail.taskStatus) {
|
return '未设置'
|
}
|
return this.getStatusText(this.taskDetail.taskStatus)
|
},
|
// 状态样式类
|
statusClass() {
|
if (!this.taskDetail || !this.taskDetail.taskStatus) {
|
return ''
|
}
|
const status = this.taskDetail.taskStatus
|
if (status === 'PENDING') return 'pending'
|
if (['DEPARTING', 'ARRIVED', 'RETURNING', 'IN_PROGRESS'].includes(status)) return 'in_progress'
|
if (status === 'COMPLETED') return 'completed'
|
if (status === 'CANCELLED') return 'cancelled'
|
return ''
|
},
|
// 显示计划开始时间
|
displayPlannedStartTime() {
|
if (!this.taskDetail || !this.taskDetail.plannedStartTime) {
|
return '未设置'
|
}
|
const formatted = formatDateTime(this.taskDetail.plannedStartTime, 'YYYY-MM-DD HH:mm')
|
// 如果年份是1900,表示无效日期,显示为未设置
|
if (formatted && formatted.startsWith('1900')) {
|
return '未设置'
|
}
|
return formatted
|
},
|
// 显示计划结束时间
|
displayPlannedEndTime() {
|
if (!this.taskDetail || !this.taskDetail.plannedEndTime) {
|
return '未设置'
|
}
|
const formatted = formatDateTime(this.taskDetail.plannedEndTime, 'YYYY-MM-DD HH:mm')
|
// 如果年份是1900,表示无效日期,显示为未设置
|
if (formatted && formatted.startsWith('1900')) {
|
return '未设置'
|
}
|
return formatted
|
},
|
// 显示实际开始时间
|
displayActualStartTime() {
|
if (!this.taskDetail || !this.taskDetail.actualStartTime) {
|
return '未设置'
|
}
|
const formatted = formatDateTime(this.taskDetail.actualStartTime, 'YYYY-MM-DD HH:mm')
|
// 如果年份是1900,表示无效日期,显示为未设置
|
if (formatted && formatted.startsWith('1900')) {
|
return '未设置'
|
}
|
return formatted
|
},
|
// 显示实际结束时间
|
displayActualEndTime() {
|
if (!this.taskDetail || !this.taskDetail.actualEndTime) {
|
return '未设置'
|
}
|
const formatted = formatDateTime(this.taskDetail.actualEndTime, 'YYYY-MM-DD HH:mm')
|
// 如果年份是1900,表示无效日期,显示为未设置
|
if (formatted && formatted.startsWith('1900')) {
|
return '未设置'
|
}
|
return formatted
|
}
|
},
|
onLoad(options) {
|
this.taskId = options.id
|
this.loadTaskDetail()
|
},
|
onShow() {
|
// 每次页面显示时重新加载数据,确保从编辑页面返回后能看到最新数据
|
if (this.taskId) {
|
this.loadTaskDetail()
|
}
|
},
|
methods: {
|
// 加载任务详情
|
loadTaskDetail() {
|
if (!this.taskId) {
|
this.$modal.showToast('任务ID不能为空')
|
return
|
}
|
|
getTask(this.taskId).then(response => {
|
this.taskDetail = response.data || response
|
// 调试:打印返回的数据
|
// console.log('任务详情完整数据:', JSON.stringify(this.taskDetail, null, 2))
|
// console.log('任务类型字段值:', this.taskDetail.taskType)
|
// console.log('任务状态字段值:', this.taskDetail.taskStatus)
|
// console.log('出发地址:', this.taskDetail.departureAddress)
|
// console.log('目的地址:', this.taskDetail.destinationAddress)
|
// console.log('转运任务信息 (emergencyInfo):', this.taskDetail.emergencyInfo)
|
|
// 如果是转运任务,加载支付信息
|
if (this.taskDetail.taskType === 'EMERGENCY_TRANSFER') {
|
this.loadPaymentInfo()
|
}
|
}).catch(error => {
|
console.error('加载任务详情失败:', error)
|
this.$modal.showToast('加载任务详情失败')
|
})
|
},
|
|
// 加载支付信息
|
loadPaymentInfo() {
|
getPaymentInfo(this.taskId).then(res => {
|
this.paymentInfo = res.data
|
console.log('支付信息:', this.paymentInfo)
|
}).catch(err => {
|
console.error('加载支付信息失败', err)
|
})
|
},
|
|
// 根据支付方式字典值获取显示标签
|
getPaymentMethodLabel(dictValue) {
|
const methodMap = {
|
'1': '现金',
|
'2': '银行转账',
|
'3': '微信支付',
|
'4': '支付宝',
|
'5': 'POS收款',
|
'6': '挂账',
|
'7': '易医通挂账',
|
'8': '退款',
|
'9': '积分'
|
}
|
return methodMap[dictValue] || dictValue
|
},
|
|
// 格式化支付时间
|
formatPaymentTime(time) {
|
if (!time) return '未知'
|
const date = new Date(time)
|
const year = date.getFullYear()
|
const month = String(date.getMonth() + 1).padStart(2, '0')
|
const day = String(date.getDate()).padStart(2, '0')
|
const hour = String(date.getHours()).padStart(2, '0')
|
const minute = String(date.getMinutes()).padStart(2, '0')
|
return `${year}-${month}-${day} ${hour}:${minute}`
|
},
|
|
// 计算剩余未付金额
|
getRemainingAmount() {
|
if (!this.paymentInfo) {
|
return '0.00'
|
}
|
const total = parseFloat(this.paymentInfo.totalAmount || 0)
|
const paid = parseFloat(this.paymentInfo.paidAmount || 0)
|
const remaining = total - paid
|
console.log('总金额:', total.toFixed(2))
|
console.log('已付金额:', paid.toFixed(2))
|
console.log('剩余未付金额:', remaining.toFixed(2))
|
return remaining > 0 ? remaining.toFixed(2) : '0.00'
|
},
|
|
// 获取车辆信息(修复:防止 assignedVehicles 为 null)
|
getVehicleInfo(task) {
|
if (task.assignedVehicles && Array.isArray(task.assignedVehicles) && task.assignedVehicles.length > 0) {
|
const firstVehicle = task.assignedVehicles[0]
|
let vehicleInfo = firstVehicle.vehicleNo || '未知车牌'
|
if (task.assignedVehicles.length > 1) {
|
vehicleInfo += ` 等${task.assignedVehicles.length}辆`
|
}
|
return vehicleInfo
|
}
|
return '未分配车辆'
|
},
|
|
// 获取出发地址
|
getDepartureAddress(task) {
|
// 优先使用departureAddress,如果为空则尝试其他可能的字段
|
return task.departureAddress || task.startAddress || task.startLocation || '未设置'
|
},
|
|
// 获取目的地址
|
getDestinationAddress(task) {
|
// 优先使用destinationAddress,如果为空则尝试其他可能的字段
|
return task.destinationAddress || task.endAddress || task.endLocation || '未设置'
|
},
|
|
// 获取距离信息:根据任务类型返回不同字段
|
getDistanceInfo(task) {
|
// 转运:优先使用transferDistance
|
if (task.taskType === 'EMERGENCY_TRANSFER' && task.emergencyInfo && task.emergencyInfo.transferDistance) {
|
return task.emergencyInfo.transferDistance
|
}
|
// 福祉车:优先使用serviceDistance
|
if (task.taskType === 'WELFARE' && task.welfareInfo && task.welfareInfo.serviceDistance) {
|
return task.welfareInfo.serviceDistance
|
}
|
// 其他任务类型:使用estimatedDistance
|
return task.estimatedDistance || null
|
},
|
|
// 返回上一页
|
goBack() {
|
uni.navigateBack()
|
},
|
|
// 处理编辑按钮
|
handleEdit() {
|
if (!this.taskDetail) {
|
this.$modal.showToast('任务信息不存在')
|
return
|
}
|
|
// 检查任务状态,已完成或已取消的任务不能编辑
|
if (this.isTaskFinished) {
|
this.$modal.showToast('已完成或已取消的任务不能编辑')
|
return
|
}
|
|
const taskType = this.taskDetail.taskType
|
const taskId = this.taskDetail.taskId
|
|
// 根据任务类型跳转到不同的编辑页面
|
if (taskType === 'EMERGENCY_TRANSFER') {
|
// 转运任务:跳转到转运任务编辑页面
|
uni.navigateTo({
|
url: `/pagesTask/edit-emergency?id=${taskId}`
|
})
|
} else if (taskType === 'WELFARE') {
|
// 福祗车任务:跳转到福祗车编辑页面
|
uni.navigateTo({
|
url: `/pagesTask/edit-welfare?id=${taskId}`
|
})
|
} else {
|
// 其他任务:跳转到通用任务编辑页面
|
uni.navigateTo({
|
url: `/pagesTask/edit?id=${taskId}`
|
})
|
}
|
},
|
|
// 获取状态文本
|
getStatusText(status) {
|
const statusMap = {
|
'PENDING': '待处理',
|
'DEPARTING': '出发中',
|
'ARRIVED': '已到达',
|
'RETURNING': '返程中',
|
'COMPLETED': '已完成',
|
'CANCELLED': '已取消',
|
'IN_PROGRESS': '处理中' // 兼容旧数据
|
}
|
return statusMap[status] || '未知'
|
},
|
|
// 获取任务类型文本
|
getTaskTypeText(type) {
|
const typeMap = {
|
'MAINTENANCE': '维修保养',
|
'FUEL': '加油',
|
'OTHER': '其他',
|
'EMERGENCY_TRANSFER': '转运任务',
|
'WELFARE': '福祉车'
|
}
|
return typeMap[type] || '未知类型'
|
},
|
|
// 获取用户类型标签
|
getUserTypeLabel(userType) {
|
const typeMap = {
|
'driver': '司机',
|
'doctor': '医生',
|
'nurse': '护士'
|
}
|
return typeMap[userType] || userType || '未知'
|
},
|
|
// 处理结算
|
handleSettlement() {
|
// 校验任务是否可以结算
|
const validation = validateTaskForSettlement(this.taskDetail)
|
if (!validation.valid) {
|
this.$modal.confirm(`${validation.message},需要先修改任务后才能结算。是否现在去修改?`).then(() => {
|
this.handleEdit()
|
}).catch(() => {})
|
return
|
}
|
|
uni.navigateTo({
|
url: '/pagesTask/settlement?taskId=' + this.taskId
|
})
|
},
|
|
// 处理任务操作
|
handleTaskAction(action) {
|
switch (action) {
|
case 'depart':
|
// 出发 -> 检查车辆是否有其他正在进行中的任务
|
this.checkVehicleAndDepart();
|
break;
|
|
case 'cancel':
|
// 取消 -> 二次确认后状态变为已取消
|
this.$modal.confirm('确定要取消此任务吗?').then(() => {
|
this.updateTaskStatus('CANCELLED', '任务已取消')
|
}).catch(() => {});
|
break;
|
|
case 'arrive':
|
// 已到达 -> 状态变为已到达
|
this.$modal.confirm('确认已到达目的地?').then(() => {
|
this.updateTaskStatus('ARRIVED', '已到达目的地')
|
}).catch(() => {});
|
break;
|
|
case 'forceCancel':
|
// 强制结束 -> 状态变为已取消
|
this.$modal.confirm('确定要强制结束此任务吗?').then(() => {
|
this.updateTaskStatus('CANCELLED', '任务已强制结束')
|
}).catch(() => {});
|
break;
|
|
case 'return':
|
// 已返程 -> 状态变为返程中
|
this.$modal.confirm('确认开始返程?').then(() => {
|
this.updateTaskStatus('RETURNING', '已开始返程')
|
}).catch(() => {});
|
break;
|
|
case 'complete':
|
// 已完成 -> 状态变为已完成
|
this.$modal.confirm('确认任务已完成?').then(() => {
|
this.updateTaskStatus('COMPLETED', '任务已完成')
|
}).catch(() => {});
|
break;
|
}
|
},
|
|
// 检查车辆状态并出发
|
async checkVehicleAndDepart() {
|
// 显示加载提示
|
uni.showLoading({
|
title: '检查任务状态...'
|
});
|
|
try {
|
// 调用工具类检查任务是否可以出发(包含基本校验和冲突检查)
|
const checkResult = await checkTaskCanDepart(this.taskDetail)
|
|
uni.hideLoading();
|
|
console.log('出发检查结果:', checkResult);
|
console.log('valid:', checkResult.valid);
|
console.log('conflicts:', checkResult.conflicts);
|
|
if (!checkResult.valid) {
|
// 校验失败,显示提示信息并提供跳转选项
|
const conflicts = checkResult.conflicts || [];
|
const conflictInfo = conflicts.length > 0 ? conflicts[0] : null;
|
|
console.log('冲突信息:', conflictInfo);
|
|
// 如果有冲突任务信息,提供跳转按钮
|
if (conflictInfo && conflictInfo.taskId) {
|
console.log('显示带跳转按钮的弹窗,任务ID:', conflictInfo.taskId);
|
|
const conflictTaskId = conflictInfo.taskId;
|
const message = checkResult.message || conflictInfo.message || '存在冲突任务';
|
|
uni.showModal({
|
title: '提示',
|
content: message,
|
confirmText: '去处理',
|
cancelText: '知道了',
|
success: function(res) {
|
console.log('弹窗点击结果:', res);
|
if (res.confirm) {
|
// 用户点击"现在去处理",跳转到冲突任务详情页
|
console.log('准备跳转到任务详情页:', conflictTaskId);
|
uni.redirectTo({
|
url: `/pagesTask/detail?id=${conflictTaskId}`
|
});
|
}
|
},
|
fail: function(err) {
|
console.error('显示弹窗失败:', err);
|
}
|
});
|
} else {
|
// 没有冲突任务ID,只显示提示
|
console.log('显示普通提示弹窗');
|
uni.showModal({
|
title: '提示',
|
content: checkResult.message || '任务校验失败',
|
showCancel: false,
|
confirmText: '知道了',
|
fail: function(err) {
|
console.error('显示弹窗失败:', err);
|
}
|
});
|
}
|
return;
|
}
|
|
// 所有检查通过,可以出发
|
this.$modal.confirm('确定要出发吗?').then(() => {
|
this.updateTaskStatus('DEPARTING', '任务已出发')
|
}).catch(() => {});
|
|
} catch (error) {
|
uni.hideLoading();
|
console.error('检查任务状态失败:', error);
|
// 检查失败时,仍然允许出发
|
this.$modal.confirm('检查任务状态失败,是否继续出发?').then(() => {
|
this.updateTaskStatus('DEPARTING', '任务已出发')
|
}).catch(() => {});
|
}
|
},
|
|
// 获取任务车辆ID
|
getVehicleId() {
|
if (!this.taskDetail) {
|
return null;
|
}
|
console.log("taskDetail assignedVehicles",this.taskDetail.assignedVehicles);
|
// 从车辆列表中获取第一个车辆的ID(后端返回的字段名是assignedVehicles)
|
if (this.taskDetail.assignedVehicles && this.taskDetail.assignedVehicles.length > 0) {
|
return this.taskDetail.assignedVehicles[0].vehicleId;
|
}
|
|
// 或者从单个车辆对象获取
|
if (this.taskDetail.vehicleId) {
|
return this.taskDetail.vehicleId;
|
}
|
|
return null;
|
},
|
|
// 更新任务状态
|
updateTaskStatus(status, remark) {
|
// 获取GPS位置信息
|
this.getLocationAndUpdateStatus(status, remark)
|
},
|
|
// 获取位置信息并更新状态
|
getLocationAndUpdateStatus(status, remark) {
|
const that = this
|
|
// 使用uni.getLocation获取GPS位置
|
uni.getLocation({
|
type: 'gcj02', // 返回可以用于uni.openLocation的坐标
|
geocode: true, // 解析地址信息
|
altitude: true, // 高精度定位,包含高度信息
|
success: function(res) {
|
console.log('GPS定位成功:', res)
|
|
const statusData = {
|
taskStatus: status,
|
remark: remark,
|
// GPS位置信息
|
latitude: res.latitude,
|
longitude: res.longitude,
|
locationAddress: res.address ? res.address.street || res.address.poiName || '' : '',
|
locationProvince: res.address ? res.address.province || '' : '',
|
locationCity: res.address ? res.address.city || '' : '',
|
locationDistrict: res.address ? res.address.district || '' : '',
|
gpsAccuracy: res.accuracy,
|
altitude: res.altitude,
|
speed: res.speed,
|
heading: res.direction || res.heading
|
}
|
|
changeTaskStatus(that.taskId, statusData).then(response => {
|
that.$modal.showToast('状态更新成功')
|
// 重新加载任务详情
|
that.loadTaskDetail()
|
}).catch(error => {
|
console.error('更新任务状态失败:', error)
|
that.$modal.showToast('状态更新失败,请重试')
|
})
|
},
|
fail: function(err) {
|
console.error('GPS定位失败:', err)
|
|
// 定位失败时提示用户,但仍然允许更新状态(不带GPS信息)
|
that.$modal.confirm('GPS定位失败,是否继续更新状态?').then(() => {
|
const statusData = {
|
taskStatus: status,
|
remark: remark
|
}
|
|
changeTaskStatus(that.taskId, statusData).then(response => {
|
that.$modal.showToast('状态更新成功')
|
that.loadTaskDetail()
|
}).catch(error => {
|
console.error('更新任务状态失败:', error)
|
that.$modal.showToast('状态更新失败,请重试')
|
})
|
}).catch(() => {
|
// 用户取消操作
|
})
|
}
|
})
|
},
|
|
// 加载附件列表
|
loadAttachmentList() {
|
if (!this.taskId) {
|
return
|
}
|
|
getAttachmentList(this.taskId).then(response => {
|
this.attachmentList = response.data || response || []
|
}).catch(error => {
|
console.error('加载附件列表失败:', error)
|
})
|
},
|
|
// 显示上传对话框
|
showUploadDialog() {
|
this.selectedCategoryIndex = 0
|
this.tempImagePath = null
|
this.$refs.uploadPopup.open()
|
},
|
|
// 关闭上传对话框
|
closeUploadDialog() {
|
this.$refs.uploadPopup.close()
|
},
|
|
// 分类选择变化
|
onCategoryChange(e) {
|
this.selectedCategoryIndex = e.detail.value
|
},
|
|
// 选择图片
|
chooseImage() {
|
const that = this
|
uni.chooseImage({
|
count: 1,
|
sizeType: ['compressed'],
|
sourceType: ['album', 'camera'],
|
success: function(res) {
|
that.tempImagePath = res.tempFilePaths[0]
|
},
|
fail: function(err) {
|
console.error('选择图片失败:', err)
|
that.$modal.showToast('选择图片失败')
|
}
|
})
|
},
|
|
// 确认上传
|
confirmUpload() {
|
if (!this.tempImagePath) {
|
this.$modal.showToast('请先选择图片')
|
return
|
}
|
|
const that = this
|
const category = this.categoryList[this.selectedCategoryIndex].value
|
|
// 微信小程序环境:先获取AccessToken,再上传到微信服务器,最后提交mediaId到后端
|
// #ifdef MP-WEIXIN
|
if (this.isWechatMiniProgram) {
|
uni.showLoading({
|
title: '上传中...'
|
})
|
|
// 第一步:从后端获取AccessToken
|
getWechatAccessToken().then(tokenResponse => {
|
// 接口返回格式:{"msg":"token值","code":200}
|
console.log('获取AccessToken成功:', tokenResponse)
|
const accessToken = tokenResponse.msg || tokenResponse.data || tokenResponse
|
if (!accessToken) {
|
uni.hideLoading()
|
that.$modal.showToast('获取AccessToken失败')
|
console.error('获取AccessToken失败,响应数据:', tokenResponse)
|
return
|
}
|
|
console.log('获取到AccessToken:', accessToken)
|
|
// 第二步:上传到微信服务器
|
const uploadUrl = `https://api.weixin.qq.com/cgi-bin/media/upload?access_token=${accessToken}&type=image`
|
|
uni.uploadFile({
|
url: uploadUrl,
|
filePath: that.tempImagePath,
|
name: 'media',
|
success: function(res) {
|
console.log('微信上传响应:', res)
|
try {
|
const data = JSON.parse(res.data)
|
if (data.media_id) {
|
// 第三步:提交mediaId到后端
|
uploadAttachmentFromWechat(that.taskId, data.media_id, category).then(response => {
|
uni.hideLoading()
|
that.$modal.showToast('上传成功')
|
that.closeUploadDialog()
|
that.loadAttachmentList()
|
}).catch(error => {
|
uni.hideLoading()
|
console.error('提交mediaId失败:', error)
|
that.$modal.showToast('上传失败:' + (error.msg || '请重试'))
|
})
|
} else {
|
uni.hideLoading()
|
const errMsg = data.errmsg || '未知错误'
|
console.error('微信返回错误:', data)
|
that.$modal.showToast('微信上传失败:' + errMsg)
|
}
|
} catch (e) {
|
uni.hideLoading()
|
console.error('解析微信响应失败:', e, res.data)
|
that.$modal.showToast('上传失败:响应解析错误')
|
}
|
},
|
fail: function(err) {
|
uni.hideLoading()
|
console.error('上传到微信失败:', err)
|
that.$modal.showToast('上传失败:' + (err.errMsg || '请检查网络'))
|
}
|
})
|
}).catch(error => {
|
uni.hideLoading()
|
console.error('获取AccessToken失败:', error)
|
that.$modal.showToast('获取AccessToken失败')
|
})
|
return
|
}
|
// #endif
|
|
// 非微信小程序环境:直接上传到后端服务器
|
uni.showLoading({
|
title: '上传中...'
|
})
|
|
uni.uploadFile({
|
url: that.$baseUrl + '/task/attachment/upload/' + that.taskId,
|
filePath: that.tempImagePath,
|
name: 'file',
|
formData: {
|
'category': category
|
},
|
header: {
|
'Authorization': 'Bearer ' + uni.getStorageSync('token')
|
},
|
success: function(uploadRes) {
|
uni.hideLoading()
|
|
if (uploadRes.statusCode === 200) {
|
const result = JSON.parse(uploadRes.data)
|
if (result.code === 200) {
|
that.$modal.showToast('上传成功')
|
that.closeUploadDialog()
|
that.loadAttachmentList()
|
} else {
|
that.$modal.showToast(result.msg || '上传失败')
|
}
|
} else {
|
that.$modal.showToast('上传失败')
|
}
|
},
|
fail: function(err) {
|
uni.hideLoading()
|
console.error('上传失败:', err)
|
that.$modal.showToast('上传失败')
|
}
|
})
|
},
|
|
// 查看附件
|
viewAttachment(item) {
|
// 如果是图片,使用图片预览
|
const imageTypes = ['jpg', 'jpeg', 'png', 'gif', 'bmp']
|
const fileExt = item.fileName.split('.').pop().toLowerCase()
|
|
if (imageTypes.includes(fileExt)) {
|
// 构建图片访问地址
|
// 如果是filePath是完整路径,需要通过下载接口访问
|
const imageUrl = this.$baseUrl + '/task/attachment/download/' + item.attachmentId
|
|
// 微信小程序中预览图片
|
// #ifdef MP-WEIXIN
|
// 微信小程序需要先下载到本地再预览
|
uni.showLoading({ title: '加载中...' })
|
uni.downloadFile({
|
url: imageUrl,
|
success: function(res) {
|
uni.hideLoading()
|
if (res.statusCode === 200) {
|
uni.previewImage({
|
urls: [res.tempFilePath],
|
current: res.tempFilePath
|
})
|
} else {
|
uni.showToast({ title: '加载图片失败', icon: 'none' })
|
}
|
},
|
fail: function() {
|
uni.hideLoading()
|
uni.showToast({ title: '下载失败', icon: 'none' })
|
}
|
})
|
// #endif
|
|
// 非微信小程序环境,直接预览
|
// #ifndef MP-WEIXIN
|
uni.previewImage({
|
urls: [imageUrl],
|
current: imageUrl
|
})
|
// #endif
|
} else {
|
this.$modal.showToast('仅支持预览图片')
|
}
|
},
|
|
// 删除附件
|
deleteAttachment(attachmentId, index) {
|
const that = this
|
this.$modal.confirm('确定要删除该附件吗?').then(() => {
|
deleteAttachment(attachmentId).then(response => {
|
that.$modal.showToast('删除成功')
|
that.attachmentList.splice(index, 1)
|
}).catch(error => {
|
console.error('删除附件失败:', error)
|
that.$modal.showToast('删除失败')
|
})
|
}).catch(() => {})
|
},
|
|
// 获取分类名称
|
getCategoryName(category) {
|
const item = this.categoryList.find(c => c.value === category)
|
return item ? item.label : '未分类'
|
},
|
|
// 格式化时间
|
formatTime(time) {
|
if (!time) return ''
|
return formatDateTime(time, 'YYYY-MM-DD HH:mm')
|
},
|
|
// 格式化文件大小
|
formatFileSize(size) {
|
if (!size) return '0B'
|
if (size < 1024) return size + 'B'
|
if (size < 1024 * 1024) return (size / 1024).toFixed(2) + 'KB'
|
return (size / 1024 / 1024).toFixed(2) + 'MB'
|
},
|
|
// 附件上传成功回调
|
onAttachmentUploaded(response) {
|
console.log('附件上传成功:', response)
|
},
|
|
// 附件删除成功回调
|
onAttachmentDeleted(attachmentId) {
|
console.log('附件删除成功:', attachmentId)
|
}
|
}
|
}
|
</script>
|
|
<style lang="scss">
|
.task-detail-container {
|
background-color: #f5f5f5;
|
min-height: 100vh;
|
|
.detail-header {
|
display: flex;
|
align-items: center;
|
padding: 20rpx;
|
background-color: white;
|
border-bottom: 1rpx solid #f0f0f0;
|
|
.back-btn {
|
width: 60rpx;
|
height: 60rpx;
|
border-radius: 50%;
|
background-color: #f0f0f0;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
margin-right: 20rpx;
|
}
|
|
.title {
|
font-size: 36rpx;
|
font-weight: bold;
|
color: #333;
|
}
|
}
|
|
.detail-content {
|
padding: 20rpx;
|
height: calc(100vh - 220rpx); // 减去header(100rpx)和按钮区域(120rpx)的高度
|
padding-bottom: 20rpx; // 底部留出空间
|
}
|
|
.detail-section {
|
background-color: white;
|
border-radius: 15rpx;
|
padding: 30rpx;
|
margin-bottom: 20rpx;
|
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
|
|
.section-title {
|
font-size: 32rpx;
|
font-weight: bold;
|
margin-bottom: 20rpx;
|
color: #333;
|
border-bottom: 1rpx solid #f0f0f0;
|
padding-bottom: 10rpx;
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
|
.upload-btn {
|
font-size: 24rpx;
|
padding: 8rpx 20rpx;
|
background-color: #007AFF;
|
color: white;
|
border-radius: 8rpx;
|
border: none;
|
}
|
}
|
|
// 执行人员列表样式
|
.assignee-list {
|
.assignee-item {
|
display: flex;
|
align-items: center;
|
padding: 20rpx;
|
margin-bottom: 15rpx;
|
background-color: #f9f9f9;
|
border-radius: 10rpx;
|
|
&:last-child {
|
margin-bottom: 0;
|
}
|
|
.assignee-index {
|
width: 50rpx;
|
height: 50rpx;
|
border-radius: 50%;
|
background-color: #007AFF;
|
color: white;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
font-size: 24rpx;
|
font-weight: bold;
|
margin-right: 20rpx;
|
flex-shrink: 0;
|
}
|
|
.assignee-info {
|
flex: 1;
|
display: flex;
|
flex-direction: column;
|
gap: 10rpx;
|
|
.assignee-name {
|
display: flex;
|
align-items: center;
|
font-size: 30rpx;
|
color: #333;
|
font-weight: 500;
|
|
.primary-badge {
|
display: inline-flex;
|
align-items: center;
|
gap: 4rpx;
|
margin-left: 12rpx;
|
padding: 4rpx 12rpx;
|
background-color: #fff3e0;
|
border-radius: 6rpx;
|
|
text {
|
font-size: 20rpx;
|
color: #ff9500;
|
font-weight: normal;
|
}
|
}
|
}
|
|
.assignee-role {
|
.role-tag {
|
display: inline-block;
|
padding: 4rpx 12rpx;
|
border-radius: 6rpx;
|
font-size: 22rpx;
|
color: white;
|
|
&.role-driver {
|
background-color: #007AFF;
|
}
|
|
&.role-doctor {
|
background-color: #34C759;
|
}
|
|
&.role-nurse {
|
background-color: #AF52DE;
|
}
|
}
|
}
|
}
|
}
|
}
|
|
.empty-assignee {
|
display: flex;
|
flex-direction: column;
|
align-items: center;
|
justify-content: center;
|
padding: 60rpx 0;
|
color: #999;
|
|
text {
|
margin-top: 20rpx;
|
font-size: 28rpx;
|
}
|
}
|
|
.info-item {
|
display: flex;
|
margin-bottom: 20rpx;
|
|
&:last-child {
|
margin-bottom: 0;
|
}
|
|
.label {
|
width: 200rpx;
|
font-size: 28rpx;
|
color: #666;
|
flex-shrink: 0;
|
}
|
|
.value {
|
flex: 1;
|
font-size: 28rpx;
|
color: #333;
|
word-break: break-all;
|
|
&.status {
|
&.pending {
|
color: #ff9500;
|
}
|
&.in_progress {
|
color: #007AFF;
|
}
|
&.completed {
|
color: #34C759;
|
}
|
&.cancelled {
|
color: #ff3b30;
|
}
|
}
|
}
|
}
|
|
.description {
|
font-size: 28rpx;
|
color: #333;
|
line-height: 1.6;
|
background-color: #f9f9f9;
|
padding: 20rpx;
|
border-radius: 10rpx;
|
}
|
}
|
|
// 支付记录样式
|
.payment-record-item {
|
background-color: #f9f9f9;
|
border-radius: 10rpx;
|
padding: 20rpx;
|
margin-bottom: 20rpx;
|
|
&:last-child {
|
margin-bottom: 0;
|
}
|
|
.payment-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
margin-bottom: 15rpx;
|
|
.payment-method-tag {
|
display: inline-block;
|
padding: 6rpx 16rpx;
|
border-radius: 6rpx;
|
font-size: 24rpx;
|
color: white;
|
font-weight: 500;
|
|
&.method-cash {
|
background-color: #34C759;
|
}
|
|
&.method-bank {
|
background-color: #5AC8FA;
|
}
|
|
&.method-wechat {
|
background-color: #09BB07;
|
}
|
|
&.method-alipay {
|
background-color: #1677FF;
|
}
|
|
&.method-pos {
|
background-color: #FF9500;
|
}
|
|
&.method-account {
|
background-color: #FF9500;
|
}
|
|
&.method-yyt {
|
background-color: #AF52DE;
|
}
|
}
|
|
.payment-amount {
|
font-size: 32rpx;
|
font-weight: bold;
|
color: #34C759;
|
}
|
}
|
|
.payment-time {
|
font-size: 24rpx;
|
color: #999;
|
margin-bottom: 10rpx;
|
}
|
|
.payment-remark {
|
font-size: 24rpx;
|
color: #666;
|
line-height: 1.5;
|
}
|
}
|
|
.loading {
|
display: flex;
|
flex-direction: column;
|
align-items: center;
|
justify-content: center;
|
height: 400rpx;
|
color: #999;
|
|
text {
|
margin-top: 20rpx;
|
font-size: 28rpx;
|
}
|
}
|
|
.action-buttons {
|
position: fixed;
|
bottom: 0;
|
left: 0;
|
right: 0;
|
display: flex;
|
padding: 20rpx;
|
background-color: white;
|
box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);
|
|
.action-btn {
|
flex: 1;
|
height: 80rpx;
|
border-radius: 10rpx;
|
font-size: 30rpx;
|
margin: 0 10rpx;
|
background-color: #f0f0f0;
|
color: #333;
|
|
&.edit {
|
background-color: #ff9500;
|
color: white;
|
}
|
|
&.primary {
|
background-color: #007AFF;
|
color: white;
|
}
|
|
&.cancel {
|
background-color: #ff3b30;
|
color: white;
|
}
|
|
&.settlement {
|
background-color: #34C759;
|
color: white;
|
}
|
|
&:first-child {
|
margin-left: 0;
|
}
|
|
&:last-child {
|
margin-right: 0;
|
}
|
}
|
}
|
}
|
</style>
|