From 6676a35122fd9c97d1b1679c211bc8a9b97f08f2 Mon Sep 17 00:00:00 2001
From: wlzboy <66905212@qq.com>
Date: 星期二, 24 三月 2026 23:17:37 +0800
Subject: [PATCH] feat: 增加日志记录历史消息
---
ruoyi-ui/src/views/task/general/detail.vue | 640 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 632 insertions(+), 8 deletions(-)
diff --git a/ruoyi-ui/src/views/task/general/detail.vue b/ruoyi-ui/src/views/task/general/detail.vue
index 3685884..3cf49f3 100644
--- a/ruoyi-ui/src/views/task/general/detail.vue
+++ b/ruoyi-ui/src/views/task/general/detail.vue
@@ -8,7 +8,7 @@
<!-- 鍩烘湰淇℃伅 -->
<el-descriptions title="鍩烘湰淇℃伅" :column="2" border>
- <el-descriptions-item label="浠诲姟缂栧彿">{{ taskDetail.taskCode }}</el-descriptions-item>
+ <el-descriptions-item label="浠诲姟缂栧彿">{{ taskDetail.showTaskCode }}</el-descriptions-item>
<el-descriptions-item label="浠诲姟绫诲瀷">
<dict-tag :options="dict.type.sys_task_type" :value="taskDetail.taskType"/>
</el-descriptions-item>
@@ -33,11 +33,11 @@
<!-- 鎬ユ晳杞繍浠诲姟鎵╁睍淇℃伅 -->
<el-descriptions v-if="taskDetail.taskType === 'EMERGENCY_TRANSFER' && taskDetail.emergencyInfo" title="鎬ユ晳杞繍淇℃伅" :column="2" border style="margin-top: 20px;">
<el-descriptions-item label="鑱旂郴浜�">
- <span v-if="taskDetail.emergencyInfo.contactPerson">{{ taskDetail.emergencyInfo.contactPerson }}</span>
+ <span v-if="taskDetail.emergencyInfo.patientContact">{{ taskDetail.emergencyInfo.patientContact }}</span>
<span v-else style="color: #C0C4CC;">--</span>
</el-descriptions-item>
<el-descriptions-item label="鑱旂郴鐢佃瘽">
- <span v-if="taskDetail.emergencyInfo.contactPhone">{{ taskDetail.emergencyInfo.contactPhone }}</span>
+ <span v-if="taskDetail.emergencyInfo.patientPhone">{{ taskDetail.emergencyInfo.patientPhone }}</span>
<span v-else style="color: #C0C4CC;">--</span>
</el-descriptions-item>
<el-descriptions-item label="鎮h�呭鍚�">
@@ -53,7 +53,7 @@
<span v-else style="color: #C0C4CC;">--</span>
</el-descriptions-item>
<el-descriptions-item label="鐥呮儏鎻忚堪" :span="2">
- <span v-if="taskDetail.emergencyInfo.illnessDescription">{{ taskDetail.emergencyInfo.illnessDescription }}</span>
+ <span v-if="taskDetail.emergencyInfo.patientCondition">{{ taskDetail.emergencyInfo.patientCondition }}</span>
<span v-else style="color: #C0C4CC;">--</span>
</el-descriptions-item>
</el-descriptions>
@@ -74,10 +74,26 @@
<i class="el-icon-error"></i> 鍚屾澶辫触
</el-tag>
<span v-else style="color: #C0C4CC;">--</span>
+ <!-- 鏈悓姝ユ垨鍚屾澶辫触鏃舵樉绀哄悓姝ユ寜閽� -->
+ <el-button
+ v-if="taskDetail.emergencyInfo.syncStatus === 0 || taskDetail.emergencyInfo.syncStatus === 3"
+ type="primary"
+ size="mini"
+ icon="el-icon-refresh"
+ :loading="syncingServiceOrder"
+ @click="syncServiceOrder"
+ style="margin-left: 10px;"
+ >鍚屾鏈嶅姟鍗�</el-button>
</el-descriptions-item>
<el-descriptions-item label="鏈嶅姟鍗曞彿">
<span v-if="taskDetail.emergencyInfo.legacyServiceOrdId">
<el-tag type="primary" size="small">{{ taskDetail.emergencyInfo.legacyServiceOrdId }}</el-tag>
+ </span>
+ <span v-else style="color: #C0C4CC;">--</span>
+ </el-descriptions-item>
+ <el-descriptions-item label="鏈嶅姟鍗曠紪鐮�">
+ <span v-if="taskDetail.emergencyInfo.serviceCode">
+ <el-tag type="success" size="small">{{ taskDetail.emergencyInfo.serviceCode }}</el-tag>
</span>
<span v-else style="color: #C0C4CC;">--</span>
</el-descriptions-item>
@@ -103,10 +119,36 @@
<i class="el-icon-error"></i> 鍚屾澶辫触
</el-tag>
<span v-else style="color: #C0C4CC;">--</span>
+ <!-- 鏈悓姝ユ垨鍚屾澶辫触鏃舵樉绀哄悓姝ユ寜閽� -->
+ <el-button
+ v-if="taskDetail.emergencyInfo.dispatchSyncStatus === 0 || taskDetail.emergencyInfo.dispatchSyncStatus === 3"
+ type="primary"
+ size="mini"
+ icon="el-icon-refresh"
+ :loading="syncingDispatchOrder"
+ @click="syncDispatchOrder"
+ style="margin-left: 10px;"
+ >鍚屾璋冨害鍗�</el-button>
+ <!-- 浠庢棫绯荤粺鍚屾鏁版嵁鍒版柊绯荤粺鎸夐挳 -->
+ <el-button
+ v-if="taskDetail.emergencyInfo.legacyServiceOrdId && taskDetail.emergencyInfo.legacyDispatchOrdId"
+ type="success"
+ size="mini"
+ icon="el-icon-download"
+ :loading="syncingFromLegacy"
+ @click="syncFromLegacySystem"
+ style="margin-left: 10px;"
+ >浠庢棫绯荤粺鍚屾</el-button>
</el-descriptions-item>
<el-descriptions-item label="璋冨害鍗曞彿">
<span v-if="taskDetail.emergencyInfo.legacyDispatchOrdId">
<el-tag type="primary" size="small">{{ taskDetail.emergencyInfo.legacyDispatchOrdId }}</el-tag>
+ </span>
+ <span v-else style="color: #C0C4CC;">--</span>
+ </el-descriptions-item>
+ <el-descriptions-item label="璋冨害鍗曠紪鐮�">
+ <span v-if="taskDetail.emergencyInfo.dispatchCode">
+ <el-tag type="success" size="small">{{ taskDetail.emergencyInfo.dispatchCode }}</el-tag>
</span>
<span v-else style="color: #C0C4CC;">--</span>
</el-descriptions-item>
@@ -118,7 +160,197 @@
<span v-if="taskDetail.emergencyInfo.dispatchSyncErrorMsg" style="color: #F56C6C;">{{ taskDetail.emergencyInfo.dispatchSyncErrorMsg }}</span>
<span v-else style="color: #C0C4CC;">--</span>
</el-descriptions-item>
+ <el-descriptions-item label="浠诲姟鐘舵�佸悓姝�" :span="2">
+ <el-alert
+ title="鎻愮ず锛氫换鍔$姸鎬佷細鑷姩鍚屾鍒版棫绯荤粺鐨勮皟搴﹀崟涓紝濡傛灉鍥犵綉缁滅瓑鍘熷洜鏈悓姝ワ紝鍙偣鍑讳笅鏂规寜閽墜鍔ㄥ悓姝ャ��"
+ type="info"
+ :closable="false"
+ show-icon
+ style="margin-bottom: 10px;">
+ </el-alert>
+ <el-button
+ v-if="taskDetail.emergencyInfo.legacyDispatchOrdId && taskDetail.emergencyInfo.legacyDispatchOrdId > 0"
+ type="warning"
+ size="small"
+ icon="el-icon-refresh"
+ :loading="syncingTaskStatus"
+ @click="syncTaskStatus"
+ >鍚屾浠诲姟鐘舵�佸埌鏃х郴缁�</el-button>
+ <el-tag v-else type="info" size="small">
+ <i class="el-icon-warning"></i> 璇峰厛鍚屾璋冨害鍗�
+ </el-tag>
+ </el-descriptions-item>
</el-descriptions>
+
+ <!-- 鏀粯淇℃伅锛堜粎鎬ユ晳杞繍浠诲姟鏄剧ず锛� -->
+ <el-card v-if="taskDetail.taskType === 'EMERGENCY_TRANSFER' && paymentInfo" class="box-card" style="margin-top: 20px;">
+ <div slot="header" class="clearfix">
+ <span>鏀粯淇℃伅</span>
+ <!-- 宸插畬鎴愪笖鏈敵璇峰彂绁ㄦ椂鏄剧ず鐢宠鍙戠エ鎸夐挳 -->
+ <el-button
+ v-if="canApplyInvoice"
+ style="float: right; padding: 3px 0"
+ type="text"
+ @click="handleApplyInvoice"
+ v-hasPermi="['system:invoice:add']"
+ >
+ <i class="el-icon-document-add"></i> 鐢宠鍙戠エ
+ </el-button>
+ </div>
+
+ <!-- 鏀粯姒傝 -->
+ <el-descriptions :column="3" border>
+ <el-descriptions-item label="鍩烘湰浠锋牸">
+ <span style="color: #409EFF; font-weight: bold;">楼{{ paymentInfo.transferPrice || '0.00' }}</span>
+ </el-descriptions-item>
+ <el-descriptions-item label="闄勫姞璐圭敤鎬婚">
+ <span style="color: #E6A23C; font-weight: bold;">楼{{ paymentInfo.additionalAmount || '0.00' }}</span>
+ </el-descriptions-item>
+ <el-descriptions-item label="鎬婚噾棰�">
+ <span style="color: #67C23A; font-weight: bold;">楼{{ paymentInfo.totalAmount || '0.00' }}</span>
+ </el-descriptions-item>
+ <el-descriptions-item label="宸叉敮浠橀噾棰�">
+ <span style="color: #67C23A; font-weight: bold;">楼{{ paymentInfo.paidAmount || '0.00' }}</span>
+ </el-descriptions-item>
+ <el-descriptions-item label="鍓╀綑鏈粯閲戦">
+ <span style="color: #F56C6C; font-weight: bold;">楼{{ getRemainingAmount() }}</span>
+ </el-descriptions-item>
+ <el-descriptions-item label="鏀粯鐘舵��">
+ <el-tag v-if="getRemainingAmount() <= 0" type="success" size="small">
+ <i class="el-icon-success"></i> 宸茬粨娓�
+ </el-tag>
+ <el-tag v-else-if="paymentInfo.paidAmount > 0" type="warning" size="small">
+ <i class="el-icon-warning"></i> 閮ㄥ垎鏀粯
+ </el-tag>
+ <el-tag v-else type="info" size="small">
+ <i class="el-icon-warning"></i> 鏈敮浠�
+ </el-tag>
+ </el-descriptions-item>
+ </el-descriptions>
+
+ <!-- 闄勫姞璐圭敤鏄庣粏 -->
+ <div style="margin-top: 20px;">
+ <h4 style="margin-bottom: 10px;">闄勫姞璐圭敤鏄庣粏</h4>
+ <el-table :data="paymentInfo.additionalFees" border>
+ <el-table-column label="璐圭敤绫诲瀷" align="center" prop="feeType" width="120">
+ <template slot-scope="scope">
+ <dict-tag :options="dict.type.task_additional_fee_type" :value="scope.row.feeType"/>
+ </template>
+ </el-table-column>
+ <el-table-column label="璐圭敤鍚嶇О" align="center" prop="feeName" />
+ <el-table-column label="鍗曚环" align="center" prop="unitAmount" width="120">
+ <template slot-scope="scope">
+ <span>楼{{ scope.row.unitAmount }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鏁伴噺" align="center" prop="quantity" width="80" />
+ <el-table-column label="灏忚" align="center" prop="totalAmount" width="120">
+ <template slot-scope="scope">
+ <span style="color: #E6A23C; font-weight: bold;">楼{{ scope.row.totalAmount }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鍚屾鐘舵��" align="center" width="120">
+ <template slot-scope="scope">
+ <el-tag v-if="scope.row.syncStatus === 0" type="info" size="small">
+ <i class="el-icon-warning"></i> 鏈悓姝�
+ </el-tag>
+ <el-tag v-else-if="scope.row.syncStatus === 1" type="warning" size="small">
+ <i class="el-icon-loading"></i> 鍚屾涓�
+ </el-tag>
+ <el-tag v-else-if="scope.row.syncStatus === 2" type="success" size="small">
+ <i class="el-icon-success"></i> 鍚屾鎴愬姛
+ </el-tag>
+ <el-tag v-else-if="scope.row.syncStatus === 3" type="danger" size="small">
+ <i class="el-icon-error"></i> 鍚屾澶辫触
+ </el-tag>
+ <span v-else style="color: #C0C4CC;">--</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="澶囨敞" align="center" prop="remark" show-overflow-tooltip>
+ <template slot-scope="scope">
+ <span v-if="scope.row.remark">{{ scope.row.remark }}</span>
+ <span v-else style="color: #C0C4CC;">--</span>
+ </template>
+ </el-table-column>
+ </el-table>
+
+ <!-- 绌虹姸鎬佹彁绀� -->
+ <div v-if="!paymentInfo.additionalFees || paymentInfo.additionalFees.length === 0" style="text-align: center; padding: 40px 0; color: #909399;">
+ <i class="el-icon-document" style="font-size: 48px; display: block; margin-bottom: 12px;"></i>
+ <span>鏆傛棤闄勫姞璐圭敤</span>
+ </div>
+ </div>
+
+ <!-- 宸叉敮浠樿褰� -->
+ <div style="margin-top: 20px;">
+ <h4 style="margin-bottom: 10px;">宸叉敮浠樿褰�</h4>
+ <el-table :data="paymentInfo.paidPayments" border>
+ <el-table-column label="鍟嗘埛璁㈠崟鍙�" align="center" prop="outTradeNo" width="200" show-overflow-tooltip />
+ <el-table-column label="鏀粯閲戦" align="center" prop="settlementAmount" width="120">
+ <template slot-scope="scope">
+ <span style="color: #67C23A; font-weight: bold;">楼{{ scope.row.settlementAmount }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鏀粯鏂瑰紡" align="center" prop="paymentMethod" width="120">
+ <template slot-scope="scope">
+ <dict-tag :options="dict.type.task_payment_method" :value="scope.row.paymentMethod"/>
+ </template>
+ </el-table-column>
+ <el-table-column label="鏀粯鐘舵��" align="center" prop="payStatus" width="120">
+ <template slot-scope="scope">
+ <el-tag v-if="scope.row.payStatus === 'PAID'" type="success" size="small">
+ <i class="el-icon-success"></i> 宸叉敮浠�
+ </el-tag>
+ <el-tag v-else-if="scope.row.payStatus === 'PENDING'" type="warning" size="small">
+ <i class="el-icon-time"></i> 寰呮敮浠�
+ </el-tag>
+ <el-tag v-else-if="scope.row.payStatus === 'FAILED'" type="danger" size="small">
+ <i class="el-icon-error"></i> 澶辫触
+ </el-tag>
+ <el-tag v-else type="info" size="small">
+ {{ scope.row.payStatus }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column label="浜ゆ槗鍙�" align="center" prop="tradeNo" width="150" show-overflow-tooltip />
+ <el-table-column label="鏀粯鏃堕棿" align="center" prop="payTime" width="180">
+ <template slot-scope="scope">
+ <span v-if="scope.row.payTime">{{ parseTime(scope.row.payTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
+ <span v-else style="color: #C0C4CC;">--</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鍚屾鐘舵��" align="center" width="120">
+ <template slot-scope="scope">
+ <el-tag v-if="scope.row.syncStatus === 0" type="info" size="small">
+ <i class="el-icon-warning"></i> 鏈悓姝�
+ </el-tag>
+ <el-tag v-else-if="scope.row.syncStatus === 1" type="warning" size="small">
+ <i class="el-icon-loading"></i> 鍚屾涓�
+ </el-tag>
+ <el-tag v-else-if="scope.row.syncStatus === 2" type="success" size="small">
+ <i class="el-icon-success"></i> 鍚屾鎴愬姛
+ </el-tag>
+ <el-tag v-else-if="scope.row.syncStatus === 3" type="danger" size="small">
+ <i class="el-icon-error"></i> 鍚屾澶辫触
+ </el-tag>
+ <span v-else style="color: #C0C4CC;">--</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="澶囨敞" align="center" prop="remark" show-overflow-tooltip>
+ <template slot-scope="scope">
+ <span v-if="scope.row.remark">{{ scope.row.remark }}</span>
+ <span v-else style="color: #C0C4CC;">--</span>
+ </template>
+ </el-table-column>
+ </el-table>
+
+ <!-- 绌虹姸鎬佹彁绀� -->
+ <div v-if="!paymentInfo.paidPayments || paymentInfo.paidPayments.length === 0" style="text-align: center; padding: 40px 0; color: #909399;">
+ <i class="el-icon-document" style="font-size: 48px; display: block; margin-bottom: 12px;"></i>
+ <span>鏆傛棤鏀粯璁板綍</span>
+ </div>
+ </div>
+ </el-card>
<!-- 绂忕杞︿换鍔℃墿灞曚俊鎭� -->
<el-descriptions v-if="taskDetail.taskType === 'WELFARE' && taskDetail.welfareInfo" title="绂忕杞︽湇鍔′俊鎭�" :column="2" border style="margin-top: 20px;">
@@ -146,11 +378,53 @@
</el-descriptions>
<!-- 鎿嶄綔鎸夐挳 -->
- <div style="margin-top: 20px; text-align: center;">
+ <!-- <div style="margin-top: 20px; text-align: center;">
<el-button type="primary" @click="handleEdit" v-hasPermi="['task:general:edit']">缂栬緫浠诲姟</el-button>
<el-button type="success" @click="handleAssign" v-hasPermi="['task:general:assign']">鍒嗛厤浠诲姟</el-button>
<el-button type="warning" @click="handleStatusChange" v-hasPermi="['task:general:status']">鐘舵�佸彉鏇�</el-button>
<el-button type="info" @click="handleVehicleAssign" v-hasPermi="['task:general:assign']">鍒嗛厤杞﹁締</el-button>
+ </div> -->
+ </el-card>
+
+ <!-- 鎵ц浜哄憳鍒楄〃 -->
+ <el-card class="box-card" style="margin-top: 20px;">
+ <div slot="header" class="clearfix">
+ <span>鎵ц浜哄憳</span>
+ </div>
+
+ <el-table :data="taskDetail.assignees" v-loading="assigneeLoading">
+ <el-table-column label="搴忓彿" align="center" width="60">
+ <template slot-scope="scope">
+ <span>{{ scope.$index + 1 }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="濮撳悕" align="center" prop="userName">
+ <template slot-scope="scope">
+ <span>{{ scope.row.userName }}</span>
+ <el-tag v-if="scope.row.isPrimary === '1'" type="warning" size="mini" style="margin-left: 8px;">
+ <i class="el-icon-star-on"></i> 璐熻矗浜�
+ </el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column label="瑙掕壊绫诲瀷" align="center" prop="userType" width="120">
+ <template slot-scope="scope">
+ <el-tag v-if="scope.row.userType === 'driver'" type="primary" size="small">鍙告満</el-tag>
+ <el-tag v-else-if="scope.row.userType === 'doctor'" type="success" size="small">鍖荤敓</el-tag>
+ <el-tag v-else-if="scope.row.userType === 'nurse'" type="info" size="small">鎶ゅ+</el-tag>
+ <el-tag v-else type="" size="small">{{ scope.row.userType }}</el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180">
+ <template slot-scope="scope">
+ <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
+ </template>
+ </el-table-column>
+ </el-table>
+
+ <!-- 绌虹姸鎬佹彁绀� -->
+ <div v-if="!taskDetail.assignees || taskDetail.assignees.length === 0" style="text-align: center; padding: 40px 0; color: #909399;">
+ <i class="el-icon-user" style="font-size: 48px; display: block; margin-bottom: 12px;"></i>
+ <span>鏆傛棤鎵ц浜哄憳</span>
</div>
</el-card>
@@ -261,6 +535,119 @@
</template>
</el-table-column>
</el-table>
+ </el-card>
+
+ <!-- 闄勫姞璐圭敤鍒楄〃 -->
+ <el-card class="box-card" style="margin-top: 20px;">
+ <div slot="header" class="clearfix">
+ <span>闄勫姞璐圭敤鍒楄〃</span>
+ </div>
+
+ <el-table :data="additionalFeeList" v-loading="feeLoading">
+ <el-table-column label="璐圭敤绫诲瀷" align="center" prop="feeType" width="120">
+ <template slot-scope="scope">
+ <dict-tag :options="dict.type.task_additional_fee_type" :value="scope.row.feeType"/>
+ </template>
+ </el-table-column>
+ <el-table-column label="璐圭敤鍚嶇О" align="center" prop="feeName" />
+ <el-table-column label="鍗曚环" align="center" prop="unitAmount" width="120">
+ <template slot-scope="scope">
+ <span>楼{{ scope.row.unitAmount }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鏁伴噺" align="center" prop="quantity" width="80" />
+ <el-table-column label="鎬婚噾棰�" align="center" prop="totalAmount" width="120">
+ <template slot-scope="scope">
+ <span style="color: #E6A23C; font-weight: bold;">楼{{ scope.row.totalAmount }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鍚屾鐘舵��" align="center" width="120">
+ <template slot-scope="scope">
+ <el-tag v-if="scope.row.syncStatus === 0" type="info" size="small">
+ <i class="el-icon-warning"></i> 鏈悓姝�
+ </el-tag>
+ <el-tag v-else-if="scope.row.syncStatus === 1" type="warning" size="small">
+ <i class="el-icon-loading"></i> 鍚屾涓�
+ </el-tag>
+ <el-tag v-else-if="scope.row.syncStatus === 2" type="success" size="small">
+ <i class="el-icon-success"></i> 鍚屾鎴愬姛
+ </el-tag>
+ <el-tag v-else-if="scope.row.syncStatus === 3" type="danger" size="small">
+ <i class="el-icon-error"></i> 鍚屾澶辫触
+ </el-tag>
+ <span v-else style="color: #C0C4CC;">--</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鍚屾鏃堕棿" align="center" prop="syncTime" width="180">
+ <template slot-scope="scope">
+ <span v-if="scope.row.syncTime">{{ parseTime(scope.row.syncTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
+ <span v-else style="color: #C0C4CC;">--</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createdTime" width="180">
+ <template slot-scope="scope">
+ <span>{{ parseTime(scope.row.createdTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鍒涘缓鑰�" align="center" prop="createdBy" width="100" />
+ <el-table-column label="澶囨敞" align="center" prop="remark" show-overflow-tooltip>
+ <template slot-scope="scope">
+ <span v-if="scope.row.remark">{{ scope.row.remark }}</span>
+ <span v-else style="color: #C0C4CC;">--</span>
+ </template>
+ </el-table-column>
+ </el-table>
+
+ <!-- 绌虹姸鎬佹彁绀� -->
+ <div v-if="!additionalFeeList || additionalFeeList.length === 0" style="text-align: center; padding: 40px 0; color: #909399;">
+ <i class="el-icon-document" style="font-size: 48px; display: block; margin-bottom: 12px;"></i>
+ <span>鏆傛棤闄勫姞璐圭敤</span>
+ </div>
+ </el-card>
+
+ <!-- 鐘舵�佸彉鏇村巻鍙� -->
+ <el-card class="box-card" style="margin-top: 20px;">
+ <div slot="header" class="clearfix">
+ <span>鐘舵�佸彉鏇村巻鍙�</span>
+ </div>
+
+ <el-timeline v-if="statusHistoryList && statusHistoryList.length > 0">
+ <el-timeline-item
+ v-for="item in statusHistoryList"
+ :key="item.id"
+ :timestamp="parseTime(item.changeTime)"
+ :color="getStatusColor(item.toStatus)"
+ placement="top"
+ >
+ <el-card shadow="never" class="status-history-card">
+ <div class="status-history-header">
+ <span class="status-arrow">
+ <el-tag v-if="item.fromStatus" size="small" :type="getTagType(item.fromStatus)">{{ item.fromStatusName || item.fromStatus }}</el-tag>
+ <span v-else style="color: #C0C4CC; font-size: 13px;">鍒濆鍒涘缓</span>
+ <i class="el-icon-arrow-right" style="margin: 0 8px; color: #909399;"></i>
+ <el-tag size="small" :type="getTagType(item.toStatus)">{{ item.toStatusName || item.toStatus }}</el-tag>
+ </span>
+ <el-tag size="mini" :type="getSourceTagType(item.changeSource)" style="margin-left: 12px;">
+ {{ getSourceLabel(item.changeSource) }}
+ </el-tag>
+ </div>
+ <div style="margin-top: 8px; color: #606266; font-size: 13px;">
+ <span><i class="el-icon-user" style="margin-right: 4px;"></i>{{ item.operatorName || '--' }}</span>
+ <span v-if="item.changeReason" style="margin-left: 16px;">
+ <i class="el-icon-chat-dot-round" style="margin-right: 4px;"></i>{{ item.changeReason }}
+ </span>
+ <span v-if="item.locationAddress" style="margin-left: 16px;">
+ <i class="el-icon-location-outline" style="margin-right: 4px;"></i>{{ item.locationAddress }}
+ </span>
+ </div>
+ </el-card>
+ </el-timeline-item>
+ </el-timeline>
+
+ <div v-else style="text-align: center; padding: 40px 0; color: #909399;">
+ <i class="el-icon-time" style="font-size: 48px; display: block; margin-bottom: 12px;"></i>
+ <span>鏆傛棤鐘舵�佸彉鏇磋褰�</span>
+ </div>
</el-card>
<!-- 鎿嶄綔鏃ュ織 -->
@@ -456,13 +843,13 @@
</template>
<script>
-import { getTask, updateTask, assignTask, changeTaskStatus, uploadAttachment, deleteAttachment, getTaskVehicles, getAvailableVehicles, assignVehiclesToTask, unassignVehicleFromTask } from "@/api/task";
+import { getTask, updateTask, assignTask, changeTaskStatus, uploadAttachment, deleteAttachment, getTaskVehicles, getAvailableVehicles, assignVehiclesToTask, unassignVehicleFromTask, getPaymentInfo, syncServiceOrder, syncDispatchOrder, syncTaskStatus, syncFromLegacySystem, checkTaskInvoice, getTaskStatusHistory } from "@/api/task";
import { listUser } from "@/api/system/user";
import { getToken } from "@/utils/auth";
export default {
name: "TaskDetail",
- dicts: ['sys_task_type', 'sys_task_status', 'sys_vehicle_type', 'sys_task_vehicle_status', 'sys_user_sex', 'hospital_department', 'sys_attachment_category'],
+ dicts: ['sys_task_type', 'sys_task_status', 'sys_vehicle_type', 'sys_task_vehicle_status', 'sys_user_sex', 'hospital_department', 'sys_attachment_category', 'task_additional_fee_type', 'task_payment_method'],
data() {
return {
// 浠诲姟璇︽儏
@@ -502,6 +889,14 @@
// 鍔犺浇鐘舵��
vehicleLoading: false,
attachmentLoading: false,
+ feeLoading: false,
+ assigneeLoading: false,
+ // 闄勫姞璐圭敤鍒楄〃
+ additionalFeeList: [],
+ // 鏀粯淇℃伅
+ paymentInfo: null,
+ // 鐘舵�佸彉鏇村巻鍙�
+ statusHistoryList: [],
// 涓婁紶鐩稿叧
uploadUrl: process.env.VUE_APP_BASE_API + "/task/attachment/upload/" + (new URLSearchParams(window.location.search).get('taskId') || ''),
uploadHeaders: {
@@ -539,21 +934,127 @@
category: [
{ required: true, message: "涓氬姟鍒嗙被涓嶈兘涓虹┖", trigger: "change" }
]
- }
+ },
+ // 鍚屾鍔犺浇鐘舵��
+ syncingServiceOrder: false,
+ syncingDispatchOrder: false,
+ syncingFromLegacy: false,
+ syncingTaskStatus: false,
+ // 鍙戠エ鐢宠鐘舵��
+ hasInvoiceApplied: false,
+ invoiceStatus: null // 0-寰呭鏍�, 1-宸查�氳繃, 2-宸查┏鍥�
};
},
created() {
this.getTaskDetail();
this.getUserList();
+ this.getAdditionalFeeList();
+ this.loadStatusHistory();
// 鍒濆鍖栦笂浼燯RL
this.uploadUrl = process.env.VUE_APP_BASE_API + "/task/attachment/upload/" + this.$route.params.taskId;
+ // 妫�鏌ュ彂绁ㄧ敵璇风姸鎬�
+ this.checkInvoiceStatus();
+ },
+ computed: {
+ /** 鏄惁鍙互鐢宠鍙戠エ */
+ canApplyInvoice() {
+ // 鍙湁鎬ユ晳杞繍浠诲姟
+ if (this.taskDetail.taskType !== 'EMERGENCY_TRANSFER') return false;
+ // 浠诲姟蹇呴』宸插畬鎴�
+ if (this.taskDetail.taskStatus !== 'COMPLETED') return false;
+ // 鏈敵璇疯繃鍙戠エ锛屾垨鑰呮浘琚┏鍥�
+ return !this.hasInvoiceApplied || this.invoiceStatus === 2;
+ }
},
methods: {
+ /** 鍔犺浇鐘舵�佸彉鏇村巻鍙� */
+ loadStatusHistory() {
+ getTaskStatusHistory(this.$route.params.taskId).then(response => {
+ this.statusHistoryList = response.data || [];
+ }).catch(() => {
+ this.statusHistoryList = [];
+ });
+ },
+ /** 鑾峰彇鐘舵�佸搴旂殑 Tag 绫诲瀷 */
+ getTagType(status) {
+ const map = {
+ PENDING: 'info',
+ DEPARTING: 'warning',
+ IN_PROGRESS: '',
+ COMPLETED: 'success',
+ CANCELLED: 'danger'
+ };
+ return map[status] || 'info';
+ },
+ /** 鑾峰彇鐘舵�佸搴旂殑鏃堕棿杞撮鑹� */
+ getStatusColor(status) {
+ const map = {
+ PENDING: '#909399',
+ DEPARTING: '#E6A23C',
+ IN_PROGRESS: '#409EFF',
+ COMPLETED: '#67C23A',
+ CANCELLED: '#F56C6C'
+ };
+ return map[status] || '#909399';
+ },
+ /** 鑾峰彇瑙﹀彂鏉ユ簮鏍囩绫诲瀷 */
+ getSourceTagType(source) {
+ const map = {
+ APP: 'primary',
+ ADMIN: 'warning',
+ SYSTEM: 'info',
+ LEGACY: ''
+ };
+ return map[source] || 'info';
+ },
+ /** 鑾峰彇瑙﹀彂鏉ユ簮鏂囧瓧 */
+ getSourceLabel(source) {
+ const map = {
+ APP: 'APP绔�',
+ ADMIN: '鍚庡彴',
+ SYSTEM: '绯荤粺',
+ LEGACY: '鏃х郴缁�'
+ };
+ return map[source] || source || '--';
+ },
/** 鑾峰彇浠诲姟璇︽儏 */
getTaskDetail() {
getTask(this.$route.params.taskId).then(response => {
this.taskDetail = response.data;
+ // 浠诲姟璇︽儏鍔犺浇瀹屾垚鍚庯紝鍔犺浇鏀粯淇℃伅
+ // console.log("TaskDetail", this.taskDetail);
+ this.loadPaymentInfo();
});
+ },
+ /** 鑾峰彇闄勫姞璐圭敤鍒楄〃 */
+ getAdditionalFeeList() {
+ this.feeLoading = true;
+ getPaymentInfo(this.$route.params.taskId).then(response => {
+ this.additionalFeeList = response.data.additionalFees || [];
+ this.feeLoading = false;
+ }).catch(() => {
+ this.feeLoading = false;
+ });
+ },
+ /** 鍔犺浇鏀粯淇℃伅 */
+ loadPaymentInfo() {
+ //EMERGENCY_TRANSFER
+ if (this.taskDetail.taskType === 'EMERGENCY_TRANSFER') {
+ getPaymentInfo(this.$route.params.taskId).then(response => {
+ // console.log("PaymentInfo", response.data);
+ this.paymentInfo = response.data;
+ }).catch(() => {
+ this.paymentInfo = null;
+ });
+ }
+ },
+ /** 璁$畻鍓╀綑鏈粯閲戦 */
+ 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;
+ return remaining > 0 ? remaining.toFixed(2) : '0.00';
},
/** 鑾峰彇鐢ㄦ埛鍒楄〃 */
getUserList() {
@@ -803,6 +1304,116 @@
if (!fileType) return false;
const imageTypes = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'];
return imageTypes.includes(fileType.toLowerCase());
+ },
+ /** 鎵嬪姩鍚屾鏈嶅姟鍗� */
+ syncServiceOrder() {
+ this.$modal.confirm('鏄惁纭鍚屾鏈嶅姟鍗曞埌鏃х郴缁燂紵').then(() => {
+ this.syncingServiceOrder = true;
+ return syncServiceOrder(this.taskDetail.taskId);
+ }).then(() => {
+ this.$modal.msgSuccess("鏈嶅姟鍗曞悓姝ユ垚鍔�");
+ // 閲嶆柊鍔犺浇浠诲姟璇︽儏
+ this.getTaskDetail();
+ }).catch(() => {
+ // 澶勭悊鍙栨秷鍜岄敊璇�
+ }).finally(() => {
+ this.syncingServiceOrder = false;
+ });
+ },
+ /** 鎵嬪姩鍚屾璋冨害鍗� */
+ syncDispatchOrder() {
+ this.$modal.confirm('鏄惁纭鍚屾璋冨害鍗曞埌鏃х郴缁燂紵').then(() => {
+ this.syncingDispatchOrder = true;
+ return syncDispatchOrder(this.taskDetail.taskId);
+ }).then(() => {
+ this.$modal.msgSuccess("璋冨害鍗曞悓姝ユ垚鍔�");
+ // 閲嶆柊鍔犺浇浠诲姟璇︽儏
+ this.getTaskDetail();
+ }).catch(() => {
+ // 澶勭悊鍙栨秷鍜岄敊璇�
+ }).finally(() => {
+ this.syncingDispatchOrder = false;
+ });
+ },
+ /** 浠庢棫绯荤粺鍚屾鏁版嵁鍒版柊绯荤粺 */
+ syncFromLegacySystem() {
+ // 妫�鏌ユ槸鍚﹀悓鏃舵湁serviceOrdID鍜宒ispatchOrdID
+ if (!this.taskDetail.emergencyInfo.legacyServiceOrdId || !this.taskDetail.emergencyInfo.legacyDispatchOrdId) {
+ this.$modal.msgError("缂哄皯蹇呰鐨勬棫绯荤粺ID淇℃伅");
+ return;
+ }
+
+ this.$modal.confirm('鏄惁纭浠庢棫绯荤粺鍚屾鏁版嵁鍒版柊绯荤粺锛�').then(() => {
+ this.syncingFromLegacy = true;
+ return syncFromLegacySystem(
+ this.taskDetail.emergencyInfo.legacyServiceOrdId,
+ this.taskDetail.emergencyInfo.legacyDispatchOrdId
+ );
+ }).then(() => {
+ this.$modal.msgSuccess("浠庢棫绯荤粺鍚屾鎴愬姛");
+ // 閲嶆柊鍔犺浇浠诲姟璇︽儏
+ this.getTaskDetail();
+ }).catch((error) => {
+ if (error !== 'cancel') {
+ this.$modal.msgError("鍚屾澶辫触: " + (error.message || "鏈煡閿欒"));
+ }
+ }).finally(() => {
+ this.syncingFromLegacy = false;
+ });
+ },
+ /** 鎵嬪姩鍚屾浠诲姟鐘舵�� */
+ syncTaskStatus() {
+ this.$modal.confirm('鏄惁纭鍚屾浠诲姟鐘舵�佸埌鏃х郴缁燂紵').then(() => {
+ this.syncingTaskStatus = true;
+ return syncTaskStatus(this.taskDetail.taskId);
+ }).then(() => {
+ this.$modal.msgSuccess("浠诲姟鐘舵�佸悓姝ユ垚鍔�");
+ // 閲嶆柊鍔犺浇浠诲姟璇︽儏
+ this.getTaskDetail();
+ }).catch(() => {
+ // 澶勭悊鍙栨秷鍜岄敊璇�
+ }).finally(() => {
+ this.syncingTaskStatus = false;
+ });
+ },
+
+ /** 妫�鏌ュ彂绁ㄧ敵璇风姸鎬� */
+ checkInvoiceStatus() {
+ // 璋冪敤鍚庣鎺ュ彛妫�鏌ヨ浠诲姟鏄惁宸茬敵璇峰彂绁�
+ checkTaskInvoice(this.$route.params.taskId)
+ .then(response => {
+ if (response.code === 200 && response.data) {
+ this.hasInvoiceApplied = true;
+ this.invoiceStatus = response.data.status;
+ }
+ })
+ .catch(() => {
+ // 蹇界暐閿欒锛岄粯璁ゆ湭鐢宠
+ });
+ },
+
+ /** 鐢宠鍙戠エ */
+ handleApplyInvoice() {
+ // 璺宠浆鍒板彂绁ㄧ敵璇烽〉闈紝甯︿笂浠诲姟淇℃伅
+ const taskInfo = {
+ taskId: this.taskDetail.taskId,
+ taskCode: this.taskDetail.taskCode || this.taskDetail.showTaskCode,
+ legacyServiceOrderId: this.taskDetail.emergencyInfo?.legacyServiceOrdId,
+ serviceCode: this.taskDetail.emergencyInfo?.serviceCode,
+ departure: this.taskDetail.departureAddress,
+ destination: this.taskDetail.destinationAddress,
+ completionTime: this.parseTime(this.taskDetail.actualEndTime),
+ transferPrice: this.paymentInfo?.transferPrice || this.paymentInfo?.totalAmount
+ };
+
+ // 灏嗕换鍔′俊鎭瓨鍌ㄥ埌 sessionStorage
+ sessionStorage.setItem('invoiceTaskInfo', JSON.stringify(taskInfo));
+
+ // 璺宠浆鍒板彂绁ㄧ敵璇烽〉闈�
+ this.$router.push({
+ path: '/system/invoice/apply',
+ query: { taskId: this.taskDetail.taskId }
+ });
}
}
};
@@ -812,4 +1423,17 @@
.box-card {
margin-bottom: 20px;
}
+.status-history-card {
+ border: none;
+ background: #fafafa;
+}
+.status-history-header {
+ display: flex;
+ align-items: center;
+ flex-wrap: wrap;
+}
+.status-arrow {
+ display: flex;
+ align-items: center;
+}
</style>
--
Gitblit v1.9.1