From 847a7773ef1a8ad418c6934d35b5f205a97c04d0 Mon Sep 17 00:00:00 2001
From: wlzboy <66905212@qq.com>
Date: 星期六, 06 十二月 2025 17:03:24 +0800
Subject: [PATCH] fix:在任务状态更新时,需要更新日志到旧系统

---
 ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml                             |    6 
 app/pagesTask/components/DepartmentSelector.vue                                             |  230 ++++++
 ruoyi-ui/src/views/system/user/index.vue                                                    |   13 
 ruoyi-system/src/main/java/com/ruoyi/system/domain/UserSyncDTO.java                         |   14 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/LegacyTransferSyncServiceImpl.java |   40 
 app/pagesTask/edit-emergency.vue                                                            |   76 ++
 ruoyi-system/src/main/java/com/ruoyi/system/event/TaskStatusChangedEvent.java               |   38 +
 ruoyi-system/src/main/java/com/ruoyi/system/listener/DispatchOrdRunningListener.java        |  195 +++++
 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java                 |   14 
 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskService.java                    |   11 
 ruoyi-system/src/main/resources/mapper/system/UserSyncMapper.xml                            |    7 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/UserSyncServiceImpl.java           |    8 
 ruoyi-system/src/main/resources/mapper/system/LegacyTransferSyncMapper.xml                  |   39 
 ruoyi-system/src/main/java/com/ruoyi/system/listener/TaskMessageListener.java               |    2 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskController.java              |   91 ++
 app/pagesTask/create-emergency.vue                                                          |  168 ++--
 app/pagesTask/components/AttachmentUpload.vue                                               |    4 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/LegacySystemSyncServiceImpl.java   |  110 ++
 app/pages/task/index.vue                                                                    |   83 ++
 ruoyi-admin/src/main/resources/application.yml                                              |    2 
 sql/add_can_view_all_consult_to_sys_user.sql                                                |   12 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java            |   97 ++
 /dev/null                                                                                   |    0 
 app/utils/taskValidator.js                                                                  |  226 ++++++
 ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskQueryVO.java                      |   12 
 ruoyi-system/src/main/resources/mapper/system/SysTaskMapper.xml                             |   37 
 prd/转运任务状态变更记录同步功能说明.md                                                                     |  397 ++++++++++
 sql/DispatchRunning.sql                                                                     |   10 
 app/pagesTask/components/HospitalSelector.vue                                               |  111 --
 app/pagesTask/detail.vue                                                                    |  122 ++-
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/LegacyTransferSyncMapper.java            |   22 
 31 files changed, 1,889 insertions(+), 308 deletions(-)

diff --git a/app/pages/task/index.vue b/app/pages/task/index.vue
index 99f61b6..cf1dbff 100644
--- a/app/pages/task/index.vue
+++ b/app/pages/task/index.vue
@@ -221,6 +221,7 @@
   import { listTask, changeTaskStatus } from '@/api/task'
   import { mapState } from 'vuex'
   import { formatDateTime } from '@/utils/common'
+  import { checkTaskCanDepart } from '@/utils/taskValidator'
   
   export default {
     components: {
@@ -461,13 +462,87 @@
       },
       
       // 澶勭悊浠诲姟鎿嶄綔
-      handleTaskAction(task, action) {
+      async handleTaskAction(task, action) {
         switch (action) {
           case 'depart':
             // 鍑哄彂 -> 鐘舵�佸彉涓哄嚭鍙戜腑
-            this.$modal.confirm('纭畾瑕佸嚭鍙戝悧锛�').then(() => {
-              this.updateTaskStatus(task.taskId, 'DEPARTING', '浠诲姟宸插嚭鍙�')
-            }).catch(() => {});
+            // 鏄剧ず鍔犺浇鎻愮ず
+            uni.showLoading({
+              title: '妫�鏌ヤ换鍔$姸鎬�...'
+            });
+            
+            try {
+              // 璋冪敤宸ュ叿绫绘鏌ヤ换鍔℃槸鍚﹀彲浠ュ嚭鍙戯紙鍖呭惈鍩烘湰鏍¢獙鍜屽啿绐佹鏌ワ級
+              const checkResult = await checkTaskCanDepart(task)
+              
+              uni.hideLoading();
+              
+              console.log('鍑哄彂妫�鏌ョ粨鏋�:', checkResult);
+              console.log('valid:', checkResult.valid);
+              console.log('conflicts:', checkResult.conflicts);
+              
+              if (!checkResult.valid) {
+                // 鏍¢獙澶辫触锛屾樉绀烘彁绀轰俊鎭苟鎻愪緵璺宠浆閫夐」
+                const conflicts = checkResult.conflicts || [];
+                const conflictInfo = conflicts.length > 0 ? conflicts[0] : null;
+                
+                console.log('鍐茬獊淇℃伅:', conflictInfo);
+                
+                // 濡傛灉鏈夊啿绐佷换鍔′俊鎭紝鎻愪緵璺宠浆鎸夐挳
+                if (conflictInfo && conflictInfo.taskId) {
+                  console.log('鏄剧ず甯﹁烦杞寜閽殑寮圭獥锛屼换鍔D:', conflictInfo.taskId);
+                  
+                  const conflictTaskId = conflictInfo.taskId;
+                  const message = checkResult.message || conflictInfo.message || '瀛樺湪鍐茬獊浠诲姟';
+                  
+                  uni.showModal({
+                    title: '鎻愮ず',
+                    content: message,
+                    confirmText: '鍘诲鐞�',
+                    cancelText: '鐭ラ亾浜�',
+                    success: function(res) {
+                      console.log('寮圭獥鐐瑰嚮缁撴灉:', res);
+                      if (res.confirm) {
+                        // 鐢ㄦ埛鐐瑰嚮"鐜板湪鍘诲鐞�"锛岃烦杞埌鍐茬獊浠诲姟璇︽儏椤�
+                        console.log('鍑嗗璺宠浆鍒颁换鍔¤鎯呴〉:', conflictTaskId);
+                        uni.navigateTo({
+                          url: `/pagesTask/detail?id=${conflictTaskId}`
+                        });
+                      }
+                    },
+                    fail: function(err) {
+                      console.error('鏄剧ず寮圭獥澶辫触:', err);
+                    }
+                  });
+                } else {
+                  // 娌℃湁鍐茬獊浠诲姟ID锛屽彧鏄剧ず鎻愮ず
+                  console.log('鏄剧ず鏅�氭彁绀哄脊绐�');
+                  uni.showModal({
+                    title: '鎻愮ず',
+                    content: checkResult.message || '浠诲姟鏍¢獙澶辫触',
+                    showCancel: false,
+                    confirmText: '鐭ラ亾浜�',
+                    fail: function(err) {
+                      console.error('鏄剧ず寮圭獥澶辫触:', err);
+                    }
+                  });
+                }
+                return;
+              }
+              
+              // 鎵�鏈夋鏌ラ�氳繃锛屽彲浠ュ嚭鍙�
+              this.$modal.confirm('纭畾瑕佸嚭鍙戝悧锛�').then(() => {
+                this.updateTaskStatus(task.taskId, 'DEPARTING', '浠诲姟宸插嚭鍙�')
+              }).catch(() => {});
+              
+            } catch (error) {
+              uni.hideLoading();
+              console.error('妫�鏌ヤ换鍔$姸鎬佸け璐�:', error);
+              // 妫�鏌ュけ璐ユ椂锛屼粛鐒跺厑璁稿嚭鍙�
+              this.$modal.confirm('妫�鏌ヤ换鍔$姸鎬佸け璐ワ紝鏄惁缁х画鍑哄彂锛�').then(() => {
+                this.updateTaskStatus(task.taskId, 'DEPARTING', '浠诲姟宸插嚭鍙�')
+              }).catch(() => {});
+            }
             break;
             
           case 'cancel':
diff --git a/app/pagesTask/components/AttachmentUpload.vue b/app/pagesTask/components/AttachmentUpload.vue
index 2f319d3..ab60409 100644
--- a/app/pagesTask/components/AttachmentUpload.vue
+++ b/app/pagesTask/components/AttachmentUpload.vue
@@ -50,7 +50,7 @@
             <view class="form-label">閫夋嫨鍥剧墖</view>
             <button class="choose-image-btn" @click="chooseImage">
               <uni-icons type="image" size="20"></uni-icons>
-              <text>鐐瑰嚮閫夋嫨</text>
+              <text class="btn-text">鐐瑰嚮閫夋嫨</text>
             </button>
           </view>
           <view class="preview-area" v-if="tempImagePath">
@@ -506,7 +506,7 @@
             color: #666;
             font-size: 28rpx;
             
-            text {
+            .btn-text {
               margin-left: 10rpx;
             }
           }
diff --git a/app/pagesTask/components/DepartmentSelector.vue b/app/pagesTask/components/DepartmentSelector.vue
new file mode 100644
index 0000000..3e2b5ef
--- /dev/null
+++ b/app/pagesTask/components/DepartmentSelector.vue
@@ -0,0 +1,230 @@
+<template>
+  <view class="form-item">
+    <view class="form-label" :class="{ required: required }">{{ label }}</view>
+    <picker 
+      v-if="!isHome && departmentOptions.length > 0"
+      mode="selector" 
+      :range="departmentOptions" 
+      range-key="text" 
+      :value="selectedIndex"
+      @change="onDepartmentChange"
+    >
+      <view class="form-input picker-input">
+        {{ displayText }}
+        <uni-icons type="arrowright" size="16" color="#999"></uni-icons>
+      </view>
+    </picker>
+    <input 
+      v-else-if="!isHome"
+      class="form-input" 
+      placeholder="璇疯緭鍏ョ瀹�" 
+      :value="value"
+      @input="onDepartmentInput"
+    />
+    <view v-else class="form-input picker-input disabled">
+      鍏跺畠
+    </view>
+  </view>
+</template>
+
+<script>
+import { getHospitalDepartments } from "@/api/dictionary"
+
+export default {
+  name: 'DepartmentSelector',
+  props: {
+    // 鏍囩鏂囨湰
+    label: {
+      type: String,
+      default: '绉戝'
+    },
+    // 鏄惁蹇呭~
+    required: {
+      type: Boolean,
+      default: false
+    },
+    // 褰撳墠閫変腑鐨勭瀹ゅ悕绉�
+    value: {
+      type: String,
+      default: ''
+    },
+    // 褰撳墠閫変腑鐨勭瀹D
+    departmentId: {
+      type: [Number, String],
+      default: null
+    },
+    // 鏄惁涓�"瀹朵腑"锛堝鏋滄槸瀹朵腑锛屾樉绀�"鍏跺畠"涓斾笉鍙�夋嫨锛�
+    isHome: {
+      type: Boolean,
+      default: false
+    },
+    // 鍗犱綅绗�
+    placeholder: {
+      type: String,
+      default: '璇烽�夋嫨绉戝'
+    }
+  },
+  data() {
+    return {
+      departmentOptions: [], // 绉戝閫夐」鍒楄〃
+      selectedIndex: -1
+    }
+  },
+  computed: {
+    displayText() {
+      if (this.selectedIndex >= 0 && this.selectedIndex < this.departmentOptions.length) {
+        return this.departmentOptions[this.selectedIndex].text
+      }
+      return this.value || this.placeholder
+    }
+  },
+  watch: {
+    value: {
+      immediate: true,
+      handler(newVal) {
+        if (newVal) {
+          this.updateSelectedIndex(newVal)
+        } else {
+          this.selectedIndex = -1
+        }
+      }
+    },
+    departmentId: {
+      immediate: true,
+      handler(newVal) {
+        if (newVal) {
+          this.updateSelectedIndexById(newVal)
+        }
+      }
+    },
+    departmentOptions: {
+      immediate: true,
+      handler() {
+        if (this.value) {
+          this.updateSelectedIndex(this.value)
+        } else if (this.departmentId) {
+          this.updateSelectedIndexById(this.departmentId)
+        }
+      }
+    }
+  },
+  mounted() {
+    this.loadDepartments()
+  },
+  methods: {
+    // 鍔犺浇绉戝鏁版嵁
+    loadDepartments() {
+      getHospitalDepartments().then(response => {
+        const list = response.data || []
+        this.departmentOptions = list.map(item => ({
+          id: item.vID,
+          text: item.vtext,
+          dictValue: item.vtext
+        }))
+      }).catch(error => {
+        console.error('鍔犺浇绉戝鏁版嵁澶辫触:', error)
+        this.departmentOptions = []
+      })
+    },
+    
+    // 鏍规嵁绉戝鍚嶇О鏇存柊閫変腑绱㈠紩
+    updateSelectedIndex(departmentName) {
+      if (!departmentName || this.departmentOptions.length === 0) {
+        this.selectedIndex = -1
+        return
+      }
+      
+      const index = this.departmentOptions.findIndex(d => d.text === departmentName)
+      this.selectedIndex = index !== -1 ? index : -1
+    },
+    
+    // 鏍规嵁绉戝ID鏇存柊閫変腑绱㈠紩
+    updateSelectedIndexById(departmentId) {
+      if (!departmentId || this.departmentOptions.length === 0) {
+        this.selectedIndex = -1
+        return
+      }
+      
+      const index = this.departmentOptions.findIndex(d => d.id == departmentId)
+      this.selectedIndex = index !== -1 ? index : -1
+    },
+    
+    // 绉戝閫夋嫨鍙樺寲锛坧icker锛�
+    onDepartmentChange(e) {
+      const index = e.detail.value
+      
+      // 瀹夊叏妫�鏌ワ細纭繚绱㈠紩鏈夋晥涓旈�夐」瀛樺湪
+      if (index < 0 || index >= this.departmentOptions.length) {
+        console.warn('绉戝閫夋嫨绱㈠紩瓒婄晫:', index, '鏁扮粍闀垮害:', this.departmentOptions.length)
+        return
+      }
+      
+      const selected = this.departmentOptions[index]
+      
+      // 浜屾妫�鏌ワ細纭繚閫変腑椤瑰瓨鍦ㄤ笖鏈塼ext灞炴��
+      if (!selected || !selected.text) {
+        console.warn('绉戝閫夐」鏁版嵁寮傚父:', selected)
+        return
+      }
+      
+      this.selectedIndex = index
+      
+      this.$emit('input', selected.text)
+      this.$emit('change', {
+        department: selected.text,
+        departmentId: selected.id
+      })
+    },
+    
+    // 绉戝杈撳叆锛堟墜鍔ㄨ緭鍏ワ級
+    onDepartmentInput(e) {
+      const department = e.detail.value
+      this.$emit('input', department)
+      this.$emit('change', {
+        department: department,
+        departmentId: null
+      })
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.form-item {
+  margin-bottom: 40rpx;
+  
+  .form-label {
+    font-size: 28rpx;
+    margin-bottom: 15rpx;
+    color: #333;
+    
+    &.required::before {
+      content: '*';
+      color: #ff0000;
+      margin-right: 5rpx;
+    }
+  }
+  
+  .form-input {
+    width: 100%;
+    height: 70rpx;
+    padding: 0 20rpx;
+    border: 1rpx solid #eee;
+    border-radius: 10rpx;
+    font-size: 28rpx;
+    box-sizing: border-box;
+    
+    &.picker-input {
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+    }
+    
+    &.disabled {
+      background-color: #f5f5f5;
+      color: #999;
+    }
+  }
+}
+</style>
+
diff --git a/app/pagesTask/components/HospitalSelector.vue b/app/pagesTask/components/HospitalSelector.vue
index 5f3c420..b82dc5b 100644
--- a/app/pagesTask/components/HospitalSelector.vue
+++ b/app/pagesTask/components/HospitalSelector.vue
@@ -27,42 +27,6 @@
       </view>
     </view>
     
-    <view class="form-item" v-if="showDepartment">
-      <view class="form-label" :class="{ required: departmentRequired }">绉戝</view>
-      <picker 
-        v-if="selectedHospitalName !== '瀹朵腑' && departmentOptions.length > 0"
-        mode="selector" 
-        :range="departmentOptions" 
-        range-key="text" 
-        @change="onDepartmentChange"
-      >
-        <view class="form-input picker-input">
-          {{ departmentValue || '璇烽�夋嫨绉戝' }}
-          <uni-icons type="arrowright" size="16" color="#999"></uni-icons>
-        </view>
-      </picker>
-      <input 
-        v-else-if="selectedHospitalName !== '瀹朵腑'"
-        class="form-input" 
-        placeholder="璇疯緭鍏ョ瀹�" 
-        :value="departmentValue"
-        @input="onDepartmentInput"
-      />
-      <view v-else class="form-input picker-input disabled">
-        鍏跺畠
-      </view>
-    </view>
-    
-    <view class="form-item" v-if="showBedNumber">
-      <view class="form-label">搴婂彿</view>
-      <input 
-        class="form-input" 
-        placeholder="璇疯緭鍏ュ簥鍙�" 
-        :value="bedNumberValue"
-        @input="onBedNumberInput"
-      />
-    </view>
-    
     <view class="form-item">
       <view class="form-label" :class="{ required: required }">{{ addressLabel }}</view>
       <view class="address-input-container" v-if="selectedHospitalName === '瀹朵腑'">
@@ -136,26 +100,6 @@
         address: ''
       })
     },
-    // 鏄惁鏄剧ず绉戝
-    showDepartment: {
-      type: Boolean,
-      default: true
-    },
-    // 绉戝鏄惁蹇呭~
-    departmentRequired: {
-      type: Boolean,
-      default: false
-    },
-    // 绉戝閫夐」鍒楄〃锛堢敤浜� picker锛�
-    departmentOptions: {
-      type: Array,
-      default: () => []
-    },
-    // 鏄惁鏄剧ず搴婂彿
-    showBedNumber: {
-      type: Boolean,
-      default: true
-    },
     // 閮ㄩ棬ID锛堢敤浜庡尯鍩熻繃婊わ級
     deptId: {
       type: [Number, String],
@@ -186,12 +130,6 @@
   computed: {
     addressValue() {
       return this.value.address || ''
-    },
-    departmentValue() {
-      return this.value.department || ''
-    },
-    bedNumberValue() {
-      return this.value.bedNumber || ''
     }
   },
   watch: {
@@ -292,16 +230,7 @@
       const hospitalData = {
         id: hospital.hospId,
         name: hospital.hospName,
-        department: this.value.department || '',
-        departmentId: this.value.departmentId || null,
-        bedNumber: this.value.bedNumber || '',
         address: hospital.hospName === '瀹朵腑' ? '' : this.buildFullAddress(hospital)
-      }
-      
-      // 濡傛灉閫夋嫨鐨勬槸"瀹朵腑"锛岀瀹よ缃负"鍏跺畠"
-      if (hospital.hospName === '瀹朵腑') {
-        hospitalData.department = '鍏跺畠'
-        hospitalData.departmentId = null
       }
       
       this.showResults = false
@@ -388,45 +317,13 @@
         ...this.value,
         address: fullAddress
       })
+      this.$emit('address-selected', {
+        address: fullAddress,
+        location: item.location
+      })
           
       this.showAddressSuggestions = false
       this.addressSuggestions = []
-    },
-    
-    // 绉戝閫夋嫨鍙樺寲锛坧icker锛�
-    onDepartmentChange(e) {
-      const index = e.detail.value
-      const selected = this.departmentOptions[index]
-      const updatedValue = {
-        ...this.value,
-        department: selected.text,
-        departmentId: selected.id
-      }
-      this.$emit('input', updatedValue)
-      this.$emit('department-change', {
-        department: selected.text,
-        departmentId: selected.id
-      })
-    },
-    
-    // 绉戝杈撳叆锛堟墜鍔ㄨ緭鍏ワ級
-    onDepartmentInput(e) {
-      const department = e.detail.value
-      this.$emit('input', {
-        ...this.value,
-        department: department
-      })
-      this.$emit('department-change', department)
-    },
-    
-    // 搴婂彿杈撳叆
-    onBedNumberInput(e) {
-      const bedNumber = e.detail.value
-      this.$emit('input', {
-        ...this.value,
-        bedNumber: bedNumber
-      })
-      this.$emit('bed-number-change', bedNumber)
     }
   }
 }
diff --git a/app/pagesTask/create-emergency.vue b/app/pagesTask/create-emergency.vue
index a752eda..e2b1d05 100644
--- a/app/pagesTask/create-emergency.vue
+++ b/app/pagesTask/create-emergency.vue
@@ -144,28 +144,60 @@
         label="鍖婚櫌鍚嶇О"
         address-label="杞嚭鍦板潃"
         :required="true"
-        :department-required="true"
+        :show-department="false"
         v-model="taskForm.hospitalOut"
         :dept-id="selectedOrganizationId"
         :region="selectedRegion"
-        :department-options="departmentOptions"
         @change="onHospitalOutChange"
         @address-selected="onHospitalOutAddressSelected"
       />
+      <DepartmentSelector
+        label="杞嚭绉戝"
+        :required="true"
+        v-model="taskForm.hospitalOut.department"
+        :department-id="taskForm.hospitalOut.departmentId"
+        :is-home="taskForm.hospitalOut.name === '瀹朵腑'"
+        @change="onHospitalOutDepartmentChange"
+      />
+      
+      <view class="form-item">
+        <view class="form-label">搴婂彿</view>
+        <input 
+          class="form-input" 
+          placeholder="璇疯緭鍏ュ簥鍙�" 
+          v-model="taskForm.hospitalOut.bedNumber"
+        />
+      </view>
       
       <view class="form-section-title">杞叆鍖婚櫌淇℃伅</view>
       <HospitalSelector
         label="鍖婚櫌鍚嶇О"
         address-label="杞叆鍦板潃"
         :required="true"
-        :department-required="true"
+        :show-department="false"
         v-model="taskForm.hospitalIn"
         :dept-id="selectedOrganizationId"
         :region="selectedRegion"
-        :department-options="departmentOptions"
         @change="onHospitalInChange"
         @address-selected="onHospitalInAddressSelected"
       />
+      <DepartmentSelector
+        label="杞叆绉戝"
+        :required="true"
+        v-model="taskForm.hospitalIn.department"
+        :department-id="taskForm.hospitalIn.departmentId"
+        :is-home="taskForm.hospitalIn.name === '瀹朵腑'"
+        @change="onHospitalInDepartmentChange"
+      />
+      
+      <view class="form-item">
+        <view class="form-label">搴婂彿</view>
+        <input 
+          class="form-input" 
+          placeholder="璇疯緭鍏ュ簥鍙�" 
+          v-model="taskForm.hospitalIn.bedNumber"
+        />
+      </view>
       
       <view class="form-item">
         <view class="form-label required">杞繍鍏噷鏁�</view>
@@ -245,13 +277,14 @@
 import { checkVehicleActiveTasks } from "@/api/task"
 
 import { getDicts } from "@/api/dict"
-import { getServiceOrdAreaTypes, getServiceOrderTypes, getHospitalDepartments } from "@/api/dictionary"
+import { getServiceOrdAreaTypes, getServiceOrderTypes } from "@/api/dictionary"
 import { listBranchCompany, getDept } from "@/api/system/dept"
 import MapSelector from './components/map-selector.vue'
 import OrganizationSelector from './components/OrganizationSelector.vue'
 import HospitalSelector from './components/HospitalSelector.vue'
 import DiseaseSelector from './components/DiseaseSelector.vue'
 import StaffSelector from './components/StaffSelector.vue'
+import DepartmentSelector from './components/DepartmentSelector.vue'
 
 export default {
   components: {
@@ -262,7 +295,8 @@
     HospitalSelector,
     DiseaseSelector,
     DepartureSelector,
-    StaffSelector
+    StaffSelector,
+    DepartmentSelector
   },
   data() {
     return {
@@ -320,7 +354,6 @@
       emergencyTaskTypeOptions: [], // 浠诲姟绫诲瀷閫夐」锛堢敤浜巔icker鏄剧ず锛�
       documentTypes: [], // 鍗曟嵁绫诲瀷鍒楄〃
       documentTypeOptions: [], // 鍗曟嵁绫诲瀷閫夐」锛堢敤浜巔icker鏄剧ず锛�
-      departmentOptions: [], // 绉戝瀛楀吀鏁版嵁
       loading: false,
       // 鏅鸿兘璇嗗埆鐩稿叧
       rawText: '',
@@ -357,8 +390,6 @@
     this.getAvailableVehicles().then(() => {
       this.getUserBoundVehicleInfo()
     })
-    // 鍔犺浇绉戝瀛楀吀鏁版嵁
-    this.loadDepartments()
     // 鍔犺浇浠诲姟绫诲瀷鏁版嵁
     this.loadEmergencyTaskTypes()
     // 鍔犺浇鍗曟嵁绫诲瀷鏁版嵁
@@ -468,22 +499,6 @@
       }
     },
     
-    // 鍔犺浇绉戝鏁版嵁锛堜粠 SQL Server 鍔ㄦ�佸姞杞斤級
-    loadDepartments() {
-      getHospitalDepartments().then(response => {
-        const list = response.data || [];
-        this.departmentOptions = list.map(item => ({
-          id: item.vID,
-          text: item.vtext,
-          dictValue: item.vtext  // 涓轰簡淇濇寔鍏煎鎬э紝淇濈暀dictValue瀛楁
-        }));
-        // console.log('绉戝鏁版嵁鍔犺浇鎴愬姛:', this.departmentOptions);
-      }).catch(error => {
-        console.error('鍔犺浇绉戝鏁版嵁澶辫触:', error)
-        this.departmentOptions = []
-      })
-    },
-    
     // 鍔犺浇浠诲姟绫诲瀷鏁版嵁锛堜粠 SQL Server锛�
     loadEmergencyTaskTypes() {
       getServiceOrderTypes().then(response => {
@@ -552,6 +567,12 @@
       console.log('杞嚭鍖婚櫌鍙樺寲:', hospitalData)
       // 缁勪欢宸茬粡閫氳繃 v-model 鏇存柊浜� taskForm.hospitalOut
       
+      // 濡傛灉閫夋嫨鐨勬槸"瀹朵腑"锛岃嚜鍔ㄨ缃瀹や负"鍏跺畠"
+      if (hospitalData.name === '瀹朵腑') {
+        this.taskForm.hospitalOut.department = '鍏跺畠'
+        this.taskForm.hospitalOut.departmentId = null
+      }
+      
       // 濡傛灉杞叆鍦板潃宸插~鍐�,鑷姩璁$畻璺濈
       if (this.taskForm.hospitalIn.address) {
         // 濡傛灉涓や釜閮戒笉鏄�"瀹朵腑",浣跨敤鍖婚櫌璺濈璁$畻
@@ -576,6 +597,12 @@
       console.log('杞叆鍖婚櫌鍙樺寲:', hospitalData)
       // 缁勪欢宸茬粡閫氳繃 v-model 鏇存柊浜� taskForm.hospitalIn
       
+      // 濡傛灉閫夋嫨鐨勬槸"瀹朵腑"锛岃嚜鍔ㄨ缃瀹や负"鍏跺畠"
+      if (hospitalData.name === '瀹朵腑') {
+        this.taskForm.hospitalIn.department = '鍏跺畠'
+        this.taskForm.hospitalIn.departmentId = null
+      }
+      
       // 濡傛灉杞嚭鍦板潃宸插~鍐�,鑷姩璁$畻璺濈
       if (this.taskForm.hospitalOut.address) {
         // 濡傛灉涓や釜閮戒笉鏄�"瀹朵腑",浣跨敤鍖婚櫌璺濈璁$畻
@@ -592,6 +619,28 @@
     onHospitalInAddressSelected(data) {
       if (this.taskForm.hospitalOut.address) {
         this.calculateDistanceByManualAddress()
+      }
+    },
+    
+    // 杞嚭绉戝鍙樺寲
+    onHospitalOutDepartmentChange(data) {
+      if (data && typeof data === 'object') {
+        this.taskForm.hospitalOut.department = data.department
+        this.taskForm.hospitalOut.departmentId = data.departmentId
+      } else {
+        this.taskForm.hospitalOut.department = data
+        this.taskForm.hospitalOut.departmentId = null
+      }
+    },
+    
+    // 杞叆绉戝鍙樺寲
+    onHospitalInDepartmentChange(data) {
+      if (data && typeof data === 'object') {
+        this.taskForm.hospitalIn.department = data.department
+        this.taskForm.hospitalIn.departmentId = data.departmentId
+      } else {
+        this.taskForm.hospitalIn.department = data
+        this.taskForm.hospitalIn.departmentId = null
       }
     },
     
@@ -1002,20 +1051,14 @@
       if (result.phone) this.taskForm.patient.phone = result.phone
       if (result.price) this.taskForm.price = result.price
       
-      // 搴旂敤绉戝淇℃伅锛堝尮閰� departmentOptions 涓殑鏁版嵁锛�
+      // 搴旂敤绉戝淇℃伅锛堥�氳繃 DepartmentSelector 缁勪欢澶勭悊锛�
       if (result.departmentOut) {
-        const deptOut = this.matchDepartment(result.departmentOut)
-        if (deptOut) {
-          this.taskForm.hospitalOut.department = deptOut.text
-          this.taskForm.hospitalOut.departmentId = deptOut.id
-        }
+        this.taskForm.hospitalOut.department = result.departmentOut
+        // 绉戝ID浼氬湪 DepartmentSelector 缁勪欢涓嚜鍔ㄥ尮閰�
       }
       if (result.departmentIn) {
-        const deptIn = this.matchDepartment(result.departmentIn)
-        if (deptIn) {
-          this.taskForm.hospitalIn.department = deptIn.text
-          this.taskForm.hospitalIn.departmentId = deptIn.id
-        }
+        this.taskForm.hospitalIn.department = result.departmentIn
+        // 绉戝ID浼氬湪 DepartmentSelector 缁勪欢涓嚜鍔ㄥ尮閰�
       }
 
       // 澶勭悊鍖婚櫌鍚嶇О 鈫� 绮剧‘鍖归厤鍖婚櫌骞惰ˉ鍏ㄥ湴鍧�涓嶪D锛堜笉闄愬埗鍒嗗叕鍙稿尯鍩燂級
@@ -1161,40 +1204,6 @@
       return ''
     },
     
-    // 鍖归厤绉戝锛堜紭鍏堜娇鐢� departmentOptions 涓殑鏁版嵁锛�
-    matchDepartment(deptName) {
-      if (!deptName || !this.departmentOptions || this.departmentOptions.length === 0) {
-        return null
-      }
-      
-      const normalized = deptName.trim().toUpperCase()
-      
-      // 1. 绮剧‘鍖归厤锛堜笉鍖哄垎澶у皬鍐欙級
-      let matched = this.departmentOptions.find(d => 
-        d.text.toUpperCase() === normalized
-      )
-      if (matched) return matched
-      
-      // 2. 鍖呭惈鍖归厤锛堢瀹ゅ悕鍖呭惈璇嗗埆鍒扮殑鍏抽敭璇嶏級
-      matched = this.departmentOptions.find(d => 
-        d.text.toUpperCase().includes(normalized) || 
-        normalized.includes(d.text.toUpperCase())
-      )
-      if (matched) return matched
-      
-      // 3. 妯$硦鍖归厤锛堝幓闄�"绉�"銆�"瀹�"绛夊悗缂�鍐嶅尮閰嶏級
-      const cleanedInput = normalized.replace(/[绉戝閮╙/g, '')
-      matched = this.departmentOptions.find(d => {
-        const cleanedDept = d.text.toUpperCase().replace(/[绉戝閮╙/g, '')
-        return cleanedDept === cleanedInput || 
-               cleanedDept.includes(cleanedInput) || 
-               cleanedInput.includes(cleanedDept)
-      })
-      if (matched) return matched
-      
-      return null
-    },
-    
     // 鎻愬彇绉戝淇℃伅
     extractDepartment(text, type) {
       // 甯歌绉戝鍏抽敭璇嶏紙浣滀负鍏滃簳鏂规锛�
@@ -1210,24 +1219,7 @@
         '妫�楠岀', '鐥呯悊绉�', '鑽墏绉�', '钀ュ吇绉�'
       ]
       
-      // 浼樺厛灏濊瘯浠� departmentOptions 涓尮閰�
-      if (this.departmentOptions && this.departmentOptions.length > 0) {
-        // 鏋勫缓 departmentOptions 鐨勫尮閰嶆ā寮忥紙鎸夐暱搴﹀�掑簭锛�
-        const optionTexts = this.departmentOptions.map(d => d.text).sort((a, b) => b.length - a.length)
-        const optionPattern = optionTexts.map(t => t.replace(/[()锛堬級]/g, '\\$&')).join('|')
-        
-        if (optionPattern) {
-          const regex = new RegExp(`(${optionPattern})`, 'gi')
-          const matches = text.match(regex)
-          
-          if (matches && matches.length > 0) {
-            // 濡傛灉鏄浆鍑猴紝鍙栫涓�涓瀹わ紱濡傛灉鏄浆鍏ワ紝鍙栨渶鍚庝竴涓瀹�
-            return type === 'out' ? matches[0] : matches[matches.length - 1]
-          }
-        }
-      }
-      
-      // 鍏滃簳锛氫娇鐢ㄩ粯璁ょ瀹ゅ垪琛ㄥ尮閰�
+      // 浣跨敤榛樿绉戝鍒楄〃鍖归厤
       const sortedDepts = departments.sort((a, b) => b.length - a.length)
       const deptPattern = sortedDepts.join('|')
       
diff --git a/app/pagesTask/detail.vue b/app/pagesTask/detail.vue
index bffcfea..277d825 100644
--- a/app/pagesTask/detail.vue
+++ b/app/pagesTask/detail.vue
@@ -37,7 +37,7 @@
           <view 
             class="assignee-item" 
             v-for="(assignee, index) in taskDetail.assignees" 
-            :key="assignee.userId || index"
+            :key="'assignee-' + (assignee.userId || assignee.userName || index)"
           >
             <view class="assignee-index">{{ index + 1 }}</view>
             <view class="assignee-info">
@@ -131,12 +131,12 @@
         </view>
       </view>
       
-      <view class="detail-section" v-if="taskDetail.taskDescription">
+      <view class="detail-section" v-if="taskDetail.taskDescription && taskDetail.taskType !== 'EMERGENCY_TRANSFER'">
         <view class="section-title">浠诲姟鎻忚堪</view>
         <view class="description">{{ taskDetail.taskDescription }}</view>
       </view>
       
-      <view class="detail-section" v-if="taskDetail.remark">
+      <view class="detail-section" v-if="taskDetail.remark && taskDetail.taskType !== 'EMERGENCY_TRANSFER'">
         <view class="section-title">澶囨敞淇℃伅</view>
         <view class="description">{{ taskDetail.remark }}</view>
       </view>
@@ -250,8 +250,8 @@
         <view class="section-title">鏀粯璁板綍</view>
         <view 
           class="payment-record-item" 
-          v-for="payment in paymentInfo.paidPayments" 
-          :key="payment.id"
+          v-for="(payment, index) in paymentInfo.paidPayments" 
+          :key="'payment-' + (payment.id || index)"
         >
           <view class="payment-header">
             <view 
@@ -449,6 +449,7 @@
   import { checkVehicleActiveTasks } from '@/api/task'
   import { getPaymentInfo } from '@/api/payment'
   import { formatDateTime } from '@/utils/common'
+  import { validateTaskForDepart, validateTaskForSettlement, getTaskVehicleId, checkTaskCanDepart } from '@/utils/taskValidator'
   import AttachmentUpload from './components/AttachmentUpload.vue'
   
   export default {
@@ -752,6 +753,15 @@
       
       // 澶勭悊缁撶畻
       handleSettlement() {
+        // 鏍¢獙浠诲姟鏄惁鍙互缁撶畻
+        const validation = validateTaskForSettlement(this.taskDetail)
+        if (!validation.valid) {
+          this.$modal.confirm(`${validation.message}锛岄渶瑕佸厛淇敼浠诲姟鍚庢墠鑳界粨绠椼�傛槸鍚︾幇鍦ㄥ幓淇敼锛焋).then(() => {
+            this.handleEdit()
+          }).catch(() => {})
+          return
+        }
+        
         uni.navigateTo({
           url: '/pagesTask/settlement?taskId=' + this.taskId
         })
@@ -803,68 +813,84 @@
       },
       
       // 妫�鏌ヨ溅杈嗙姸鎬佸苟鍑哄彂
-      checkVehicleAndDepart() {
-        // 妫�鏌ュ嚭鍙戞椂闂存槸鍚︿负绌烘垨1900骞达紙淇锛氶槻姝㈡棤鏁堟椂闂达級
-        if (!this.taskDetail.plannedStartTime || this.taskDetail.plannedStartTime.startsWith('1900')) {
-          this.$modal.confirm('浠诲姟鐨勮浆杩愭椂闂存湭璁剧疆鎴栨棤鏁堬紝闇�瑕佸厛淇敼浠诲姟琛ュ厖杞繍鏃堕棿鍚庢墠鑳藉嚭鍙戙�傛槸鍚︾幇鍦ㄥ幓淇敼锛�').then(() => {
-            this.handleEdit()
-          }).catch(() => {})
-          return
-        }
-        
-        // 鑾峰彇浠诲姟杞﹁締ID
-        const vehicleId = this.getVehicleId();
-        if (!vehicleId) {
-          this.$modal.showToast('鏈壘鍒颁换鍔¤溅杈嗕俊鎭�');
-          return;
-        }
-        
+      async checkVehicleAndDepart() {
         // 鏄剧ず鍔犺浇鎻愮ず
         uni.showLoading({
-          title: '妫�鏌ヨ溅杈嗙姸鎬�...'
+          title: '妫�鏌ヤ换鍔$姸鎬�...'
         });
         
-        checkVehicleActiveTasks(vehicleId).then(response => {
+        try {
+          // 璋冪敤宸ュ叿绫绘鏌ヤ换鍔℃槸鍚﹀彲浠ュ嚭鍙戯紙鍖呭惈鍩烘湰鏍¢獙鍜屽啿绐佹鏌ワ級
+          const checkResult = await checkTaskCanDepart(this.taskDetail)
+          
           uni.hideLoading();
           
-          const activeTasks = response.data || [];
+          console.log('鍑哄彂妫�鏌ョ粨鏋�:', checkResult);
+          console.log('valid:', checkResult.valid);
+          console.log('conflicts:', checkResult.conflicts);
           
-          // 杩囨护鎺夊綋鍓嶄换鍔℃湰韬紙淇锛氶槻姝� activeTasks 涓� null锛�
-          const otherActiveTasks = (activeTasks && Array.isArray(activeTasks)) ? activeTasks.filter(task => task.taskId !== this.taskId) : [];
-          
-          if (otherActiveTasks.length > 0) {
-            // 杞﹁締鏈夊叾浠栨鍦ㄨ繘琛屼腑鐨勪换鍔�
-            const task = otherActiveTasks[0];
-            const taskStatus = this.getStatusText(task.taskStatus);
-            const message = `璇ヨ溅杈嗗凡鏈夋鍦ㄨ浆杩愪腑鐨勪换鍔★紒
-
-浠诲姟鍗曞彿锛�${task.taskCode}
-浠诲姟鐘舵�侊細${taskStatus}
-
-璇峰厛瀹屾垚褰撳墠浠诲姟鍚庡啀鍑哄彂鏂颁换鍔°�俙;
+          if (!checkResult.valid) {
+            // 鏍¢獙澶辫触锛屾樉绀烘彁绀轰俊鎭苟鎻愪緵璺宠浆閫夐」
+            const conflicts = checkResult.conflicts || [];
+            const conflictInfo = conflicts.length > 0 ? conflicts[0] : null;
             
-            uni.showModal({
-              title: '鎻愮ず',
-              content: message,
-              showCancel: false,
-              confirmText: '鎴戠煡閬撲簡'
-            });
+            console.log('鍐茬獊淇℃伅:', conflictInfo);
+            
+            // 濡傛灉鏈夊啿绐佷换鍔′俊鎭紝鎻愪緵璺宠浆鎸夐挳
+            if (conflictInfo && conflictInfo.taskId) {
+              console.log('鏄剧ず甯﹁烦杞寜閽殑寮圭獥锛屼换鍔D:', conflictInfo.taskId);
+              
+              const conflictTaskId = conflictInfo.taskId;
+              const message = checkResult.message || conflictInfo.message || '瀛樺湪鍐茬獊浠诲姟';
+              
+              uni.showModal({
+                title: '鎻愮ず',
+                content: message,
+                confirmText: '鍘诲鐞�',
+                cancelText: '鐭ラ亾浜�',
+                success: function(res) {
+                  console.log('寮圭獥鐐瑰嚮缁撴灉:', res);
+                  if (res.confirm) {
+                    // 鐢ㄦ埛鐐瑰嚮"鐜板湪鍘诲鐞�"锛岃烦杞埌鍐茬獊浠诲姟璇︽儏椤�
+                    console.log('鍑嗗璺宠浆鍒颁换鍔¤鎯呴〉:', conflictTaskId);
+                    uni.redirectTo({
+                      url: `/pagesTask/detail?id=${conflictTaskId}`
+                    });
+                  }
+                },
+                fail: function(err) {
+                  console.error('鏄剧ず寮圭獥澶辫触:', err);
+                }
+              });
+            } else {
+              // 娌℃湁鍐茬獊浠诲姟ID锛屽彧鏄剧ず鎻愮ず
+              console.log('鏄剧ず鏅�氭彁绀哄脊绐�');
+              uni.showModal({
+                title: '鎻愮ず',
+                content: checkResult.message || '浠诲姟鏍¢獙澶辫触',
+                showCancel: false,
+                confirmText: '鐭ラ亾浜�',
+                fail: function(err) {
+                  console.error('鏄剧ず寮圭獥澶辫触:', err);
+                }
+              });
+            }
             return;
           }
           
-          // 杞﹁締娌℃湁鍏朵粬姝e湪杩涜涓殑浠诲姟锛屽彲浠ュ嚭鍙�
+          // 鎵�鏈夋鏌ラ�氳繃锛屽彲浠ュ嚭鍙�
           this.$modal.confirm('纭畾瑕佸嚭鍙戝悧锛�').then(() => {
             this.updateTaskStatus('DEPARTING', '浠诲姟宸插嚭鍙�')
           }).catch(() => {});
           
-        }).catch(error => {
+        } catch (error) {
           uni.hideLoading();
-          console.error('妫�鏌ヨ溅杈嗙姸鎬佸け璐�:', error);
+          console.error('妫�鏌ヤ换鍔$姸鎬佸け璐�:', error);
           // 妫�鏌ュけ璐ユ椂锛屼粛鐒跺厑璁稿嚭鍙�
-          this.$modal.confirm('妫�鏌ヨ溅杈嗙姸鎬佸け璐ワ紝鏄惁缁х画鍑哄彂锛�').then(() => {
+          this.$modal.confirm('妫�鏌ヤ换鍔$姸鎬佸け璐ワ紝鏄惁缁х画鍑哄彂锛�').then(() => {
             this.updateTaskStatus('DEPARTING', '浠诲姟宸插嚭鍙�')
           }).catch(() => {});
-        });
+        }
       },
       
       // 鑾峰彇浠诲姟杞﹁締ID
diff --git a/app/pagesTask/edit-emergency.vue b/app/pagesTask/edit-emergency.vue
index eefd5df..4790118 100644
--- a/app/pagesTask/edit-emergency.vue
+++ b/app/pagesTask/edit-emergency.vue
@@ -119,25 +119,61 @@
       
       <view class="form-section-title">杞嚭鍖婚櫌淇℃伅</view>
       <HospitalSelector
-        label="鍖洪櫌鍚嶇О"
+        label="鍖婚櫌鍚嶇О"
         address-label="杞嚭鍦板潃"
         :required="true"
+        :show-department="false"
         v-model="taskForm.hospitalOut"
         :dept-id="selectedOrganizationId"
         @change="onHospitalOutChange"
         @address-selected="onHospitalOutAddressSelected"
       />
+      <DepartmentSelector
+        label="杞嚭绉戝"
+        :required="true"
+        v-model="taskForm.hospitalOut.department"
+        :department-id="taskForm.hospitalOut.departmentId"
+        :is-home="taskForm.hospitalOut.name === '瀹朵腑'"
+        @change="onHospitalOutDepartmentChange"
+      />
+      
+      <view class="form-item">
+        <view class="form-label">搴婂彿</view>
+        <input 
+          class="form-input" 
+          placeholder="璇疯緭鍏ュ簥鍙�" 
+          v-model="taskForm.hospitalOut.bedNumber"
+        />
+      </view>
       
       <view class="form-section-title">杞叆鍖婚櫌淇℃伅</view>
       <HospitalSelector
         label="鍖婚櫌鍚嶇О"
         address-label="杞叆鍦板潃"
         :required="true"
+        :show-department="false"
         v-model="taskForm.hospitalIn"
         :dept-id="selectedOrganizationId"
         @change="onHospitalInChange"
         @address-selected="onHospitalInAddressSelected"
       />
+      <DepartmentSelector
+        label="杞叆绉戝"
+        :required="true"
+        v-model="taskForm.hospitalIn.department"
+        :department-id="taskForm.hospitalIn.departmentId"
+        :is-home="taskForm.hospitalIn.name === '瀹朵腑'"
+        @change="onHospitalInDepartmentChange"
+      />
+      
+      <view class="form-item">
+        <view class="form-label">搴婂彿</view>
+        <input 
+          class="form-input" 
+          placeholder="璇疯緭鍏ュ簥鍙�" 
+          v-model="taskForm.hospitalIn.bedNumber"
+        />
+      </view>
       
       <view class="form-item">
         <view class="form-label">杞繍璺濈</view>
@@ -204,6 +240,7 @@
 import DiseaseSelector from './components/DiseaseSelector.vue'
 import DepartureSelector from './components/DepartureSelector.vue'
 import StaffSelector from './components/StaffSelector.vue'
+import DepartmentSelector from './components/DepartmentSelector.vue'
 import distanceCalculator from '@/mixins/distanceCalculator.js'
 
 export default {
@@ -216,7 +253,8 @@
     HospitalSelector,
     DiseaseSelector,
     DepartureSelector,
-    StaffSelector
+    StaffSelector,
+    DepartmentSelector
   },
   mixins: [distanceCalculator],
   data() {
@@ -526,6 +564,12 @@
       console.log('杞嚭鍖婚櫌鍙樺寲:', hospitalData)
       // 缁勪欢宸茬粡閫氳繃 v-model 鏇存柊浜� taskForm.hospitalOut
       
+      // 濡傛灉閫夋嫨鐨勬槸"瀹朵腑"锛岃嚜鍔ㄨ缃瀹や负"鍏跺畠"
+      if (hospitalData.name === '瀹朵腑') {
+        this.taskForm.hospitalOut.department = '鍏跺畠'
+        this.taskForm.hospitalOut.departmentId = null
+      }
+      
       // 濡傛灉杞叆鍦板潃宸插~鍐�,鑷姩璁$畻璺濈
       if (this.taskForm.hospitalIn.address) {
         // 濡傛灉涓や釜閮戒笉鏄�"瀹朵腑",浣跨敤鍖婚櫌璺濈璁$畻
@@ -550,6 +594,12 @@
       console.log('杞叆鍖婚櫌鍙樺寲:', hospitalData)
       // 缁勪欢宸茬粡閫氳繃 v-model 鏇存柊浜� taskForm.hospitalIn
       
+      // 濡傛灉閫夋嫨鐨勬槸"瀹朵腑"锛岃嚜鍔ㄨ缃瀹や负"鍏跺畠"
+      if (hospitalData.name === '瀹朵腑') {
+        this.taskForm.hospitalIn.department = '鍏跺畠'
+        this.taskForm.hospitalIn.departmentId = null
+      }
+      
       // 濡傛灉杞嚭鍦板潃宸插~鍐�,鑷姩璁$畻璺濈
       if (this.taskForm.hospitalOut.address) {
         // 濡傛灉涓や釜閮戒笉鏄�"瀹朵腑",浣跨敤鍖婚櫌璺濈璁$畻
@@ -569,6 +619,28 @@
       }
     },
     
+    // 杞嚭绉戝鍙樺寲
+    onHospitalOutDepartmentChange(data) {
+      if (data && typeof data === 'object') {
+        this.taskForm.hospitalOut.department = data.department
+        this.taskForm.hospitalOut.departmentId = data.departmentId
+      } else {
+        this.taskForm.hospitalOut.department = data
+        this.taskForm.hospitalOut.departmentId = null
+      }
+    },
+    
+    // 杞叆绉戝鍙樺寲
+    onHospitalInDepartmentChange(data) {
+      if (data && typeof data === 'object') {
+        this.taskForm.hospitalIn.department = data.department
+        this.taskForm.hospitalIn.departmentId = data.departmentId
+      } else {
+        this.taskForm.hospitalIn.department = data
+        this.taskForm.hospitalIn.departmentId = null
+      }
+    },
+    
     // 鐥呮儏鍙樺寲
     onDiseaseChange(diseases) {
       console.log('鐥呮儏鍙樺寲:', diseases)
diff --git a/app/utils/taskValidator.js b/app/utils/taskValidator.js
new file mode 100644
index 0000000..c52bc0c
--- /dev/null
+++ b/app/utils/taskValidator.js
@@ -0,0 +1,226 @@
+/**
+ * 浠诲姟鏍¢獙宸ュ叿绫�
+ * 鐢ㄤ簬缁熶竴绠$悊浠诲姟鐩稿叧鐨勫墠缃牎楠岄�昏緫
+ */
+
+import request from '@/utils/request'
+
+/**
+ * 鏍¢獙浠诲姟鏄惁鍙互鎵ц鎿嶄綔锛堝嚭鍙戙�佺粨绠楃瓑锛�
+ * @param {Object} task - 浠诲姟瀵硅薄
+ * @param {Object} options - 鏍¢獙閫夐」
+ * @param {Boolean} options.checkAssignees - 鏄惁妫�鏌ユ墽琛屼汉鍛橈紝榛樿true
+ * @param {Boolean} options.checkVehicles - 鏄惁妫�鏌ヨ溅杈嗭紝榛樿true
+ * @param {Boolean} options.checkPlannedTime - 鏄惁妫�鏌ラ绾︽椂闂达紝榛樿true
+ * @returns {Object} { valid: Boolean, message: String, field: String }
+ */
+export function validateTaskForAction(task, options = {}) {
+  const {
+    checkAssignees = true,
+    checkVehicles = true,
+    checkPlannedTime = true
+  } = options
+
+  // 1. 妫�鏌ユ墽琛屼汉鍛�
+  if (checkAssignees) {
+    const assigneeResult = validateAssignees(task)
+    if (!assigneeResult.valid) {
+      return assigneeResult
+    }
+  }
+
+  // 2. 妫�鏌ヨ溅杈�
+  if (checkVehicles) {
+    const vehicleResult = validateVehicles(task)
+    if (!vehicleResult.valid) {
+      return vehicleResult
+    }
+  }
+
+  // 3. 妫�鏌ラ绾︽椂闂�
+  if (checkPlannedTime) {
+    const timeResult = validatePlannedTime(task)
+    if (!timeResult.valid) {
+      return timeResult
+    }
+  }
+
+  return { valid: true, message: '', field: '' }
+}
+
+/**
+ * 妫�鏌ヤ换鍔℃槸鍚﹀凡鍒嗛厤鎵ц浜哄憳
+ * @param {Object} task - 浠诲姟瀵硅薄
+ * @returns {Object} { valid: Boolean, message: String, field: String }
+ */
+export function validateAssignees(task) {
+  if (!task.assignees || task.assignees.length === 0) {
+    return {
+      valid: false,
+      message: '浠诲姟鏈垎閰嶆墽琛屼汉鍛�',
+      field: 'assignees'
+    }
+  }
+  return { valid: true, message: '', field: '' }
+}
+
+/**
+ * 妫�鏌ヤ换鍔℃槸鍚﹀凡鍒嗛厤杞﹁締
+ * @param {Object} task - 浠诲姟瀵硅薄
+ * @returns {Object} { valid: Boolean, message: String, field: String }
+ */
+export function validateVehicles(task) {
+  // 鏀寔涓ょ瀛楁鍚嶏細vehicleList 鍜� assignedVehicles
+  const vehicles = task.vehicleList || task.assignedVehicles
+  
+  if (!vehicles || vehicles.length === 0) {
+    return {
+      valid: false,
+      message: '浠诲姟鏈垎閰嶈溅杈�',
+      field: 'vehicles'
+    }
+  }
+  return { valid: true, message: '', field: '' }
+}
+
+/**
+ * 妫�鏌ヤ换鍔¢绾︽椂闂存槸鍚︽湁鏁�
+ * @param {Object} task - 浠诲姟瀵硅薄
+ * @returns {Object} { valid: Boolean, message: String, field: String }
+ */
+export function validatePlannedTime(task) {
+  if (!task.plannedStartTime) {
+    return {
+      valid: false,
+      message: '浠诲姟鐨勮浆杩愭椂闂存湭璁剧疆',
+      field: 'plannedStartTime'
+    }
+  }
+
+  // 妫�鏌ユ槸鍚︿负鏃犳晥鏃堕棿锛�1900骞达級
+  if (task.plannedStartTime.startsWith('1900')) {
+    return {
+      valid: false,
+      message: '浠诲姟鐨勮浆杩愭椂闂存棤鏁�',
+      field: 'plannedStartTime'
+    }
+  }
+
+  return { valid: true, message: '', field: '' }
+}
+
+/**
+ * 鑾峰彇浠诲姟鐨勮溅杈咺D
+ * @param {Object} task - 浠诲姟瀵硅薄
+ * @returns {Number|null} 杞﹁締ID锛屾湭鎵惧埌杩斿洖null
+ */
+export function getTaskVehicleId(task) {
+  if (!task) {
+    return null
+  }
+
+  // 浠庤溅杈嗗垪琛ㄤ腑鑾峰彇绗竴涓溅杈嗙殑ID
+  const vehicles = task.assignedVehicles || task.vehicleList
+  if (vehicles && vehicles.length > 0) {
+    return vehicles[0].vehicleId
+  }
+
+  // 鎴栬�呬粠鍗曚釜杞﹁締瀵硅薄鑾峰彇
+  if (task.vehicleId) {
+    return task.vehicleId
+  }
+
+  return null
+}
+
+/**
+ * 鏍¢獙浠诲姟鏄惁鍙互鍑哄彂
+ * @param {Object} task - 浠诲姟瀵硅薄
+ * @returns {Object} { valid: Boolean, message: String, field: String }
+ */
+export function validateTaskForDepart(task) {
+  return validateTaskForAction(task, {
+    checkAssignees: true,
+    checkVehicles: true,
+    checkPlannedTime: true
+  })
+}
+
+/**
+ * 鏍¢獙浠诲姟鏄惁鍙互缁撶畻
+ * @param {Object} task - 浠诲姟瀵硅薄
+ * @returns {Object} { valid: Boolean, message: String, field: String }
+ */
+export function validateTaskForSettlement(task) {
+  return validateTaskForAction(task, {
+    checkAssignees: true,
+    checkVehicles: true,
+    checkPlannedTime: true
+  })
+}
+
+/**
+ * 妫�鏌ヤ换鍔℃槸鍚﹀彲浠ュ嚭鍙戯紙璋冪敤鍚庣鎺ュ彛锛�
+ * 妫�鏌ワ細
+ * 1. 鍩烘湰鏍¢獙锛氳溅杈嗐�佹墽琛屼汉鍛樸�侀绾︽椂闂�
+ * 2. 杞﹁締鍐茬獊妫�鏌ワ細鏄惁鏈夋湭瀹屾垚鐨勪换鍔�
+ * 3. 浜哄憳鍐茬獊妫�鏌ワ細鎵ц浜烘槸鍚︽湁鏈畬鎴愮殑浠诲姟
+ * 
+ * @param {Object} task - 浠诲姟瀵硅薄
+ * @returns {Promise<Object>} { valid: Boolean, message: String, conflicts: Array }
+ */
+export async function checkTaskCanDepart(task) {
+  // 1. 鍏堣繘琛屽熀鏈牎楠�
+  const basicValidation = validateTaskForDepart(task)
+  if (!basicValidation.valid) {
+    return {
+      ...basicValidation,
+      conflicts: [] // 纭繚杩斿洖鐨勫璞″寘鍚玞onflicts瀛楁
+    }
+  }
+  
+  // 2. 璋冪敤鍚庣鎺ュ彛妫�鏌ヨ溅杈嗗拰浜哄憳鍐茬獊
+  try {
+    const response = await request({
+      url: `/task/${task.taskId}/check-depart`,
+      method: 'get'
+    })
+    
+    console.log('鍚庣杩斿洖鐨勫師濮嬫暟鎹�:', response)
+    
+    if (response.code === 200 && response.data) {
+      const { valid, conflicts } = response.data
+      
+      console.log('valid:', valid)
+      console.log('conflicts:', conflicts)
+      
+      if (!valid && conflicts && conflicts.length > 0) {
+        // 鏈夊啿绐侊紝杩斿洖绗竴涓啿绐佷俊鎭�
+        return {
+          valid: false,
+          message: conflicts[0].message,
+          conflicts: conflicts
+        }
+      }
+      
+      return { valid: true, message: '', conflicts: [] }
+    }
+    
+    return { valid: false, message: '妫�鏌ュけ璐ワ紝璇烽噸璇�', conflicts: [] }
+  } catch (error) {
+    console.error('妫�鏌ヤ换鍔℃槸鍚﹀彲浠ュ嚭鍙戝け璐�:', error)
+    // 鎺ュ彛澶辫触鏃讹紝鍙繘琛屽熀鏈牎楠岋紝鍏佽鍑哄彂
+    return { valid: true, message: '', conflicts: [] }
+  }
+}
+
+export default {
+  validateTaskForAction,
+  validateAssignees,
+  validateVehicles,
+  validatePlannedTime,
+  getTaskVehicleId,
+  validateTaskForDepart,
+  validateTaskForSettlement,
+  checkTaskCanDepart
+}
diff --git "a/prd/\350\275\254\350\277\220\344\273\273\345\212\241\347\212\266\346\200\201\345\217\230\346\233\264\350\256\260\345\275\225\345\220\214\346\255\245\345\212\237\350\203\275\350\257\264\346\230\216.md" "b/prd/\350\275\254\350\277\220\344\273\273\345\212\241\347\212\266\346\200\201\345\217\230\346\233\264\350\256\260\345\275\225\345\220\214\346\255\245\345\212\237\350\203\275\350\257\264\346\230\216.md"
new file mode 100644
index 0000000..8205519
--- /dev/null
+++ "b/prd/\350\275\254\350\277\220\344\273\273\345\212\241\347\212\266\346\200\201\345\217\230\346\233\264\350\256\260\345\275\225\345\220\214\346\255\245\345\212\237\350\203\275\350\257\264\346\230\216.md"
@@ -0,0 +1,397 @@
+# 杞繍浠诲姟鐘舵�佸彉鏇磋褰曞悓姝ュ埌鏃х郴缁熷姛鑳借鏄�
+
+## 涓�銆佸姛鑳芥杩�
+
+鏈姛鑳藉疄鐜颁簡鍦ㄨ浆杩愪换鍔$姸鎬佸彂鐢熷彉鏇存椂锛岃嚜鍔ㄥ皢鐘舵�佸彉鏇磋褰曞悓姝ュ埌SQL Server鏃х郴缁熺殑 `DispatchOrd_Running` 琛ㄤ腑銆傝鍔熻兘閫氳繃Spring浜嬩欢鐩戝惉鏈哄埗瀹炵幇锛岀‘淇濈姸鎬佸彉鏇寸殑瀹屾暣璁板綍鍜岃拷韪��
+
+## 浜屻�佹牳蹇冪粍浠�
+
+### 1. 鏁版嵁搴撹〃缁撴瀯
+
+**鏃х郴缁熻〃锛欴ispatchOrd_Running**锛圫QL Server锛�
+
+```sql
+create table DispatchOrd_Running(
+    id int comment "鑷涓婚敭",
+    DispatchOrdIDDt bigint comment '璋冨害鍗旾D',
+    DispatchOrdState int comment '鐘舵��',
+    DispatchOrdStartDate datetime comment '鐘舵�佹椂闂�',
+    DispatchOrdStartOA int comment '鎿嶄綔鐘舵�佺殑OA鐢ㄦ埛ID',
+    OA_latitude float comment '鏇存柊鐘舵�佹椂鐨勭含搴�',
+    OA_longitude float comment '鏇存柊鐘舵�佹椂鐨勭粡搴�',
+    OA_address nvarchar(400) comment '鏇存柊鐘舵�佹椂鐨勫湴鍧�'
+)
+```
+
+### 2. Mapper鎺ュ彛
+
+**LegacyTransferSyncMapper.java**
+
+鏂板鏂规硶锛�
+```java
+/**
+ * 鎻掑叆璋冨害鍗曠姸鎬佸彉鏇磋褰曞埌 DispatchOrd_Running 琛�
+ * 
+ * @param dispatchOrdID 璋冨害鍗旾D
+ * @param dispatchOrdState 鐘舵�佺爜
+ * @param dispatchOrdStartDate 鐘舵�佹椂闂�
+ * @param dispatchOrdStartOA 鎿嶄綔鐘舵�佺殑OA鐢ㄦ埛ID
+ * @param oaLatitude 鏇存柊鐘舵�佹椂鐨勭含搴�
+ * @param oaLongitude 鏇存柊鐘舵�佹椂鐨勭粡搴�
+ * @param oaAddress 鏇存柊鐘舵�佹椂鐨勫湴鍧�
+ * @return 褰卞搷琛屾暟
+ */
+int insertDispatchOrdRunning(
+    @Param("dispatchOrdID") Long dispatchOrdID,
+    @Param("dispatchOrdState") Integer dispatchOrdState,
+    @Param("dispatchOrdStartDate") java.util.Date dispatchOrdStartDate,
+    @Param("dispatchOrdStartOA") Long dispatchOrdStartOA,
+    @Param("oaLatitude") Double oaLatitude,
+    @Param("oaLongitude") Double oaLongitude,
+    @Param("oaAddress") String oaAddress
+);
+```
+
+### 3. Mapper XML閰嶇疆
+
+**LegacyTransferSyncMapper.xml**
+
+```xml
+<!-- 鎻掑叆璋冨害鍗曠姸鎬佸彉鏇磋褰曞埌 DispatchOrd_Running 琛� -->
+<insert id="insertDispatchOrdRunning">
+    INSERT INTO DispatchOrd_Running (
+        DispatchOrdIDDt,
+        DispatchOrdState,
+        DispatchOrdStartDate,
+        DispatchOrdStartOA,
+        OA_latitude,
+        OA_longitude,
+        OA_address
+    ) VALUES (
+        #{dispatchOrdID},
+        #{dispatchOrdState},
+        #{dispatchOrdStartDate},
+        #{dispatchOrdStartOA},
+        #{oaLatitude},
+        #{oaLongitude},
+        #{oaAddress}
+    )
+</insert>
+```
+
+### 4. 浜嬩欢鐩戝惉鍣�
+
+**DispatchOrdRunningListener.java**
+
+- **浣嶇疆**: `ruoyi-system/src/main/java/com/ruoyi/system/listener/`
+- **鍔熻兘**: 鐩戝惉浠诲姟鐘舵�佸彉鏇翠簨浠讹紙TaskStatusChangedEvent锛夛紝鑷姩鍚屾鐘舵�佸彉鏇磋褰曞埌鏃х郴缁�
+- **鐗规��**:
+  - 鉁� **寮傛澶勭悊**: 浣跨敤 `@Async` 娉ㄨВ锛屼笉闃诲涓讳笟鍔℃祦绋�
+  - 鉁� **浜嬩欢鐩戝惉**: 浣跨敤 `@EventListener` 娉ㄨВ鐩戝惉鐘舵�佸彉鏇翠簨浠�
+  - 鉁� **鏅鸿兘杩囨护**: 鍙鐞嗘�ユ晳杞繍浠诲姟涓斿凡鍚屾鍒版棫绯荤粺鐨勪换鍔�
+  - 鉁� **鐘舵�佽浆鎹�**: 鑷姩灏嗘柊绯荤粺鐘舵�佽浆鎹负鏃х郴缁熺姸鎬佺爜
+  - 鉁� **GPS璁板綍**: 璁板綍鐘舵�佸彉鏇存椂鐨凣PS浣嶇疆鍜屽湴鍧�淇℃伅
+  - 鉁� **瀹归敊澶勭悊**: 寮傚父涓嶅奖鍝嶄富涓氬姟娴佺▼
+
+## 涓夈�佸伐浣滄祦绋�
+
+```mermaid
+graph TB
+    A[杞繍浠诲姟鐘舵�佸彉鏇碷 --> B[SysTaskServiceImpl.changeTaskStatus]
+    B --> C[鍙戝竷TaskStatusChangedEvent浜嬩欢]
+    C --> D[DispatchOrdRunningListener鐩戝惉]
+    D --> E{鏄惁鍚敤鏃х郴缁熷悓姝�?}
+    E -->|鍚 F[璺宠繃鍚屾]
+    E -->|鏄瘄 G{鏄惁鎬ユ晳杞繍浠诲姟?}
+    G -->|鍚 F
+    G -->|鏄瘄 H{璋冨害鍗曟槸鍚﹀凡鍚屾?}
+    H -->|鍚 F
+    H -->|鏄瘄 I[杞崲鐘舵�佺爜]
+    I --> J{鐘舵�侀渶瑕佸悓姝�?}
+    J -->|鍚 F
+    J -->|鏄瘄 K[鎻掑叆DispatchOrd_Running琛╙
+    K --> L[璁板綍鏃ュ織]
+```
+
+## 鍥涖�佺姸鎬佹槧灏勫叧绯�
+
+鏂扮郴缁熺姸鎬� 鈫� 鏃х郴缁熺姸鎬佺爜鏄犲皠锛�
+
+| 鏂扮郴缁熺姸鎬� | TaskStatus鏋氫妇 | 鏃х郴缁熺姸鎬佺爜 | 鏃х郴缁熺姸鎬佹弿杩� |
+|-----------|---------------|-------------|---------------|
+| 鍑哄彂涓� | DEPARTING | 4 | 宸插嚭杞︼紙鍘绘帴鎮h�呴�斾腑锛� |
+| 浠诲姟涓� | IN_PROGRESS | 6 | 宸插嚭杞︼紙鏈嶅姟涓級 |
+| 杩旂▼涓� | RETURNING | 7 | 宸查�佽揪锛堝洖绋嬩腑锛� |
+| 宸插畬鎴� | COMPLETED | 8 | 宸茶繑鍥� |
+| 宸插彇娑� | CANCELLED | 10 | 鍙栨秷 |
+| 寰呭鐞� | PENDING | - | 涓嶅悓姝� |
+| 宸插埌杈� | ARRIVED | - | 涓嶅悓姝� |
+
+## 浜斻�佸悓姝ユ潯浠�
+
+婊¤冻浠ヤ笅**鎵�鏈夋潯浠�**鏃舵墠浼氬悓姝ョ姸鎬佸彉鏇磋褰曪細
+
+1. 鉁� 鏃х郴缁熷悓姝ュ姛鑳藉凡鍚敤锛坄legacy.system.enabled=true`锛�
+2. 鉁� 浠诲姟绫诲瀷涓烘�ユ晳杞繍锛坄EMERGENCY_TRANSFER`锛�
+3. 鉁� 浠诲姟宸插悓姝ュ埌鏃х郴缁燂紙`legacy_dispatch_ord_id` 涓嶄负绌猴級
+4. 鉁� 鏂扮姸鎬侀渶瑕佸悓姝ュ埌鏃х郴缁燂紙鍙傝鐘舵�佹槧灏勮〃锛�
+
+## 鍏�佷娇鐢ㄧず渚�
+
+### 1. 鑷姩瑙﹀彂锛堟帹鑽愶級
+
+褰撹浆杩愪换鍔$姸鎬佸彂鐢熷彉鏇存椂锛岀郴缁熶細鑷姩瑙﹀彂鍚屾锛�
+
+```java
+// 鍦⊿ysTaskServiceImpl涓彉鏇寸姸鎬�
+sysTaskService.changeTaskStatus(taskId, TaskStatus.DEPARTING, "鍙告満宸插嚭鍙�");
+
+// 绯荤粺鑷姩锛�
+// 1. 鍙戝竷TaskStatusChangedEvent浜嬩欢
+// 2. DispatchOrdRunningListener鐩戝惉骞跺鐞�
+// 3. 鎻掑叆璁板綍鍒癉ispatchOrd_Running琛�
+```
+
+### 2. 鏃ュ織绀轰緥
+
+**鎴愬姛鍚屾鐨勬棩蹇�**锛�
+```
+2025-12-05 14:30:15 INFO  DispatchOrdRunningListener - 鏀跺埌浠诲姟鐘舵�佸彉鏇翠簨浠讹紝鍑嗗鍚屾鍒癉ispatchOrd_Running锛屼换鍔D锛�1001锛屾棫鐘舵�侊細PENDING锛屾柊鐘舵�侊細DEPARTING
+2025-12-05 14:30:15 INFO  DispatchOrdRunningListener - 寮�濮嬪悓姝ョ姸鎬佸彉鏇磋褰曞埌DispatchOrd_Running锛孌ispatchOrdID: 12345, 鐘舵�佺爜: 4, 鐘舵�佹弿杩�: 宸插嚭杞︼紙鍘绘帴鎮h�呴�斾腑锛�
+2025-12-05 14:30:15 INFO  DispatchOrdRunningListener - 鐘舵�佸彉鏇磋褰曞凡鍚屾鍒癉ispatchOrd_Running锛孌ispatchOrdID: 12345, 鐘舵�佺爜: 4 (宸插嚭杞︼紙鍘绘帴鎮h�呴�斾腑锛�), GPS: [113.264385, 23.12911], 鍦板潃: 骞垮窞甯傝秺绉�鍖篨X璺疿X鍙�
+```
+
+**璺宠繃鍚屾鐨勬棩蹇�**锛�
+```
+2025-12-05 14:30:15 DEBUG DispatchOrdRunningListener - 璋冨害鍗曟湭鍚屾鍒版棫绯荤粺锛岃烦杩嘍ispatchOrd_Running鍚屾锛屼换鍔D: 1001
+```
+
+## 涓冦�佹暟鎹褰曞唴瀹�
+
+姣忔鐘舵�佸彉鏇翠細璁板綍浠ヤ笅淇℃伅锛�
+
+| 瀛楁 | 璇存槑 | 鏁版嵁鏉ユ簮 |
+|-----|------|---------|
+| DispatchOrdIDDt | 璋冨害鍗旾D | sys_task_emergency.legacy_dispatch_ord_id |
+| DispatchOrdState | 鐘舵�佺爜 | 浠庢柊绯荤粺TaskStatus杞崲鑰屾潵 |
+| DispatchOrdStartDate | 鐘舵�佹椂闂� | 褰撳墠鏃堕棿 |
+| DispatchOrdStartOA | 鎿嶄綔浜篒D | TaskStatusChangedEvent.creatorId |
+| OA_latitude | 绾害 | TaskStatusChangedEvent.latitude |
+| OA_longitude | 缁忓害 | TaskStatusChangedEvent.longitude |
+| OA_address | 鍦板潃 | TaskStatusChangedEvent.address |
+
+## 鍏�佺洃鎺у拰璋冭瘯
+
+### 1. 鏌ョ湅鐘舵�佸彉鏇磋褰�
+
+```sql
+-- SQL Server涓煡璇㈡渶杩戠殑鐘舵�佸彉鏇磋褰�
+SELECT TOP 20 
+    DispatchOrdIDDt,
+    DispatchOrdState,
+    DispatchOrdStartDate,
+    DispatchOrdStartOA,
+    OA_latitude,
+    OA_longitude,
+    OA_address
+FROM DispatchOrd_Running
+ORDER BY DispatchOrdStartDate DESC
+```
+
+### 2. 鏌ヨ鐗瑰畾璋冨害鍗曠殑鐘舵�佸彉鏇村巻鍙�
+
+```sql
+-- 鏌ヨ鏌愪釜璋冨害鍗曠殑鎵�鏈夌姸鎬佸彉鏇磋褰�
+SELECT 
+    DispatchOrdState,
+    DispatchOrdStartDate,
+    OA_latitude,
+    OA_longitude,
+    OA_address
+FROM DispatchOrd_Running
+WHERE DispatchOrdIDDt = 12345
+ORDER BY DispatchOrdStartDate DESC
+```
+
+### 3. 缁熻浠婃棩鐘舵�佸彉鏇存鏁�
+
+```sql
+-- 缁熻浠婃棩鍚勭姸鎬佺殑鍙樻洿娆℃暟
+SELECT 
+    DispatchOrdState,
+    CASE DispatchOrdState
+        WHEN 4 THEN '宸插嚭杞︼紙鍘绘帴鎮h�呴�斾腑锛�'
+        WHEN 6 THEN '宸插嚭杞︼紙鏈嶅姟涓級'
+        WHEN 7 THEN '宸查�佽揪锛堝洖绋嬩腑锛�'
+        WHEN 8 THEN '宸茶繑鍥�'
+        WHEN 10 THEN '鍙栨秷'
+        ELSE '鍏朵粬'
+    END AS StateName,
+    COUNT(*) AS ChangeCount
+FROM DispatchOrd_Running
+WHERE CONVERT(DATE, DispatchOrdStartDate) = CONVERT(DATE, GETDATE())
+GROUP BY DispatchOrdState
+ORDER BY DispatchOrdState
+```
+
+## 涔濄�佹灦鏋勪紭鍔�
+
+### 1. 瀹屽叏瑙h��
+- 涓氬姟閫昏緫涓庡悓姝ラ�昏緫鍒嗙
+- 鐘舵�佸彉鏇翠笉渚濊禆鏃х郴缁熷悓姝ョ粨鏋�
+- 鍙嫭绔嬫祴璇曞拰缁存姢
+
+### 2. 寮傛澶勭悊
+- 涓嶉樆濉炰富涓氬姟娴佺▼
+- 鎻愰珮绯荤粺鍝嶅簲閫熷害
+- 瀹归敊鑳藉姏寮�
+
+### 3. 鑷姩鍖�
+- 鏃犻渶鎵嬪姩瑙﹀彂
+- 瀹炴椂鍚屾鐘舵�佸彉鏇�
+- 鍑忓皯浜哄伐鎿嶄綔
+
+### 4. 鍙拷婧��
+- 瀹屾暣璁板綍姣忔鐘舵�佸彉鏇�
+- 鍖呭惈GPS浣嶇疆淇℃伅
+- 渚夸簬闂鎺掓煡鍜屽璁�
+
+## 鍗併�佹敞鎰忎簨椤�
+
+### 1. 鏁版嵁婧愰厤缃�
+
+纭繚 `LegacyTransferSyncMapper` 浣跨敤SQL Server鏁版嵁婧愶細
+```java
+@DataSource(DataSourceType.SQLSERVER)
+public interface LegacyTransferSyncMapper {
+    // ...
+}
+```
+
+### 2. 寮傛绾跨▼姹�
+
+寮傛澶勭悊渚濊禆绾跨▼姹犻厤缃紙AsyncConfig.java锛夛細
+```java
+@Configuration
+@EnableAsync
+public class AsyncConfig {
+    @Bean(name = "taskExecutor")
+    public Executor taskExecutor() {
+        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+        executor.setCorePoolSize(5);
+        executor.setMaxPoolSize(10);
+        executor.setQueueCapacity(100);
+        // ...
+    }
+}
+```
+
+### 3. 寮傚父澶勭悊
+
+鐩戝惉鍣ㄤ腑鐨勫紓甯镐笉浼氬奖鍝嶄富涓氬姟锛�
+- 璁板綍璇︾粏鏃ュ織
+- 涓嶆姏鍑哄紓甯�
+- 涓嶅奖鍝嶇姸鎬佸彉鏇存搷浣�
+
+### 4. 鎬ц兘浼樺寲
+
+- 浣跨敤 `@Async` 寮傛澶勭悊
+- 鍙悓姝ュ繀瑕佺殑鐘舵�佸彉鏇�
+- 鏅鸿兘杩囨护涓嶉渶瑕佸悓姝ョ殑浠诲姟
+
+## 鍗佷竴銆佹祴璇曢獙璇�
+
+### 1. 娴嬭瘯姝ラ
+
+**姝ラ1锛氬垱寤哄苟鍚屾杞繍浠诲姟**
+```java
+// 鍒涘缓鎬ユ晳杞繍浠诲姟
+Long taskId = sysTaskService.insertSysTask(createVO);
+
+// 纭繚浠诲姟宸插悓姝ュ埌鏃х郴缁�
+legacySystemSyncService.syncDispatchOrderToLegacy(taskId);
+```
+
+**姝ラ2锛氬彉鏇翠换鍔$姸鎬�**
+```java
+// 鍙樻洿鐘舵�佷负"鍑哄彂涓�"
+sysTaskService.changeTaskStatus(taskId, TaskStatus.DEPARTING, "鍙告満宸插嚭鍙�");
+```
+
+**姝ラ3锛氶獙璇丼QL Server璁板綍**
+```sql
+-- 鏌ヨDispatchOrd_Running琛�
+SELECT * FROM DispatchOrd_Running 
+WHERE DispatchOrdIDDt = (
+    SELECT legacy_dispatch_ord_id 
+    FROM sys_task_emergency 
+    WHERE task_id = ?
+)
+ORDER BY DispatchOrdStartDate DESC
+```
+
+### 2. 棰勬湡缁撴灉
+
+| 娴嬭瘯鍦烘櫙 | 棰勬湡缁撴灉 |
+|---------|---------|
+| 鎬ユ晳杞繍浠诲姟鐘舵�佸彉鏇� | 鎻掑叆璁板綍鍒癉ispatchOrd_Running |
+| 闈炴�ユ晳杞繍浠诲姟鐘舵�佸彉鏇� | 涓嶆彃鍏ヨ褰� |
+| 鏈悓姝ョ殑浠诲姟鐘舵�佸彉鏇� | 涓嶆彃鍏ヨ褰� |
+| 涓嶉渶瑕佸悓姝ョ殑鐘舵�侊紙PENDING锛� | 涓嶆彃鍏ヨ褰� |
+| 鏃х郴缁熷悓姝ュ凡绂佺敤 | 涓嶆彃鍏ヨ褰� |
+
+## 鍗佷簩銆佺浉鍏虫枃浠舵竻鍗�
+
+### 鏂板鏂囦欢
+- `DispatchOrdRunningListener.java` - 鐘舵�佸彉鏇寸洃鍚櫒
+
+### 淇敼鏂囦欢
+- `LegacyTransferSyncMapper.java` - 娣诲姞insertDispatchOrdRunning鏂规硶
+- `LegacyTransferSyncMapper.xml` - 娣诲姞鎻掑叆SQL
+
+### 渚濊禆鏂囦欢锛堟棤闇�淇敼锛�
+- `SysTaskServiceImpl.java` - 鍙戝竷鐘舵�佸彉鏇翠簨浠�
+- `TaskStatusChangedEvent.java` - 鐘舵�佸彉鏇翠簨浠�
+- `TaskStatusPushConverter.java` - 鐘舵�佽浆鎹㈠伐鍏�
+- `DispatchRunning.sql` - 鏁版嵁搴撹〃缁撴瀯瀹氫箟
+
+## 鍗佷笁銆佹晠闅滄帓鏌�
+
+### 闂1锛氱姸鎬佸彉鏇存病鏈夊悓姝ュ埌鏃х郴缁�
+
+**鎺掓煡姝ラ**锛�
+1. 妫�鏌ユ棫绯荤粺鍚屾鏄惁鍚敤锛歚legacy.system.enabled=true`
+2. 妫�鏌ヤ换鍔℃槸鍚︿负鎬ユ晳杞繍浠诲姟
+3. 妫�鏌ヨ皟搴﹀崟鏄惁宸插悓姝ワ細`legacy_dispatch_ord_id` 涓嶄负绌�
+4. 鏌ョ湅鏃ュ織纭鏄惁鏈夊紓甯�
+5. 妫�鏌ョ姸鎬佹槸鍚﹂渶瑕佸悓姝ワ紙鍙傝�冪姸鎬佹槧灏勮〃锛�
+
+### 闂2锛氭棩蹇椾腑鍑虹幇寮傚父
+
+**甯歌鍘熷洜**锛�
+- SQL Server杩炴帴澶辫触
+- 鏁版嵁婧愰厤缃敊璇�
+- 瀛楁绫诲瀷涓嶅尮閰�
+
+**瑙e喅鏂规硶**锛�
+- 妫�鏌ユ暟鎹簮閰嶇疆
+- 楠岃瘉SQL Server杩炴帴
+- 鏌ョ湅璇︾粏閿欒鏃ュ織
+
+### 闂3锛氭�ц兘闂
+
+**浼樺寲寤鸿**锛�
+- 璋冩暣绾跨▼姹犻厤缃�
+- 妫�鏌QL Server鎬ц兘
+- 浼樺寲鏁版嵁搴撶储寮�
+
+## 鍗佸洓銆佹�荤粨
+
+鏈姛鑳介�氳繃Spring浜嬩欢椹卞姩鏈哄埗锛屽疄鐜颁簡杞繍浠诲姟鐘舵�佸彉鏇磋褰曞埌鏃х郴缁熺殑鑷姩鍚屾锛屽叿鏈変互涓嬬壒鐐癸細
+
+- 鉁� **鑷姩鍖�**锛氱姸鎬佸彉鏇磋嚜鍔ㄥ悓姝ワ紝鏃犻渶鎵嬪姩鎿嶄綔
+- 鉁� **瑙h��**锛氫笟鍔¢�昏緫涓庡悓姝ラ�昏緫瀹屽叏鍒嗙
+- 鉁� **寮傛**锛氫笉褰卞搷涓讳笟鍔℃�ц兘
+- 鉁� **瀹屾暣**锛氳褰旼PS浣嶇疆绛夎缁嗕俊鎭�
+- 鉁� **鍙潬**锛氬閿欏鐞嗭紝寮傚父涓嶅奖鍝嶄富娴佺▼
+- 鉁� **鍙拷婧�**锛氬畬鏁寸殑鐘舵�佸彉鏇村巻鍙茶褰�
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskController.java
index 30081ad..fb8d9c0 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskController.java
@@ -1,7 +1,11 @@
 package com.ruoyi.web.controller.task;
 
 import java.util.List;
+import javax.annotation.Resource;
 import javax.servlet.http.HttpServletResponse;
+
+import com.ruoyi.system.service.*;
+import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -16,6 +20,8 @@
 import com.ruoyi.common.annotation.Log;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.core.domain.entity.SysDept;
 import com.ruoyi.common.enums.BusinessType;
 import com.ruoyi.system.domain.SysTask;
 import com.ruoyi.system.domain.SysTaskLog;
@@ -25,10 +31,9 @@
 import com.ruoyi.system.domain.vo.TaskUpdateVO;
 import com.ruoyi.system.domain.vo.TaskStatisticsVO;
 import com.ruoyi.system.domain.enums.TaskStatus;
-import com.ruoyi.system.service.ISysTaskService;
-import com.ruoyi.system.service.IVehicleInfoService;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.utils.StringUtils;
 
 /**
  * 浠诲姟绠$悊Controller
@@ -45,6 +50,17 @@
     
     @Autowired
     private IVehicleInfoService vehicleInfoService;
+    
+    @Autowired
+    private ISysUserService userService;
+    
+    @Autowired
+    private ISysDeptService deptService;
+
+
+    @Autowired
+    @Qualifier("tiandituMapService")
+    private IMapService mapService;
 
     /**
      * 鏌ヨ浠诲姟绠$悊鍒楄〃锛堝悗鍙扮鐞嗙锛�
@@ -60,21 +76,52 @@
 
     /**
      * 鏌ヨ浠诲姟鍒楄〃锛圓PP绔級
-     * 浠呮樉绀哄綋鍓嶇敤鎴风浉鍏崇殑浠诲姟锛�
-     * 1. 褰撳墠鐢ㄦ埛鎵�鍦ㄦ満鏋勭殑浠诲姟
-     * 2. 褰撳墠鐢ㄦ埛鍒涘缓鐨勪换鍔�
-     * 3. 鍒嗛厤缁欏綋鍓嶇敤鎴风殑浠诲姟
+     * 鏍规嵁鐢ㄦ埛鏉冮檺杩斿洖涓嶅悓鑼冨洿鐨勪换鍔★細
+     * 1. 鏈夋煡鐪嬫墍鏈夊挩璇㈠崟鏉冮檺锛坈anViewAllConsult='1'锛夛細杩斿洖璇ョ敤鎴风鐞嗘墍鏈夊垎鍏徃涓嬬殑鎵�鏈変换鍔″崟
+     * 2. 鏃犳潈闄愶紙canViewAllConsult='0'锛夛細鍙繑鍥炲垎閰嶇粰璇ョ敤鎴风殑鍗曟垨璇ョ敤鎴峰垱寤虹殑鍗�
      */
     @GetMapping("/list")
     public TableDataInfo appList(TaskQueryVO queryVO) {
-        // 鍦ㄥ悗绔嚜鍔ㄨ幏鍙栧綋鍓嶇敤鎴蜂俊鎭紝瀹炵幇缁煎悎鏌ヨ
+        // 鑾峰彇褰撳墠鐢ㄦ埛淇℃伅
         Long currentUserId = getUserId();
-        Long currentDeptId = getDeptId();
+        SysUser currentUser = userService.selectUserById(currentUserId);
         
-        // APP绔己鍒朵娇鐢ㄥ綋鍓嶇櫥褰曠敤鎴蜂俊鎭繘琛岃繃婊�
-        queryVO.setDeptId(currentDeptId);
-        queryVO.setCreatorId(currentUserId);
-        queryVO.setAssigneeId(currentUserId);
+        if (currentUser == null) {
+            return getDataTable(new java.util.ArrayList<>());
+        }
+        
+        // 鍒ゆ柇鐢ㄦ埛鏄惁鏈夋煡鐪嬫墍鏈夊挩璇㈠崟鐨勬潈闄�
+        String canViewAllConsult = currentUser.getCanViewAllConsult();
+        
+        if ("1".equals(canViewAllConsult)) {
+            // 鏈夋潈闄愶細杩斿洖璇ョ敤鎴风鐞嗘墍鏈夊垎鍏徃涓嬬殑鎵�鏈変换鍔″崟
+            // 1. 鑾峰彇鐢ㄦ埛绠$悊鐨勫垎鍏徃鍒楄〃
+            List<SysDept> branchCompanies = deptService.computeBranchCompaniesForUser(currentUser);
+            
+            if (branchCompanies != null && !branchCompanies.isEmpty()) {
+                // 2. 鎻愬彇鎵�鏈夊垎鍏徃ID
+                List<Long> deptIds = new java.util.ArrayList<>();
+                for (SysDept dept : branchCompanies) {
+                    deptIds.add(dept.getDeptId());
+                }
+                
+                // 3. 璁剧疆鏌ヨ鏉′欢涓哄垎鍏徃ID鍒楄〃锛圫QL浼氳嚜鍔ㄥ寘鍚墍鏈夊瓙閮ㄩ棬锛�
+                queryVO.setDeptIds(deptIds);
+                // 娓呯┖鍒涘缓浜哄拰鎵ц浜鸿繃婊ゆ潯浠讹紝杩斿洖杩欎簺鍒嗗叕鍙镐笅鐨勬墍鏈変换鍔�
+                queryVO.setCreatorId(null);
+                queryVO.setAssigneeId(null);
+            } else {
+                // 濡傛灉娌℃湁鎵惧埌鍒嗗叕鍙革紝杩斿洖绌哄垪琛�
+                return getDataTable(new java.util.ArrayList<>());
+            }
+        } else {
+            // 鏃犳潈闄愶細鍙繑鍥炲垎閰嶇粰璇ョ敤鎴风殑鍗曟垨璇ョ敤鎴峰垱寤虹殑鍗�
+            // 娓呯┖deptId鍜宒eptIds锛屼娇鐢╟reatorId鍜宎ssigneeId杩涜OR鏌ヨ
+            queryVO.setDeptId(null);
+            queryVO.setDeptIds(null);
+            queryVO.setCreatorId(currentUserId);
+            queryVO.setAssigneeId(currentUserId);
+        }
         
         startPage();
         List<SysTask> list = sysTaskService.selectSysTaskList(queryVO);
@@ -214,6 +261,8 @@
         
         // 濡傛灉鍖呭惈GPS浣嶇疆淇℃伅锛屼娇鐢ㄥ甫浣嶇疆鐨勬柟娉�
         if (request.getLatitude() != null && request.getLongitude() != null) {
+           String address= mapService.reverseGeocoding(request.getLongitude(), request.getLatitude());
+           request.setLocationAddress(address);
             SysTaskLog locationLog = new SysTaskLog();
             locationLog.setLatitude(request.getLatitude());
             locationLog.setLongitude(request.getLongitude());
@@ -225,10 +274,10 @@
             locationLog.setAltitude(request.getAltitude());
             locationLog.setSpeed(request.getSpeed());
             locationLog.setHeading(request.getHeading());
-            
+
             return toAjax(sysTaskService.changeTaskStatusWithLocation(taskId, newStatus, request.getRemark(), locationLog));
         }
-        
+
         return toAjax(sysTaskService.changeTaskStatus(taskId, newStatus, request.getRemark()));
     }
 
@@ -290,6 +339,20 @@
     }
 
     /**
+     * 妫�鏌ヤ换鍔℃槸鍚﹀彲浠ュ嚭鍙戯紙APP绔級
+     * 妫�鏌ワ細
+     * 1. 杞﹁締鏄惁鏈夋湭瀹屾垚鐨勪换鍔�
+     * 2. 鎵ц浜哄憳鏄惁鏈夋湭瀹屾垚鐨勪换鍔�
+     * 
+     * @param taskId 浠诲姟ID
+     * @return 鏍¢獙缁撴灉
+     */
+    @GetMapping("/{taskId}/check-depart")
+    public AjaxResult checkTaskCanDepart(@PathVariable Long taskId) {
+        return sysTaskService.checkTaskCanDepart(taskId);
+    }
+
+    /**
      * 鍒嗛厤浠诲姟璇锋眰瀵硅薄
      */
     public static class AssignTaskRequest {
diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml
index b039b84..8ab857f 100644
--- a/ruoyi-admin/src/main/resources/application.yml
+++ b/ruoyi-admin/src/main/resources/application.yml
@@ -58,7 +58,7 @@
     basename: i18n/messages
   profiles:
     # 鐜 dev|test|prod
-    active: prod
+    active: dev
   # 鏂囦欢涓婁紶
   servlet:
     multipart:
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java
index c2c48c6..b08d680 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java
@@ -103,6 +103,10 @@
     
     /** 寰俊鏄电О */
     private String wechatNickname;
+    
+    /** 鏄惁鍙煡鐪嬫墍鏈夊挩璇㈠崟锛�0鍚� 1鏄級 */
+    @Excel(name = "鍙煡鐪嬫墍鏈夊挩璇㈠崟", readConverterExp = "0=鍚�,1=鏄�")
+    private String canViewAllConsult;
 
 
 
@@ -364,6 +368,15 @@
         this.wechatNickname = wechatNickname;
     }
     
+    public String getCanViewAllConsult()
+    {
+        return canViewAllConsult;
+    }
+    
+    public void setCanViewAllConsult(String canViewAllConsult)
+    {
+        this.canViewAllConsult = canViewAllConsult;
+    }
 
 
     @Override
@@ -393,6 +406,7 @@
             .append("openId", getOpenId())
             .append("unionId", getUnionId())
             .append("wechatNickname", getWechatNickname())
+            .append("canViewAllConsult", getCanViewAllConsult())
 
             .toString();
     }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/UserSyncDTO.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/UserSyncDTO.java
index 79db005..d0d840c 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/UserSyncDTO.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/UserSyncDTO.java
@@ -22,6 +22,9 @@
 
     /** 鐢ㄦ埛鍙敤鍒嗗叕鍙哥紪鐮佸垪琛紙鏉ユ簮浜嶰A_User.OA_OrderClass锛� */
     private String oaOrderClass;
+    
+    /** 鏄惁鍙煡鐪嬫墍鏈夊挩璇㈠崟锛�0鍚� 1鏄級 */
+    private String canViewAllConsult;
 
     /** 鐢ㄦ埛鎬у埆锛�0=鐢�,1=濂�,2=鏈煡锛� */
     private String sex;
@@ -111,6 +114,16 @@
     {
         this.oaOrderClass = oaOrderClass;
     }
+    
+    public String getCanViewAllConsult()
+    {
+        return canViewAllConsult;
+    }
+    
+    public void setCanViewAllConsult(String canViewAllConsult)
+    {
+        this.canViewAllConsult = canViewAllConsult;
+    }
 
     @Override
     public String toString()
@@ -124,6 +137,7 @@
                 ", email='" + email + '\'' +
                 ", phonenumber='" + phonenumber + '\'' +
                 ", oaOrderClass='" + oaOrderClass + '\'' +
+                ", canViewAllConsult='" + canViewAllConsult + '\'' +
                 '}';
     }
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskQueryVO.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskQueryVO.java
index 6736fee..d899481 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskQueryVO.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskQueryVO.java
@@ -1,6 +1,7 @@
 package com.ruoyi.system.domain.vo;
 
 import java.util.Date;
+import java.util.List;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.common.core.domain.BaseEntity;
 
@@ -33,6 +34,9 @@
 
     /** 褰掑睘閮ㄩ棬ID */
     private Long deptId;
+    
+    /** 褰掑睘閮ㄩ棬ID鍒楄〃锛堢敤浜庢煡璇㈠涓垎鍏徃鐨勪换鍔★級 */
+    private List<Long> deptIds;
 
     /** 璁″垝寮�濮嬫椂闂�-寮�濮� */
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@@ -108,6 +112,14 @@
     public void setDeptId(Long deptId) {
         this.deptId = deptId;
     }
+    
+    public List<Long> getDeptIds() {
+        return deptIds;
+    }
+    
+    public void setDeptIds(List<Long> deptIds) {
+        this.deptIds = deptIds;
+    }
 
     public Date getPlannedStartTimeBegin() {
         return plannedStartTimeBegin;
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/event/TaskStatusChangedEvent.java b/ruoyi-system/src/main/java/com/ruoyi/system/event/TaskStatusChangedEvent.java
index 81708b8..1df49e3 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/event/TaskStatusChangedEvent.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/event/TaskStatusChangedEvent.java
@@ -1,5 +1,8 @@
 package com.ruoyi.system.event;
 
+import lombok.Data;
+
+import java.math.BigDecimal;
 import java.util.List;
 
 /**
@@ -8,6 +11,7 @@
  * @author ruoyi
  * @date 2025-10-25
  */
+
 public class TaskStatusChangedEvent extends TaskEvent {
     
     private static final long serialVersionUID = 1L;
@@ -30,10 +34,18 @@
     /** 鍒涘缓浜篒D */
     private Long creatorId;
 
+    private Double longitude;
+
+    /** 绾害 */
+    private Double latitude;
+
+    private String address;
+
     public TaskStatusChangedEvent(Object source, Long taskId, String taskCode,
                                  String oldStatus, String newStatus,
                                  String oldStatusDesc, String newStatusDesc,
-                                 List<Long> assigneeIds, Long creatorId) {
+                                 List<Long> assigneeIds, Long creatorId,Long operationId, Double longitude,
+                                  Double latitude,String  address) {
         super(source, taskId, taskCode);
         this.oldStatus = oldStatus;
         this.newStatus = newStatus;
@@ -41,8 +53,32 @@
         this.newStatusDesc = newStatusDesc;
         this.assigneeIds = assigneeIds;
         this.creatorId = creatorId;
+        this.longitude = longitude;
+        this.latitude = latitude;
+        this.address = address;
+        this.setOperatorId(operationId);
     }
 
+
+
+    public Double getLongitude() {
+        return longitude;
+    }
+    public void setLongitude(Double longitude) {
+        this.longitude = longitude;
+    }
+    public Double getLatitude() {
+        return latitude;
+    }
+    public void setLatitude(Double latitude) {
+        this.latitude = latitude;
+    }
+    public String getAddress() {
+        return address;
+    }
+    public void setAddress(String address) {
+        this.address = address;
+    }
     public String getOldStatus() {
         return oldStatus;
     }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/listener/DispatchOrdRunningListener.java b/ruoyi-system/src/main/java/com/ruoyi/system/listener/DispatchOrdRunningListener.java
new file mode 100644
index 0000000..861d5a9
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/listener/DispatchOrdRunningListener.java
@@ -0,0 +1,195 @@
+package com.ruoyi.system.listener;
+
+import com.ruoyi.common.config.LegacySystemConfig;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.system.domain.SysTask;
+import com.ruoyi.system.domain.SysTaskEmergency;
+import com.ruoyi.system.domain.enums.TaskStatus;
+import com.ruoyi.system.event.TaskStatusChangedEvent;
+import com.ruoyi.system.mapper.LegacyTransferSyncMapper;
+import com.ruoyi.system.mapper.SysTaskEmergencyMapper;
+import com.ruoyi.system.mapper.SysTaskMapper;
+import com.ruoyi.system.mapper.SysUserMapper;
+import com.ruoyi.system.utils.TaskStatusPushConverter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.event.EventListener;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Component;
+
+import java.util.Date;
+
+/**
+ * 璋冨害鍗曠姸鎬佸彉鏇磋褰曠洃鍚櫒
+ * 鐩戝惉浠诲姟鐘舵�佸彉鏇翠簨浠讹紝骞跺皢鐘舵�佸彉鏇磋褰曞悓姝ュ埌SQL Server鐨凞ispatchOrd_Running琛�
+ * 
+ * @author ruoyi
+ * @date 2025-12-05
+ */
+@Component
+public class DispatchOrdRunningListener {
+    
+    private static final Logger log = LoggerFactory.getLogger(DispatchOrdRunningListener.class);
+    
+    @Autowired
+    private LegacySystemConfig legacyConfig;
+    
+    @Autowired
+    private SysTaskMapper sysTaskMapper;
+    
+    @Autowired
+    private SysTaskEmergencyMapper sysTaskEmergencyMapper;
+    
+    @Autowired
+    private LegacyTransferSyncMapper legacyTransferSyncMapper;
+
+    @Autowired
+    private SysUserMapper sysUserMapper;
+    
+    /**
+     * 鐩戝惉浠诲姟鐘舵�佸彉鏇翠簨浠�
+     * 
+     * @param event 浠诲姟鐘舵�佸彉鏇翠簨浠�
+     */
+    @Async
+    @EventListener
+    public void handleTaskStatusChangedEvent(TaskStatusChangedEvent event) {
+        try {
+            log.info("鏀跺埌浠诲姟鐘舵�佸彉鏇翠簨浠讹紝鍑嗗鍚屾鍒癉ispatchOrd_Running锛屼换鍔D锛歿}锛屾棫鐘舵�侊細{}锛屾柊鐘舵�侊細{}", 
+                    event.getTaskId(), event.getOldStatus(), event.getNewStatus());
+            
+            // 妫�鏌ユ棫绯荤粺鍚屾鏄惁鍚敤
+            if (!legacyConfig.isEnabled()) {
+                log.debug("鏃х郴缁熷悓姝ュ凡绂佺敤锛岃烦杩嘍ispatchOrd_Running鍚屾锛屼换鍔D: {}", event.getTaskId());
+                return;
+            }
+            
+            // 鏌ヨ浠诲姟淇℃伅
+            SysTask task = sysTaskMapper.selectSysTaskByTaskId(event.getTaskId());
+            if (task == null) {
+                log.error("浠诲姟涓嶅瓨鍦紝浠诲姟ID: {}", event.getTaskId());
+                return;
+            }
+            
+            // 鍙鐞嗘�ユ晳杞繍浠诲姟
+            if (!"EMERGENCY_TRANSFER".equals(task.getTaskType())) {
+                log.debug("闈炴�ユ晳杞繍浠诲姟锛岃烦杩嘍ispatchOrd_Running鍚屾锛屼换鍔D: {}", event.getTaskId());
+                return;
+            }
+            
+            // 鏌ヨ鎬ユ晳杞繍鎵╁睍淇℃伅
+            SysTaskEmergency emergency = sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(event.getTaskId());
+            if (emergency == null) {
+                log.error("鎬ユ晳杞繍鎵╁睍淇℃伅涓嶅瓨鍦紝浠诲姟ID: {}", event.getTaskId());
+                return;
+            }
+            
+            // 蹇呴』宸茬粡鍚屾杩囪皟搴﹀崟
+            if (emergency.getLegacyDispatchOrdId() == null || emergency.getLegacyDispatchOrdId() <= 0) {
+                log.debug("璋冨害鍗曟湭鍚屾鍒版棫绯荤粺锛岃烦杩嘍ispatchOrd_Running鍚屾锛屼换鍔D: {}", event.getTaskId());
+                return;
+            }
+            
+            // 鑾峰彇鏂扮郴缁熺姸鎬�
+            TaskStatus newTaskStatus = TaskStatus.getByCode(event.getNewStatus());
+            if (newTaskStatus == null) {
+                log.error("鏃犳晥鐨勪换鍔$姸鎬侊紝浠诲姟ID: {}, 鐘舵�佺爜: {}", event.getTaskId(), event.getNewStatus());
+                return;
+            }
+
+            SysUser user= sysUserMapper.selectUserById(event.getOperatorId());
+            if(user==null){
+                log.error("鎿嶄綔浜轰笉瀛樺湪锛屼换鍔D: {}, 鎿嶄綔浜篒D: {}", event.getTaskId(), event.getOperatorId());
+                return;
+            }
+            Integer oaUserId=user.getOaUserId();
+            
+            // 杞崲涓烘棫绯荤粺鐘舵�佺爜
+            Integer legacyStatusCode = TaskStatusPushConverter.convertToLegacyStatus(newTaskStatus);
+            if (legacyStatusCode == null) {
+                log.debug("浠诲姟鐘舵�佷笉闇�瑕佸悓姝ュ埌鏃х郴缁燂紝浠诲姟ID: {}, 鐘舵��: {}",
+                    event.getTaskId(), newTaskStatus.getInfo());
+                return;
+            }
+            
+            // 鎻掑叆鐘舵�佸彉鏇磋褰曞埌DispatchOrd_Running琛�
+            syncDispatchOrdRunning(
+                emergency.getLegacyDispatchOrdId(),
+                legacyStatusCode,
+                new Date(), // 浣跨敤褰撳墠鏃堕棿浣滀负鐘舵�佸彉鏇存椂
+                    oaUserId.longValue(),
+                event.getLatitude(),
+                event.getLongitude(),
+                event.getAddress()
+            );
+            
+        } catch (Exception e) {
+            log.error("澶勭悊浠诲姟鐘舵�佸彉鏇翠簨浠跺苟鍚屾鍒癉ispatchOrd_Running澶辫触锛屼换鍔D: {}", event.getTaskId(), e);
+            // 涓嶆姏鍑哄紓甯革紝閬垮厤褰卞搷涓绘祦绋�
+        }
+    }
+    
+    /**
+     * 鍚屾鐘舵�佸彉鏇磋褰曞埌DispatchOrd_Running琛�
+     * 
+     * @param dispatchOrdId 璋冨害鍗旾D
+     * @param statusCode 鐘舵�佺爜
+     * @param statusTime 鐘舵�佹椂闂�
+     * @param operatorId 鎿嶄綔浜篒D
+     * @param latitude 绾害
+     * @param longitude 缁忓害
+     * @param address 鍦板潃
+     */
+    private void syncDispatchOrdRunning(Long dispatchOrdId, Integer statusCode, 
+                                        Date statusTime, Long operatorId,
+                                        Double latitude, Double longitude, String address) {
+        try {
+            // 鍒ゆ柇鏄惁鏈塆PS淇℃伅
+            boolean hasGps = (latitude != null && longitude != null);
+            if (hasGps) {
+                log.info("寮�濮嬪悓姝ョ姸鎬佸彉鏇磋褰曞埌DispatchOrd_Running锛孌ispatchOrdID: {}, 鐘舵�佺爜: {} ({}), GPS: [{}, {}]", 
+                    dispatchOrdId, statusCode, TaskStatusPushConverter.getLegacyStatusDescription(statusCode),
+                    latitude, longitude);
+            } else {
+                log.info("寮�濮嬪悓姝ョ姸鎬佸彉鏇磋褰曞埌DispatchOrd_Running锛孌ispatchOrdID: {}, 鐘舵�佺爜: {} ({}), 鏃燝PS淇℃伅", 
+                    dispatchOrdId, statusCode, TaskStatusPushConverter.getLegacyStatusDescription(statusCode));
+            }
+            
+            // 璋冪敤Mapper鎻掑叆璁板綍
+            int rows = legacyTransferSyncMapper.insertDispatchOrdRunning(
+                dispatchOrdId,
+                statusCode,
+                statusTime,
+                operatorId,
+                latitude,
+                longitude,
+                address
+            );
+            
+            if (rows > 0) {
+                if (hasGps) {
+                    log.info("鐘舵�佸彉鏇磋褰曞凡鍚屾鍒癉ispatchOrd_Running锛孌ispatchOrdID: {}, 鐘舵�佺爜: {} ({}), GPS: [{}, {}], 鍦板潃: {}", 
+                        dispatchOrdId, 
+                        statusCode, 
+                        TaskStatusPushConverter.getLegacyStatusDescription(statusCode),
+                        latitude, 
+                        longitude,
+                        address != null ? address : "鏃�");
+                } else {
+                    log.info("鐘舵�佸彉鏇磋褰曞凡鍚屾鍒癉ispatchOrd_Running锛孌ispatchOrdID: {}, 鐘舵�佺爜: {} ({}), 鏃燝PS淇℃伅", 
+                        dispatchOrdId, 
+                        statusCode, 
+                        TaskStatusPushConverter.getLegacyStatusDescription(statusCode));
+                }
+            } else {
+                log.warn("鍚屾鐘舵�佸彉鏇磋褰曞け璐ワ紝鏈彃鍏ユ暟鎹紝DispatchOrdID: {}", dispatchOrdId);
+            }
+            
+        } catch (Exception e) {
+            log.error("鍚屾鐘舵�佸彉鏇磋褰曞埌DispatchOrd_Running寮傚父锛孌ispatchOrdID: {}, 鐘舵�佺爜: {}", 
+                dispatchOrdId, statusCode, e);
+            // 涓嶆姏鍑哄紓甯革紝閬垮厤褰卞搷涓绘祦绋�
+        }
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/listener/TaskMessageListener.java b/ruoyi-system/src/main/java/com/ruoyi/system/listener/TaskMessageListener.java
index 87a04f4..c46d1d8 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/listener/TaskMessageListener.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/listener/TaskMessageListener.java
@@ -92,6 +92,8 @@
         }
     }
 
+
+
     /**
      * 鐩戝惉浠诲姟鍒嗛厤浜嬩欢
      * 
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/LegacyTransferSyncMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/LegacyTransferSyncMapper.java
index 4112657..89fa80b 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/LegacyTransferSyncMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/LegacyTransferSyncMapper.java
@@ -73,4 +73,26 @@
      * @return 绉戝鍚嶇О
      */
     String selectDepartmentNameByDeptID(@Param("deptID") String deptID);
+    
+    /**
+     * 鎻掑叆璋冨害鍗曠姸鎬佸彉鏇磋褰曞埌 DispatchOrd_Running 琛�
+     * 
+     * @param dispatchOrdID 璋冨害鍗旾D
+     * @param dispatchOrdState 鐘舵�佺爜
+     * @param dispatchOrdStartDate 鐘舵�佹椂闂�
+     * @param dispatchOrdStartOA 鎿嶄綔鐘舵�佺殑OA鐢ㄦ埛ID
+     * @param oaLatitude 鏇存柊鐘舵�佹椂鐨勭含搴�
+     * @param oaLongitude 鏇存柊鐘舵�佹椂鐨勭粡搴�
+     * @param oaAddress 鏇存柊鐘舵�佹椂鐨勫湴鍧�
+     * @return 褰卞搷琛屾暟
+     */
+    int insertDispatchOrdRunning(
+        @Param("dispatchOrdID") Long dispatchOrdID,
+        @Param("dispatchOrdState") Integer dispatchOrdState,
+        @Param("dispatchOrdStartDate") java.util.Date dispatchOrdStartDate,
+        @Param("dispatchOrdStartOA") Long dispatchOrdStartOA,
+        @Param("oaLatitude") Double oaLatitude,
+        @Param("oaLongitude") Double oaLongitude,
+        @Param("oaAddress") String oaAddress
+    );
 }
\ No newline at end of file
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskService.java
index 9fbe692..d0630b0 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskService.java
@@ -273,4 +273,15 @@
      */
     public boolean existsByLegacyDispatchOrdId(Long legacyDispatchOrdId);
 
+    /**
+     * 妫�鏌ヤ换鍔℃槸鍚﹀彲浠ュ嚭鍙�
+     * 妫�鏌ワ細
+     * 1. 杞﹁締鏄惁鏈夋湭瀹屾垚鐨勪换鍔�
+     * 2. 鎵ц浜哄憳鏄惁鏈夋湭瀹屾垚鐨勪换鍔�
+     * 
+     * @param taskId 浠诲姟ID
+     * @return AjaxResult 鏍¢獙缁撴灉锛屽寘鍚� valid 鍜� conflicts 淇℃伅
+     */
+    public com.ruoyi.common.core.domain.AjaxResult checkTaskCanDepart(Long taskId);
+
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/LegacySystemSyncServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/LegacySystemSyncServiceImpl.java
index 4646829..4413acb 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/LegacySystemSyncServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/LegacySystemSyncServiceImpl.java
@@ -89,6 +89,8 @@
 
     @Autowired
     private ITaskAttachmentService taskAttachmentService;
+
+
     
     /**
      * 鍚屾鎬ユ晳杞繍浠诲姟鍒版棫绯荤粺
@@ -342,8 +344,70 @@
                 return null;
             }
 
-
-
+            // ====== 鍓嶇疆鏍¢獙锛氱‘淇濅换鍔℃暟鎹畬鏁� ======
+            
+            // 1. 妫�鏌ユ槸鍚﹀凡鍒嗛厤杞﹁締
+            List<SysTaskVehicle> taskVehicles = sysTaskVehicleMapper.selectSysTaskVehicleByTaskId(taskId);
+            if (taskVehicles == null || taskVehicles.isEmpty()) {
+                log.warn("浠诲姟鏈垎閰嶈溅杈嗭紝璺宠繃璋冨害鍗曞悓姝ワ紝浠诲姟ID: {}", taskId);
+                return null;
+            }
+            
+            // 2. 妫�鏌ユ槸鍚﹀凡鍒嗛厤鎵ц浜哄憳
+            List<SysTaskAssignee> taskAssignees = sysTaskAssigneeMapper.selectSysTaskAssigneeByTaskId(taskId);
+            if (taskAssignees == null || taskAssignees.isEmpty()) {
+                log.warn("浠诲姟鏈垎閰嶆墽琛屼汉鍛橈紝璺宠繃璋冨害鍗曞悓姝ワ紝浠诲姟ID: {}", taskId);
+                return null;
+            }
+            
+            // 3. 妫�鏌ラ绾︽椂闂存槸鍚︽湁鏁堬紙蹇呴』澶т簬1970骞达級
+            if (task.getPlannedStartTime() == null) {
+                log.warn("浠诲姟鏈缃绾︽椂闂达紝璺宠繃璋冨害鍗曞悓姝ワ紝浠诲姟ID: {}", taskId);
+                return null;
+            }
+            
+            // 妫�鏌ラ绾︽椂闂存槸鍚﹀ぇ浜�1970-01-01锛堟椂闂存埑0瀵瑰簲1970-01-01 00:00:00锛�
+            long timestamp1970 = 0L;
+            if (task.getPlannedStartTime().getTime() <= timestamp1970) {
+                log.warn("浠诲姟棰勭害鏃堕棿鏃犳晥锛堝皬浜庣瓑浜�1970骞达級锛岃烦杩囪皟搴﹀崟鍚屾锛屼换鍔D: {}, 棰勭害鏃堕棿: {}", 
+                    taskId, task.getPlannedStartTime());
+                return null;
+            }
+            
+            // 4. 妫�鏌ヨ浆鍑哄尰闄俊鎭�
+            if (StringUtils.isEmpty(emergency.getHospitalOutName())) {
+                log.warn("浠诲姟鏈缃浆鍑哄尰闄紝璺宠繃璋冨害鍗曞悓姝ワ紝浠诲姟ID: {}", taskId);
+                return null;
+            }
+            
+            if (StringUtils.isEmpty(emergency.getHospitalOutAddress())) {
+                log.warn("浠诲姟鏈缃浆鍑哄尰闄㈠湴鍧�锛岃烦杩囪皟搴﹀崟鍚屾锛屼换鍔D: {}", taskId);
+                return null;
+            }
+            
+            // 5. 妫�鏌ヨ浆鍏ュ尰闄俊鎭�
+            if (StringUtils.isEmpty(emergency.getHospitalInName())) {
+                log.warn("浠诲姟鏈缃浆鍏ュ尰闄紝璺宠繃璋冨害鍗曞悓姝ワ紝浠诲姟ID: {}", taskId);
+                return null;
+            }
+            
+            if (StringUtils.isEmpty(emergency.getHospitalInAddress())) {
+                log.warn("浠诲姟鏈缃浆鍏ュ尰闄㈠湴鍧�锛岃烦杩囪皟搴﹀崟鍚屾锛屼换鍔D: {}", taskId);
+                return null;
+            }
+            
+            // 6. 妫�鏌ユ偅鑰呭熀鏈俊鎭�
+            if (StringUtils.isEmpty(emergency.getPatientName())) {
+                log.warn("浠诲姟鏈缃偅鑰呭鍚嶏紝璺宠繃璋冨害鍗曞悓姝ワ紝浠诲姟ID: {}", taskId);
+                return null;
+            }
+            
+            if (StringUtils.isEmpty(emergency.getPatientPhone())) {
+                log.warn("浠诲姟鏈缃偅鑰呯數璇濓紝璺宠繃璋冨害鍗曞悓姝ワ紝浠诲姟ID: {}", taskId);
+                return null;
+            }
+            
+            log.info("浠诲姟鏁版嵁鏍¢獙閫氳繃锛屽紑濮嬪悓姝ヨ皟搴﹀崟锛屼换鍔D: {}", taskId);
 
             // 鏇存柊鍚屾鐘舵�佷负鍚屾涓�
             emergency.setDispatchSyncStatus(1);
@@ -1181,7 +1245,47 @@
                 return false;
             }
             
-            log.info("寮�濮嬮噸鏂板悓姝ヨ皟搴﹀崟锛屼换鍔D: {}, DispatchOrdID: {}", taskId, emergency.getLegacyDispatchOrdId());
+            // ====== 鍓嶇疆鏍¢獙锛氱‘淇濅换鍔℃暟鎹畬鏁� ======
+            
+            // 1. 妫�鏌ユ槸鍚﹀凡鍒嗛厤杞﹁締
+            List<SysTaskVehicle> taskVehicles = sysTaskVehicleMapper.selectSysTaskVehicleByTaskId(taskId);
+            if (taskVehicles == null || taskVehicles.isEmpty()) {
+                log.warn("浠诲姟鏈垎閰嶈溅杈嗭紝璺宠繃璋冨害鍗曢噸鏂板悓姝ワ紝浠诲姟ID: {}", taskId);
+                return false;
+            }
+            
+            // 2. 妫�鏌ユ槸鍚﹀凡鍒嗛厤鎵ц浜哄憳
+            List<SysTaskAssignee> taskAssignees = sysTaskAssigneeMapper.selectSysTaskAssigneeByTaskId(taskId);
+            if (taskAssignees == null || taskAssignees.isEmpty()) {
+                log.warn("浠诲姟鏈垎閰嶆墽琛屼汉鍛橈紝璺宠繃璋冨害鍗曢噸鏂板悓姝ワ紝浠诲姟ID: {}", taskId);
+                return false;
+            }
+            
+            // 3. 妫�鏌ラ绾︽椂闂存槸鍚︽湁鏁�
+            if (task.getPlannedStartTime() == null || task.getPlannedStartTime().getTime() <= 0L) {
+                log.warn("浠诲姟棰勭害鏃堕棿鏃犳晥锛岃烦杩囪皟搴﹀崟閲嶆柊鍚屾锛屼换鍔D: {}", taskId);
+                return false;
+            }
+            
+            // 4. 妫�鏌ヨ浆鍑哄尰闄俊鎭�
+            if (StringUtils.isEmpty(emergency.getHospitalOutName()) || StringUtils.isEmpty(emergency.getHospitalOutAddress())) {
+                log.warn("浠诲姟杞嚭鍖婚櫌淇℃伅涓嶅畬鏁达紝璺宠繃璋冨害鍗曢噸鏂板悓姝ワ紝浠诲姟ID: {}", taskId);
+                return false;
+            }
+            
+            // 5. 妫�鏌ヨ浆鍏ュ尰闄俊鎭�
+            if (StringUtils.isEmpty(emergency.getHospitalInName()) || StringUtils.isEmpty(emergency.getHospitalInAddress())) {
+                log.warn("浠诲姟杞叆鍖婚櫌淇℃伅涓嶅畬鏁达紝璺宠繃璋冨害鍗曢噸鏂板悓姝ワ紝浠诲姟ID: {}", taskId);
+                return false;
+            }
+            
+            // 6. 妫�鏌ユ偅鑰呭熀鏈俊鎭�
+            if (StringUtils.isEmpty(emergency.getPatientName()) || StringUtils.isEmpty(emergency.getPatientPhone())) {
+                log.warn("浠诲姟鎮h�呬俊鎭笉瀹屾暣锛岃烦杩囪皟搴﹀崟閲嶆柊鍚屾锛屼换鍔D: {}", taskId);
+                return false;
+            }
+            
+            log.info("浠诲姟鏁版嵁鏍¢獙閫氳繃锛屽紑濮嬮噸鏂板悓姝ヨ皟搴﹀崟锛屼换鍔D: {}, DispatchOrdID: {}", taskId, emergency.getLegacyDispatchOrdId());
             
             // 鏋勫缓璇锋眰鍙傛暟锛堜娇鐢ㄧ浉鍚岀殑鍙傛暟鏋勫缓鏂规硶锛�
             Map<String, String> params = buildDispatchOrderParams(task, emergency);
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/LegacyTransferSyncServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/LegacyTransferSyncServiceImpl.java
index c2b98b1..7bdf7ab 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/LegacyTransferSyncServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/LegacyTransferSyncServiceImpl.java
@@ -170,22 +170,24 @@
                 log.error("鏈嶅姟鍗旾D涓嶈兘涓虹┖");
                 return false;
             }
-            
+            // 鐩存帴鏌ヨ鎸囧畾鐨勮浆杩愬崟淇℃伅
+            List<Map<String, Object>> transferOrders = legacyTransferSyncMapper.selectTransferOrdersByIDs(serviceOrdID, dispatchOrdID);
+
+            Map<String, Object> order = transferOrders.get(0);
+
             // 妫�鏌ユ槸鍚﹀凡鍚屾
             if (isTransferOrderSynced(serviceOrdID, dispatchOrdID)) {
                 log.info("杞繍鍗曞凡鍚屾锛岃烦杩�: ServiceOrdID={}, DispatchOrdID={}", serviceOrdID, dispatchOrdID);
+                updateTransferOrder(serviceOrdID, dispatchOrdID, order);
                 return true;
             }
             
-            // 鐩存帴鏌ヨ鎸囧畾鐨勮浆杩愬崟淇℃伅
-            List<Map<String, Object>> transferOrders = legacyTransferSyncMapper.selectTransferOrdersByIDs(serviceOrdID, dispatchOrdID);
-            
+
             if (transferOrders == null || transferOrders.isEmpty()) {
                 log.error("鏈煡璇㈠埌瀵瑰簲鐨勮浆杩愬崟淇℃伅: ServiceOrdID={}, DispatchOrdID={}", serviceOrdID, dispatchOrdID);
                 return false;
             }
-            
-            Map<String, Object> order = transferOrders.get(0);
+
             
             // 鍚屾鍗曚釜杞繍鍗�
             return syncSingleTransferOrder(serviceOrdID, dispatchOrdID, order);
@@ -294,7 +296,10 @@
             String serviceOrdClass = getStringValue(order,"ServiceOrdClass");
             String serviceOrdNo = getStringValue(order,"ServiceOrdNo");
 
-            Integer oauserId=getIntegerValue(order,"ServiceOrd_NS_ID");
+            /**
+             * 鍒涘缓浜篒D
+             */
+            Integer oauserId=getIntegerValue(order,"ServiceOrd_CC_ID");
             SysUser sysUser=sysUserService.selectUserByOaUserId(oauserId);
             Long taskCreatorId=sysUser==null?null:sysUser.getUserId();
             String createUserName=sysUser==null?"system":sysUser.getUserName();
@@ -495,9 +500,9 @@
                     hospitalInInfo.setName(hospitalInName);
                 }
             }
-            String DispatchOrdTraEnd = getStringValue(order, "DispatchOrdTraEnd");
-            if(DispatchOrdTraEnd!= null){
-                hospitalInInfo.setAddress(DispatchOrdTraEnd);
+            String serviceOrdTraEnd = getStringValue(order, "ServiceOrdTraEnd");
+            if(serviceOrdTraEnd!= null){
+                hospitalInInfo.setAddress(serviceOrdTraEnd);
             }
             //杞叆搴婁綅
             String serviceOrdPtInServices =getStringValue(order, "ServiceOrdPtInServices");
@@ -523,14 +528,15 @@
             // 璁剧疆浠锋牸鍜岃窛绂讳俊鎭�
             createTaskVo.setPrice(getBigDecimalValue(order, "ServiceOrdTraTxnPrice"));
             // 璺濈淇℃伅闇�瑕佷粠鍏朵粬瀛楁璁$畻鎴栬幏鍙�
-            
-            // 璁剧疆鎵ц浜轰俊鎭�
-            List<TaskCreateVO.AssigneeInfo> assignees = queryAssignees(dispatchOrdID);
-            createTaskVo.setAssignees(assignees);
-            if(!assignees.isEmpty()){
-                createTaskVo.setAssigneeId(assignees.get(0).getUserId());
+
+            if(dispatchOrdID!=null) {
+                // 璁剧疆鎵ц浜轰俊鎭�
+                List<TaskCreateVO.AssigneeInfo> assignees = queryAssignees(dispatchOrdID);
+                createTaskVo.setAssignees(assignees);
+                if (!assignees.isEmpty()) {
+                    createTaskVo.setAssigneeId(assignees.get(0).getUserId());
+                }
             }
-            
             // 璁剧疆杞﹁締淇℃伅
             // 杞﹁締ID闇�瑕佹牴鎹瓺ispatchOrdCarID鏌ヨ鑾峰彇
             String carID = getStringValue(order, "DispatchOrdCarID");
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java
index a04871a..b983222 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java
@@ -1024,7 +1024,6 @@
      * @return 缁撴灉
      */
     @Override
-    @Transactional
     public int changeTaskStatus(Long taskId, TaskStatus newStatus, String remark) {
         return changeTaskStatusWithLocation(taskId, newStatus, remark, null);
     }
@@ -1039,7 +1038,6 @@
      * @return 缁撴灉
      */
     @Override
-    @Transactional
     public int changeTaskStatusWithLocation(Long taskId, TaskStatus newStatus, String remark, SysTaskLog locationLog) {
         SysTask oldTask = sysTaskMapper.selectSysTaskByTaskId(taskId);
         if (oldTask == null) {
@@ -1091,7 +1089,10 @@
                     .map(SysTaskAssignee::getUserId)
                     .collect(Collectors.toList());
             }
-            
+            Long userId=SecurityUtils.getUserId();
+            Double lng=locationLog==null?null: locationLog.getLongitude();
+            Double lat=locationLog==null?null: locationLog.getLatitude();
+            String address=locationLog==null?null: locationLog.getLocationAddress();
             eventPublisher.publishEvent(new TaskStatusChangedEvent(
                 this,
                 oldTask.getTaskId(),
@@ -1101,7 +1102,11 @@
                 oldTaskStatus.getInfo(),
                 newStatus.getInfo(),
                 assigneeIds,
-                oldTask.getCreatorId()
+                oldTask.getCreatorId(),
+                userId,
+                    lng, lat,
+                    address
+
             ));
         }
         
@@ -2262,5 +2267,89 @@
         }
     }
     
+    /**
+     * 妫�鏌ヤ换鍔℃槸鍚﹀彲浠ュ嚭鍙�
+     * 妫�鏌ワ細
+     * 1. 杞﹁締鏄惁鏈夋湭瀹屾垚鐨勪换鍔�
+     * 2. 鎵ц浜哄憳鏄惁鏈夋湭瀹屾垚鐨勪换鍔�
+     * 
+     * @param taskId 浠诲姟ID
+     * @return AjaxResult 鏍¢獙缁撴灉
+     */
+    @Override
+    public com.ruoyi.common.core.domain.AjaxResult checkTaskCanDepart(Long taskId) {
+        // 鑾峰彇浠诲姟璇︽儏
+        SysTask task = this.getTaskDetail(taskId);
+        if (task == null) {
+            return com.ruoyi.common.core.domain.AjaxResult.error("浠诲姟涓嶅瓨鍦�");
+        }
+        
+        List<Map<String, Object>> conflicts = new ArrayList<>();
+        
+        // 1. 妫�鏌ヨ溅杈嗘槸鍚︽湁鏈畬鎴愮殑浠诲姟
+        List<SysTaskVehicle> taskVehicles = task.getAssignedVehicles();
+        if (taskVehicles != null && !taskVehicles.isEmpty()) {
+            for (SysTaskVehicle taskVehicle : taskVehicles) {
+                Long vehicleId = taskVehicle.getVehicleId();
+                List<SysTask> vehicleActiveTasks = this.checkVehicleActiveTasks(vehicleId);
+                
+                // 杩囨护鎺夊綋鍓嶄换鍔℃湰韬�
+                vehicleActiveTasks = vehicleActiveTasks.stream()
+                    .filter(t -> !t.getTaskId().equals(taskId))
+                    .collect(Collectors.toList());
+                
+                if (!vehicleActiveTasks.isEmpty()) {
+                    for (SysTask activeTask : vehicleActiveTasks) {
+                        Map<String, Object> conflict = new HashMap<>();
+                        conflict.put("type", "vehicle");
+                        conflict.put("vehicleNo", taskVehicle.getVehicleNo());
+                        conflict.put("taskId", activeTask.getTaskId());
+                        conflict.put("taskCode", activeTask.getTaskCode());
+                        conflict.put("taskStatus", activeTask.getTaskStatus());
+                        conflict.put("message", String.format("杞﹁締 %s 灏氭湁鏈畬鎴愮殑浠诲姟 %s锛岃鍏堝畬鎴�", 
+                            taskVehicle.getVehicleNo(), activeTask.getTaskCode()));
+                        conflicts.add(conflict);
+                    }
+                }
+            }
+        }
+        
+        // 2. 妫�鏌ユ墽琛屼汉鍛樻槸鍚︽湁鏈畬鎴愮殑浠诲姟
+        List<SysTaskAssignee> assignees = task.getAssignees();
+        if (assignees != null && !assignees.isEmpty()) {
+            for (SysTaskAssignee assignee : assignees) {
+                Long userId = assignee.getUserId();
+                
+                // 鏌ヨ璇ユ墽琛屼汉鐨勬墍鏈夋鍦ㄨ繘琛屼腑鐨勪换鍔★紙鎺掗櫎PENDING銆丆OMPLETED銆丆ANCELLED锛�
+                List<SysTask> userActiveTasks = this.selectMyTasks(userId).stream()
+                    .filter(t -> !TaskStatus.PENDING.getCode().equals(t.getTaskStatus())
+                              && !TaskStatus.COMPLETED.getCode().equals(t.getTaskStatus()) 
+                              && !TaskStatus.CANCELLED.getCode().equals(t.getTaskStatus())
+                              && !t.getTaskId().equals(taskId)) // 杩囨护鎺夊綋鍓嶄换鍔�
+                    .collect(Collectors.toList());
+                
+                if (!userActiveTasks.isEmpty()) {
+                    for (SysTask activeTask : userActiveTasks) {
+                        Map<String, Object> conflict = new HashMap<>();
+                        conflict.put("type", "assignee");
+                        conflict.put("userName", assignee.getUserName());
+                        conflict.put("taskId", activeTask.getTaskId());
+                        conflict.put("taskCode", activeTask.getTaskCode());
+                        conflict.put("taskStatus", activeTask.getTaskStatus());
+                        conflict.put("message", String.format("鎵ц浜� %s 灏氭湁姝e湪杩涜涓殑浠诲姟 %s锛岃鍏堝畬鎴�", 
+                            assignee.getUserName(), activeTask.getTaskCode()));
+                        conflicts.add(conflict);
+                    }
+                }
+            }
+        }
+        
+        // 杩斿洖缁撴灉
+        Map<String, Object> result = new HashMap<>();
+        result.put("valid", conflicts.isEmpty());
+        result.put("conflicts", conflicts);
+        
+        return com.ruoyi.common.core.domain.AjaxResult.success(result);
+    }
    
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/UserSyncServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/UserSyncServiceImpl.java
index ecadd20..97e49ae 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/UserSyncServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/UserSyncServiceImpl.java
@@ -223,6 +223,10 @@
         {
             existingUser.setOaOrderClass(dto.getOaOrderClass());
         }
+        if (StringUtils.isNotEmpty(dto.getCanViewAllConsult()))
+        {
+            existingUser.setCanViewAllConsult(dto.getCanViewAllConsult());
+        }
         sysUserMapper.updateUser(existingUser);
     }
 
@@ -239,6 +243,10 @@
         {
             newUser.setOaOrderClass(dto.getOaOrderClass());
         }
+        if (StringUtils.isNotEmpty(dto.getCanViewAllConsult()))
+        {
+            newUser.setCanViewAllConsult(dto.getCanViewAllConsult());
+        }
         
         if (deptId != null)
         {
diff --git a/ruoyi-system/src/main/resources/mapper/system/LegacyTransferSyncMapper.xml b/ruoyi-system/src/main/resources/mapper/system/LegacyTransferSyncMapper.xml
index 8000982..906b028 100644
--- a/ruoyi-system/src/main/resources/mapper/system/LegacyTransferSyncMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/LegacyTransferSyncMapper.xml
@@ -43,6 +43,7 @@
         <result property="Old_ServiceOrdID_TXT" column="Old_ServiceOrdID_TXT" />
         <result property="ServiceOrdTraDistance" column="ServiceOrdTraDistance" />
         <result property="ServiceOrdApptDate" column="ServiceOrdApptDate" />
+        <result property="DispatchOrdState" column="DispatchOrdState" />
     </resultMap>
     
     <!-- 鎵ц浜虹粨鏋滄槧灏� -->
@@ -87,16 +88,17 @@
             b.DispatchOrdActualDate,
             b.DispatchOrdReturnDate,
             b.DispatchOrdTraEnd,
+            b.DispatchOrdState,
             b.DispatchOrdID,
             b.DispatchOrdCarID,
             a.ServiceOrdPtServices,
             a.ServiceOrdPtInServices,
             a.ServiceOrdPtName
         FROM ServiceOrder as a 
-        INNER JOIN DispatchOrd b on a.ServiceOrdID = b.ServiceOrdIDDt
-        WHERE a.ServiceOrdState = 3 
+        left JOIN DispatchOrd b on a.ServiceOrdID = b.ServiceOrdIDDt
+        WHERE a.ServiceOrdState &lt;= 3
             AND a.ServiceOrd_CC_Time > #{startDate} 
-            AND b.DispatchOrdState != 0
+            
     </select>
     
     <!-- 鏍规嵁鏈嶅姟鍗旾D鍜岃皟搴﹀崟ID鏌ヨ杞繍鍗曟暟鎹� -->
@@ -137,13 +139,13 @@
             b.DispatchOrdCarID,
             a.ServiceOrdPtServices,
             a.ServiceOrdPtInServices,
-            a.ServiceOrdPtName
+            a.ServiceOrdPtName,
+            b.DispatchOrdState
         FROM ServiceOrder as a 
-        INNER JOIN DispatchOrd b on a.ServiceOrdID = b.ServiceOrdIDDt
+        left JOIN DispatchOrd b on a.ServiceOrdID = b.ServiceOrdIDDt
         WHERE a.ServiceOrdID = #{serviceOrdID}
-            AND b.DispatchOrdID = #{dispatchOrdID}
-            AND a.ServiceOrdState = 3 
-            AND b.DispatchOrdState != 0
+            AND a.ServiceOrdState &lt;=3
+
     </select>
     
     <!-- 鏍规嵁鏈嶅姟鍗旾D鏌ヨ鐥呮儏淇℃伅 -->
@@ -184,4 +186,25 @@
         WHERE vID = #{deptID} AND vtitle = 'HospitalDepartment'
     </select>
     
+    <!-- 鎻掑叆璋冨害鍗曠姸鎬佸彉鏇磋褰曞埌 DispatchOrd_Running 琛� -->
+    <insert id="insertDispatchOrdRunning">
+        INSERT INTO DispatchOrd_Running (
+            DispatchOrdIDDt,
+            DispatchOrdState,
+            DispatchOrdStartDate,
+            DispatchOrdStartOA
+            <if test="oaLatitude != null">,OA_latitude</if>
+            <if test="oaLongitude != null">,OA_longitude</if>
+            <if test="oaAddress != null and oaAddress != ''">,OA_address</if>
+        ) VALUES (
+            #{dispatchOrdID},
+            #{dispatchOrdState},
+            #{dispatchOrdStartDate},
+            #{dispatchOrdStartOA}
+            <if test="oaLatitude != null">,#{oaLatitude}</if>
+            <if test="oaLongitude != null">,#{oaLongitude}</if>
+            <if test="oaAddress != null and oaAddress != ''">,#{oaAddress}</if>
+        )
+    </insert>
+    
 </mapper>
\ No newline at end of file
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysTaskMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysTaskMapper.xml
index d8abfba..a7efd95 100644
--- a/ruoyi-system/src/main/resources/mapper/system/SysTaskMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/SysTaskMapper.xml
@@ -88,16 +88,36 @@
             <if test="taskStatus != null  and taskStatus != ''"> and t.task_status = #{taskStatus}</if>
             <if test="vehicleNo != null  and vehicleNo != ''"> and v.vehicle_no like concat('%', #{vehicleNo}, '%')</if>
             <!-- 缁煎悎鏌ヨ锛氬綋鍓嶇敤鎴锋墍鍦ㄦ満鏋� OR 褰撳墠鐢ㄦ埛鍒涘缓 OR 鍒嗛厤缁欏綋鍓嶇敤鎴� -->
-            <if test="(creatorId != null and creatorId != 0) or (assigneeId != null and assigneeId != 0) or (deptId != null and deptId != 0)">
+            <if test="(creatorId != null and creatorId != 0) or (assigneeId != null and assigneeId != 0) or (deptId != null and deptId != 0) or (deptIds != null and deptIds.size() > 0)">
                 and (
-                    <if test="deptId != null and deptId != 0">t.dept_id = #{deptId}</if>
-                    <if test="creatorId != null and creatorId != 0">
+                    <!-- 鏌ヨ鎸囧畾鍒嗗叕鍙稿強鍏舵墍鏈夊瓙閮ㄩ棬鐨勪换鍔� -->
+                    <if test="deptId != null and deptId != 0">
+                        (t.dept_id = #{deptId} OR t.dept_id IN (
+                            SELECT dept_id FROM sys_dept 
+                            WHERE del_flag = '0' AND find_in_set(#{deptId}, ancestors)
+                        ))
+                    </if>
+                    <!-- 鏌ヨ澶氫釜鍒嗗叕鍙稿強鍏舵墍鏈夊瓙閮ㄩ棬鐨勪换鍔� -->
+                    <if test="deptIds != null and deptIds.size() > 0">
                         <if test="deptId != null and deptId != 0"> or </if>
+                        (
+                            <foreach collection="deptIds" item="branchDeptId" separator=" OR ">
+                                (t.dept_id = #{branchDeptId} OR t.dept_id IN (
+                                    SELECT dept_id FROM sys_dept 
+                                    WHERE del_flag = '0' AND find_in_set(#{branchDeptId}, ancestors)
+                                ))
+                            </foreach>
+                        )
+                    </if>
+                    <if test="creatorId != null and creatorId != 0">
+                        <if test="(deptId != null and deptId != 0) or (deptIds != null and deptIds.size() > 0)"> or </if>
                         t.creator_id = #{creatorId}
                     </if>
                     <if test="assigneeId != null and assigneeId != 0">
-                        <if test="(deptId != null and deptId != 0) or (creatorId != null and creatorId != 0)"> or </if>
-                        t.assignee_id = #{assigneeId}
+                        <if test="(deptId != null and deptId != 0) or (deptIds != null and deptIds.size() > 0) or (creatorId != null and creatorId != 0)"> or </if>
+                        t.task_id IN (
+                            SELECT task_id FROM sys_task_assignee WHERE user_id = #{assigneeId}
+                        )
                     </if>
                 )
             </if>
@@ -145,7 +165,12 @@
 
     <select id="selectMyTasks" parameterType="Long" resultMap="SysTaskResult">
         <include refid="selectSysTaskVo"/>
-        where t.del_flag = '0' and (t.creator_id = #{userId} or t.assignee_id = #{userId})
+        where t.del_flag = '0' and (
+            t.creator_id = #{userId} 
+            OR t.task_id IN (
+                SELECT task_id FROM sys_task_assignee WHERE user_id = #{userId}
+            )
+        )
         order by 
             CASE t.task_status
                 WHEN 'PENDING' THEN 1
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
index a1f910a..f5fab34 100644
--- a/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
@@ -28,6 +28,7 @@
         <result property="openId"       column="open_id"       />
         <result property="unionId"     column="union_id"     />
         <result property="wechatNickname" column="wechat_nickname" />
+        <result property="canViewAllConsult" column="can_view_all_consult" />
         <association property="dept"    javaType="SysDept"         resultMap="deptResult" />
         <collection  property="roles"   javaType="java.util.List"  resultMap="RoleResult" />
     </resultMap>
@@ -52,7 +53,7 @@
     </resultMap>
 	
 	<sql id="selectUserVo">
-        select u.user_id, u.dept_id, u.user_name,u.oa_user_id, u.oa_order_class, u.nick_name, u.email, u.avatar, u.phonenumber, u.password, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.oa_user_id, u.create_by, u.create_time, u.remark,u.open_id,u.union_id,u.wechat_nickname,
+        select u.user_id, u.dept_id, u.user_name,u.oa_user_id, u.oa_order_class, u.nick_name, u.email, u.avatar, u.phonenumber, u.password, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.oa_user_id, u.create_by, u.create_time, u.remark,u.open_id,u.union_id,u.wechat_nickname,u.can_view_all_consult,
         d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.status as dept_status,
         r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.status as role_status
         from sys_user u
@@ -169,6 +170,7 @@
  			<if test="status != null and status != ''">status,</if>
  			<if test="oaUserId != null">oa_user_id,</if>
  			<if test="oaOrderClass != null and oaOrderClass != ''">oa_order_class,</if>
+ 			<if test="canViewAllConsult != null and canViewAllConsult != ''">can_view_all_consult,</if>
  			<if test="createBy != null and createBy != ''">create_by,</if>
  			<if test="remark != null and remark != ''">remark,</if>
  			create_time
@@ -185,6 +187,7 @@
  			<if test="status != null and status != ''">#{status},</if>
  			<if test="oaUserId != null">#{oaUserId},</if>
  			<if test="oaOrderClass != null and oaOrderClass != ''">#{oaOrderClass},</if>
+ 			<if test="canViewAllConsult != null and canViewAllConsult != ''">#{canViewAllConsult},</if>
  			<if test="createBy != null and createBy != ''">#{createBy},</if>
  			<if test="remark != null and remark != ''">#{remark},</if>
  			sysdate()
@@ -204,6 +207,7 @@
  			<if test="status != null and status != ''">status = #{status},</if>
  			<if test="oaUserId != null">oa_user_id = #{oaUserId},</if>
  			<if test="oaOrderClass != null">oa_order_class = #{oaOrderClass},</if>
+ 			<if test="canViewAllConsult != null and canViewAllConsult != ''">can_view_all_consult = #{canViewAllConsult},</if>
  			<if test="openId != null and openId != ''">open_id = #{openId},</if>
  			<if test="unionId != null and unionId != ''">union_id = #{unionId},</if>
  			<if test="loginIp != null and loginIp != ''">login_ip = #{loginIp},</if>
diff --git a/ruoyi-system/src/main/resources/mapper/system/UserSyncMapper.xml b/ruoyi-system/src/main/resources/mapper/system/UserSyncMapper.xml
index f96ef3c..420e03e 100644
--- a/ruoyi-system/src/main/resources/mapper/system/UserSyncMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/UserSyncMapper.xml
@@ -13,6 +13,7 @@
         <result property="email" column="email" />
         <result property="phonenumber" column="phonenumber" />
         <result property="oaOrderClass" column="OA_OrderClass" />
+        <result property="canViewAllConsult" column="can_view_all_consult" />
     </resultMap>
 
     <!-- 鏌ヨSQL Server涓殑OA鐢ㄦ埛鍒楄〃 -->
@@ -26,7 +27,11 @@
             OA_gender AS sex,
             OA_email AS email,
             OA_mobile AS phonenumber,
-            OA_OrderClass AS OA_OrderClass
+            OA_OrderClass AS OA_OrderClass,
+            CASE 
+                WHEN OA_Power LIKE '%,020112,%' THEN '1'
+                ELSE '0'
+            END AS can_view_all_consult
         FROM OA_User
         WHERE OA_User IS NOT NULL 
           AND OA_Name IS NOT NULL
diff --git a/ruoyi-system/src/test/java/com/ruoyi/system/mapper/SysDeptMapperTest.java b/ruoyi-system/src/test/java/com/ruoyi/system/mapper/SysDeptMapperTest.java
deleted file mode 100644
index e69de29..0000000
--- a/ruoyi-system/src/test/java/com/ruoyi/system/mapper/SysDeptMapperTest.java
+++ /dev/null
diff --git a/ruoyi-system/src/test/java/com/ruoyi/system/service/LegacySystemHttpsTest.java b/ruoyi-system/src/test/java/com/ruoyi/system/service/LegacySystemHttpsTest.java
deleted file mode 100644
index 24d0af8..0000000
--- a/ruoyi-system/src/test/java/com/ruoyi/system/service/LegacySystemHttpsTest.java
+++ /dev/null
@@ -1,260 +0,0 @@
-package com.ruoyi.system.service;
-
-import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.X509TrustManager;
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.net.URLEncoder;
-import java.security.cert.X509Certificate;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * 鏃х郴缁烪TTPS鎺ュ彛娴嬭瘯
- * 娴嬭瘯admin_save_19.gds鎺ュ彛璋冪敤
- * 
- * @author ruoyi
- * @date 2025-11-09
- */
-public class LegacySystemHttpsTest {
-    
-    private static final Logger log = LoggerFactory.getLogger(LegacySystemHttpsTest.class);
-    
-    /**
-     * 娴嬭瘯璋冪敤admin_save_19.gds鎺ュ彛锛堝垱寤烘湇鍔″崟锛�
-     */
-    @Test
-    public void testCreateServiceOrder() {
-        try {
-            String url = "https://sys.966120.com.cn/admin_save_19.gds";
-            
-            // 鏋勫缓璇锋眰鍙傛暟
-            Map<String, String> params = buildTestParams();
-            
-            // 鍙戦�佽姹�
-            String response = sendHttpsPost(url, params);
-            
-            // 杈撳嚭鍝嶅簲
-            log.info("鎺ュ彛鍝嶅簲锛歿}", response);
-            System.out.println("鎺ュ彛鍝嶅簲锛�" + response);
-            
-            // 瑙f瀽鍝嶅簲
-            if (response != null && response.startsWith("OK:")) {
-                String serviceOrdId = response.substring(3).trim();
-                log.info("鏈嶅姟鍗曞垱寤烘垚鍔燂紝ServiceOrdID: {}", serviceOrdId);
-                System.out.println("鉁� 鏈嶅姟鍗曞垱寤烘垚鍔燂紝ServiceOrdID: " + serviceOrdId);
-            } else {
-                log.error("鏈嶅姟鍗曞垱寤哄け璐ワ紝鍝嶅簲: {}", response);
-                System.out.println("鉂� 鏈嶅姟鍗曞垱寤哄け璐ワ紝鍝嶅簲: " + response);
-            }
-            
-        } catch (Exception e) {
-            log.error("娴嬭瘯寮傚父", e);
-            e.printStackTrace();
-        }
-    }
-    
-    /**
-     * 鏋勫缓娴嬭瘯鍙傛暟
-     */
-    private Map<String, String> buildTestParams() {
-        Map<String, String> params = new HashMap<>();
-        
-        // 鍩虹淇℃伅
-        params.put("adminID", "1312");
-        params.put("ServiceOrdClass", "BF");
-        params.put("ServiceOrdAreaType", "1");
-        params.put("ServiceOrdType", "20");
-        params.put("ServiceOrdState", "2");
-        params.put("ServiceOrdStartDate", "2025-11-09");
-        
-        // 棰勭害鏃堕棿
-        params.put("ServiceOrdApptDate", "2025-11-09 16:56:31");
-        
-        // 鑱旂郴浜轰俊鎭�
-        params.put("ServiceOrdCoName", "鏉庢祴璇�11");
-        params.put("ServiceOrdCoPhone", "13602220102");
-        params.put("ServiceOrdCoTies", "");
-        
-        // 鎮h�呬俊鎭�
-        params.put("ServiceOrdPtName", "鏉庢祴璇�21");
-        params.put("ServiceOrdPtAge", "");
-        params.put("ServiceOrdPtKG", "");
-        params.put("ServiceOrdPtSex", "");
-        params.put("ServiceOrdPtNat", "");
-        params.put("ServiceOrdPtIDCard", "");
-        
-        // 鍖婚櫌淇℃伅
-        params.put("ServiceOrdPtOutHosp", "骞夸笢鐪佺浜屼汉姘戝尰闄㈠ぉ娌冲尰闄�(骞夸笢鐕曞箔鍖婚櫌)");
-        params.put("ServiceOrdPtOutHospID", "310");
-        params.put("ServiceOrdPtInHosp", "瀹朵腑");
-        params.put("ServiceOrdPtInHospID", "153");
-        
-        // 绉戝淇℃伅
-        params.put("ServiceOrdPtServices", "鍏朵粬");
-        params.put("ServiceOrdPtServicesID", "22");
-        params.put("ServiceOrdPtInServices", "鍏朵粬");
-        params.put("ServiceOrdPtInServicesID", "0");
-        
-        // 鐥呮儏淇℃伅
-        params.put("ServiceOrdPtDiagnosis", "");
-        params.put("ServiceOrdPtCondition", "");
-        params.put("ServiceOrdTaskRemarks", "");
-        params.put("ServiceOrdPtDoctor", "");
-        params.put("ServiceOrdPtDoctorPhone", "");
-        
-        // 鍦板潃淇℃伅
-        params.put("province", "");
-        params.put("city", "");
-        params.put("ServiceOrdTraStreet", "骞夸笢鐪佸箍宸炲競澶╂渤鍖烘瀹夎矾533鍙�");
-        params.put("ServiceOrdTraStreetCoo", "");
-        params.put("ServiceOrdTraEnd", "澶╂渤鍖哄箍宸炲競-澶╂渤鍖�-鏌忓痉璺�101鍙�");
-        params.put("ServiceOrdTraEndCoo", "");
-        params.put("ServiceOrdTraVia", "");
-        
-        // 璺濈鍜屼环鏍间俊鎭�
-        params.put("ServiceOrdViaDistance", "0");
-        params.put("ServiceOrdTraDistance", "10.70");
-        params.put("ServiceOrdTraDuration", "");
-        params.put("ServiceOrdTraUnitPrice", "0");
-        params.put("ServiceOrdTraOfferPrice", "154.00");
-        params.put("ServiceOrdTraTxnPrice", "154.00");
-        params.put("ServiceOrdTraPrePayment", "0");
-        params.put("SettlementPrice", "0");
-        params.put("ServiceOrdTraPriceReason", "");
-        
-        // 鍏朵粬淇℃伅
-        params.put("Phone", "13602220102");
-        params.put("TEL_Time", "2025-11-09 16:58:21");
-        params.put("TEL_Remarks", "鏂扮郴缁熷悓姝�");
-        params.put("TransferModeID", "");
-        params.put("ServiceOrdVIP", "0");
-        params.put("ServiceOrd_CC_ID", "");
-        params.put("ServiceOrd_Sale_ID", "");
-        params.put("ServiceOrdIntroducer", "");
-        params.put("ServiceOrd_work_ID", "");
-        params.put("ServiceOrd_work_IDs", "");
-        params.put("ServiceOrd_work_is", "0");
-        params.put("CommissionScenarioID", "0");
-        params.put("ServiceOrdOperationRemarks", "鏂扮郴缁熷悓姝ュ垱寤�");
-        params.put("ServiceOrdEstimatedOrderDate", "");
-        params.put("ServiceOrdSource", "10");
-        params.put("OrderLevel", "0");
-        params.put("ServiceOrdDepartureType", "1");
-        params.put("ConditionLevel", "0");
-        params.put("DirectionType", "0");
-        params.put("ServiceOrd_m", "1");
-        params.put("FromHQ2_is", "0");
-        params.put("OrderPrice_Auto", "0");
-        
-        return params;
-    }
-    
-    /**
-     * 鍙戦�丠TTPS POST璇锋眰锛堝拷鐣SL璇佷功楠岃瘉锛�
-     */
-    private String sendHttpsPost(String urlString, Map<String, String> params) throws Exception {
-        URL url = new URL(urlString);
-        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
-        
-        // 濡傛灉鏄疕TTPS璇锋眰锛岄厤缃甋SL淇′换鎵�鏈夎瘉涔�
-        if (conn instanceof HttpsURLConnection) {
-            HttpsURLConnection httpsConn = (HttpsURLConnection) conn;
-            httpsConn.setSSLSocketFactory(createTrustAllSSLContext().getSocketFactory());
-            httpsConn.setHostnameVerifier((hostname, session) -> true);
-            log.info("閰嶇疆HTTPS杩炴帴锛屼俊浠绘墍鏈塖SL璇佷功");
-        }
-        
-        try {
-            // 璁剧疆杩炴帴灞炴��
-            conn.setRequestMethod("POST");
-            conn.setConnectTimeout(30000);
-            conn.setReadTimeout(60000);
-            conn.setDoOutput(true);
-            conn.setDoInput(true);
-            conn.setUseCaches(false);
-            conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=GBK");
-            conn.setRequestProperty("Accept-Charset", "GBK");
-            conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
-            
-            // 鏋勫缓POST鏁版嵁
-            StringBuilder postData = new StringBuilder();
-            for (Map.Entry<String, String> entry : params.entrySet()) {
-                if (postData.length() > 0) {
-                    postData.append("&");
-                }
-                postData.append(URLEncoder.encode(entry.getKey(), "GBK"));
-                postData.append("=");
-                postData.append(URLEncoder.encode(entry.getValue(), "GBK"));
-            }
-            
-            log.info("璇锋眰URL: {}", urlString);
-            log.info("璇锋眰鍙傛暟闀垮害: {}", postData.length());
-            
-            // 鍙戦�丳OST鏁版嵁
-            try (OutputStream os = conn.getOutputStream()) {
-                os.write(postData.toString().getBytes("GBK"));
-                os.flush();
-            }
-            
-            // 璇诲彇鍝嶅簲
-            int responseCode = conn.getResponseCode();
-            log.info("鍝嶅簲鐮�: {}", responseCode);
-            
-            if (responseCode == HttpURLConnection.HTTP_OK) {
-                try (BufferedReader reader = new BufferedReader(
-                        new InputStreamReader(conn.getInputStream(), "GBK"))) {
-                    StringBuilder response = new StringBuilder();
-                    String line;
-                    while ((line = reader.readLine()) != null) {
-                        response.append(line);
-                    }
-                    return response.toString().trim();
-                }
-            } else {
-                log.error("璇锋眰澶辫触锛屽搷搴旂爜: {}", responseCode);
-                throw new Exception("HTTPS璇锋眰澶辫触锛屽搷搴旂爜: " + responseCode);
-            }
-            
-        } finally {
-            conn.disconnect();
-        }
-    }
-    
-    /**
-     * 鍒涘缓淇′换鎵�鏈塖SL璇佷功鐨凷SLContext
-     */
-    private SSLContext createTrustAllSSLContext() throws Exception {
-        TrustManager[] trustAllCerts = new TrustManager[] {
-            new X509TrustManager() {
-                @Override
-                public X509Certificate[] getAcceptedIssuers() {
-                    return null;
-                }
-                
-                @Override
-                public void checkClientTrusted(X509Certificate[] certs, String authType) {
-                    // 淇′换鎵�鏈夊鎴风璇佷功
-                }
-                
-                @Override
-                public void checkServerTrusted(X509Certificate[] certs, String authType) {
-                    // 淇′换鎵�鏈夋湇鍔″櫒璇佷功
-                }
-            }
-        };
-        
-        SSLContext sslContext = SSLContext.getInstance("TLS");
-        sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
-        return sslContext;
-    }
-}
diff --git a/ruoyi-system/src/test/java/com/ruoyi/system/service/SysDeptServiceTest.java b/ruoyi-system/src/test/java/com/ruoyi/system/service/SysDeptServiceTest.java
deleted file mode 100644
index e69de29..0000000
--- a/ruoyi-system/src/test/java/com/ruoyi/system/service/SysDeptServiceTest.java
+++ /dev/null
diff --git a/ruoyi-ui/src/views/system/user/index.vue b/ruoyi-ui/src/views/system/user/index.vue
index f479f46..ed3749d 100644
--- a/ruoyi-ui/src/views/system/user/index.vue
+++ b/ruoyi-ui/src/views/system/user/index.vue
@@ -172,6 +172,16 @@
         </el-row>
         <el-row>
           <el-col :span="12">
+            <el-form-item label="鏌ョ湅鎵�鏈夊挩璇㈠崟">
+              <el-radio-group v-model="form.canViewAllConsult">
+                <el-radio label="0">鍚�</el-radio>
+                <el-radio label="1">鏄�</el-radio>
+              </el-radio-group>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
             <el-form-item label="宀椾綅">
               <el-select v-model="form.postIds" multiple placeholder="璇烽�夋嫨宀椾綅">
                 <el-option v-for="item in postOptions" :key="item.postId" :label="item.postName" :value="item.postId" :disabled="item.status == 1" ></el-option>
@@ -451,7 +461,8 @@
         status: "0",
         remark: undefined,
         postIds: [],
-        roleIds: []
+        roleIds: [],
+        canViewAllConsult: "0"
       };
       this.resetForm("form");
     },
diff --git a/sql/DispatchRunning.sql b/sql/DispatchRunning.sql
new file mode 100644
index 0000000..73c7bed
--- /dev/null
+++ b/sql/DispatchRunning.sql
@@ -0,0 +1,10 @@
+create table DispatchOrd_Running(
+    id	int	comment "鑷涓婚敭",
+DispatchOrdIDDt	bigint	comment '璋冨害鍗旾D',
+DispatchOrdState	int	comment '鐘舵��',
+DispatchOrdStartDate	datetime	comment '鐘舵�佹椂闂�',
+DispatchOrdStartOA	int	comment '鎿嶄綔鐘舵�佺殑OA鐢ㄦ埛ID',
+OA_latitude	float	comment '鏇存柊鐘舵�佹椂鐨勭含搴�',
+OA_longitude	float	comment '鏇存柊鐘舵�佹椂鐨勭粡搴�',
+OA_address	nvarchar(400)	comment '鏇存柊鐘舵�佹椂鐨勫湴鍧�'
+)
\ No newline at end of file
diff --git a/sql/add_can_view_all_consult_to_sys_user.sql b/sql/add_can_view_all_consult_to_sys_user.sql
new file mode 100644
index 0000000..6ce673b
--- /dev/null
+++ b/sql/add_can_view_all_consult_to_sys_user.sql
@@ -0,0 +1,12 @@
+-- 娣诲姞sys_user琛ㄥ瓧娈碉細鏄惁鍙互鏌ョ湅绠$悊閮ㄩ棬鐨勬墍鏈夊挩璇㈠崟
+-- 鎵ц鏃堕棿: 2025-12-04
+-- 鍔熻兘璇存槑: 鐢ㄤ簬鏍囪瘑鐢ㄦ埛鏄惁鎷ユ湁鏌ョ湅鍏剁鐞嗛儴闂ㄦ墍鏈夊挩璇㈠崟鐨勬潈闄�
+
+-- 娣诲姞瀛楁
+ALTER TABLE `sys_user` ADD COLUMN `can_view_all_consult` CHAR(1) DEFAULT '0' COMMENT '鏄惁鍙煡鐪嬫墍鏈夊挩璇㈠崟锛�0鍚� 1鏄級' AFTER `wechat_nickname`;
+
+-- 璇存槑
+-- 1. can_view_all_consult: 鏍囪瘑鐢ㄦ埛鏄惁鍙互鏌ョ湅绠$悊閮ㄩ棬鐨勬墍鏈夊挩璇㈠崟
+-- 2. 榛樿鍊间负 '0'锛堝惁锛夛紝琛ㄧず鏅�氱敤鎴�
+-- 3. 鍊间负 '1'锛堟槸锛夎〃绀鸿鐢ㄦ埛鏈夋煡鐪嬫墍鏈夊挩璇㈠崟鐨勬潈闄�
+-- 4. 璇ユ潈闄愪笌OA绯荤粺涓殑OA_Power瀛楁鍏宠仈锛屽寘鍚�',020112,'琛ㄧず鎷ユ湁璇ユ潈闄�

--
Gitblit v1.9.1