From 9529220c815bfe6e43c992fde2f392be823450eb Mon Sep 17 00:00:00 2001
From: wlzboy <66905212@qq.com>
Date: 星期二, 11 十一月 2025 20:27:33 +0800
Subject: [PATCH] feat:增加天地图接口,并增加车辆GPS统计

---
 ruoyi-ui/src/views/task/general/detail.vue |  285 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 258 insertions(+), 27 deletions(-)

diff --git a/ruoyi-ui/src/views/task/general/detail.vue b/ruoyi-ui/src/views/task/general/detail.vue
index 379fff6..3685884 100644
--- a/ruoyi-ui/src/views/task/general/detail.vue
+++ b/ruoyi-ui/src/views/task/general/detail.vue
@@ -30,6 +30,121 @@
         <el-descriptions-item label="澶囨敞" :span="2">{{ taskDetail.remark }}</el-descriptions-item>
       </el-descriptions>
 
+      <!-- 鎬ユ晳杞繍浠诲姟鎵╁睍淇℃伅 -->
+      <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-else style="color: #C0C4CC;">--</span>
+        </el-descriptions-item>
+        <el-descriptions-item label="鑱旂郴鐢佃瘽">
+          <span v-if="taskDetail.emergencyInfo.contactPhone">{{ taskDetail.emergencyInfo.contactPhone }}</span>
+          <span v-else style="color: #C0C4CC;">--</span>
+        </el-descriptions-item>
+        <el-descriptions-item label="鎮h�呭鍚�">
+          <span v-if="taskDetail.emergencyInfo.patientName">{{ taskDetail.emergencyInfo.patientName }}</span>
+          <span v-else style="color: #C0C4CC;">--</span>
+        </el-descriptions-item>
+        <el-descriptions-item label="鎮h�呮�у埆">
+          <dict-tag v-if="taskDetail.emergencyInfo.patientGender" :options="dict.type.sys_user_sex" :value="taskDetail.emergencyInfo.patientGender"/>
+          <span v-else style="color: #C0C4CC;">--</span>
+        </el-descriptions-item>
+        <el-descriptions-item label="韬唤淇℃伅" :span="2">
+          <span v-if="taskDetail.emergencyInfo.patientIdCard">{{ taskDetail.emergencyInfo.patientIdCard }}</span>
+          <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-else style="color: #C0C4CC;">--</span>
+        </el-descriptions-item>
+      </el-descriptions>
+
+      <!-- 鏃х郴缁熷悓姝ヤ俊鎭紙浠呮�ユ晳杞繍浠诲姟鏄剧ず锛� -->
+      <el-descriptions v-if="taskDetail.taskType === 'EMERGENCY_TRANSFER' && taskDetail.emergencyInfo" title="鏃х郴缁熷悓姝ヤ俊鎭�" :column="2" border style="margin-top: 20px;">
+        <el-descriptions-item label="鏈嶅姟鍗曞悓姝ョ姸鎬�">
+          <el-tag v-if="taskDetail.emergencyInfo.syncStatus === 0" type="info" size="small">
+            <i class="el-icon-warning"></i> 鏈悓姝�
+          </el-tag>
+          <el-tag v-else-if="taskDetail.emergencyInfo.syncStatus === 1" type="warning" size="small">
+            <i class="el-icon-loading"></i> 鍚屾涓�
+          </el-tag>
+          <el-tag v-else-if="taskDetail.emergencyInfo.syncStatus === 2" type="success" size="small">
+            <i class="el-icon-success"></i> 鍚屾鎴愬姛
+          </el-tag>
+          <el-tag v-else-if="taskDetail.emergencyInfo.syncStatus === 3" type="danger" size="small">
+            <i class="el-icon-error"></i> 鍚屾澶辫触
+          </el-tag>
+          <span v-else style="color: #C0C4CC;">--</span>
+        </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.syncTime">{{ parseTime(taskDetail.emergencyInfo.syncTime) }}</span>
+          <span v-else style="color: #C0C4CC;">--</span>
+        </el-descriptions-item>
+        <el-descriptions-item label="鏈嶅姟鍗曞悓姝ラ敊璇�" :span="1">
+          <span v-if="taskDetail.emergencyInfo.syncErrorMsg" style="color: #F56C6C;">{{ taskDetail.emergencyInfo.syncErrorMsg }}</span>
+          <span v-else style="color: #C0C4CC;">--</span>
+        </el-descriptions-item>
+        <el-descriptions-item label="璋冨害鍗曞悓姝ョ姸鎬�">
+          <el-tag v-if="taskDetail.emergencyInfo.dispatchSyncStatus === 0" type="info" size="small">
+            <i class="el-icon-warning"></i> 鏈悓姝�
+          </el-tag>
+          <el-tag v-else-if="taskDetail.emergencyInfo.dispatchSyncStatus === 1" type="warning" size="small">
+            <i class="el-icon-loading"></i> 鍚屾涓�
+          </el-tag>
+          <el-tag v-else-if="taskDetail.emergencyInfo.dispatchSyncStatus === 2" type="success" size="small">
+            <i class="el-icon-success"></i> 鍚屾鎴愬姛
+          </el-tag>
+          <el-tag v-else-if="taskDetail.emergencyInfo.dispatchSyncStatus === 3" type="danger" size="small">
+            <i class="el-icon-error"></i> 鍚屾澶辫触
+          </el-tag>
+          <span v-else style="color: #C0C4CC;">--</span>
+        </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.dispatchSyncTime">{{ parseTime(taskDetail.emergencyInfo.dispatchSyncTime) }}</span>
+          <span v-else style="color: #C0C4CC;">--</span>
+        </el-descriptions-item>
+        <el-descriptions-item label="璋冨害鍗曞悓姝ラ敊璇�" :span="1">
+          <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>
+
+      <!-- 绂忕杞︿换鍔℃墿灞曚俊鎭� -->
+      <el-descriptions v-if="taskDetail.taskType === 'WELFARE' && taskDetail.welfareInfo" title="绂忕杞︽湇鍔′俊鎭�" :column="2" border style="margin-top: 20px;">
+        <el-descriptions-item label="涔樺濮撳悕">{{ taskDetail.welfareInfo.passengerName }}</el-descriptions-item>
+        <el-descriptions-item label="涔樺鎬у埆">
+          <dict-tag :options="dict.type.sys_user_sex" :value="taskDetail.welfareInfo.passengerGender"/>
+        </el-descriptions-item>
+        <el-descriptions-item label="涔樺骞撮緞">{{ taskDetail.welfareInfo.passengerAge }}</el-descriptions-item>
+        <el-descriptions-item label="鑱旂郴鐢佃瘽">{{ taskDetail.welfareInfo.contactPhone }}</el-descriptions-item>
+        <el-descriptions-item label="鏈嶅姟绫诲瀷" :span="2">
+          <span v-if="taskDetail.welfareInfo.serviceType">{{ taskDetail.welfareInfo.serviceType }}</span>
+          <span v-else style="color: #C0C4CC;">--</span>
+        </el-descriptions-item>
+        <el-descriptions-item label="鐗规畩闇�姹�" :span="2">
+          <span v-if="taskDetail.welfareInfo.specialRequirements">{{ taskDetail.welfareInfo.specialRequirements }}</span>
+          <span v-else style="color: #C0C4CC;">--</span>
+        </el-descriptions-item>
+        <el-descriptions-item label="鏄惁闇�瑕佽疆妞�">
+          <el-tag v-if="taskDetail.welfareInfo.needsWheelchair == 1" type="success" size="small">鏄�</el-tag>
+          <el-tag v-else type="info" size="small">鍚�</el-tag>
+        </el-descriptions-item>
+        <el-descriptions-item label="闄悓浜烘暟">{{ taskDetail.welfareInfo.companionCount || 0 }} 浜�</el-descriptions-item>
+        <el-descriptions-item label="棰勪及璐圭敤">{{ taskDetail.welfareInfo.estimatedCost || '--' }} 鍏�</el-descriptions-item>
+        <el-descriptions-item label="瀹為檯璐圭敤">{{ taskDetail.welfareInfo.actualCost || '--' }} 鍏�</el-descriptions-item>
+      </el-descriptions>
+
       <!-- 鎿嶄綔鎸夐挳 -->
       <div style="margin-top: 20px; text-align: center;">
         <el-button type="primary" @click="handleEdit" v-hasPermi="['task:general:edit']">缂栬緫浠诲姟</el-button>
@@ -88,11 +203,38 @@
       </div>
       
       <el-table :data="taskDetail.attachments" v-loading="attachmentLoading">
-        <el-table-column label="鏂囦欢鍚�" align="center" prop="fileName" />
-        <el-table-column label="鏂囦欢绫诲瀷" align="center" prop="fileType" />
-        <el-table-column label="鏂囦欢澶у皬" align="center" prop="fileSize">
+        <el-table-column label="缂╃暐鍥�" align="center" width="120">
           <template slot-scope="scope">
-            <span>{{ formatFileSize(scope.row.fileSize) }}</span>
+            <el-image
+              v-if="isImage(scope.row.fileType)"
+              :src="scope.row.fileUrl"
+              :preview-src-list="[scope.row.fileUrl]"
+              fit="cover"
+              style="width: 80px; height: 80px; border-radius: 4px; cursor: pointer;"
+            >
+              <div slot="error" class="image-slot">
+                <i class="el-icon-picture-outline" style="font-size: 40px; color: #C0C4CC;"></i>
+              </div>
+            </el-image>
+            <div v-else style="text-align: center;">
+              <i class="el-icon-document" style="font-size: 40px; color: #909399;"></i>
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column label="涓氬姟鍒嗙被" align="center" prop="attachmentCategory" width="150">
+          <template slot-scope="scope">
+            <dict-tag :options="dict.type.sys_attachment_category" :value="scope.row.attachmentCategory"/>
+          </template>
+        </el-table-column>
+        <el-table-column label="鍚屾鐘舵��" align="center" width="120">
+          <template slot-scope="scope">
+            <el-tag v-if="scope.row.syncedToImageData === 0" type="info" size="small">
+              <i class="el-icon-warning"></i> 鏈悓姝�
+            </el-tag>
+            <el-tag v-else-if="scope.row.syncedToImageData === 1" type="success" size="small">
+              <i class="el-icon-success"></i> 宸插悓姝�
+            </el-tag>
+            <span v-else style="color: #C0C4CC;">--</span>
           </template>
         </el-table-column>
         <el-table-column label="涓婁紶鏃堕棿" align="center" prop="uploadTime" width="180">
@@ -273,21 +415,42 @@
     </el-dialog>
 
     <!-- 涓婁紶闄勪欢瀵硅瘽妗� -->
-    <el-dialog title="涓婁紶闄勪欢" :visible.sync="uploadOpen" width="500px" append-to-body>
-      <el-upload
-        class="upload-demo"
-        drag
-        :action="uploadUrl"
-        :headers="uploadHeaders"
-        :data="uploadData"
-        :on-success="handleUploadSuccess"
-        :on-error="handleUploadError"
-        :before-upload="beforeUpload"
-        multiple>
-        <i class="el-icon-upload"></i>
-        <div class="el-upload__text">灏嗘枃浠舵嫋鍒版澶勶紝鎴�<em>鐐瑰嚮涓婁紶</em></div>
-        <div class="el-upload__tip" slot="tip">鍙兘涓婁紶jpg/png/pdf/doc/docx鏂囦欢锛屼笖涓嶈秴杩�10MB</div>
-      </el-upload>
+    <el-dialog title="涓婁紶闄勪欢" :visible.sync="uploadOpen" width="500px" append-to-body @close="cancelUpload">
+      <el-form ref="uploadForm" :model="uploadForm" :rules="uploadRules" label-width="100px">
+        <el-form-item label="涓氬姟鍒嗙被" prop="category">
+          <el-select v-model="uploadForm.category" placeholder="璇烽�夋嫨涓氬姟鍒嗙被" clearable style="width: 100%;">
+            <el-option
+              v-for="dict in dict.type.sys_attachment_category"
+              :key="dict.value"
+              :label="dict.label"
+              :value="dict.value"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="闄勪欢" prop="files">
+          <el-upload
+            ref="upload"
+            class="upload-demo"
+            :action="uploadUrl"
+            :headers="uploadHeaders"
+            :data="uploadData"
+            :on-success="handleUploadSuccess"
+            :on-error="handleUploadError"
+            :before-upload="beforeUpload"
+            :file-list="fileList"
+            :auto-upload="false"
+            multiple
+            drag>
+            <i class="el-icon-upload"></i>
+            <div class="el-upload__text">灏嗘枃浠舵嫋鍒版澶勶紝鎴�<em>鐐瑰嚮涓婁紶</em></div>
+            <div class="el-upload__tip" slot="tip">鍙兘涓婁紶jpg/png/pdf/doc/docx鏂囦欢锛屼笖涓嶈秴杩�100MB</div>
+          </el-upload>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitUpload">纭� 瀹�</el-button>
+        <el-button @click="cancelUpload">鍙� 娑�</el-button>
+      </div>
     </el-dialog>
   </div>
 </template>
@@ -299,7 +462,7 @@
 
 export default {
   name: "TaskDetail",
-  dicts: ['sys_task_type', 'sys_task_status', 'sys_vehicle_type', 'sys_task_vehicle_status'],
+  dicts: ['sys_task_type', 'sys_task_status', 'sys_vehicle_type', 'sys_task_vehicle_status', 'sys_user_sex', 'hospital_department', 'sys_attachment_category'],
   data() {
     return {
       // 浠诲姟璇︽儏
@@ -318,6 +481,12 @@
       vehicleAssignOpen: false,
       // 鏄惁鏄剧ず涓婁紶瀵硅瘽妗�
       uploadOpen: false,
+      // 涓婁紶琛ㄥ崟
+      uploadForm: {
+        category: null
+      },
+      // 鏂囦欢鍒楄〃
+      fileList: [],
       // 缂栬緫琛ㄥ崟
       editForm: {},
       // 鍒嗛厤琛ㄥ崟
@@ -334,7 +503,7 @@
       vehicleLoading: false,
       attachmentLoading: false,
       // 涓婁紶鐩稿叧
-      uploadUrl: process.env.VUE_APP_BASE_API + "/task/attachment/upload/" + this.$route.params.taskId,
+      uploadUrl: process.env.VUE_APP_BASE_API + "/task/attachment/upload/" + (new URLSearchParams(window.location.search).get('taskId') || ''),
       uploadHeaders: {
         Authorization: "Bearer " + getToken()
       },
@@ -365,12 +534,19 @@
         vehicleIds: [
           { required: true, message: "杞﹁締涓嶈兘涓虹┖", trigger: "change" }
         ]
+      },
+      uploadRules: {
+        category: [
+          { required: true, message: "涓氬姟鍒嗙被涓嶈兘涓虹┖", trigger: "change" }
+        ]
       }
     };
   },
   created() {
     this.getTaskDetail();
     this.getUserList();
+    // 鍒濆鍖栦笂浼燯RL
+    this.uploadUrl = process.env.VUE_APP_BASE_API + "/task/attachment/upload/" + this.$route.params.taskId;
   },
   methods: {
     /** 鑾峰彇浠诲姟璇︽儏 */
@@ -439,6 +615,10 @@
     },
     /** 涓婁紶闄勪欢 */
     handleUpload() {
+      this.uploadForm = {
+        category: null
+      };
+      this.fileList = [];
       this.uploadOpen = true;
     },
     /** 鍙栨秷杞﹁締鍒嗛厤 */
@@ -533,22 +713,67 @@
     },
     /** 涓婁紶鍓嶆鏌� */
     beforeUpload(file) {
+      // 妫�鏌ユ槸鍚﹂�夋嫨浜嗕笟鍔″垎绫�
+      if (!this.uploadForm.category) {
+        this.$message.error('璇峰厛閫夋嫨涓氬姟鍒嗙被!');
+        return false;
+      }
+      
+      // 鏇存柊uploadData锛岀‘淇濇瘡娆′笂浼犻兘甯︽湁category鍙傛暟
+      this.uploadData = {
+        category: this.uploadForm.category
+      };
+      
       const isValidType = ['image/jpeg', 'image/png', 'application/pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'].includes(file.type);
-      const isLt10M = file.size / 1024 / 1024 < 10;
+      const isLt10M = file.size / 1024 / 1024 < 100;
 
       if (!isValidType) {
         this.$message.error('鍙兘涓婁紶 JPG/PNG/PDF/DOC/DOCX 鏍煎紡鐨勬枃浠�!');
+        return false;
       }
       if (!isLt10M) {
-        this.$message.error('涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃 10MB!');
+        this.$message.error('涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃 100MB!');
+        return false;
       }
-      return isValidType && isLt10M;
+      return true;
+    },
+    /** 鎻愪氦涓婁紶 */
+    submitUpload() {
+      this.$refs["uploadForm"].validate(valid => {
+        if (valid) {
+          // 妫�鏌ユ槸鍚﹂�夋嫨浜嗘枃浠�
+          const fileList = this.$refs.upload.uploadFiles;
+          if (!fileList || fileList.length === 0) {
+            this.$message.warning('璇烽�夋嫨瑕佷笂浼犵殑鏂囦欢');
+            return;
+          }
+          
+          // 瑙﹀彂涓婁紶
+          this.$refs.upload.submit();
+        }
+      });
+    },
+    /** 鍙栨秷涓婁紶 */
+    cancelUpload() {
+      this.uploadOpen = false;
+      this.uploadForm = {
+        category: null
+      };
+      this.fileList = [];
+      if (this.$refs.upload) {
+        this.$refs.upload.clearFiles();
+      }
     },
     /** 涓婁紶鎴愬姛 */
     handleUploadSuccess(response, file, fileList) {
-      this.$modal.msgSuccess("涓婁紶鎴愬姛");
-      this.uploadOpen = false;
-      this.getTaskDetail();
+      // 妫�鏌ユ槸鍚︽墍鏈夋枃浠堕兘涓婁紶瀹屾垚
+      const allDone = fileList.every(f => f.status === 'success' || f.status === 'fail');
+      
+      if (allDone) {
+        this.$modal.msgSuccess("涓婁紶鎴愬姛");
+        this.cancelUpload();
+        this.getTaskDetail();
+      }
     },
     /** 涓婁紶澶辫触 */
     handleUploadError(err, file, fileList) {
@@ -572,6 +797,12 @@
         return typeItem ? typeItem.label : vehicleType;
       }
       return vehicleType;
+    },
+    /** 鍒ゆ柇鏄惁涓哄浘鐗囩被鍨� */
+    isImage(fileType) {
+      if (!fileType) return false;
+      const imageTypes = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'];
+      return imageTypes.includes(fileType.toLowerCase());
     }
   }
 };

--
Gitblit v1.9.1