wlzboy
2025-12-06 5d75fcaea0a3774052b7484a4ffe755258502363
app/pagesTask/detail.vue
@@ -59,6 +59,15 @@
                >
                  {{ getUserTypeLabel(assignee.userType) }}
                </view>
                <view
                  class="ready-badge"
                  :class="{
                    'ready': isAssigneeReady(assignee),
                    'unready': !isAssigneeReady(assignee)
                  }"
                >
                  {{ isAssigneeReady(assignee) ? '已就绪' : '未就绪' }}
                </view>
              </view>
            </view>
          </view>
@@ -362,18 +371,27 @@
        >
          修改
        </button>
        <button
          class="action-btn primary"
          @click="handleTaskAction('depart')"
        >
          出发
        </button>
        <button
          class="action-btn cancel"
          @click="handleTaskAction('cancel')"
        >
          取消
        </button>
        <template v-if="isCurrentUserAssignee()">
          <button
            v-if="showAssigneeReadyFeature() && isMultipleAssignees() && !isCurrentUserReady()"
            class="action-btn primary"
            @click="handleReadyAction()"
          >
            就绪
          </button>
          <button
            class="action-btn primary"
            @click="handleDepartAction()"
          >
            出发
          </button>
          <button
            class="action-btn cancel"
            @click="handleTaskAction('cancel')"
          >
            取消
          </button>
        </template>
      </template>
      
      <!-- 出发中状态: 显示编辑、已到达、强制结束 -->
@@ -384,18 +402,20 @@
        >
          修改
        </button>
        <button
          class="action-btn primary"
          @click="handleTaskAction('arrive')"
        >
          已到达
        </button>
        <button
          class="action-btn cancel"
          @click="handleTaskAction('forceCancel')"
        >
          强制结束
        </button>
        <template v-if="isCurrentUserAssignee()">
          <button
            class="action-btn primary"
            @click="handleTaskAction('arrive')"
          >
            已到达
          </button>
          <button
            class="action-btn cancel"
            @click="handleTaskAction('forceCancel')"
          >
            强制结束
          </button>
        </template>
      </template>
      
      <!-- 已到达状态: 显示编辑、已返程 -->
@@ -406,12 +426,14 @@
        >
          修改
        </button>
        <button
          class="action-btn primary"
          @click="handleTaskAction('return')"
        >
          已返程
        </button>
        <template v-if="isCurrentUserAssignee()">
          <button
            class="action-btn primary"
            @click="handleTaskAction('return')"
          >
            已返程
          </button>
        </template>
      </template>
      
      <!-- 返程中状态: 显示编辑、已完成 -->
@@ -422,12 +444,14 @@
        >
          修改
        </button>
        <button
          class="action-btn primary"
          @click="handleTaskAction('complete')"
        >
          已完成
        </button>
        <template v-if="isCurrentUserAssignee()">
          <button
            class="action-btn primary"
            @click="handleTaskAction('complete')"
          >
            已完成
          </button>
        </template>
      </template>
      
      <!-- 已完成/已取消: 不显示按钮,但如果是转运任务则显示结算按钮 -->
@@ -445,12 +469,13 @@
</template>
<script>
  import { getTask, changeTaskStatus } from '@/api/task'
  import { getTask, changeTaskStatus, setAssigneeReady } 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'
  import config from '@/config'
  
  export default {
    components: {
@@ -771,8 +796,7 @@
      handleTaskAction(action) {
        switch (action) {
          case 'depart':
            // 出发 -> 检查车辆是否有其他正在进行中的任务
            this.checkVehicleAndDepart();
            this.ensureReadyThenDepart();
            break;
            
          case 'cancel':
@@ -1235,6 +1259,145 @@
      // 附件删除成功回调
      onAttachmentDeleted(attachmentId) {
        console.log('附件删除成功:', attachmentId)
      },
      // 是否显示“就绪”功能(配置开关)
      showAssigneeReadyFeature() {
        return !!(config && config.features && config.features.showAssigneeReadyButton)
      },
      // 当前用户是否为该执行人
      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)
      },
      // 执行人点击“就绪”
      markAssigneeReady(assignee) {
        if (!assignee || !this.taskDetail) {
          this.$modal.showToast('执行人或任务信息不存在')
          return
        }
        const userId = assignee.userId || assignee.oaUserId
        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))
      },
      // 是否多人执行
      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()
      }
    }
  }
@@ -1383,6 +1546,31 @@
                  background-color: #AF52DE;
                }
              }
              .assignee-ready-btn {
                margin-left: 12rpx;
                padding: 8rpx 16rpx;
                font-size: 24rpx;
                border-radius: 6rpx;
                background-color: #34C759;
                color: #fff;
                border: none;
              }
              .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;
                }
              }
            }
          }
        }