From 40a8157440e3b906da8f52e07d939d78c3f4c313 Mon Sep 17 00:00:00 2001
From: wlzboy <66905212@qq.com>
Date: 星期日, 12 四月 2026 16:14:06 +0800
Subject: [PATCH] feat: 任务增加统计、同步增加通知
---
ruoyi-ui/src/views/task/general/detail.vue | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 150 insertions(+), 2 deletions(-)
diff --git a/ruoyi-ui/src/views/task/general/detail.vue b/ruoyi-ui/src/views/task/general/detail.vue
index e0b0bd8..3cf49f3 100644
--- a/ruoyi-ui/src/views/task/general/detail.vue
+++ b/ruoyi-ui/src/views/task/general/detail.vue
@@ -129,6 +129,16 @@
@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">
@@ -595,6 +605,51 @@
</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>
+
<!-- 鎿嶄綔鏃ュ織 -->
<el-card class="box-card" style="margin-top: 20px;">
<div slot="header" class="clearfix">
@@ -788,7 +843,7 @@
</template>
<script>
-import { getTask, updateTask, assignTask, changeTaskStatus, uploadAttachment, deleteAttachment, getTaskVehicles, getAvailableVehicles, assignVehiclesToTask, unassignVehicleFromTask, getPaymentInfo, syncServiceOrder, syncDispatchOrder, syncTaskStatus } 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";
@@ -840,6 +895,8 @@
additionalFeeList: [],
// 鏀粯淇℃伅
paymentInfo: null,
+ // 鐘舵�佸彉鏇村巻鍙�
+ statusHistoryList: [],
// 涓婁紶鐩稿叧
uploadUrl: process.env.VUE_APP_BASE_API + "/task/attachment/upload/" + (new URLSearchParams(window.location.search).get('taskId') || ''),
uploadHeaders: {
@@ -881,6 +938,7 @@
// 鍚屾鍔犺浇鐘舵��
syncingServiceOrder: false,
syncingDispatchOrder: false,
+ syncingFromLegacy: false,
syncingTaskStatus: false,
// 鍙戠エ鐢宠鐘舵��
hasInvoiceApplied: false,
@@ -891,6 +949,7 @@
this.getTaskDetail();
this.getUserList();
this.getAdditionalFeeList();
+ this.loadStatusHistory();
// 鍒濆鍖栦笂浼燯RL
this.uploadUrl = process.env.VUE_APP_BASE_API + "/task/attachment/upload/" + this.$route.params.taskId;
// 妫�鏌ュ彂绁ㄧ敵璇风姸鎬�
@@ -908,6 +967,56 @@
}
},
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 => {
@@ -1226,6 +1335,32 @@
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(() => {
@@ -1245,7 +1380,7 @@
/** 妫�鏌ュ彂绁ㄧ敵璇风姸鎬� */
checkInvoiceStatus() {
// 璋冪敤鍚庣鎺ュ彛妫�鏌ヨ浠诲姟鏄惁宸茬敵璇峰彂绁�
- this.$axios.get(`/system/invoice/checkTaskInvoice/${this.$route.params.taskId}`)
+ checkTaskInvoice(this.$route.params.taskId)
.then(response => {
if (response.code === 200 && response.data) {
this.hasInvoiceApplied = true;
@@ -1288,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