From c459808efab29dc1b8439fbb90556bdb16f4c88b Mon Sep 17 00:00:00 2001
From: wlzboy <66905212@qq.com>
Date: 星期三, 01 四月 2026 22:40:59 +0800
Subject: [PATCH] feat: 优化支付时显示任务ID

---
 app/pagesTask/detail.vue |  284 ++++++++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 214 insertions(+), 70 deletions(-)

diff --git a/app/pagesTask/detail.vue b/app/pagesTask/detail.vue
index 375ace9..56ec248 100644
--- a/app/pagesTask/detail.vue
+++ b/app/pagesTask/detail.vue
@@ -7,6 +7,7 @@
       <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>
     
@@ -70,7 +71,7 @@
             </view>
             <!-- 褰撳墠鐧诲綍浜烘槸璇ユ墽琛屼汉涓旀湭灏辩华鏃舵樉绀哄氨缁寜閽� -->
             <view 
-              v-if="showAssigneeReadyFeature() && isAssigneeSelf(assignee) && !isAssigneeReady(assignee) && taskDetail.taskStatus === 'PENDING'"
+              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"
@@ -236,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>
@@ -264,7 +275,7 @@
       </view>
       
       <!-- 鍙栨秷淇℃伅锛堜粎鍦ㄤ换鍔″凡鍙栨秷涓旀湁鍙栨秷鍘熷洜鏃舵樉绀猴級 -->
-      <view class="detail-section" v-if="taskDetail.taskStatus === 'CANCELLED' && taskDetail.emergencyInfo && taskDetail.emergencyInfo.cancelReason">
+      <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>
@@ -454,33 +465,36 @@
     
     <!-- 鎿嶄綔鎸夐挳鍖哄煙 -->
     <view class="action-buttons" v-if="taskDetail">
-      <!-- 寰呭鐞嗙姸鎬�: 鏄剧ず鍑哄彂銆佸彇娑堛�佸己鍒跺畬鎴� -->
-      <template v-if="taskDetail.taskStatus === 'PENDING'">
-        <template v-if="isCurrentUserAssignee()">
-          <button 
-            class="action-btn primary" 
-            @click="handleDepartAction()"
-          >
-            鍑哄彂
-          </button>
-          <button 
-            class="action-btn cancel" 
-            @click="handleTaskAction('cancel')"
-          >
-            鍙栨秷
-          </button>
-          <button 
-            class="action-btn force-complete" 
-            @click="showForceCompleteTimeDialog()"
-          >
-            寮哄埗瀹屾垚
-          </button>
-        </template>
+      <!-- 寰呭鐞嗙姸鎬侊細鏄剧ず鍑哄彂銆佸彇娑堛�佸己鍒跺畬鎴� -->
+      <template v-if="taskDetail.taskStatus === TaskStatus.PENDING 
+      || taskDetail.taskStatus === TaskStatus.NOT_DEPARTED 
+      || taskDetail.taskStatus === TaskStatus.NOT_CONFIRMED
+      || taskDetail.taskStatus === TaskStatus.PARTIALLY_CONFIRMED">
+        <button 
+          v-if="canOperateTask()"
+          class="action-btn primary" 
+          @click="handleDepartAction()"
+        >
+          鍑哄彂
+        </button>
+        <button 
+          class="action-btn cancel" 
+          @click="handleTaskAction('cancel')"
+        >
+          鍙栨秷
+        </button>
+        <button 
+          v-if="canOperateTask() && showForceCompleteFeature()"
+          class="action-btn force-complete" 
+          @click="showForceCompleteTimeDialog()"
+        >
+          寮哄埗瀹屾垚
+        </button>
       </template>
-      
-      <!-- 鍑哄彂涓姸鎬�: 鏄剧ず宸插埌杈俱�佸己鍒剁粨鏉� -->
-      <template v-else-if="taskDetail.taskStatus === 'DEPARTING'">
-        <template v-if="isCurrentUserAssignee()">
+          
+      <!-- 鍑哄彂涓姸鎬侊細鏄剧ず宸插埌杈俱�佸己鍒跺彇娑堛�佸己鍒跺畬鎴� -->
+      <template v-else-if="taskDetail.taskStatus === TaskStatus.DEPARTING">
+        <template v-if="canOperateTask()">
           <button 
             class="action-btn primary" 
             @click="handleTaskAction('arrive')"
@@ -491,14 +505,21 @@
             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 === 'ARRIVED'">
-        <template v-if="isCurrentUserAssignee()">
+      <!-- 宸插埌杈剧姸鎬侊細鏄剧ず宸茶繑绋� -->
+      <template v-else-if="taskDetail.taskStatus === TaskStatus.ARRIVED">
+        <template v-if="canOperateTask()">
           <button 
             class="action-btn primary" 
             @click="handleTaskAction('return')"
@@ -508,15 +529,34 @@
         </template>
       </template>
       
-      <!-- 杩旂▼涓姸鎬�: 鏄剧ず宸插畬鎴� -->
-      <template v-else-if="taskDetail.taskStatus === 'RETURNING'">
-        <template v-if="isCurrentUserAssignee()">
+      <!-- 杩旂▼涓姸鎬侊細鏄剧ず宸插畬鎴� -->
+      <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>
       
@@ -535,12 +575,14 @@
 </template>
 
 <script>
-  import { getTask, changeTaskStatus, setAssigneeReady, checkTaskConsentAttachment } from '@/api/task'
+  import { getTask, changeTaskStatus, setAssigneeReady, checkTaskConsentAttachment, syncTaskStatus } 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'
   
@@ -550,6 +592,7 @@
     },
     data() {
       return {
+        TaskStatus, // 鏆撮湶 TaskStatus 缁欐ā鏉夸娇鐢�
         taskDetail: null,
         taskId: null,
         paymentInfo: null, // 鏀粯淇℃伅
@@ -560,7 +603,9 @@
         forceCompleteForm: {
           actualStartTime: '',
           actualEndTime: ''
-        }
+        },
+        hasInvoiceApplied: false, // 鏄惁宸茬敵璇峰彂绁�
+        invoiceStatus: null // 鍙戠エ鐘舵�侊細0-寰呭鏍�, 1-宸查�氳繃, 2-宸查┏鍥�
       }
     },
     computed: {
@@ -570,6 +615,16 @@
           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
       },
       
       // 鐢熸垚鎵ц浜哄憳瑙掕壊鏍囩鐨勭被鍚�
@@ -613,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 ''
       },
       // 鏄剧ず璁″垝寮�濮嬫椂闂�
@@ -672,6 +727,8 @@
       this.taskId = options.id
       this.loadTaskDetail()
       this.loadCancelReasonDict() // 鍔犺浇鍙栨秷鍘熷洜瀛楀吀
+      // 妫�鏌ュ彂绁ㄧ敵璇风姸鎬�
+      this.checkInvoiceStatus()
     },
     onShow() {
       // 姣忔椤甸潰鏄剧ず鏃堕噸鏂板姞杞芥暟鎹紝纭繚浠庣紪杈戦〉闈㈣繑鍥炲悗鑳界湅鍒版渶鏂版暟鎹�
@@ -843,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)
       },
       
       // 鑾峰彇鐢ㄦ埛绫诲瀷鏍囩
@@ -888,9 +929,29 @@
           return
         }
         
-        uni.navigateTo({
-          url: '/pagesTask/settlement?taskId=' + this.taskId
-        })
+        // 妫�鏌ヤ换鍔$紪鍙锋槸鍚︿互T2寮�澶达紙鏈悓姝ュ埌鏃х郴缁燂級
+        const serviceCode = this.taskDetail.showTaskCode;
+        if (serviceCode && serviceCode.startsWith('T2')) {
+          // 鍏堝悓姝ュ啀杩涘叆缁撶畻椤�
+          uni.showLoading({ title: '鍚屾涓�...' })
+          syncTaskStatus(this.taskId).then(() => {
+            uni.hideLoading()
+            uni.navigateTo({
+              url: '/pagesTask/settlement?taskId=' + this.taskId
+            })
+          }).catch((err) => {
+            uni.hideLoading()
+            // 鍚屾澶辫触涓嶉樆鏂粨绠楋紝鍙褰曟棩蹇�
+            console.warn('浠诲姟鍚屾鏃х郴缁熷け璐ワ紝涓嶅奖鍝嶇粨绠楁祦绋�:', err)
+            uni.navigateTo({
+              url: '/pagesTask/settlement?taskId=' + this.taskId
+            })
+          })
+        } else {
+          uni.navigateTo({
+            url: '/pagesTask/settlement?taskId=' + this.taskId
+          })
+        }
       },
       
       // 澶勭悊浠诲姟鎿嶄綔
@@ -913,10 +974,8 @@
             break;
             
           case 'forceCancel':
-            // 寮哄埗缁撴潫 -> 鐘舵�佸彉涓哄凡鍙栨秷
-            this.$modal.confirm('纭畾瑕佸己鍒剁粨鏉熸浠诲姟鍚楋紵').then(() => {
-              this.updateTaskStatus('CANCELLED', '浠诲姟宸插己鍒剁粨鏉�')
-            }).catch(() => {});
+            // 寮哄埗鍙栨秷 -> 鏄剧ず鍙栨秷鍘熷洜閫夋嫨瀵硅瘽妗�
+            this.showCancelReasonDialog();
             break;
             
           case 'return':
@@ -1033,6 +1092,45 @@
         }
         
         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}`
+        });
       },
       
       // 鏇存柊浠诲姟鐘舵��
@@ -1421,9 +1519,14 @@
         console.log('闄勪欢鍒犻櫎鎴愬姛:', attachmentId)
       },
 
-      // 鏄惁鏄剧ず鈥滃氨缁�濆姛鑳斤紙閰嶇疆寮�鍏筹級
+      // 鏄惁鏄剧ず"灏辩华"鍔熻兘锛堥厤缃紑鍏筹級
       showAssigneeReadyFeature() {
         return !!(config && config.features && config.features.showAssigneeReadyButton)
+      },
+            
+      // 鏄惁鏄剧ず"寮哄埗瀹屾垚"鍔熻兘锛堥厤缃紑鍏筹級
+      showForceCompleteFeature() {
+        return !!(config && config.features && config.features.showForceCompleteButton)
       },
 
       // 褰撳墠鐢ㄦ埛鏄惁涓鸿鎵ц浜�
@@ -1497,6 +1600,19 @@
         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()
       },
 
       // 鏄惁澶氫汉鎵ц
@@ -1871,12 +1987,18 @@
       }
       
       .edit-btn {
-        width: 60rpx;
+        width: 120rpx;
         height: 60rpx;
         display: flex;
         align-items: center;
         justify-content: center;
         cursor: pointer;
+        
+        .edit-text {
+          margin-left: 8rpx;
+          font-size: 28rpx;
+          color: #007AFF;
+        }
       }
     }
     
@@ -2192,10 +2314,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;
@@ -2209,6 +2334,11 @@
         
         &.cancel {
           background-color: #ff3b30;
+          color: white;
+        }
+        
+        &.force-end {
+          background-color: #ff6b22;
           color: white;
         }
         
@@ -2253,6 +2383,20 @@
       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 {

--
Gitblit v1.9.1