wlzboy
2026-03-19 c5ac97682e3b4ca748541ace97cb37a2295bd81e
app/pagesTask/detail.vue
@@ -5,6 +5,10 @@
        <uni-icons type="arrowleft" size="20"></uni-icons>
      </view>
      <view class="title">任务详情</view>
      <view class="edit-btn" @click="handleEdit" v-if="taskDetail && !isTaskFinished">
        <uni-icons type="compose" size="20" color="#007AFF"></uni-icons>
        <text class="edit-text">修改</text>
      </view>
    </view>
    
    <scroll-view class="detail-content" scroll-y="true" v-if="taskDetail">
@@ -12,7 +16,11 @@
        <view class="section-title">基本信息</view>
        <view class="info-item">
          <view class="label">任务编号</view>
          <view class="value">{{ taskDetail.taskCode }}</view>
          <view class="value">
            {{ taskDetail.showTaskCode }}
            <text v-if="taskDetail.emergencyInfo && taskDetail.emergencyInfo.serviceOrdVip === '1'" class="vip-tag">VIP</text>
            <text v-if="taskDetail.emergencyInfo && taskDetail.emergencyInfo.fromHq2Is === '1'" class="hq-tag">广总</text>
          </view>
        </view>
        <view class="info-item">
          <view class="label">任务类型</view>
@@ -37,7 +45,7 @@
          <view 
            class="assignee-item" 
            v-for="(assignee, index) in taskDetail.assignees" 
            :key="assignee.userId || index"
            :key="getAssigneeKey(assignee, index)"
          >
            <view class="assignee-index">{{ index + 1 }}</view>
            <view class="assignee-info">
@@ -51,15 +59,26 @@
              <view class="assignee-role">
                <view 
                  class="role-tag"
                  :class="{
                    'role-driver': assignee.userType === 'driver',
                    'role-doctor': assignee.userType === 'doctor',
                    'role-nurse': assignee.userType === 'nurse'
                  }"
                >
                  :class="{'role-driver': assignee.userType === 'driver','role-doctor': assignee.userType === 'doctor','role-nurse': assignee.userType === 'nurse'}">
                  {{ getUserTypeLabel(assignee.userType) }}
                </view>
                <view
                  class="ready-badge"
                  :class="{'ready': isAssigneeReady(assignee),'unready': !isAssigneeReady(assignee)}">
                  {{ isAssigneeReady(assignee) ? '已就绪' : '未就绪' }}
                </view>
              </view>
            </view>
            <!-- 当前登录人是该执行人且未就绪时显示就绪按钮 -->
            <view
              v-if="showAssigneeReadyFeature() && isAssigneeSelf(assignee) && !isAssigneeReady(assignee) && taskDetail.taskStatus === TaskStatus.PENDING"
              class="assignee-ready-btn"
              :data-user-id="assignee.userId || assignee.oaUserId"
              :data-user-name="assignee.userName"
              :data-index="index"
              @click="handleReadyClick"
            >
              点击就绪
            </view>
          </view>
        </view>
@@ -93,13 +112,13 @@
        <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="info-item" v-if="taskDetail.emergencyInfo.hospitalOutName">
            <view class="label">转出医院</view>
            <view class="value">{{ taskDetail.emergencyInfo.hospitalOutAddress }}</view>
            <view class="value">{{ taskDetail.emergencyInfo.hospitalOutName }}</view>
          </view>
          <view class="info-item" v-if="taskDetail.emergencyInfo.hospitalInAddress">
          <view class="info-item" v-if="taskDetail.emergencyInfo.hospitalInName">
            <view class="label">转入医院</view>
            <view class="value">{{ taskDetail.emergencyInfo.hospitalInAddress }}</view>
            <view class="value">{{ taskDetail.emergencyInfo.hospitalInName }}</view>
          </view>
        </template>
        <!-- 福祉车任务:显示接送/目的地址 -->
@@ -131,12 +150,12 @@
        </view>
      </view>
      
      <view class="detail-section" v-if="taskDetail.taskDescription">
      <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">
      <view class="detail-section" v-if="taskDetail.remark && taskDetail.taskType !== 'EMERGENCY_TRANSFER'">
        <view class="section-title">备注信息</view>
        <view class="description">{{ taskDetail.remark }}</view>
      </view>
@@ -218,7 +237,17 @@
      
      <!-- 转运 - 费用信息 -->
      <view class="detail-section" v-if="taskDetail.taskType === 'EMERGENCY_TRANSFER' && taskDetail.emergencyInfo">
        <view class="section-title">费用信息</view>
        <view class="section-title">
          费用信息
          <!-- 已完成且未申请发票时显示申请发票按钮 -->
          <button
            v-if="canApplyInvoice"
            class="apply-invoice-btn"
            @click="handleApplyInvoice"
          >
            <text class="cuIcon-form"></text> 申请发票
          </button>
        </view>
        <view class="info-item" v-if="taskDetail.emergencyInfo.transferDistance">
          <view class="label">转运公里数</view>
          <view class="value">{{ taskDetail.emergencyInfo.transferDistance }}公里</view>
@@ -245,13 +274,30 @@
        </view>
      </view>
      
      <!-- 取消信息(仅在任务已取消且有取消原因时显示) -->
      <view class="detail-section" v-if="taskDetail.taskStatus === TaskStatus.CANCELLED && taskDetail.emergencyInfo && taskDetail.emergencyInfo.cancelReason">
        <view class="section-title">取消信息</view>
        <view class="info-item">
          <view class="label">取消原因</view>
          <view class="value">{{ getCancelReasonLabel(taskDetail.emergencyInfo.cancelReason) }}</view>
        </view>
        <view class="info-item" v-if="taskDetail.emergencyInfo.cancelBy">
          <view class="label">取消人</view>
          <view class="value">{{ taskDetail.emergencyInfo.cancelBy }}</view>
        </view>
        <view class="info-item" v-if="taskDetail.emergencyInfo.cancelTime">
          <view class="label">取消时间</view>
          <view class="value">{{ formatTime(taskDetail.emergencyInfo.cancelTime) }}</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 in paymentInfo.paidPayments"
          :key="payment.id"
          v-for="(payment, index) in paymentInfo.paidPayments"
          :key="getPaymentKey(payment, index)"
        >
          <view class="payment-header">
            <view 
@@ -352,19 +398,82 @@
      <text>加载中...</text>
    </view>
    
    <!-- 强制完成对话框 -->
    <uni-popup ref="forceCompletePopup" type="center" :is-mask-click="false">
      <view class="force-complete-dialog">
        <view class="dialog-title">请输入时间</view>
        <view class="time-picker-item">
          <view class="time-label">转运开始时间</view>
          <picker
            mode="date"
            :value="getDateFromDateTime(forceCompleteForm.actualStartTime)"
            @change="selectStartDate"
          >
            <view class="picker-value">{{ getDateFromDateTime(forceCompleteForm.actualStartTime) || '请选择日期' }}</view>
          </picker>
          <picker
            mode="time"
            :value="getTimeFromDateTime(forceCompleteForm.actualStartTime)"
            @change="selectStartTime"
          >
            <view class="picker-value">{{ getTimeFromDateTime(forceCompleteForm.actualStartTime) || '请选择时间' }}</view>
          </picker>
        </view>
        <view class="time-picker-item">
          <view class="time-label">转运结束时间</view>
          <picker
            mode="date"
            :value="getDateFromDateTime(forceCompleteForm.actualEndTime)"
            @change="selectEndDate"
          >
            <view class="picker-value">{{ getDateFromDateTime(forceCompleteForm.actualEndTime) || '请选择日期' }}</view>
          </picker>
          <picker
            mode="time"
            :value="getTimeFromDateTime(forceCompleteForm.actualEndTime)"
            @change="selectEndTime"
          >
            <view class="picker-value">{{ getTimeFromDateTime(forceCompleteForm.actualEndTime) || '请选择时间' }}</view>
          </picker>
        </view>
        <view class="dialog-buttons">
          <button class="cancel-btn" @click="closeForceCompleteDialog">取消</button>
          <button class="confirm-btn" @click="confirmForceComplete">确定</button>
        </view>
      </view>
    </uni-popup>
    <!-- 取消原因选择对话框 -->
    <uni-popup ref="cancelPopup" type="center" :is-mask-click="false">
      <view class="cancel-dialog">
        <view class="dialog-title">请选择取消原因</view>
        <picker mode="selector" :range="cancelReasonList" range-key="label" @change="selectCancelReason">
          <view class="reason-picker">
            <view class="picker-label">取消原因</view>
            <view class="picker-value">
              {{ selectedCancelReasonLabel }}
            </view>
            <uni-icons type="arrowright" size="16"></uni-icons>
          </view>
        </picker>
        <view class="dialog-buttons">
          <button class="cancel-btn" @click="closeCancelDialog">取消</button>
          <button class="confirm-btn" @click="confirmCancelTask">确定</button>
        </view>
      </view>
    </uni-popup>
    <!-- 操作按钮区域 -->
    <view class="action-buttons" v-if="taskDetail">
      <!-- 待处理状态: 显示编辑、出发、取消 -->
      <template v-if="taskDetail.taskStatus === 'PENDING'">
      <!-- 待处理状态:显示出发、取消、强制完成 -->
      <template v-if="taskDetail.taskStatus === TaskStatus.PENDING
      || taskDetail.taskStatus === TaskStatus.NOT_DEPARTED
      || taskDetail.taskStatus === TaskStatus.NOT_CONFIRMED
      || taskDetail.taskStatus === TaskStatus.PARTIALLY_CONFIRMED">
        <button 
          class="action-btn edit"
          @click="handleEdit"
        >
          修改
        </button>
        <button
          v-if="canOperateTask()"
          class="action-btn primary" 
          @click="handleTaskAction('depart')"
          @click="handleDepartAction()"
        >
          出发
        </button>
@@ -374,60 +483,81 @@
        >
          取消
        </button>
      </template>
      <!-- 出发中状态: 显示编辑、已到达、强制结束 -->
      <template v-else-if="taskDetail.taskStatus === 'DEPARTING'">
        <button 
          class="action-btn edit"
          @click="handleEdit"
          v-if="canOperateTask() && showForceCompleteFeature()"
          class="action-btn force-complete"
          @click="showForceCompleteTimeDialog()"
        >
          修改
        </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 v-else-if="taskDetail.taskStatus === TaskStatus.DEPARTING">
        <template v-if="canOperateTask()">
          <button
            class="action-btn primary"
            @click="handleTaskAction('arrive')"
          >
            已到达
          </button>
          <button
            class="action-btn cancel"
            @click="handleTaskAction('forceCancel')"
          >
            强制结束
          </button>
          <button
            v-if="showForceCompleteFeature()"
            class="action-btn force-complete"
            @click="showForceCompleteTimeDialog()"
          >
            强制完成
          </button>
        </template>
      </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 v-else-if="taskDetail.taskStatus === TaskStatus.ARRIVED">
        <template v-if="canOperateTask()">
          <button
            class="action-btn primary"
            @click="handleTaskAction('return')"
          >
            已返程
          </button>
        </template>
      </template>
      <!-- 返程中状态:显示已完成 -->
      <template v-else-if="taskDetail.taskStatus === TaskStatus.RETURNING">
        <template v-if="canOperateTask()">
          <button
            class="action-btn primary"
            @click="handleTaskAction('complete')"
          >
            已完成
          </button>
        </template>
      </template>
      <!-- 处理中状态:显示强制完成、取消 -->
      <template v-else-if="taskDetail.taskStatus === TaskStatus.IN_PROGRESS">
        <template v-if="canOperateTask()">
           <button
            class="action-btn primary"
            @click="handleTaskAction('arrive')"
          >
            已到达
          </button>
          <button
            v-if="showForceCompleteFeature()"
            class="action-btn force-complete"
            @click="showForceCompleteTimeDialog()"
          >
            强制完成
          </button>
        </template>
      </template>
      
      <!-- 已完成/已取消: 不显示按钮,但如果是转运任务则显示结算按钮 -->
@@ -445,11 +575,16 @@
</template>
<script>
  import { getTask, changeTaskStatus } from '@/api/task'
  import { getTask, changeTaskStatus, setAssigneeReady, checkTaskConsentAttachment } from '@/api/task'
  import { checkVehicleActiveTasks } from '@/api/task'
  import { getPaymentInfo } from '@/api/payment'
  import { getDicts } from '@/api/dict'
  import { checkTaskInvoice } from '@/api/invoice'
  import { formatDateTime } from '@/utils/common'
  import { validateTaskForDepart, validateTaskForSettlement, getTaskVehicleId, checkTaskCanDepart } from '@/utils/taskValidator'
  import { getStatusText as getTaskStatusText, getTaskTypeText as getTaskTypeTextUtil, TaskStatus } from '@/utils/TaskUtil'
  import AttachmentUpload from './components/AttachmentUpload.vue'
  import config from '@/config'
  
  export default {
    components: {
@@ -457,9 +592,20 @@
    },
    data() {
      return {
        TaskStatus, // 暴露 TaskStatus 给模板使用
        taskDetail: null,
        taskId: null,
        paymentInfo: null // 支付信息
        paymentInfo: null, // 支付信息
        cancelReasonList: [], // 取消原因列表
        showCancelDialog: false, // 显示取消原因对话框
        selectedCancelReason: '', // 选中的取消原因
        showForceCompleteDialog: false, // 显示强制完成对话框
        forceCompleteForm: {
          actualStartTime: '',
          actualEndTime: ''
        },
        hasInvoiceApplied: false, // 是否已申请发票
        invoiceStatus: null // 发票状态:0-待审核, 1-已通过, 2-已驳回
      }
    },
    computed: {
@@ -469,6 +615,38 @@
          return false
        }
        return ['COMPLETED', 'CANCELLED'].includes(this.taskDetail.taskStatus)
      },
      // 是否可以申请发票
      canApplyInvoice() {
        // 仅急救转运任务
        if (this.taskDetail?.taskType !== 'EMERGENCY_TRANSFER') return false
        // 任务必须已完成
        if (this.taskDetail?.taskStatus !== 'COMPLETED') return false
        // 未申请过发票,或曾被驳回
        return !this.hasInvoiceApplied || this.invoiceStatus === 2
      },
      // 生成执行人员角色标签的类名
      getRoleTagClass() {
        return (userType) => {
          const baseClass = 'role-tag'
          const roleClasses = {
            'driver': 'role-driver',
            'doctor': 'role-doctor',
            'nurse': 'role-nurse'
          }
          return [baseClass, roleClasses[userType] || '']
        }
      },
      // 获取选中的取消原因标签(用于弹窗显示)
      selectedCancelReasonLabel() {
        if (!this.selectedCancelReason || !this.cancelReasonList.length) {
          return '请选择'
        }
        const reason = this.cancelReasonList.find(r => r.value === this.selectedCancelReason)
        return reason ? reason.label : '请选择'
      },
      // 显示任务类型
      displayTaskType() {
@@ -490,10 +668,10 @@
          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'
        if (status === TaskStatus.PENDING || status === TaskStatus.NOT_CONFIRMED || status === TaskStatus.NOT_DEPARTED || status === TaskStatus.PARTIALLY_CONFIRMED) return 'pending'
        if ([TaskStatus.DEPARTING, TaskStatus.ARRIVED, TaskStatus.RETURNING, TaskStatus.IN_PROGRESS].includes(status)) return 'in_progress'
        if (status === TaskStatus.COMPLETED) return 'completed'
        if (status === TaskStatus.CANCELLED) return 'cancelled'
        return ''
      },
      // 显示计划开始时间
@@ -502,9 +680,9 @@
          return '未设置'
        }
        const formatted = formatDateTime(this.taskDetail.plannedStartTime, 'YYYY-MM-DD HH:mm')
        // 如果年份是1900,表示无效日期,显示为未设置
        if (formatted && formatted.startsWith('1900')) {
          return '未设置'
        // 如果年份是1900或1970,表示无效日期,显示为未分配时间
        if (formatted && (formatted.startsWith('1900') || formatted.startsWith('1970'))) {
          return '未分配时间'
        }
        return formatted
      },
@@ -514,9 +692,9 @@
          return '未设置'
        }
        const formatted = formatDateTime(this.taskDetail.plannedEndTime, 'YYYY-MM-DD HH:mm')
        // 如果年份是1900,表示无效日期,显示为未设置
        if (formatted && formatted.startsWith('1900')) {
          return '未设置'
        // 如果年份是1900或1970,表示无效日期,显示为未分配时间
        if (formatted && (formatted.startsWith('1900') || formatted.startsWith('1970'))) {
          return '未分配时间'
        }
        return formatted
      },
@@ -526,9 +704,9 @@
          return '未设置'
        }
        const formatted = formatDateTime(this.taskDetail.actualStartTime, 'YYYY-MM-DD HH:mm')
        // 如果年份是1900,表示无效日期,显示为未设置
        if (formatted && formatted.startsWith('1900')) {
          return '未设置'
        // 如果年份是1900或1970,表示无效日期,显示为未分配时间
        if (formatted && (formatted.startsWith('1900') || formatted.startsWith('1970'))) {
          return '未分配时间'
        }
        return formatted
      },
@@ -538,9 +716,9 @@
          return '未设置'
        }
        const formatted = formatDateTime(this.taskDetail.actualEndTime, 'YYYY-MM-DD HH:mm')
        // 如果年份是1900,表示无效日期,显示为未设置
        if (formatted && formatted.startsWith('1900')) {
          return '未设置'
        // 如果年份是1900或1970,表示无效日期,显示为未分配时间
        if (formatted && (formatted.startsWith('1900') || formatted.startsWith('1970'))) {
          return '未分配时间'
        }
        return formatted
      }
@@ -548,6 +726,9 @@
    onLoad(options) {
      this.taskId = options.id
      this.loadTaskDetail()
      this.loadCancelReasonDict() // 加载取消原因字典
      // 检查发票申请状态
      this.checkInvoiceStatus()
    },
    onShow() {
      // 每次页面显示时重新加载数据,确保从编辑页面返回后能看到最新数据
@@ -565,13 +746,7 @@
        
        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') {
@@ -676,7 +851,16 @@
      
      // 返回上一页
      goBack() {
        uni.navigateBack()
        // 检查是否有页面可以返回
        uni.navigateBack({
          delta: 1,
          fail: () => {
            // 如果无法返回,则跳转到任务列表页面
            uni.switchTab({
              url: '/pages/task/index'
            })
          }
        })
      },
      
      // 处理编辑按钮
@@ -716,28 +900,12 @@
      
      // 获取状态文本
      getStatusText(status) {
        const statusMap = {
          'PENDING': '待处理',
          'DEPARTING': '出发中',
          'ARRIVED': '已到达',
          'RETURNING': '返程中',
          'COMPLETED': '已完成',
          'CANCELLED': '已取消',
          'IN_PROGRESS': '处理中' // 兼容旧数据
        }
        return statusMap[status] || '未知'
        return getTaskStatusText(status)
      },
      
      // 获取任务类型文本
      getTaskTypeText(type) {
        const typeMap = {
          'MAINTENANCE': '维修保养',
          'FUEL': '加油',
          'OTHER': '其他',
          'EMERGENCY_TRANSFER': '转运任务',
          'WELFARE': '福祉车'
        }
        return typeMap[type] || '未知类型'
        return getTaskTypeTextUtil(type)
      },
      
      // 获取用户类型标签
@@ -752,6 +920,15 @@
      
      // 处理结算
      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
        })
@@ -761,15 +938,12 @@
      handleTaskAction(action) {
        switch (action) {
          case 'depart':
            // 出发 -> 检查车辆是否有其他正在进行中的任务
            this.checkVehicleAndDepart();
            this.ensureReadyThenDepart();
            break;
            
          case 'cancel':
            // 取消 -> 二次确认后状态变为已取消
            this.$modal.confirm('确定要取消此任务吗?').then(() => {
              this.updateTaskStatus('CANCELLED', '任务已取消')
            }).catch(() => {});
            // 取消 -> 显示取消原因选择对话框
            this.showCancelReasonDialog();
            break;
            
          case 'arrive':
@@ -780,10 +954,8 @@
            break;
            
          case 'forceCancel':
            // 强制结束 -> 状态变为已取消
            this.$modal.confirm('确定要强制结束此任务吗?').then(() => {
              this.updateTaskStatus('CANCELLED', '任务已强制结束')
            }).catch(() => {});
            // 强制结束 -> 显示取消原因选择对话框
            this.showCancelReasonDialog();
            break;
            
          case 'return':
@@ -803,68 +975,84 @@
      },
      
      // 检查车辆状态并出发
      checkVehicleAndDepart() {
        // 检查出发时间是否为空或1900年(修复:防止无效时间)
        if (!this.taskDetail.plannedStartTime || this.taskDetail.plannedStartTime.startsWith('1900')) {
          this.$modal.confirm('任务的转运时间未设置或无效,需要先修改任务补充转运时间后才能出发。是否现在去修改?').then(() => {
            this.handleEdit()
          }).catch(() => {})
          return
        }
        // 获取任务车辆ID
        const vehicleId = this.getVehicleId();
        if (!vehicleId) {
          this.$modal.showToast('未找到任务车辆信息');
          return;
        }
      async checkVehicleAndDepart() {
        // 显示加载提示
        uni.showLoading({
          title: '检查车辆状态...'
          title: '检查任务状态...'
        });
        
        checkVehicleActiveTasks(vehicleId).then(response => {
        try {
          // 调用工具类检查任务是否可以出发(包含基本校验和冲突检查)
          const checkResult = await checkTaskCanDepart(this.taskDetail)
          uni.hideLoading();
          
          const activeTasks = response.data || [];
          console.log('出发检查结果:', checkResult);
          console.log('valid:', checkResult.valid);
          console.log('conflicts:', checkResult.conflicts);
          
          // 过滤掉当前任务本身(修复:防止 activeTasks 为 null)
          const otherActiveTasks = (activeTasks && Array.isArray(activeTasks)) ? activeTasks.filter(task => task.taskId !== this.taskId) : [];
          if (otherActiveTasks.length > 0) {
            // 车辆有其他正在进行中的任务
            const task = otherActiveTasks[0];
            const taskStatus = this.getStatusText(task.taskStatus);
            const message = `该车辆已有正在转运中的任务!
任务单号:${task.taskCode}
任务状态:${taskStatus}
请先完成当前任务后再出发新任务。`;
          if (!checkResult.valid) {
            // 校验失败,显示提示信息并提供跳转选项
            const conflicts = checkResult.conflicts || [];
            const conflictInfo = conflicts.length > 0 ? conflicts[0] : null;
            
            uni.showModal({
              title: '提示',
              content: message,
              showCancel: false,
              confirmText: '我知道了'
            });
            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 => {
        } catch (error) {
          uni.hideLoading();
          console.error('检查车辆状态失败:', error);
          console.error('检查任务状态失败:', error);
          // 检查失败时,仍然允许出发
          this.$modal.confirm('检查车辆状态失败,是否继续出发?').then(() => {
          this.$modal.confirm('检查任务状态失败,是否继续出发?').then(() => {
            this.updateTaskStatus('DEPARTING', '任务已出发')
          }).catch(() => {});
        });
        }
      },
      
      // 获取任务车辆ID
@@ -886,14 +1074,104 @@
        return null;
      },
      
      // 检查发票申请状态
      checkInvoiceStatus() {
        if (!this.taskId) return;
        // 调用后端接口检查该任务是否已申请发票
        checkTaskInvoice(this.taskId).then(response => {
          if (response.code === 200 && response.data) {
            this.hasInvoiceApplied = true;
            this.invoiceStatus = response.data.status;
          }
        }).catch(error => {
          console.error('检查发票申请状态失败:', error);
          // 忽略错误,默认未申请
        });
      },
      // 申请发票
      handleApplyInvoice() {
        // 准备任务信息
        const taskInfo = {
          taskId: this.taskDetail.taskId,
          taskCode: this.taskDetail.showTaskCode || this.taskDetail.taskCode,
          legacyServiceOrderId: this.taskDetail.emergencyInfo?.legacyServiceOrdId,
          serviceCode: this.taskDetail.emergencyInfo?.serviceCode,
          departure: this.taskDetail.departureAddress,
          destination: this.taskDetail.destinationAddress,
          completionTime: this.formatTime(this.taskDetail.actualEndTime),
          transferPrice: this.paymentInfo?.transferPrice || this.paymentInfo?.totalAmount
        };
        // 将任务信息序列化为 URL 参数
        const taskInfoParam = encodeURIComponent(JSON.stringify(taskInfo));
        // 跳转到发票申请页面,传递任务信息
        uni.navigateTo({
          url: `/pages/mine/invoice/apply?taskInfo=${taskInfoParam}`
        });
      },
      // 更新任务状态
      updateTaskStatus(status, remark) {
        // 获取GPS位置信息
        this.getLocationAndUpdateStatus(status, remark)
        // 如果是完成状态,需要检查是否上传了知情同意书
        if (status === 'COMPLETED') {
          this.checkConsentAttachmentAndThen(status, remark);
        } else {
          // 获取GPS位置信息
          this.getLocationAndUpdateStatus(status, remark);
        }
      },
      // 检查知情同意书附件并更新状态
      async checkConsentAttachmentAndThen(status, remark) {
        try {
          uni.showLoading({
            title: '检查附件...'
          });
          // 注意:这里会被请求拦截器处理,code !== 200 时会 reject
          const response = await checkTaskConsentAttachment(this.taskId).catch(err => {
            // 拦截器 reject 的情况,返回一个默认对象
            console.log('请求被拦截器 reject,err:', err);
            return { code: -1, msg: '未上传知情同意书' };
          });
          uni.hideLoading();
          console.log('检查附件结果:', response);
          // 后台返回 code: 200 表示已上传,code: -1 表示未上传
          if (response && response.code === 200) {
            // 已上传知情同意书,继续更新状态
            console.log('已上传知情同意书,继续完成任务');
            this.getLocationAndUpdateStatus(status, remark);
          } else {
            // 未上传知情同意书或其他错误,阻止完成
            const message = (response && response.msg) || '任务未上传知情同意书,无法完成任务';
            console.log('未上传知情同意书,阻止完成');
            this.$modal.confirm(message + '。是否现在去上传?').then(() => {
              // 滚动到附件上传区域
              this.$nextTick(() => {
                uni.pageScrollTo({
                  scrollTop: 9999, // 滚动到底部
                  duration: 300
                });
              });
            }).catch(() => {});
          }
        } catch (error) {
          uni.hideLoading();
          console.error('检查附件异常:', error);
          // 如果检查失败(网络异常等),不允许完成任务
          this.$modal.showToast('检查附件状态失败,无法完成任务');
        }
      },
      
      // 获取位置信息并更新状态
      getLocationAndUpdateStatus(status, remark) {
      getLocationAndUpdateStatus(status, remark, cancelReason) {
        const that = this
        
        // 使用uni.getLocation获取GPS位置
@@ -920,6 +1198,11 @@
              heading: res.direction || res.heading
            }
            
            // 如果有取消原因,添加到请求数据中
            if (cancelReason) {
              statusData.cancelReason = cancelReason
            }
            changeTaskStatus(that.taskId, statusData).then(response => {
              that.$modal.showToast('状态更新成功')
              // 重新加载任务详情
@@ -937,6 +1220,11 @@
              const statusData = {
                taskStatus: status,
                remark: remark
              }
              // 如果有取消原因,添加到请求数据中
              if (cancelReason) {
                statusData.cancelReason = cancelReason
              }
              
              changeTaskStatus(that.taskId, statusData).then(response => {
@@ -1209,7 +1497,441 @@
      // 附件删除成功回调
      onAttachmentDeleted(attachmentId) {
        console.log('附件删除成功:', attachmentId)
      }
      },
      // 是否显示"就绪"功能(配置开关)
      showAssigneeReadyFeature() {
        return !!(config && config.features && config.features.showAssigneeReadyButton)
      },
      // 是否显示"强制完成"功能(配置开关)
      showForceCompleteFeature() {
        return !!(config && config.features && config.features.showForceCompleteButton)
      },
      // 当前用户是否为该执行人
      isAssigneeSelf(assignee) {
        const userId = this.$store && this.$store.state && this.$store.state.user && this.$store.state.user.userId
        return assignee && (assignee.userId === userId || assignee.oaUserId === userId)
      },
      // 处理就绪按钮点击(通过data属性获取执行人信息)
      handleReadyClick(e) {
        const dataset = e.currentTarget.dataset
        const index = dataset.index
        console.log('handleReadyClick - dataset:', dataset)
        console.log('handleReadyClick - index:', index)
        if (index === undefined || index === null) {
          this.$modal.showToast('无法获取执行人索引')
          return
        }
        const assignee = this.taskDetail.assignees[index]
        console.log('handleReadyClick - assignee:', assignee)
        if (!assignee) {
          this.$modal.showToast('执行人信息不存在')
          return
        }
        this.markAssigneeReady(assignee)
      },
      // 执行人点击"就绪"
      markAssigneeReady(assignee) {
        console.log('markAssigneeReady 被调用,参数:', assignee)
        console.log('taskDetail:', this.taskDetail)
        if (!this.taskDetail) {
          this.$modal.showToast('任务信息不存在')
          return
        }
        if (!assignee) {
          this.$modal.showToast('执行人信息不存在')
          return
        }
        const userId = assignee.userId || assignee.oaUserId
        console.log('执行人ID:', userId)
        if (!userId) {
          this.$modal.showToast('无法识别执行人ID')
          return
        }
        this.$modal.showLoading && this.$modal.showLoading('提交中...')
        setAssigneeReady(this.taskId).then(() => {
          this.$modal.hideLoading && this.$modal.hideLoading()
          this.$modal.showToast('已就绪')
          // 刷新任务详情
          this.loadTaskDetail()
        }).catch(err => {
          this.$modal.hideLoading && this.$modal.hideLoading()
          console.error('标记就绪失败:', err)
          this.$modal.showToast('标记就绪失败')
        })
      },
      // 是否当前用户是任务执行人
      isCurrentUserAssignee() {
        const userId = this.$store && this.$store.state && this.$store.state.user && this.$store.state.user.userId;
        console.log("当前用户ID:", userId)
        const list = (this.taskDetail && Array.isArray(this.taskDetail.assignees)) ? this.taskDetail.assignees : []
        return list.some(a => a && (a.userId === userId || a.oaUserId === userId))
      },
      // 是否当前用户可以操作任务(执行人或管理员)
      canOperateTask() {
        // 检查是否是管理员(canViewAllConsult === '1')
        const canViewAllConsult = this.$store && this.$store.state && this.$store.state.user && this.$store.state.user.canViewAllConsult
        console.log("当前用户是否是管理员:", canViewAllConsult)
        if (canViewAllConsult === '1') {
          return true
        }
        // 检查是否是任务执行人
        return this.isCurrentUserAssignee()
      },
      // 是否多人执行
      isMultipleAssignees() {
        const list = (this.taskDetail && Array.isArray(this.taskDetail.assignees)) ? this.taskDetail.assignees : []
        return list.length > 1
      },
      // 执行人是否已就绪
      isAssigneeReady(assignee) {
        if (!assignee) return false
        return assignee.isReady === '1' || assignee.ready === true || assignee.readyStatus === 'READY' || assignee.readyFlag === 'Y'
      },
      // 所有执行人是否已就绪
      areAllAssigneesReady() {
        const list = (this.taskDetail && Array.isArray(this.taskDetail.assignees)) ? this.taskDetail.assignees : []
        if (list.length === 0) return false
        return list.every(a => this.isAssigneeReady(a))
      },
      // 获取当前用户对应的执行人记录
      getCurrentUserAssignee() {
        const userId = this.$store && this.$store.state && this.$store.state.user && this.$store.state.user.userId
        console.log('userId', userId)
        const list = (this.taskDetail && Array.isArray(this.taskDetail.assignees)) ? this.taskDetail.assignees : []
        return list.find(a => a && (a.userId === userId || a.oaUserId === userId)) || null
      },
      // 操作区就绪按钮(多人任务)
      markCurrentAssigneeReady() {
        const me = this.getCurrentUserAssignee()
        if (!me) {
          this.$modal.showToast('仅任务执行人可操作')
          return
        }
        this.markAssigneeReady(me)
      },
      // 当前用户是否已就绪
      isCurrentUserReady() {
        const me = this.getCurrentUserAssignee()
        return me ? this.isAssigneeReady(me) : false
      },
      // 处理就绪按钮点击
      async handleReadyAction() {
        const me = this.getCurrentUserAssignee()
        if (!me) {
          this.$modal.showToast('仅任务执行人可操作')
          return
        }
        try {
          await setAssigneeReady(this.taskId)
          this.$modal.showToast('已就绪')
          // 刷新任务详情
          await this.loadTaskDetail()
        } catch (err) {
          console.error('标记就绪失败:', err)
          this.$modal.showToast('标记就绪失败')
        }
      },
      // 处理出发按钮点击
      async handleDepartAction() {
        if (!this.taskDetail) return
        const list = (this.taskDetail && Array.isArray(this.taskDetail.assignees)) ? this.taskDetail.assignees : []
        // 如果开启了就绪功能且是多人任务,需要检查所有人是否就绪
        if (this.showAssigneeReadyFeature() && list.length > 1) {
          if (!this.areAllAssigneesReady()) {
            this.$modal.showToast('其他人未就绪,所有人就绪后才能出发')
            return
          }
        }
        // 单人任务或未开启就绪功能:自动标记就绪
        if (this.showAssigneeReadyFeature() && list.length === 1) {
          const me = this.getCurrentUserAssignee()
          if (me && !this.isAssigneeReady(me)) {
            try {
              await setAssigneeReady(this.taskId)
            } catch (e) {
              console.error('自动就绪失败:', e)
            }
          }
        }
        // 执行出发流程
        this.checkVehicleAndDepart()
      },
      // 出发前保证就绪(保留向后兼容)
      async ensureReadyThenDepart() {
        this.handleDepartAction()
      },
      // 获取执行人员的key值
      getAssigneeKey(assignee, index) {
        // 确保返回有效的字符串key
        if (!assignee) return 'assignee-' + index;
        // 优先使用userId,其次是userName,最后使用index
        const key = assignee.userId || assignee.userName || index;
        return 'assignee-' + (key !== null && key !== undefined ? key : index);
      },
      // 获取支付记录的key值
      getPaymentKey(payment, index) {
        // 确保返回有效的字符串key
        if (!payment) return 'payment-' + index;
        // 优先使用id,其次使用index
        const key = payment.id || index;
        return 'payment-' + (key !== null && key !== undefined ? key : index);
      },
      // 加载取消原因字典
      loadCancelReasonDict() {
        // 从后端获取取消原因字典
        getDicts('task_cancel_reason').then(response => {
          if (response.code === 200 && response.data) {
            this.cancelReasonList = response.data.map(item => ({
              value: item.dictValue,
              label: item.dictLabel
            }))
          }
        }).catch(error => {
          console.error('加载取消原因字典失败:', error)
        })
      },
      // 显示取消原因对话框
      showCancelReasonDialog() {
        this.selectedCancelReason = ''
        this.$refs.cancelPopup.open()
      },
      // 确认取消任务
      confirmCancelTask() {
        if (!this.selectedCancelReason) {
          this.$modal.showToast('请选择取消原因')
          return
        }
        this.$refs.cancelPopup.close()
        // 调用更新状态方法,传递取消原因
        this.updateTaskStatusWithCancelReason('CANCELLED', '任务已取消', this.selectedCancelReason)
      },
      // 取消对话框关闭
      closeCancelDialog() {
        this.$refs.cancelPopup.close()
        this.selectedCancelReason = ''
      },
      // 选择取消原因
      selectCancelReason(e) {
        const index = parseInt(e.detail.value)
        if (this.cancelReasonList && this.cancelReasonList[index]) {
          this.selectedCancelReason = this.cancelReasonList[index].value
        }
      },
      // 带取消原因的状态更新
      updateTaskStatusWithCancelReason(status, remark, cancelReason) {
        this.getLocationAndUpdateStatus(status, remark, cancelReason)
      },
      // 根据取消原因value获取label
      getCancelReasonLabel(value) {
        if (!value || !this.cancelReasonList.length) {
          return value || '未知'
        }
        const reason = this.cancelReasonList.find(r => r.value === value)
        return reason ? reason.label : value
      },
      // 显示强制完成时间对话框
      showForceCompleteTimeDialog() {
        // 校验任务是否满足强制完成条件
        const validation = this.validateForceComplete()
        if (!validation.valid) {
          this.$modal.showToast(validation.message)
          return
        }
        // 重置表单
        const now = new Date()
        const nowDateStr = this.formatDateForPicker(now)
        const nowTimeStr = this.formatTimeForPicker(now)
        // 开始时间:优先使用预约时间,如果没有则使用当前时间
        let startTimeStr = nowDateStr + ' ' + nowTimeStr
        if (this.taskDetail && this.taskDetail.plannedStartTime) {
          const plannedTime = new Date(this.taskDetail.plannedStartTime)
          const year = plannedTime.getFullYear()
          // 检查是否是有效时间(排除1900、1970等无效年份)
          if (year > 2000) {
            const plannedDateStr = this.formatDateForPicker(plannedTime)
            const plannedTimeStr = this.formatTimeForPicker(plannedTime)
            startTimeStr = plannedDateStr + ' ' + plannedTimeStr
          }
        }
        this.forceCompleteForm = {
          actualStartTime: startTimeStr,
          actualEndTime: nowDateStr + ' ' + nowTimeStr
        }
        this.$refs.forceCompletePopup.open()
      },
      // 校验是否可以强制完成
      validateForceComplete() {
        if (!this.taskDetail) {
          return { valid: false, message: '任务信息不存在' }
        }
        // 检查是否有执行人
        if (!this.taskDetail.assignees || this.taskDetail.assignees.length === 0) {
          return { valid: false, message: '请先分配执行人' }
        }
        // 检查是否有车辆
        if (!this.taskDetail.assignedVehicles || this.taskDetail.assignedVehicles.length === 0) {
          return { valid: false, message: '请先分配执行车辆' }
        }
        return { valid: true }
      },
      // 关闭强制完成对话框
      closeForceCompleteDialog() {
        this.$refs.forceCompletePopup.close()
      },
      // 确认强制完成
      confirmForceComplete() {
        // 校验时间
        if (!this.forceCompleteForm.actualStartTime || !this.forceCompleteForm.actualEndTime) {
          this.$modal.showToast('请选择开始和结束时间')
          return
        }
        const startTime = new Date(this.forceCompleteForm.actualStartTime)
        const endTime = new Date(this.forceCompleteForm.actualEndTime)
        if (startTime >= endTime) {
          this.$modal.showToast('结束时间必须大于开始时间')
          return
        }
        this.$refs.forceCompletePopup.close()
        // 调用API更新任务
        this.forceCompleteTask()
      },
      // 强制完成任务
      forceCompleteTask() {
        uni.showLoading({
          title: '处理中...'
        })
        const statusData = {
          taskStatus: 'COMPLETED',
          actualStartTime: this.forceCompleteForm.actualStartTime,
          actualEndTime: this.forceCompleteForm.actualEndTime,
          remark: '强制完成任务'
        }
        changeTaskStatus(this.taskId, statusData).then(response => {
          uni.hideLoading()
          this.$modal.showToast('任务已完成')
          // 重新加载任务详情
          this.loadTaskDetail()
        }).catch(error => {
          uni.hideLoading()
          console.error('强制完成任务失败:', error)
          this.$modal.showToast('操作失败,请重试')
        })
      },
      // 选择开始日期
      selectStartDate(e) {
        const date = e.detail.value
        const time = this.getTimeFromDateTime(this.forceCompleteForm.actualStartTime) || '00:00'
        this.forceCompleteForm.actualStartTime = date + ' ' + time
      },
      // 选择开始时间
      selectStartTime(e) {
        const time = e.detail.value
        const date = this.getDateFromDateTime(this.forceCompleteForm.actualStartTime) || this.formatDateForPicker(new Date())
        this.forceCompleteForm.actualStartTime = date + ' ' + time
      },
      // 选择结束日期
      selectEndDate(e) {
        const date = e.detail.value
        const time = this.getTimeFromDateTime(this.forceCompleteForm.actualEndTime) || '00:00'
        this.forceCompleteForm.actualEndTime = date + ' ' + time
      },
      // 选择结束时间
      selectEndTime(e) {
        const time = e.detail.value
        const date = this.getDateFromDateTime(this.forceCompleteForm.actualEndTime) || this.formatDateForPicker(new Date())
        this.forceCompleteForm.actualEndTime = date + ' ' + time
      },
      // 从日期时间字符串中提取日期
      getDateFromDateTime(dateTimeStr) {
        if (!dateTimeStr) return ''
        return dateTimeStr.split(' ')[0] || ''
      },
      // 从日期时间字符串中提取时间
      getTimeFromDateTime(dateTimeStr) {
        if (!dateTimeStr) return ''
        return dateTimeStr.split(' ')[1] || ''
      },
      // 格式化日期为 picker 需要的格式 (YYYY-MM-DD)
      formatDateForPicker(date) {
        const year = date.getFullYear()
        const month = String(date.getMonth() + 1).padStart(2, '0')
        const day = String(date.getDate()).padStart(2, '0')
        return `${year}-${month}-${day}`
      },
      // 格式化时间为 picker 需要的格式 (HH:mm)
      formatTimeForPicker(date) {
        const hour = String(date.getHours()).padStart(2, '0')
        const minute = String(date.getMinutes()).padStart(2, '0')
        return `${hour}:${minute}`
      },
    }
  }
</script>
@@ -1238,9 +1960,25 @@
      }
      
      .title {
        flex: 1;
        font-size: 36rpx;
        font-weight: bold;
        color: #333;
      }
      .edit-btn {
        width: 120rpx;
        height: 60rpx;
        display: flex;
        align-items: center;
        justify-content: center;
        cursor: pointer;
        .edit-text {
          margin-left: 8rpx;
          font-size: 28rpx;
          color: #007AFF;
        }
      }
    }
    
@@ -1338,6 +2076,9 @@
            }
            
            .assignee-role {
              display: flex;
              align-items: center;
              .role-tag {
                display: inline-block;
                padding: 4rpx 12rpx;
@@ -1357,7 +2098,34 @@
                  background-color: #AF52DE;
                }
              }
              .ready-badge {
                display: inline-block;
                margin-left: 12rpx;
                padding: 4rpx 12rpx;
                font-size: 22rpx;
                border-radius: 6rpx;
                &.ready {
                  background-color: #e6ffed;
                  color: #34C759;
                }
                &.unready {
                  background-color: #f0f0f0;
                  color: #999;
                }
              }
            }
          }
          .assignee-ready-btn {
            margin-left: 12rpx;
            padding: 8rpx 16rpx;
            font-size: 24rpx;
            border-radius: 6rpx;
            background-color: #34C759;
            color: #fff;
            border: none;
            flex-shrink: 0;
          }
        }
      }
@@ -1526,10 +2294,13 @@
        flex: 1;
        height: 80rpx;
        border-radius: 10rpx;
        font-size: 30rpx;
        font-size: 28rpx;
        margin: 0 10rpx;
        background-color: #f0f0f0;
        color: #333;
        white-space: nowrap;
        padding: 0 10rpx;
        min-width: 0;
        
        &.edit {
          background-color: #ff9500;
@@ -1546,8 +2317,18 @@
          color: white;
        }
        
        &.force-end {
          background-color: #ff6b22;
          color: white;
        }
        &.settlement {
          background-color: #34C759;
          color: white;
        }
        &.force-complete {
          background-color: #5856d6;
          color: white;
        }
        
@@ -1560,5 +2341,172 @@
        }
      }
    }
    .vip-tag {
      display: inline-block;
      padding: 2rpx 8rpx;
      font-size: 20rpx;
      color: #fff;
      background-color: #ff0000;
      border-radius: 4rpx;
      margin-left: 10rpx;
      vertical-align: middle;
    }
    .hq-tag {
      display: inline-block;
      padding: 2rpx 8rpx;
      font-size: 20rpx;
      color: #fff;
      background-color: #5856d6;
      border-radius: 4rpx;
      margin-left: 10rpx;
      vertical-align: middle;
    }
    .apply-invoice-btn {
      padding: 8rpx 16rpx;
      font-size: 24rpx;
      color: #fff;
      background-color: #34C759;
      border: none;
      border-radius: 6rpx;
      margin-left: 20rpx;
    }
    .apply-invoice-btn::after {
      border: none;
    }
    // 取消原因对话框样式
    .cancel-dialog {
      width: 600rpx;
      background-color: white;
      border-radius: 20rpx;
      padding: 40rpx;
      .dialog-title {
        font-size: 32rpx;
        font-weight: bold;
        text-align: center;
        margin-bottom: 30rpx;
        color: #333;
      }
      .reason-picker {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 20rpx 30rpx;
        background-color: #f5f5f5;
        border-radius: 10rpx;
        margin-bottom: 30rpx;
        .picker-label {
          font-size: 28rpx;
          color: #666;
        }
        .picker-value {
          flex: 1;
          text-align: right;
          font-size: 28rpx;
          color: #333;
          margin: 0 10rpx;
        }
      }
      .dialog-buttons {
        display: flex;
        gap: 20rpx;
        button {
          flex: 1;
          height: 80rpx;
          border-radius: 10rpx;
          font-size: 30rpx;
          border: none;
          &.cancel-btn {
            background-color: #f0f0f0;
            color: #666;
          }
          &.confirm-btn {
            background-color: #007AFF;
            color: white;
          }
        }
      }
    }
    // 强制完成对话框样式
    .force-complete-dialog {
      width: 600rpx;
      background-color: white;
      border-radius: 20rpx;
      padding: 40rpx;
      .dialog-title {
        font-size: 32rpx;
        font-weight: bold;
        text-align: center;
        margin-bottom: 30rpx;
        color: #333;
      }
      .time-picker-item {
        margin-bottom: 30rpx;
        .time-label {
          font-size: 28rpx;
          color: #333;
          margin-bottom: 15rpx;
          font-weight: 500;
        }
        picker {
          display: inline-block;
          width: 48%;
          &:first-of-type {
            margin-right: 4%;
          }
          .picker-value {
            padding: 20rpx;
            background-color: #f5f5f5;
            border-radius: 10rpx;
            font-size: 26rpx;
            color: #333;
            text-align: center;
          }
        }
      }
      .dialog-buttons {
        display: flex;
        gap: 20rpx;
        margin-top: 40rpx;
        button {
          flex: 1;
          height: 80rpx;
          border-radius: 10rpx;
          font-size: 30rpx;
          border: none;
          &.cancel-btn {
            background-color: #f0f0f0;
            color: #666;
          }
          &.confirm-btn {
            background-color: #5856d6;
            color: white;
          }
        }
      }
    }
  }
</style>