From 77b8624957ea9afafc81af72e52212c15b5f091e Mon Sep 17 00:00:00 2001
From: wlzboy <66905212@qq.com>
Date: 星期四, 25 十二月 2025 01:34:32 +0800
Subject: [PATCH] feat: 优化新建 保存同步
---
app/pagesTask/detail.vue | 342 +++++++++++++++++++++++++++++++++++++++++++++++---------
1 files changed, 287 insertions(+), 55 deletions(-)
diff --git a/app/pagesTask/detail.vue b/app/pagesTask/detail.vue
index 8cf97d9..c6b060a 100644
--- a/app/pagesTask/detail.vue
+++ b/app/pagesTask/detail.vue
@@ -14,7 +14,8 @@
<view class="label">浠诲姟缂栧彿</view>
<view class="value">
{{ taskDetail.showTaskCode }}
- <text v-if="taskDetail.isHeadPush === '1'" class="head-push-tag">鎬�</text>
+ <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">
@@ -54,21 +55,12 @@
<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)
- }"
- >
+ :class="{'ready': isAssigneeReady(assignee),'unready': !isAssigneeReady(assignee)}">
{{ isAssigneeReady(assignee) ? '宸插氨缁�' : '鏈氨缁�' }}
</view>
</view>
@@ -105,13 +97,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>
<!-- 绂忕杞︿换鍔★細鏄剧ず鎺ラ��/鐩殑鍦板潃 -->
@@ -257,6 +249,23 @@
</view>
</view>
+ <!-- 鍙栨秷淇℃伅锛堜粎鍦ㄤ换鍔″凡鍙栨秷涓旀湁鍙栨秷鍘熷洜鏃舵樉绀猴級 -->
+ <view class="detail-section" v-if="taskDetail.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>
@@ -363,6 +372,26 @@
<uni-icons type="spinner-cycle" size="40" color="#007AFF"></uni-icons>
<text>鍔犺浇涓�...</text>
</view>
+
+ <!-- 鍙栨秷鍘熷洜閫夋嫨瀵硅瘽妗� -->
+ <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">
@@ -472,9 +501,10 @@
</template>
<script>
- import { getTask, changeTaskStatus, setAssigneeReady } 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 { formatDateTime } from '@/utils/common'
import { validateTaskForDepart, validateTaskForSettlement, getTaskVehicleId, checkTaskCanDepart } from '@/utils/taskValidator'
import AttachmentUpload from './components/AttachmentUpload.vue'
@@ -488,7 +518,10 @@
return {
taskDetail: null,
taskId: null,
- paymentInfo: null // 鏀粯淇℃伅
+ paymentInfo: null, // 鏀粯淇℃伅
+ cancelReasonList: [], // 鍙栨秷鍘熷洜鍒楄〃
+ showCancelDialog: false, // 鏄剧ず鍙栨秷鍘熷洜瀵硅瘽妗�
+ selectedCancelReason: '' // 閫変腑鐨勫彇娑堝師鍥�
}
},
computed: {
@@ -498,6 +531,28 @@
return false
}
return ['COMPLETED', 'CANCELLED'].includes(this.taskDetail.taskStatus)
+ },
+
+ // 鐢熸垚鎵ц浜哄憳瑙掕壊鏍囩鐨勭被鍚�
+ 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() {
@@ -531,9 +586,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
},
@@ -543,9 +598,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
},
@@ -555,9 +610,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
},
@@ -567,9 +622,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
}
@@ -577,6 +632,7 @@
onLoad(options) {
this.taskId = options.id
this.loadTaskDetail()
+ this.loadCancelReasonDict() // 鍔犺浇鍙栨秷鍘熷洜瀛楀吀
},
onShow() {
// 姣忔椤甸潰鏄剧ず鏃堕噸鏂板姞杞芥暟鎹紝纭繚浠庣紪杈戦〉闈㈣繑鍥炲悗鑳界湅鍒版渶鏂版暟鎹�
@@ -594,13 +650,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') {
@@ -812,10 +862,8 @@
break;
case 'cancel':
- // 鍙栨秷 -> 浜屾纭鍚庣姸鎬佸彉涓哄凡鍙栨秷
- this.$modal.confirm('纭畾瑕佸彇娑堟浠诲姟鍚楋紵').then(() => {
- this.updateTaskStatus('CANCELLED', '浠诲姟宸插彇娑�')
- }).catch(() => {});
+ // 鍙栨秷 -> 鏄剧ず鍙栨秷鍘熷洜閫夋嫨瀵硅瘽妗�
+ this.showCancelReasonDialog();
break;
case 'arrive':
@@ -950,12 +998,54 @@
// 鏇存柊浠诲姟鐘舵��
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: '妫�鏌ラ檮浠�...'
+ });
+
+ const response = await checkTaskConsentAttachment(this.taskId);
+
+ uni.hideLoading();
+
+ if (response.code === 200) {
+ // 宸蹭笂浼犵煡鎯呭悓鎰忎功锛岀户缁洿鏂扮姸鎬�
+ this.getLocationAndUpdateStatus(status, remark);
+ } else {
+ // 鏈笂浼犵煡鎯呭悓鎰忎功锛屾樉绀烘彁绀�
+ this.$modal.confirm('浠诲姟鏈笂浼犵煡鎯呭悓鎰忎功锛屾棤娉曞畬鎴愪换鍔°�傛槸鍚︾幇鍦ㄥ幓涓婁紶锛�').then(() => {
+ // 婊氬姩鍒伴檮浠朵笂浼犲尯鍩�
+ this.$nextTick(() => {
+ uni.pageScrollTo({
+ scrollTop: 9999, // 婊氬姩鍒板簳閮�
+ duration: 300
+ });
+ });
+ }).catch(() => {});
+ }
+ } catch (error) {
+ uni.hideLoading();
+ console.error('妫�鏌ラ檮浠跺け璐�:', error);
+
+ // 濡傛灉妫�鏌ュけ璐ワ紝璇㈤棶鐢ㄦ埛鏄惁缁х画
+ this.$modal.confirm('妫�鏌ラ檮浠剁姸鎬佸け璐ワ紝鏄惁缁х画瀹屾垚浠诲姟锛�').then(() => {
+ this.getLocationAndUpdateStatus(status, remark);
+ }).catch(() => {});
+ }
},
// 鑾峰彇浣嶇疆淇℃伅骞舵洿鏂扮姸鎬�
- getLocationAndUpdateStatus(status, remark) {
+ getLocationAndUpdateStatus(status, remark, cancelReason) {
const that = this
// 浣跨敤uni.getLocation鑾峰彇GPS浣嶇疆
@@ -982,6 +1072,11 @@
heading: res.direction || res.heading
}
+ // 濡傛灉鏈夊彇娑堝師鍥狅紝娣诲姞鍒拌姹傛暟鎹腑
+ if (cancelReason) {
+ statusData.cancelReason = cancelReason
+ }
+
changeTaskStatus(that.taskId, statusData).then(response => {
that.$modal.showToast('鐘舵�佹洿鏂版垚鍔�')
// 閲嶆柊鍔犺浇浠诲姟璇︽儏
@@ -999,6 +1094,11 @@
const statusData = {
taskStatus: status,
remark: remark
+ }
+
+ // 濡傛灉鏈夊彇娑堝師鍥狅紝娣诲姞鍒拌姹傛暟鎹腑
+ if (cancelReason) {
+ statusData.cancelReason = cancelReason
}
changeTaskStatus(that.taskId, statusData).then(response => {
@@ -1430,6 +1530,65 @@
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) {
+ this.selectedCancelReason = e.detail.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
+ },
+
}
}
</script>
@@ -1462,17 +1621,6 @@
font-weight: bold;
color: #333;
}
- }
-
- // 鎬婚儴鎺ㄩ�佹爣璁版牱寮�
- .head-push-tag {
- color: #ff0000;
- font-size: 24rpx;
- font-weight: bold;
- margin-left: 10rpx;
- padding: 2rpx 8rpx;
- border: 1rpx solid #ff0000;
- border-radius: 4rpx;
}
.detail-content {
@@ -1816,5 +1964,89 @@
}
}
}
+
+ .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;
+ }
+
+ // 鍙栨秷鍘熷洜瀵硅瘽妗嗘牱寮�
+ .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;
+ }
+ }
+ }
+ }
}
</style>
\ No newline at end of file
--
Gitblit v1.9.1