From cdcc529ce5fb9aa0dd1dea5bb2a620fc09b7d25c Mon Sep 17 00:00:00 2001
From: wlzboy <66905212@qq.com>
Date: 星期六, 08 十一月 2025 20:03:56 +0800
Subject: [PATCH] feat: 上传附件

---
 ruoyi-system/src/main/java/com/ruoyi/system/file/FileUploadServiceImpl.java                 |   21 
 ruoyi-common/src/main/java/com/ruoyi/common/config/ImageUrlConfig.java                      |   27 
 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskAttachment.java                   |   48 +
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/TaskAttachmentSyncController.java   |  108 +++
 app/components/AttachmentUpload.vue                                                         |  629 +++++++++++++++++++
 prd/任务附件同步ImageData功能说明.md                                                                  |  223 ++++++
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/LegacySystemSyncServiceImpl.java   |   64 +
 ruoyi-admin/src/main/resources/application.yml                                              |    2 
 sql/update_sys_task_attachment_sync_fields.sql                                              |   16 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java            |   93 ++
 ruoyi-system/src/main/java/com/ruoyi/system/task/TaskAttachmentServiceImpl.java             |   35 +
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskAttachmentMapper.java             |    2 
 ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/LegacySystemSyncTask.java                  |    3 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskAttachmentController.java    |   53 +
 ruoyi-system/src/main/java/com/ruoyi/system/service/ITaskAttachmentSyncService.java         |   36 +
 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskEmergency.java                    |    2 
 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskService.java                    |    8 
 ruoyi-system/src/main/java/com/ruoyi/system/imagedata/ImageDataServiceImpl.java             |   41 -
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TaskAttachmentSyncServiceImpl.java |  204 ++++++
 ruoyi-system/src/main/resources/mapper/system/SysTaskAttachmentMapper.xml                   |   14 
 app/pages/task/detail.vue                                                                   |  277 --------
 ruoyi-system/src/main/java/com/ruoyi/system/task/ITaskAttachmentService.java                |    9 
 22 files changed, 1,562 insertions(+), 353 deletions(-)

diff --git a/app/components/AttachmentUpload.vue b/app/components/AttachmentUpload.vue
new file mode 100644
index 0000000..58714cd
--- /dev/null
+++ b/app/components/AttachmentUpload.vue
@@ -0,0 +1,629 @@
+<template>
+  <view class="attachment-upload-container">
+    <view class="detail-section">
+      <view class="section-title">
+        {{ title }}
+        <button class="upload-btn" @click="showUploadDialog">涓婁紶闄勪欢</button>
+      </view>
+      <view v-if="attachmentList && attachmentList.length > 0">
+        <view class="attachment-item" v-for="(item, index) in attachmentList" :key="item.attachmentId">
+          <view class="attachment-thumbnail" @click="viewAttachment(item)">
+            <image :src="getImageUrl(item)" mode="aspectFill" class="thumbnail-image"></image>
+          </view>
+          <view class="attachment-info">
+            <view class="attachment-category">
+              <text class="category-tag">{{ getCategoryName(item.attachmentCategory) }}</text>
+            </view>
+            <view class="attachment-meta">
+              <text class="upload-time">{{ formatTime(item.uploadTime) }}</text>
+            </view>
+          </view>
+          <view class="attachment-actions">
+            <button class="action-btn view-btn" @click="viewAttachment(item)">鏌ョ湅</button>
+            <button class="action-btn delete-btn" @click="deleteAttachment(item.attachmentId, index)">鍒犻櫎</button>
+          </view>
+        </view>
+      </view>
+      <view v-else class="no-attachment">
+        <text>鏆傛棤闄勪欢</text>
+      </view>
+    </view>
+    
+    <!-- 闄勪欢涓婁紶瀵硅瘽妗� -->
+    <uni-popup ref="uploadPopup" type="bottom">
+      <view class="upload-dialog">
+        <view class="dialog-header">
+          <text class="dialog-title">涓婁紶闄勪欢</text>
+          <uni-icons type="closeempty" size="24" @click="closeUploadDialog"></uni-icons>
+        </view>
+        <view class="dialog-content">
+          <view class="form-item">
+            <view class="form-label">闄勪欢鍒嗙被</view>
+            <picker @change="onCategoryChange" :value="selectedCategoryIndex" :range="categoryList" range-key="label">
+              <view class="picker-value">
+                {{ categoryList[selectedCategoryIndex].label }}
+                <uni-icons type="arrowdown" size="16"></uni-icons>
+              </view>
+            </picker>
+          </view>
+          <view class="form-item">
+            <view class="form-label">閫夋嫨鍥剧墖</view>
+            <button class="choose-image-btn" @click="chooseImage">
+              <uni-icons type="image" size="20"></uni-icons>
+              <text>鐐瑰嚮閫夋嫨</text>
+            </button>
+          </view>
+          <view class="preview-area" v-if="tempImagePath">
+            <image :src="tempImagePath" mode="aspectFit" class="preview-image"></image>
+          </view>
+        </view>
+        <view class="dialog-footer">
+          <button class="cancel-btn" @click="closeUploadDialog">鍙栨秷</button>
+          <button class="confirm-btn" @click="confirmUpload" :disabled="!tempImagePath">纭畾涓婁紶</button>
+        </view>
+      </view>
+    </uni-popup>
+  </view>
+</template>
+
+<script>
+  import { getAttachmentList, uploadAttachmentFromWechat, deleteAttachment, getWechatAccessToken } from '@/api/task'
+  import { formatDateTime } from '@/utils/common'
+  
+  export default {
+    name: 'AttachmentUpload',
+    props: {
+      // 浠诲姟ID
+      taskId: {
+        type: [String, Number],
+        required: true
+      },
+      // 鏍囬
+      title: {
+        type: String,
+        default: '浠诲姟闄勪欢'
+      },
+      // 鏄惁鑷姩鍔犺浇闄勪欢鍒楄〃
+      autoLoad: {
+        type: Boolean,
+        default: true
+      }
+    },
+    data() {
+      return {
+        attachmentList: [],
+        categoryList: [
+          { label: '鐭ユ儏鍚屾剰涔�', value: '1' },
+          { label: '鐥呬汉璧勬枡', value: '2' },
+          { label: '鎿嶄綔璁板綍', value: '3' },
+          { label: '鍑鸿溅鍓�', value: '4' },
+          { label: '鍑鸿溅鍚�', value: '5' },
+          { label: '绯诲畨鍏ㄥ甫', value: '6' }
+        ],
+        selectedCategoryIndex: 0,
+        tempImagePath: null,
+        isWechatMiniProgram: false
+      }
+    },
+    mounted() {
+      // 妫�娴嬫槸鍚︽槸寰俊灏忕▼搴忕幆澧�
+      // #ifdef MP-WEIXIN
+      this.isWechatMiniProgram = true
+      // #endif
+      
+      // 鑷姩鍔犺浇闄勪欢鍒楄〃
+      if (this.autoLoad && this.taskId) {
+        this.loadAttachmentList()
+      }
+    },
+    watch: {
+      // 鐩戝惉taskId鍙樺寲锛岄噸鏂板姞杞介檮浠跺垪琛�
+      taskId(newVal) {
+        if (newVal && this.autoLoad) {
+          this.loadAttachmentList()
+        }
+      }
+    },
+    methods: {
+      // 鍔犺浇闄勪欢鍒楄〃
+      loadAttachmentList() {
+        if (!this.taskId) {
+          return
+        }
+        
+        getAttachmentList(this.taskId).then(response => {
+          this.attachmentList = response.data || response || []
+          this.$emit('loaded', this.attachmentList)
+        }).catch(error => {
+          console.error('鍔犺浇闄勪欢鍒楄〃澶辫触:', error)
+          this.$emit('error', error)
+        })
+      },
+      
+      // 鏄剧ず涓婁紶瀵硅瘽妗�
+      showUploadDialog() {
+        this.selectedCategoryIndex = 0
+        this.tempImagePath = null
+        this.$refs.uploadPopup.open()
+      },
+      
+      // 鍏抽棴涓婁紶瀵硅瘽妗�
+      closeUploadDialog() {
+        this.$refs.uploadPopup.close()
+      },
+      
+      // 鍒嗙被閫夋嫨鍙樺寲
+      onCategoryChange(e) {
+        this.selectedCategoryIndex = e.detail.value
+      },
+      
+      // 閫夋嫨鍥剧墖
+      chooseImage() {
+        const that = this
+        uni.chooseImage({
+          count: 1,
+          sizeType: ['compressed'],
+          sourceType: ['album', 'camera'],
+          success: function(res) {
+            that.tempImagePath = res.tempFilePaths[0]
+          },
+          fail: function(err) {
+            console.error('閫夋嫨鍥剧墖澶辫触:', err)
+            that.$modal.showToast('閫夋嫨鍥剧墖澶辫触')
+          }
+        })
+      },
+      
+      // 纭涓婁紶
+      confirmUpload() {
+        if (!this.tempImagePath) {
+          this.$modal.showToast('璇峰厛閫夋嫨鍥剧墖')
+          return
+        }
+        
+        const that = this
+        const category = this.categoryList[this.selectedCategoryIndex].value
+        
+        // 寰俊灏忕▼搴忕幆澧冿細鍏堣幏鍙朅ccessToken锛屽啀涓婁紶鍒板井淇℃湇鍔″櫒锛屾渶鍚庢彁浜ediaId鍒板悗绔�
+        // #ifdef MP-WEIXIN
+        if (this.isWechatMiniProgram) {
+          uni.showLoading({
+            title: '涓婁紶涓�...'
+          })
+          
+          // 绗竴姝ワ細浠庡悗绔幏鍙朅ccessToken
+          getWechatAccessToken().then(tokenResponse => {
+            // 鎺ュ彛杩斿洖鏍煎紡锛歿"msg":"token鍊�","code":200}
+            console.log('鑾峰彇AccessToken鎴愬姛:', tokenResponse)
+            const accessToken = tokenResponse.msg || tokenResponse.data || tokenResponse
+            if (!accessToken) {
+              uni.hideLoading()
+              that.$modal.showToast('鑾峰彇AccessToken澶辫触')
+              console.error('鑾峰彇AccessToken澶辫触锛屽搷搴旀暟鎹�:', tokenResponse)
+              return
+            }
+            
+            console.log('鑾峰彇鍒癆ccessToken:', accessToken)
+            
+            // 绗簩姝ワ細涓婁紶鍒板井淇℃湇鍔″櫒
+            const uploadUrl = `https://api.weixin.qq.com/cgi-bin/media/upload?access_token=${accessToken}&type=image`
+            
+            uni.uploadFile({
+              url: uploadUrl,
+              filePath: that.tempImagePath,
+              name: 'media',
+              success: function(res) {
+                console.log('寰俊涓婁紶鍝嶅簲:', res)
+                try {
+                  const data = JSON.parse(res.data)
+                  if (data.media_id) {
+                    // 绗笁姝ワ細鎻愪氦mediaId鍒板悗绔�
+                    uploadAttachmentFromWechat(that.taskId, data.media_id, category).then(response => {
+                      uni.hideLoading()
+                      that.$modal.showToast('涓婁紶鎴愬姛')
+                      that.closeUploadDialog()
+                      that.loadAttachmentList()
+                      that.$emit('uploaded', response)
+                    }).catch(error => {
+                      uni.hideLoading()
+                      console.error('鎻愪氦mediaId澶辫触:', error)
+                      that.$modal.showToast('涓婁紶澶辫触锛�' + (error.msg || '璇烽噸璇�'))
+                      that.$emit('error', error)
+                    })
+                  } else {
+                    uni.hideLoading()
+                    const errMsg = data.errmsg || '鏈煡閿欒'
+                    console.error('寰俊杩斿洖閿欒:', data)
+                    that.$modal.showToast('寰俊涓婁紶澶辫触锛�' + errMsg)
+                  }
+                } catch (e) {
+                  uni.hideLoading()
+                  console.error('瑙f瀽寰俊鍝嶅簲澶辫触:', e, res.data)
+                  that.$modal.showToast('涓婁紶澶辫触锛氬搷搴旇В鏋愰敊璇�')
+                }
+              },
+              fail: function(err) {
+                uni.hideLoading()
+                console.error('涓婁紶鍒板井淇″け璐�:', err)
+                that.$modal.showToast('涓婁紶澶辫触锛�' + (err.errMsg || '璇锋鏌ョ綉缁�'))
+                that.$emit('error', err)
+              }
+            })
+          }).catch(error => {
+            uni.hideLoading()
+            console.error('鑾峰彇AccessToken澶辫触:', error)
+            that.$modal.showToast('鑾峰彇AccessToken澶辫触')
+            that.$emit('error', error)
+          })
+          return
+        }
+        // #endif
+        
+        // 闈炲井淇″皬绋嬪簭鐜锛氱洿鎺ヤ笂浼犲埌鍚庣鏈嶅姟鍣�
+        uni.showLoading({
+          title: '涓婁紶涓�...'
+        })
+        
+        uni.uploadFile({
+          url: that.$baseUrl + '/task/attachment/upload/' + that.taskId,
+          filePath: that.tempImagePath,
+          name: 'file',
+          formData: {
+            'category': category
+          },
+          header: {
+            'Authorization': 'Bearer ' + uni.getStorageSync('token')
+          },
+          success: function(uploadRes) {
+            uni.hideLoading()
+            
+            if (uploadRes.statusCode === 200) {
+              const result = JSON.parse(uploadRes.data)
+              if (result.code === 200) {
+                that.$modal.showToast('涓婁紶鎴愬姛')
+                that.closeUploadDialog()
+                that.loadAttachmentList()
+                that.$emit('uploaded', result)
+              } else {
+                that.$modal.showToast(result.msg || '涓婁紶澶辫触')
+                that.$emit('error', result)
+              }
+            } else {
+              that.$modal.showToast('涓婁紶澶辫触')
+              that.$emit('error', uploadRes)
+            }
+          },
+          fail: function(err) {
+            uni.hideLoading()
+            console.error('涓婁紶澶辫触:', err)
+            that.$modal.showToast('涓婁紶澶辫触')
+            that.$emit('error', err)
+          }
+        })
+      },
+      
+      // 鏌ョ湅闄勪欢
+      viewAttachment(item) {
+        // 濡傛灉鏄浘鐗囷紝浣跨敤鍥剧墖棰勮
+        const imageTypes = ['jpg', 'jpeg', 'png', 'gif', 'bmp']
+        const fileExt = item.fileName.split('.').pop().toLowerCase()
+        
+        if (imageTypes.includes(fileExt)) {
+          // 浼樺厛浣跨敤fileUrl瀛楁锛堝悗绔嫾鎺ュソ鐨勫畬鏁碪RL锛�
+          let imageUrl = item.fileUrl
+          // 濡傛灉娌℃湁fileUrl锛屽垯浣跨敤涓嬭浇鎺ュ彛
+          if (!imageUrl) {
+            imageUrl = this.$baseUrl + '/task/attachment/download/' + item.attachmentId
+          }
+          
+          // 寰俊灏忕▼搴忎腑棰勮鍥剧墖
+          // #ifdef MP-WEIXIN
+          // 寰俊灏忕▼搴忛渶瑕佸厛涓嬭浇鍒版湰鍦板啀棰勮
+          uni.showLoading({ title: '鍔犺浇涓�...' })
+          uni.downloadFile({
+            url: imageUrl,
+            success: function(res) {
+              uni.hideLoading()
+              if (res.statusCode === 200) {
+                uni.previewImage({
+                  urls: [res.tempFilePath],
+                  current: res.tempFilePath
+                })
+              } else {
+                uni.showToast({ title: '鍔犺浇鍥剧墖澶辫触', icon: 'none' })
+              }
+            },
+            fail: function() {
+              uni.hideLoading()
+              uni.showToast({ title: '涓嬭浇澶辫触', icon: 'none' })
+            }
+          })
+          // #endif
+          
+          // 闈炲井淇″皬绋嬪簭鐜锛岀洿鎺ラ瑙�
+          // #ifndef MP-WEIXIN
+          uni.previewImage({
+            urls: [imageUrl],
+            current: imageUrl
+          })
+          // #endif
+        } else {
+          this.$modal.showToast('浠呮敮鎸侀瑙堝浘鐗�')
+        }
+        
+        this.$emit('view', item)
+      },
+      
+      // 鍒犻櫎闄勪欢
+      deleteAttachment(attachmentId, index) {
+        const that = this
+        this.$modal.confirm('纭畾瑕佸垹闄よ闄勪欢鍚楋紵').then(() => {
+          deleteAttachment(attachmentId).then(response => {
+            that.$modal.showToast('鍒犻櫎鎴愬姛')
+            that.attachmentList.splice(index, 1)
+            that.$emit('deleted', attachmentId)
+          }).catch(error => {
+            console.error('鍒犻櫎闄勪欢澶辫触:', error)
+            that.$modal.showToast('鍒犻櫎澶辫触')
+            that.$emit('error', error)
+          })
+        }).catch(() => {})
+      },
+      
+      // 鑾峰彇鍒嗙被鍚嶇О
+      getCategoryName(category) {
+        console.log('category', category)
+        const item = this.categoryList.find(c => c.value === category)
+        return item ? item.label : '鏈垎绫�'
+      },
+      
+      // 鏍煎紡鍖栨椂闂�
+      formatTime(time) {
+        if (!time) return ''
+        return formatDateTime(time, 'YYYY-MM-DD HH:mm')
+      },
+      
+      // 鏍煎紡鍖栨枃浠跺ぇ灏�
+      formatFileSize(size) {
+        if (!size) return '0B'
+        if (size < 1024) return size + 'B'
+        if (size < 1024 * 1024) return (size / 1024).toFixed(2) + 'KB'
+        return (size / 1024 / 1024).toFixed(2) + 'MB'
+      },
+      
+      // 鑾峰彇鍥剧墖URL
+      getImageUrl(item) {
+        
+        // 浼樺厛浣跨敤fileUrl瀛楁锛堝悗绔嫾鎺ュソ鐨勫畬鏁碪RL锛�
+        if (item.fileUrl) {
+          return item.fileUrl
+        }
+        // 浣跨敤涓嬭浇鎺ュ彛
+        if (item.attachmentId) {
+          return this.$baseUrl + '/task/attachment/download/' + item.attachmentId
+        }
+        // 榛樿鍗犱綅鍥�
+        return '/static/images/default-image.png'
+      },
+      
+      // 鍒锋柊闄勪欢鍒楄〃锛堜緵澶栭儴璋冪敤锛�
+      refresh() {
+        this.loadAttachmentList()
+      }
+    }
+  }
+</script>
+
+<style lang="scss" scoped>
+  .attachment-upload-container {
+    .detail-section {
+      background-color: white;
+      border-radius: 15rpx;
+      padding: 30rpx;
+      margin-bottom: 20rpx;
+      box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
+      
+      .section-title {
+        font-size: 32rpx;
+        font-weight: bold;
+        margin-bottom: 20rpx;
+        color: #333;
+        border-bottom: 1rpx solid #f0f0f0;
+        padding-bottom: 10rpx;
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        
+        .upload-btn {
+          font-size: 24rpx;
+          padding: 8rpx 20rpx;
+          background-color: #007AFF;
+          color: white;
+          border-radius: 8rpx;
+          border: none;
+        }
+      }
+      
+      .no-attachment {
+        text-align: center;
+        padding: 40rpx 0;
+        color: #999;
+        font-size: 28rpx;
+      }
+      
+      .attachment-item {
+        display: flex;
+        align-items: center;
+        padding: 20rpx;
+        margin-bottom: 15rpx;
+        background-color: #f9f9f9;
+        border-radius: 10rpx;
+        
+        &:last-child {
+          margin-bottom: 0;
+        }
+        
+        .attachment-thumbnail {
+          width: 120rpx;
+          height: 120rpx;
+          border-radius: 8rpx;
+          overflow: hidden;
+          margin-right: 20rpx;
+          flex-shrink: 0;
+          background-color: #f0f0f0;
+          
+          .thumbnail-image {
+            width: 100%;
+            height: 100%;
+          }
+        }
+        
+        .attachment-info {
+          flex: 1;
+          margin-right: 20rpx;
+          
+          .attachment-category {
+            margin-bottom: 8rpx;
+            
+            .category-tag {
+              display: inline-block;
+              padding: 4rpx 12rpx;
+              background-color: #007AFF;
+              color: white;
+              font-size: 22rpx;
+              border-radius: 4rpx;
+            }
+          }
+          
+          .attachment-meta {
+            font-size: 24rpx;
+            color: #999;
+            
+            .upload-time {
+              margin-right: 20rpx;
+            }
+          }
+        }
+        
+        .attachment-actions {
+          display: flex;
+          flex-direction: column;
+          gap: 10rpx;
+          
+          .action-btn {
+            padding: 8rpx 20rpx;
+            font-size: 24rpx;
+            border-radius: 6rpx;
+            border: none;
+            
+            &.view-btn {
+              background-color: #007AFF;
+              color: white;
+            }
+            
+            &.delete-btn {
+              background-color: #ff3b30;
+              color: white;
+            }
+          }
+        }
+      }
+    }
+    
+    .upload-dialog {
+      background-color: white;
+      border-radius: 20rpx 20rpx 0 0;
+      padding: 30rpx;
+      
+      .dialog-header {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        margin-bottom: 30rpx;
+        
+        .dialog-title {
+          font-size: 32rpx;
+          font-weight: bold;
+          color: #333;
+        }
+      }
+      
+      .dialog-content {
+        .form-item {
+          margin-bottom: 30rpx;
+          
+          .form-label {
+            font-size: 28rpx;
+            color: #333;
+            margin-bottom: 15rpx;
+          }
+          
+          .picker-value {
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+            padding: 20rpx;
+            background-color: #f5f5f5;
+            border-radius: 10rpx;
+            font-size: 28rpx;
+            color: #333;
+          }
+          
+          .choose-image-btn {
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            padding: 30rpx;
+            background-color: #f5f5f5;
+            border-radius: 10rpx;
+            border: 2rpx dashed #ccc;
+            color: #666;
+            font-size: 28rpx;
+            
+            text {
+              margin-left: 10rpx;
+            }
+          }
+        }
+        
+        .preview-area {
+          margin-top: 20rpx;
+          
+          .preview-image {
+            width: 100%;
+            height: 400rpx;
+            border-radius: 10rpx;
+          }
+        }
+      }
+      
+      .dialog-footer {
+        display: flex;
+        gap: 20rpx;
+        margin-top: 30rpx;
+        
+        button {
+          flex: 1;
+          height: 80rpx;
+          border-radius: 10rpx;
+          font-size: 30rpx;
+          border: none;
+        }
+        
+        .cancel-btn {
+          background-color: #f5f5f5;
+          color: #666;
+        }
+        
+        .confirm-btn {
+          background-color: #007AFF;
+          color: white;
+          
+          &:disabled {
+            background-color: #ccc;
+          }
+        }
+      }
+    }
+  }
+</style>
diff --git a/app/pages/task/detail.vue b/app/pages/task/detail.vue
index 3932e66..8803e0a 100644
--- a/app/pages/task/detail.vue
+++ b/app/pages/task/detail.vue
@@ -195,33 +195,12 @@
       </view>
       
       <!-- 闄勪欢淇℃伅 -->
-      <view class="detail-section">
-        <view class="section-title">
-          浠诲姟闄勪欢
-          <button class="upload-btn" @click="showUploadDialog">涓婁紶闄勪欢</button>
-        </view>
-        <view v-if="attachmentList && attachmentList.length > 0">
-          <view class="attachment-item" v-for="(item, index) in attachmentList" :key="item.attachmentId">
-            <view class="attachment-info">
-              <view class="attachment-category">
-                <text class="category-tag">{{ getCategoryName(item.attachmentCategory) }}</text>
-              </view>
-              <view class="attachment-name">{{ item.fileName }}</view>
-              <view class="attachment-meta">
-                <text class="upload-time">{{ formatTime(item.uploadTime) }}</text>
-                <text class="file-size">{{ formatFileSize(item.fileSize) }}</text>
-              </view>
-            </view>
-            <view class="attachment-actions">
-              <button class="action-btn view-btn" @click="viewAttachment(item)">鏌ョ湅</button>
-              <button class="action-btn delete-btn" @click="deleteAttachment(item.attachmentId, index)">鍒犻櫎</button>
-            </view>
-          </view>
-        </view>
-        <view v-else class="no-attachment">
-          <text>鏆傛棤闄勪欢</text>
-        </view>
-      </view>
+      <AttachmentUpload 
+        :taskId="taskId" 
+        title="浠诲姟闄勪欢"
+        @uploaded="onAttachmentUploaded"
+        @deleted="onAttachmentDeleted"
+      />
       
       <!-- 绂忕杞︿换鍔$壒鏈変俊鎭� -->
       <view class="detail-section" v-if="taskDetail.taskType === 'WELFARE' && taskDetail.welfareInfo">
@@ -343,66 +322,22 @@
       
       <!-- 宸插畬鎴�/宸插彇娑�: 涓嶆樉绀烘寜閽� -->
     </view>
-    
-    <!-- 闄勪欢涓婁紶瀵硅瘽妗� -->
-    <uni-popup ref="uploadPopup" type="bottom">
-      <view class="upload-dialog">
-        <view class="dialog-header">
-          <text class="dialog-title">涓婁紶闄勪欢</text>
-          <uni-icons type="closeempty" size="24" @click="closeUploadDialog"></uni-icons>
-        </view>
-        <view class="dialog-content">
-          <view class="form-item">
-            <view class="form-label">闄勪欢鍒嗙被</view>
-            <picker @change="onCategoryChange" :value="selectedCategoryIndex" :range="categoryList" range-key="label">
-              <view class="picker-value">
-                {{ categoryList[selectedCategoryIndex].label }}
-                <uni-icons type="arrowdown" size="16"></uni-icons>
-              </view>
-            </picker>
-          </view>
-          <view class="form-item">
-            <view class="form-label">閫夋嫨鍥剧墖</view>
-            <button class="choose-image-btn" @click="chooseImage">
-              <uni-icons type="image" size="20"></uni-icons>
-              <text>鐐瑰嚮閫夋嫨</text>
-            </button>
-          </view>
-          <view class="preview-area" v-if="tempImagePath">
-            <image :src="tempImagePath" mode="aspectFit" class="preview-image"></image>
-          </view>
-        </view>
-        <view class="dialog-footer">
-          <button class="cancel-btn" @click="closeUploadDialog">鍙栨秷</button>
-          <button class="confirm-btn" @click="confirmUpload" :disabled="!tempImagePath">纭畾涓婁紶</button>
-        </view>
-      </view>
-    </uni-popup>
   </view>
 </template>
 
 <script>
   import { getTask, changeTaskStatus } from '@/api/task'
-  import { getAttachmentList, uploadAttachmentFromWechat, deleteAttachment, getWechatAccessToken } from '@/api/task'
   import { formatDateTime } from '@/utils/common'
+  import AttachmentUpload from '@/components/AttachmentUpload.vue'
   
   export default {
+    components: {
+      AttachmentUpload
+    },
     data() {
       return {
         taskDetail: null,
-        taskId: null,
-        attachmentList: [],
-        categoryList: [
-          { label: '鐭ユ儏鍚屾剰涔�', value: '1' },
-          { label: '鐥呬汉璧勬枡', value: '2' },
-          { label: '鎿嶄綔璁板綍', value: '3' },
-          { label: '鍑鸿溅鍓�', value: '4' },
-          { label: '鍑鸿溅鍚�', value: '5' },
-          { label: '绯诲畨鍏ㄥ甫', value: '6' }
-        ],
-        selectedCategoryIndex: 0,
-        tempImagePath: null,
-        isWechatMiniProgram: false // 鏄惁鏄井淇″皬绋嬪簭鐜
+        taskId: null
       }
     },
     computed: {
@@ -464,12 +399,6 @@
     onLoad(options) {
       this.taskId = options.id
       this.loadTaskDetail()
-      this.loadAttachmentList()
-      
-      // 妫�娴嬫槸鍚︽槸寰俊灏忕▼搴忕幆澧�
-      // #ifdef MP-WEIXIN
-      this.isWechatMiniProgram = true
-      // #endif
     },
     methods: {
       // 鍔犺浇浠诲姟璇︽儏
@@ -923,6 +852,16 @@
         if (size < 1024) return size + 'B'
         if (size < 1024 * 1024) return (size / 1024).toFixed(2) + 'KB'
         return (size / 1024 / 1024).toFixed(2) + 'MB'
+      },
+      
+      // 闄勪欢涓婁紶鎴愬姛鍥炶皟
+      onAttachmentUploaded(response) {
+        console.log('闄勪欢涓婁紶鎴愬姛:', response)
+      },
+      
+      // 闄勪欢鍒犻櫎鎴愬姛鍥炶皟
+      onAttachmentDeleted(attachmentId) {
+        console.log('闄勪欢鍒犻櫎鎴愬姛:', attachmentId)
       }
     }
   }
@@ -1038,84 +977,6 @@
         padding: 20rpx;
         border-radius: 10rpx;
       }
-      
-      .no-attachment {
-        text-align: center;
-        padding: 40rpx 0;
-        color: #999;
-        font-size: 28rpx;
-      }
-      
-      .attachment-item {
-        display: flex;
-        justify-content: space-between;
-        align-items: center;
-        padding: 20rpx;
-        margin-bottom: 15rpx;
-        background-color: #f9f9f9;
-        border-radius: 10rpx;
-        
-        &:last-child {
-          margin-bottom: 0;
-        }
-        
-        .attachment-info {
-          flex: 1;
-          margin-right: 20rpx;
-          
-          .attachment-category {
-            margin-bottom: 8rpx;
-            
-            .category-tag {
-              display: inline-block;
-              padding: 4rpx 12rpx;
-              background-color: #007AFF;
-              color: white;
-              font-size: 22rpx;
-              border-radius: 4rpx;
-            }
-          }
-          
-          .attachment-name {
-            font-size: 28rpx;
-            color: #333;
-            margin-bottom: 8rpx;
-            word-break: break-all;
-          }
-          
-          .attachment-meta {
-            font-size: 24rpx;
-            color: #999;
-            
-            .upload-time {
-              margin-right: 20rpx;
-            }
-          }
-        }
-        
-        .attachment-actions {
-          display: flex;
-          flex-direction: column;
-          gap: 10rpx;
-          
-          .action-btn {
-            padding: 8rpx 20rpx;
-            font-size: 24rpx;
-            border-radius: 6rpx;
-            border: none;
-            
-            &.view-btn {
-              background-color: #007AFF;
-              color: white;
-            }
-            
-            &.delete-btn {
-              background-color: #ff3b30;
-              color: white;
-            }
-          }
-        }
-      }
     }
     
     .loading {
@@ -1167,102 +1028,6 @@
         
         &:last-child {
           margin-right: 0;
-        }
-      }
-    }
-    
-    .upload-dialog {
-      background-color: white;
-      border-radius: 20rpx 20rpx 0 0;
-      padding: 30rpx;
-      
-      .dialog-header {
-        display: flex;
-        justify-content: space-between;
-        align-items: center;
-        margin-bottom: 30rpx;
-        
-        .dialog-title {
-          font-size: 32rpx;
-          font-weight: bold;
-          color: #333;
-        }
-      }
-      
-      .dialog-content {
-        .form-item {
-          margin-bottom: 30rpx;
-          
-          .form-label {
-            font-size: 28rpx;
-            color: #333;
-            margin-bottom: 15rpx;
-          }
-          
-          .picker-value {
-            display: flex;
-            justify-content: space-between;
-            align-items: center;
-            padding: 20rpx;
-            background-color: #f5f5f5;
-            border-radius: 10rpx;
-            font-size: 28rpx;
-            color: #333;
-          }
-          
-          .choose-image-btn {
-            display: flex;
-            align-items: center;
-            justify-content: center;
-            padding: 30rpx;
-            background-color: #f5f5f5;
-            border-radius: 10rpx;
-            border: 2rpx dashed #ccc;
-            color: #666;
-            font-size: 28rpx;
-            
-            text {
-              margin-left: 10rpx;
-            }
-          }
-        }
-        
-        .preview-area {
-          margin-top: 20rpx;
-          
-          .preview-image {
-            width: 100%;
-            height: 400rpx;
-            border-radius: 10rpx;
-          }
-        }
-      }
-      
-      .dialog-footer {
-        display: flex;
-        gap: 20rpx;
-        margin-top: 30rpx;
-        
-        button {
-          flex: 1;
-          height: 80rpx;
-          border-radius: 10rpx;
-          font-size: 30rpx;
-          border: none;
-        }
-        
-        .cancel-btn {
-          background-color: #f5f5f5;
-          color: #666;
-        }
-        
-        .confirm-btn {
-          background-color: #007AFF;
-          color: white;
-          
-          &:disabled {
-            background-color: #ccc;
-          }
         }
       }
     }
diff --git "a/prd/\344\273\273\345\212\241\351\231\204\344\273\266\345\220\214\346\255\245ImageData\345\212\237\350\203\275\350\257\264\346\230\216.md" "b/prd/\344\273\273\345\212\241\351\231\204\344\273\266\345\220\214\346\255\245ImageData\345\212\237\350\203\275\350\257\264\346\230\216.md"
new file mode 100644
index 0000000..866152f
--- /dev/null
+++ "b/prd/\344\273\273\345\212\241\351\231\204\344\273\266\345\220\214\346\255\245ImageData\345\212\237\350\203\275\350\257\264\346\230\216.md"
@@ -0,0 +1,223 @@
+# 浠诲姟闄勪欢鍚屾ImageData鍔熻兘璇存槑
+
+## 鍔熻兘姒傝堪
+
+鏈姛鑳藉疄鐜颁簡灏嗕换鍔¢檮浠讹紙sys_task_attachment琛級鑷姩鍚屾鍒癐mageData琛ㄧ殑鑳藉姏銆傚綋浠诲姟鍏宠仈浜嗘湇鍔″崟锛坰erviceOrderId锛夋垨璋冨害鍗曪紙dispatchOrdId锛夊悗锛岀郴缁熶細鑷姩灏嗕换鍔¢檮浠跺悓姝ュ埌ImageData琛紝浠ヤ究鍦ㄦ棫绯荤粺涓煡鐪嬪拰浣跨敤銆�
+
+## 鏍稿績鍔熻兘
+
+### 1. 鑷姩鍚屾
+- 涓婁紶闄勪欢鏃讹紝濡傛灉浠诲姟宸插叧鑱旀湇鍔″崟鎴栬皟搴﹀崟锛岃嚜鍔ㄥ悓姝ュ埌ImageData
+- 鏀寔鏅�氭枃浠朵笂浼犲拰寰俊涓婁紶涓ょ鏂瑰紡
+- 鍚屾澶辫触涓嶅奖鍝嶉檮浠朵笂浼犵殑涓绘祦绋�
+
+### 2. 鎵嬪姩鍚屾
+- 鎻愪緵API鎺ュ彛锛屾敮鎸佹墜鍔ㄨЕ鍙戝悓姝�
+- 鏀寔鎵归噺鍚屾浠诲姟鐨勬墍鏈夐檮浠�
+- 鏀寔妫�鏌ラ檮浠舵槸鍚﹀凡鍚屾
+
+### 3. 闄勪欢鍒嗙被鏄犲皠
+闄勪欢鍒嗙被鑷姩鏄犲皠鍒癐mageData鐨勫浘鐗囩被鍨嬶細
+- 1-鐭ユ儏鍚屾剰涔� 鈫� ImageType 0
+- 2-鐥呬汉璧勬枡 鈫� ImageType 1  
+- 3-鎿嶄綔璁板綍 鈫� ImageType 2
+- 4-鍑鸿溅鍓� 鈫� ImageType 3
+- 5-鍑鸿溅鍚� 鈫� ImageType 4
+- 6-绯诲畨鍏ㄥ甫 鈫� ImageType 5
+
+## 鏁版嵁搴撳彉鏇�
+
+### sys_task_attachment 琛ㄦ柊澧炲瓧娈�
+
+```sql
+-- 鏄惁宸插悓姝ュ埌ImageData (0-鏈悓姝� 1-宸插悓姝�)
+synced_to_image_data TINYINT(1) DEFAULT 0
+
+-- 鍚屾鏃堕棿
+sync_time DATETIME
+
+-- 鍏宠仈鐨処mageData ID
+image_data_id BIGINT
+```
+
+### 鎵цSQL鑴氭湰
+
+```bash
+鎵ц鏂囦欢: sql/update_sys_task_attachment_sync_fields.sql
+```
+
+## 鏂板鏂囦欢
+
+### 1. 鏈嶅姟鎺ュ彛
+- `ITaskAttachmentSyncService.java` - 闄勪欢鍚屾鏈嶅姟鎺ュ彛
+- `TaskAttachmentSyncServiceImpl.java` - 闄勪欢鍚屾鏈嶅姟瀹炵幇
+
+### 2. Controller
+- `TaskAttachmentSyncController.java` - 闄勪欢鍚屾鎺у埗鍣�
+
+### 3. SQL鑴氭湰
+- `update_sys_task_attachment_sync_fields.sql` - 鏁版嵁搴撴洿鏂拌剼鏈�
+
+## 淇敼鏂囦欢
+
+### 1. 瀹炰綋绫�
+- `SysTaskAttachment.java` - 娣诲姞鍚屾鐩稿叧瀛楁
+
+### 2. Mapper
+- `SysTaskAttachmentMapper.xml` - 鏇存柊SQL璇彞
+
+### 3. 鏈嶅姟瀹炵幇
+- `SysTaskServiceImpl.java` - 闆嗘垚鑷姩鍚屾閫昏緫
+
+## API鎺ュ彛
+
+### 1. 鎵嬪姩鍚屾浠诲姟闄勪欢
+
+**鎺ュ彛**: `POST /task/attachment/sync/task/{taskId}`
+
+**鏉冮檺**: `task:general:edit`
+
+**鍙傛暟**:
+- `taskId`: 浠诲姟ID锛堣矾寰勫弬鏁帮級
+
+**杩斿洖绀轰緥**:
+```json
+{
+  "code": 200,
+  "msg": "鎴愬姛鍚屾 3 涓檮浠�"
+}
+```
+
+### 2. 妫�鏌ラ檮浠跺悓姝ョ姸鎬�
+
+**鎺ュ彛**: `GET /task/attachment/sync/check/{attachmentId}`
+
+**鏉冮檺**: `task:general:query`
+
+**鍙傛暟**:
+- `attachmentId`: 闄勪欢ID锛堣矾寰勫弬鏁帮級
+
+**杩斿洖绀轰緥**:
+```json
+{
+  "code": 200,
+  "msg": "宸插悓姝�",
+  "data": true
+}
+```
+
+## 浣跨敤鍦烘櫙
+
+### 鍦烘櫙1锛氭柊涓婁紶闄勪欢鑷姩鍚屾
+
+1. 鐢ㄦ埛鍦ㄥ皬绋嬪簭涓婁紶浠诲姟闄勪欢
+2. 绯荤粺淇濆瓨闄勪欢鍒皊ys_task_attachment琛�
+3. 妫�娴嬩换鍔℃槸鍚﹀凡鍏宠仈鏈嶅姟鍗�/璋冨害鍗�
+4. 濡傛灉宸插叧鑱旓紝鑷姩鍚屾鍒癐mageData琛�
+5. 鏇存柊闄勪欢鐨勫悓姝ョ姸鎬佸瓧娈�
+
+### 鍦烘櫙2锛氭墜鍔ㄦ壒閲忓悓姝�
+
+1. 浠诲姟鍚庢湡鍏宠仈浜嗘湇鍔″崟/璋冨害鍗�
+2. 璋冪敤鎵嬪姩鍚屾鎺ュ彛鍚屾鍘嗗彶闄勪欢
+3. 绯荤粺鎵归噺鍚屾璇ヤ换鍔$殑鎵�鏈夋湭鍚屾闄勪欢
+4. 杩斿洖鍚屾鎴愬姛鐨勯檮浠舵暟閲�
+
+### 鍦烘櫙3锛氭棫绯荤粺鏌ョ湅闄勪欢
+
+1. 鐢ㄦ埛鍦ㄦ棫绯荤粺涓煡鐪嬭皟搴﹀崟
+2. 璋冪敤ImageData鎺ュ彛鑾峰彇鍥剧墖鍒楄〃
+3. 鏄剧ず閫氳繃鏂扮郴缁熶笂浼犵殑浠诲姟闄勪欢
+4. 瀹炵幇鏂版棫绯荤粺鏁版嵁浜掗��
+
+## 鎶�鏈疄鐜�
+
+### 1. 鍚屾鏈嶅姟
+
+```java
+@Service
+public class TaskAttachmentSyncServiceImpl implements ITaskAttachmentSyncService {
+    
+    // 鍚屾鍗曚釜闄勪欢
+    public boolean syncAttachmentToImageData(
+        SysTaskAttachment attachment, 
+        Long serviceOrderId, 
+        Long dispatchOrdId);
+    
+    // 鎵归噺鍚屾浠诲姟闄勪欢
+    public int syncTaskAttachmentsToImageData(
+        Long taskId, 
+        Long serviceOrderId, 
+        Long dispatchOrdId);
+}
+```
+
+### 2. 鑷姩鍚屾瑙﹀彂
+
+鍦ㄤ笂浼犻檮浠舵椂鑷姩瑙﹀彂锛�
+
+```java
+// 涓婁紶闄勪欢鎴愬姛鍚�
+if (result > 0) {
+    // 灏濊瘯鑷姩鍚屾鍒癐mageData
+    tryAutoSyncAttachment(attachment, taskId);
+}
+```
+
+### 3. 鏁版嵁婧愬垏鎹�
+
+鍚屾鍒癐mageData鏃惰嚜鍔ㄥ垏鎹㈠埌SQL Server鏁版嵁婧愶細
+
+```java
+@DataSource(DataSourceType.SQLSERVER)
+public boolean syncAttachmentToImageData(...) {
+    // 鍦⊿QL Server鏁版嵁婧愪腑鎵ц
+    imageDataService.insertImageData(imageData);
+}
+```
+
+## 娉ㄦ剰浜嬮」
+
+### 1. 鏁版嵁婧愰厤缃�
+- 纭繚SQL Server鏁版嵁婧愰厤缃纭�
+- 纭繚ImageData琛ㄥ瓨鍦ㄤ笖鍙闂�
+
+### 2. 鏂囦欢璺緞
+- 闄勪欢璺緞浣跨敤鐩稿璺緞瀛樺偍
+- 鍚屾鏃朵繚鎸佽矾寰勬牸寮忎竴鑷�
+
+### 3. 浜嬪姟绠$悊
+- 鍚屾澶辫触涓嶅奖鍝嶄富娴佺▼
+- 閿欒淇℃伅浠呰褰曟棩蹇�
+
+### 4. 鎬ц兘鑰冭檻
+- 鑷姩鍚屾鏄紓姝ョ殑锛屼笉褰卞搷鐢ㄦ埛浣撻獙
+- 鎵归噺鍚屾鏃堕�愪釜澶勭悊锛岄伩鍏嶄簨鍔¤秴鏃�
+
+## 甯歌闂
+
+### Q1: 濡備綍鍒ゆ柇闄勪欢鏄惁闇�瑕佸悓姝ワ紵
+A: 妫�鏌ヤ换鍔℃槸鍚﹀叧鑱斾簡serviceOrderId鎴杁ispatchOrdId
+
+### Q2: 鍚屾澶辫触浼氬奖鍝嶉檮浠朵笂浼犲悧锛�
+A: 涓嶄細锛屽悓姝ュけ璐ュ彧璁板綍鏃ュ織锛屼笉褰卞搷涓绘祦绋�
+
+### Q3: 濡備綍閲嶆柊鍚屾澶辫触鐨勯檮浠讹紵
+A: 璋冪敤鎵嬪姩鍚屾鎺ュ彛锛岀郴缁熶細鑷姩璺宠繃宸插悓姝ョ殑闄勪欢
+
+### Q4: ImageData鐨勫浘鐗囩被鍨嬪浣曠‘瀹氾紵
+A: 鏍规嵁闄勪欢鍒嗙被鑷姩鏄犲皠鍒板搴旂殑ImageType
+
+## 鎵╁睍寤鸿
+
+### 1. 瀹氭椂鍚屾浠诲姟
+鍙互娣诲姞瀹氭椂浠诲姟锛屽畾鏈熸鏌ュ苟鍚屾鏈悓姝ョ殑闄勪欢
+
+### 2. 鍚屾鐘舵�侀�氱煡
+鍙互鍦ㄥ悓姝ュ畬鎴愬悗鍙戦�侀�氱煡缁欑浉鍏充汉鍛�
+
+### 3. 鍚屾鏃ュ織
+鍙互娣诲姞璇︾粏鐨勫悓姝ユ棩蹇楄〃锛岃褰曟瘡娆″悓姝ョ殑璇︾粏淇℃伅
+
+### 4. 鎵归噺鎿嶄綔
+鍙互娣诲姞鎵归噺鍚屾澶氫釜浠诲姟闄勪欢鐨勫姛鑳�
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskAttachmentController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskAttachmentController.java
index d9e5490..7175013 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskAttachmentController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskAttachmentController.java
@@ -1,5 +1,6 @@
 package com.ruoyi.web.controller.task;
 
+import java.util.Date;
 import java.util.List;
 import java.io.File;
 import java.io.FileInputStream;
@@ -9,6 +10,11 @@
 import com.ruoyi.common.utils.WechatUtils;
 import com.ruoyi.common.config.WechatConfig;
 import com.ruoyi.system.domain.SysTask;
+import com.ruoyi.system.domain.SysTaskEmergency;
+import com.ruoyi.system.service.ISysTaskEmergencyService;
+import com.ruoyi.system.service.ISysUserService;
+import com.ruoyi.system.service.ITaskAttachmentSyncService;
+import com.ruoyi.system.task.ITaskAttachmentService;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -38,10 +44,24 @@
     
     @Autowired
     private ISysTaskService sysTaskService;
+
+    @Autowired
+    private ISysUserService sysUserService;
+
+    @Autowired
+    private ITaskAttachmentSyncService taskAttachmentSyncService;
+
+    @Autowired
+    private ITaskAttachmentService taskAttachmentService;
     
     @Autowired
     private WechatConfig wechatConfig;
 
+    @Autowired
+    private ISysTaskEmergencyService sysTaskEmergencyService;
+
+    @Autowired
+    private ISysUserService userService;
     /**
      * 鏌ヨ浠诲姟闄勪欢鍒楄〃
      */
@@ -62,8 +82,10 @@
                             @RequestParam("file") MultipartFile file,
                             @RequestParam(value = "category", required = false) String category) {
         try {
-            int result = sysTaskService.uploadAttachment(taskId, file, category);
-            if (result > 0) {
+            Long attachmentId= sysTaskService.uploadAttachment(taskId, file, category);
+            if (attachmentId > 0) {
+                //鍦ㄨ繖閲岃繘琛屽悓姝�
+                SyncAttachmentToImageData(taskId,sysTaskService.getTaskDetail(taskId).getCreatorId(),attachmentId);
                 return success("涓婁紶鎴愬姛");
             } else {
                 return error("涓婁紶澶辫触");
@@ -73,6 +95,27 @@
         }
     }
 
+    private void SyncAttachmentToImageData(Long taskId,Long taskCreatorId, Long attachmentId) {
+       Integer oaUserId= sysUserService.selectUserById(taskCreatorId).getOaUserId();
+        SysTaskEmergency taskEmergency= sysTaskEmergencyService.selectSysTaskEmergencyByTaskId(taskId);
+        if(taskEmergency!=null ){
+            Long serviceOrderId= taskEmergency.getLegacyServiceOrdId();
+            Long dispathOrdId=taskEmergency.getLegacyDispatchOrdId();
+
+            if(serviceOrderId!=null && dispathOrdId!=null){
+                SysTaskAttachment attachment=sysTaskService.getAttachmentById(attachmentId);
+               Long imageDataId= taskAttachmentSyncService.syncAttachmentToImageData(attachment, serviceOrderId, dispathOrdId,oaUserId);
+                //鍚屾鎴愬姛
+                if(imageDataId>0){
+                    attachment.setSyncedToImageData(1);
+                    attachment.setSyncTime(new Date());
+                    attachment.setImageDataId(imageDataId);
+                    taskAttachmentService.updateAttachment(attachment);
+                }
+
+            }
+        }
+    }
     /**
      * 鍒犻櫎浠诲姟闄勪欢
      */
@@ -112,8 +155,10 @@
             }
             
             // 閫氳繃mediaId涓婁紶闄勪欢
-            int result = sysTaskService.uploadAttachmentFromWechat(taskId, accessToken, mediaId, category);
-            if (result > 0) {
+            Long attachmentId = sysTaskService.uploadAttachmentFromWechat(taskId, accessToken, mediaId, category);
+            SysTask task=sysTaskService.getTaskDetail(taskId);
+            if (attachmentId > 0) {
+                this.SyncAttachmentToImageData(taskId,task.getCreatorId(),attachmentId);
                 return success("涓婁紶鎴愬姛");
             } else {
                 return error("涓婁紶澶辫触");
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/TaskAttachmentSyncController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/TaskAttachmentSyncController.java
new file mode 100644
index 0000000..88187c7
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/TaskAttachmentSyncController.java
@@ -0,0 +1,108 @@
+package com.ruoyi.web.controller.task;
+
+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.enums.BusinessType;
+import com.ruoyi.system.domain.SysTask;
+import com.ruoyi.system.domain.SysTaskAttachment;
+import com.ruoyi.system.service.ISysTaskService;
+import com.ruoyi.system.service.ISysUserService;
+import com.ruoyi.system.service.ITaskAttachmentSyncService;
+import com.ruoyi.system.task.ITaskAttachmentService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 浠诲姟闄勪欢鍚屾Controller
+ * 鐢ㄤ簬灏嗕换鍔¢檮浠跺悓姝ュ埌ImageData琛�
+ * 
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/task/attachment/sync")
+public class TaskAttachmentSyncController extends BaseController {
+    
+    @Autowired
+    private ITaskAttachmentSyncService taskAttachmentSyncService;
+
+    @Autowired
+    private ITaskAttachmentService taskAttachmentService;
+    
+    @Autowired
+    private ISysTaskService sysTaskService;
+
+    @Autowired
+    private ISysUserService sysUserService;
+
+    /**
+     * 鎵嬪姩鍚屾鍗曚釜浠诲姟鐨勯檮浠跺埌ImageData
+     * 
+     * @param taskId 浠诲姟ID
+     * @return 鍚屾缁撴灉
+     */
+    @PreAuthorize("@ss.hasPermi('task:general:edit')")
+    @Log(title = "浠诲姟闄勪欢鍚屾", businessType = BusinessType.OTHER)
+    @PostMapping("/task/{taskId}")
+    public AjaxResult syncTaskAttachments(@PathVariable("taskId") Long taskId) {
+        try {
+            // 鏌ヨ浠诲姟璇︽儏
+            SysTask task = sysTaskService.getTaskDetail(taskId);
+            SysUser user = sysUserService.selectUserById(task.getCreatorId());
+            Integer oaUserId=user.getOaUserId();
+            if (task == null) {
+                return error("浠诲姟涓嶅瓨鍦�");
+            }
+            
+            // 鑾峰彇serviceOrderId鍜宒ispatchOrdId
+            Long serviceOrderId = null;
+            Long dispatchOrdId = null;
+            
+            if (task.getEmergencyInfo() != null) {
+                serviceOrderId = task.getEmergencyInfo().getLegacyServiceOrdId();
+                dispatchOrdId = task.getEmergencyInfo().getLegacyDispatchOrdId();
+            }
+            
+            if (serviceOrderId == null && dispatchOrdId == null) {
+                return error("浠诲姟鏈叧鑱旀湇鍔″崟鎴栬皟搴﹀崟锛屾棤娉曞悓姝�");
+            }
+            List<SysTaskAttachment> attachmentList=sysTaskService.getAttachmentsByTaskId(taskId);
+            // 鎵ц鍚屾
+            List<SysTaskAttachment> attachments = taskAttachmentSyncService.syncTaskAttachmentsToImageData(
+                    attachmentList, serviceOrderId, dispatchOrdId,oaUserId);
+
+            for(SysTaskAttachment attachment:attachments){
+
+                taskAttachmentService.updateAttachment(attachment);
+            }
+
+            return success("鎴愬姛鍚屾 " + attachments.stream().count() + " 涓檮浠�");
+        } catch (Exception e) {
+            logger.error("鍚屾浠诲姟闄勪欢澶辫触", e);
+            return error("鍚屾澶辫触锛�" + e.getMessage());
+        }
+    }
+
+
+    /**
+     * 妫�鏌ラ檮浠舵槸鍚﹀凡鍚屾
+     * 
+     * @param attachmentId 闄勪欢ID
+     * @return 鍚屾鐘舵��
+     */
+    @PreAuthorize("@ss.hasPermi('task:general:query')")
+    @GetMapping("/check/{attachmentId}")
+    public AjaxResult checkAttachmentSynced(@PathVariable("attachmentId") Long attachmentId) {
+        try {
+            boolean synced = taskAttachmentService.isAttachmentSynced(attachmentId);
+            return AjaxResult.success(synced ? "宸插悓姝�" : "鏈悓姝�", synced);
+        } catch (Exception e) {
+            logger.error("妫�鏌ラ檮浠跺悓姝ョ姸鎬佸け璐�", e);
+            return error("妫�鏌ュけ璐ワ細" + e.getMessage());
+        }
+    }
+}
diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml
index 18f8574..2bc8351 100644
--- a/ruoyi-admin/src/main/resources/application.yml
+++ b/ruoyi-admin/src/main/resources/application.yml
@@ -14,6 +14,8 @@
   addressEnabled: false
   # 楠岃瘉鐮佺被鍨� math 鏁板瓧璁$畻 char 瀛楃楠岃瘉
   captchaType: math
+  # 鍥剧墖璧勬簮鍩熷悕锛堢敤浜庤闂檮浠跺浘鐗囷級
+  imageUrl: https://dsp.966120.com.cn/images/
  
 
 # 寮�鍙戠幆澧冮厤缃�
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/config/ImageUrlConfig.java b/ruoyi-common/src/main/java/com/ruoyi/common/config/ImageUrlConfig.java
new file mode 100644
index 0000000..51e0894
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/config/ImageUrlConfig.java
@@ -0,0 +1,27 @@
+package com.ruoyi.common.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * 鍥剧墖URL閰嶇疆
+ * 
+ * @author ruoyi
+ */
+@Component
+@ConfigurationProperties(prefix = "ruoyi")
+public class ImageUrlConfig {
+    
+    /**
+     * 鍥剧墖璧勬簮鍩熷悕
+     */
+    private String imageUrl;
+    
+    public String getImageUrl() {
+        return imageUrl;
+    }
+    
+    public void setImageUrl(String imageUrl) {
+        this.imageUrl = imageUrl;
+    }
+}
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/LegacySystemSyncTask.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/LegacySystemSyncTask.java
index 2404483..89bc162 100644
--- a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/LegacySystemSyncTask.java
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/LegacySystemSyncTask.java
@@ -1,5 +1,6 @@
 package com.ruoyi.quartz.task;
 
+import com.ruoyi.system.service.ITaskAttachmentSyncService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -28,6 +29,8 @@
     
     @Autowired
     private ITaskStatusPushService taskStatusPushService;
+
+
     
     /**
      * 鎵归噺鍚屾鏈悓姝ョ殑鎬ユ晳杞繍浠诲姟鍒版棫绯荤粺
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskAttachment.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskAttachment.java
index 51a83db..8926496 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskAttachment.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskAttachment.java
@@ -2,8 +2,10 @@
 
 import java.util.Date;
 import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.ruoyi.common.annotation.Excel;
 import com.ruoyi.common.core.domain.BaseEntity;
+import org.springframework.beans.factory.annotation.Value;
 
 /**
  * 浠诲姟闄勪欢瀵硅薄 sys_task_attachment
@@ -37,6 +39,7 @@
     @Excel(name = "鏂囦欢绫诲瀷")
     private String fileType;
 
+
     /** 闄勪欢鍒嗙被 */
     @Excel(name = "闄勪欢鍒嗙被")
     private String attachmentCategory;
@@ -49,6 +52,19 @@
     /** 涓婁紶鑰� */
     @Excel(name = "涓婁紶鑰�")
     private String uploadBy;
+    
+    /** 鏄惁宸插悓姝ュ埌ImageData (0-鏈悓姝� 1-宸插悓姝�) */
+    private Integer syncedToImageData;
+    
+    /** 鍚屾鏃堕棿 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date syncTime;
+    
+    /** 鍏宠仈鐨処mageData ID */
+    private Long imageDataId;
+    
+    /** 瀹屾暣鏂囦欢URL锛堜笉瀛樺偍锛岀敤浜庤繑鍥炵粰鍓嶇锛� */
+    private String fileUrl;
 
     public void setAttachmentId(Long attachmentId) {
         this.attachmentId = attachmentId;
@@ -121,6 +137,38 @@
     public String getUploadBy() {
         return uploadBy;
     }
+    
+    public void setFileUrl(String fileUrl) {
+        this.fileUrl = fileUrl;
+    }
+    
+    public String getFileUrl() {
+        return fileUrl;
+    }
+    
+    public void setSyncedToImageData(Integer syncedToImageData) {
+        this.syncedToImageData = syncedToImageData;
+    }
+    
+    public Integer getSyncedToImageData() {
+        return syncedToImageData;
+    }
+    
+    public void setSyncTime(Date syncTime) {
+        this.syncTime = syncTime;
+    }
+    
+    public Date getSyncTime() {
+        return syncTime;
+    }
+    
+    public void setImageDataId(Long imageDataId) {
+        this.imageDataId = imageDataId;
+    }
+    
+    public Long getImageDataId() {
+        return imageDataId;
+    }
 
     @Override
     public String toString() {
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskEmergency.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskEmergency.java
index 05c00d7..325700d 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskEmergency.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskEmergency.java
@@ -129,6 +129,8 @@
     /** 璋冨害鍗曞悓姝ラ敊璇俊鎭� */
     private String dispatchSyncErrorMsg;
 
+
+
     public Long getId() {
         return id;
     }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/file/FileUploadServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/file/FileUploadServiceImpl.java
index 1abb2aa..ae26026 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/file/FileUploadServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/file/FileUploadServiceImpl.java
@@ -85,7 +85,7 @@
             log.info("寮�濮嬩笂浼犳枃浠跺埌PHP鎺ュ彛: fileName={}, targetPath={}", fileName, targetPath);
             
             // 璋冪敤PHP涓婁紶鎺ュ彛
-            String response = HttpUtils.postFile(legacyConfig.getFileServerUrl(), params, fileName);
+            String response = HttpUtils.postFile(legacyConfig.getFileUploadUrl(), params, fileName);
             
             log.info("PHP鎺ュ彛鍝嶅簲: {}", response);
             
@@ -305,6 +305,8 @@
                         int end = dataSection.indexOf("\"", start);
                         if (start > 11 && end > start) {
                             String filePath = dataSection.substring(start, end);
+                            // 鍘婚櫎杞箟瀛楃
+                            filePath = filePath.replace("\\", "");
                             log.info("鎻愬彇鍒版枃浠惰矾寰�: {}", filePath);
                             return filePath;
                         }
@@ -346,6 +348,7 @@
                         if (start > 16 && end > start) {
                             String thumbnailPath = dataSection.substring(start, end);
                             log.info("鎻愬彇鍒扮缉鐣ュ浘璺緞: {}", thumbnailPath);
+                            thumbnailPath = thumbnailPath.replace("\\", ""); // 鍘婚櫎杞箟瀛楃
                             return thumbnailPath;
                         }
                     }
@@ -359,6 +362,7 @@
                 if (start > 16 && end > start) {
                     String thumbnailPath = response.substring(start, end);
                     log.info("鎻愬彇鍒扮缉鐣ュ浘璺緞(鏃ф牸寮�): {}", thumbnailPath);
+                    thumbnailPath = thumbnailPath.replace("\\", ""); // 鍘婚櫎杞箟瀛楃
                     return thumbnailPath;
                 }
             }
@@ -471,20 +475,7 @@
                 return uploadResponse;
             }
             
-            // 濡傛灉鏄浘鐗囷紝鐢熸垚缂╃暐鍥�
-            if (isImage && uploadResponse.getFilePath() != null) {
-                String originalPath = uploadResponse.getFilePath();
-                String thumbnailPath = generateThumbnailPath(originalPath);
-                
-                // 鐢熸垚缂╃暐鍥�
-                if (createThumbnail(originalPath, thumbnailPath, 100, 0)) {
-                    uploadResponse.setThumbnailPath(thumbnailPath);
-                    log.info("缂╃暐鍥剧敓鎴愭垚鍔燂細{}", thumbnailPath);
-                } else {
-                    log.warn("缂╃暐鍥剧敓鎴愬け璐ワ細{}", originalPath);
-                }
-            }
-            
+            log.info("涓婁紶鏂囦欢鎴愬姛 鏂囦欢:{} 缂╃暐:{}",uploadResponse.getFilePath(),uploadResponse.getThumbnailPath());
             return uploadResponse;
             
         } catch (Exception e) {
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/imagedata/ImageDataServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/imagedata/ImageDataServiceImpl.java
index f98fe8a..6aa0a2a 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/imagedata/ImageDataServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/imagedata/ImageDataServiceImpl.java
@@ -223,10 +223,6 @@
             if (dispatchOrdID != null && dispatchOrdID > 0) {
                 return processDispatchOrderImage(dispatchOrdID, serviceOrdID, mediaId, imageTypeEnum, adminId);
             }
-            // 濡傛灉鍙湁OA鐢ㄦ埛ID锛屽垯鏇存柊鐢ㄦ埛澶村儚
-            else if (oaid != null && oaid > 0) {
-                return updateUserAvatar(oaid, mediaId);
-            }
             else {
                 return "鍙傛暟閿欒锛氱己灏戝繀瑕佺殑鍙傛暟";
             }
@@ -270,23 +266,6 @@
         }
     }
 
-    /**
-     * 鏇存柊鐢ㄦ埛澶村儚
-     */
-    private String updateUserAvatar(Integer oaid, String mediaId) {
-        try {
-            // 杩欓噷闇�瑕佽皟鐢∣A鐢ㄦ埛鏈嶅姟鏉ユ洿鏂板ご鍍�
-            // 鐢变簬娌℃湁OA鐢ㄦ埛鏈嶅姟鐨勫叿浣撳疄鐜帮紝杩欓噷鍙槸绀轰緥
-            String avatarUrl = "/upload/" + oaid + "_" + mediaId + ".jpg";
-
-            // TODO: 璋冪敤OA鐢ㄦ埛鏈嶅姟鏇存柊澶村儚
-            // oaUserService.updateAvatar(oaid, avatarUrl);
-
-            return "鐢ㄦ埛澶村儚鏇存柊鎴愬姛";
-        } catch (Exception e) {
-            return "鏇存柊鐢ㄦ埛澶村儚澶辫触锛�" + e.getMessage();
-        }
-    }
 
     /**
      * 鐢熸垚鍥剧墖URL
@@ -435,20 +414,7 @@
         }
     }
 
-    /**
-     * 鏇存柊鐢ㄦ埛澶村儚锛堝寘鍚枃浠禪RL锛�
-     */
-    private String updateUserAvatarWithFile(Integer oaid, String mediaId, String imageUrl) {
-        try {
-            // 杩欓噷闇�瑕佽皟鐢∣A鐢ㄦ埛鏈嶅姟鏉ユ洿鏂板ご鍍�
-            // TODO: 璋冪敤OA鐢ㄦ埛鏈嶅姟鏇存柊澶村儚
-            // oaUserService.updateAvatar(oaid, imageUrl);
-
-            return "鐢ㄦ埛澶村儚鏇存柊鎴愬姛锛孶RL锛�" + imageUrl;
-        } catch (Exception e) {
-            return "鏇存柊鐢ㄦ埛澶村儚澶辫触锛�" + e.getMessage();
-        }
-    }
+  
 
     /**
      * 妫�鏌ユ枃浠跺吋瀹规�э紙纭繚涓庢棫绯荤粺鍏煎锛�
@@ -529,9 +495,6 @@
                 ImageTypeEnum imageTypeEnum = ImageTypeEnum.getByCode(imageType);
                 return processDispatchOrderImageWithFiles(dispatchOrdID, serviceOrdID, null,
                         imageTypeEnum, adminId, imageUrl, thumbnailUrl);
-            } else if (oaid != null && oaid > 0) {
-                // OA鐢ㄦ埛澶村儚
-                return updateUserAvatarWithFile(oaid, null, imageUrl);
             } else {
                 return "鍙傛暟閿欒锛氱己灏戝繀瑕佺殑鍙傛暟锛堣皟搴﹀崟ID鎴朞A鐢ㄦ埛ID锛�";
             }
@@ -612,8 +575,6 @@
             if (dispatchOrdID != null && dispatchOrdID > 0) {
                 return processDispatchOrderImageWithFiles(dispatchOrdID, null, mediaId,
                         ImageTypeEnum.getByCode(imageType), adminId, originalImageUrl, thumbnailUrl);
-            } else if (oaid != null && oaid > 0) {
-                return updateUserAvatarWithFile(oaid, mediaId, originalImageUrl);
             }
 
             return "鍥剧墖涓婁紶鎴愬姛锛屾枃浠惰矾寰勶細" + originalImageUrl;
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskAttachmentMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskAttachmentMapper.java
index 69b7200..41f51ba 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskAttachmentMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskAttachmentMapper.java
@@ -41,7 +41,7 @@
      * @param sysTaskAttachment 浠诲姟闄勪欢
      * @return 缁撴灉
      */
-    public int insertSysTaskAttachment(SysTaskAttachment sysTaskAttachment);
+    public Long insertSysTaskAttachment(SysTaskAttachment sysTaskAttachment);
 
     /**
      * 淇敼浠诲姟闄勪欢
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 de3a1c3..7de29d3 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
@@ -99,7 +99,7 @@
      * @param category 闄勪欢鍒嗙被
      * @return 缁撴灉
      */
-    public int uploadAttachment(Long taskId, MultipartFile file, String category);
+    public Long uploadAttachment(Long taskId, MultipartFile file, String category);
     
     /**
      * 浠庡井淇ediaId涓婁紶浠诲姟闄勪欢
@@ -108,9 +108,9 @@
      * @param accessToken 寰俊AccessToken
      * @param mediaId 寰俊mediaId
      * @param category 闄勪欢鍒嗙被
-     * @return 缁撴灉
+     * @return
      */
-    public int uploadAttachmentFromWechat(Long taskId, String accessToken, String mediaId, String category);
+    public Long uploadAttachmentFromWechat(Long taskId, String accessToken, String mediaId, String category);
 
     /**
      * 鍒犻櫎浠诲姟闄勪欢
@@ -128,6 +128,8 @@
      */
     public SysTaskAttachment getAttachmentById(Long attachmentId);
 
+
+    public List<SysTaskAttachment> getAttachmentsByTaskId(Long taskId);
     /**
      * 鍒嗛厤杞﹁締缁欎换鍔�
      * 
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ITaskAttachmentSyncService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ITaskAttachmentSyncService.java
new file mode 100644
index 0000000..fc2545e
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ITaskAttachmentSyncService.java
@@ -0,0 +1,36 @@
+package com.ruoyi.system.service;
+
+import com.ruoyi.system.domain.SysTaskAttachment;
+
+import java.util.List;
+
+/**
+ * 浠诲姟闄勪欢鍚屾鏈嶅姟鎺ュ彛
+ * 鐢ㄤ簬灏嗕换鍔¢檮浠跺悓姝ュ埌ImageData琛�
+ * 
+ * @author ruoyi
+ */
+public interface ITaskAttachmentSyncService {
+    
+    /**
+     * 鍚屾鍗曚釜闄勪欢鍒癐mageData
+     * 
+     * @param attachment 浠诲姟闄勪欢瀵硅薄
+     * @param serviceOrderId 鏈嶅姟鍗旾D
+     * @param dispatchOrdId 璋冨害鍗旾D
+     * @return 鏄惁鍚屾鎴愬姛
+     */
+    Long syncAttachmentToImageData(SysTaskAttachment attachment, Long serviceOrderId, Long dispatchOrdId,Integer oaUserId);
+    
+    /**
+     * 鎵归噺鍚屾浠诲姟鐨勬墍鏈夐檮浠跺埌ImageData
+     * 
+     * @param attachmentList 浠诲姟鍒楄〃
+     * @param serviceOrderId 鏈嶅姟鍗旾D
+     * @param dispatchOrdId 璋冨害鍗旾D
+     * @return 鍚屾鎴愬姛鐨勯檮浠舵暟閲�
+     */
+    List<SysTaskAttachment> syncTaskAttachmentsToImageData(List<SysTaskAttachment> attachmentList, Long serviceOrderId, Long dispatchOrdId, Integer oaUserId);
+    
+
+}
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 612d67a..db1fa94 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
@@ -12,6 +12,9 @@
 import java.util.List;
 import java.util.Map;
 
+import com.ruoyi.system.domain.*;
+import com.ruoyi.system.service.*;
+import com.ruoyi.system.task.ITaskAttachmentService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -22,11 +25,6 @@
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.core.domain.entity.SysUser;
 import com.ruoyi.common.core.domain.entity.SysDept;
-import com.ruoyi.system.domain.SysTask;
-import com.ruoyi.system.domain.SysTaskEmergency;
-import com.ruoyi.system.domain.SysTaskVehicle;
-import com.ruoyi.system.domain.SysTaskAssignee;
-import com.ruoyi.system.domain.VehicleInfo;
 import com.ruoyi.system.domain.vo.TaskCreateVO;
 import com.ruoyi.system.mapper.SysTaskMapper;
 import com.ruoyi.system.mapper.SysTaskEmergencyMapper;
@@ -35,10 +33,7 @@
 import com.ruoyi.system.mapper.VehicleInfoMapper;
 import com.ruoyi.system.mapper.SysUserMapper;
 import com.ruoyi.system.mapper.SysDeptMapper;
-import com.ruoyi.system.service.ILegacySystemSyncService;
 import com.ruoyi.system.utils.TaskStatusConverter;
-import com.ruoyi.system.service.IDispatchOrdService;
-import com.ruoyi.system.service.ISysTaskEmergencyService;
 
 /**
  * 鏃х郴缁熷悓姝ervice涓氬姟灞傚鐞�
@@ -77,6 +72,15 @@
     
     @Autowired
     private ISysTaskEmergencyService sysTaskEmergencyService;
+
+    @Autowired
+    private ITaskAttachmentSyncService taskAttachmentSyncService;
+
+    @Autowired
+    private ISysTaskService sysTaskService;
+
+    @Autowired
+    private ITaskAttachmentService taskAttachmentService;
     
     /**
      * 鍚屾鎬ユ晳杞繍浠诲姟鍒版棫绯荤粺
@@ -265,7 +269,27 @@
             return false;
         }
     }
-    
+
+
+    /**
+     * 鍚屾浠诲姟闄勪欢鍒版棫绯荤粺
+     * @param taskAttachments
+     * @param serviceOrdId
+     * @param dispatchOrdId
+     * @param oaUserID
+     */
+    public void syncAttachmentToLegacy(List<SysTaskAttachment> taskAttachments, Long serviceOrdId,Long dispatchOrdId,Integer oaUserID) {
+        taskAttachments.forEach((taskAttachment)->{
+            Long imageDataId=  taskAttachmentSyncService.syncAttachmentToImageData(taskAttachment,serviceOrdId,dispatchOrdId,oaUserID);
+            if (imageDataId != null && imageDataId > 0) {
+
+                taskAttachment.setSyncedToImageData(1);
+                taskAttachment.setSyncTime(new Date());
+                taskAttachment.setImageDataId(imageDataId);
+                taskAttachmentService.updateAttachment(taskAttachment);
+            }
+        });
+    }
     /**
      * 鍚屾璋冨害鍗曞埌鏃х郴缁燂紙admin_save_24.asp锛�
      */
@@ -303,16 +327,23 @@
                 log.info("璋冨害鍗曞凡鍚屾杩囷紝浠诲姟ID: {}, DispatchOrdID: {}", taskId, emergency.getLegacyDispatchOrdId());
                 return emergency.getLegacyDispatchOrdId();
             }
-            
+
+            Long serviceOrdId=emergency.getLegacyServiceOrdId();
             // 蹇呴』鍏堝悓姝ユ湇鍔″崟
-            if (emergency.getLegacyServiceOrdId() == null || emergency.getLegacyServiceOrdId() <= 0) {
+            if (serviceOrdId == null || serviceOrdId <= 0) {
                 log.warn("鏈嶅姟鍗曟湭鍚屾锛屾棤娉曞悓姝ヨ皟搴﹀崟锛屼换鍔D: {}", taskId);
                 return null;
             }
-            
+
+
+
+
             // 鏇存柊鍚屾鐘舵�佷负鍚屾涓�
             emergency.setDispatchSyncStatus(1);
             sysTaskEmergencyService.updateSysTaskEmergency(emergency);
+
+            SysUser u=sysUserMapper.selectUserById(task.getCreatorId());
+            Integer oaUserID= u.getOaUserId();
             
             // 鏋勫缓璇锋眰鍙傛暟
             Map<String, String> params = buildDispatchOrderParams(task, emergency);
@@ -330,7 +361,13 @@
                 emergency.setDispatchSyncTime(new Date());
                 emergency.setDispatchSyncErrorMsg(null);
                 sysTaskEmergencyService.updateSysTaskEmergency(emergency);
-                
+
+                List<SysTaskAttachment> taskAttachments= sysTaskService.getAttachmentsByTaskId(taskId);
+                if (taskAttachments != null && !taskAttachments.isEmpty()) {
+                    //鍚屾闄勪欢
+                   this.syncAttachmentToLegacy(taskAttachments,serviceOrdId,dispatchOrdId,oaUserID);
+                }
+
                 log.info("璋冨害鍗曞悓姝ユ垚鍔燂紝浠诲姟ID: {}, DispatchOrdID: {}", taskId, dispatchOrdId);
                 return dispatchOrdId;
             } else {
@@ -395,6 +432,7 @@
                 for (SysTaskEmergency emergency : pendingTasks) {
                     log.info("寮�濮嬪悓姝ヨ皟搴﹀崟锛屼换鍔D: {}", emergency.getTaskId());
                     Long dispatchOrdId = syncDispatchOrderToLegacy(emergency.getTaskId());
+
                     if (dispatchOrdId != null && dispatchOrdId > 0) {
                         pageSuccessCount++;
                     }
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 56a2244..593f13c 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
@@ -1,6 +1,7 @@
 package com.ruoyi.system.service.impl;
 
 import java.math.BigDecimal;
+import java.util.Collections;
 import java.util.Date;
 import java.util.List;
 import java.util.ArrayList;
@@ -12,7 +13,10 @@
 import java.net.HttpURLConnection;
 import java.net.URL;
 
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.system.mapper.*;
 import com.ruoyi.system.utils.TaskCodeGenerator;
+import com.ruoyi.common.config.ImageUrlConfig;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -35,20 +39,15 @@
 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.mapper.SysTaskMapper;
-import com.ruoyi.system.mapper.SysTaskVehicleMapper;
-import com.ruoyi.system.mapper.SysTaskAttachmentMapper;
-import com.ruoyi.system.mapper.SysTaskLogMapper;
-import com.ruoyi.system.mapper.SysTaskEmergencyMapper;
-import com.ruoyi.system.mapper.SysTaskWelfareMapper;
-import com.ruoyi.system.mapper.SysTaskAssigneeMapper;
-import com.ruoyi.system.mapper.VehicleInfoMapper;
 import com.ruoyi.system.domain.VehicleInfo;
 import com.ruoyi.system.service.ISysTaskService;
 import com.ruoyi.system.service.ILegacySystemSyncService;
+import com.ruoyi.system.service.ITaskAttachmentSyncService;
 import com.ruoyi.system.event.TaskCreatedEvent;
 import com.ruoyi.system.event.TaskAssignedEvent;
 import com.ruoyi.system.event.TaskStatusChangedEvent;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.ApplicationEventPublisher;
 
@@ -60,6 +59,8 @@
  */
 @Service
 public class SysTaskServiceImpl implements ISysTaskService {
+    
+    private static final Logger log = LoggerFactory.getLogger(SysTaskServiceImpl.class);
     
     @Autowired
     private SysTaskMapper sysTaskMapper;
@@ -90,6 +91,15 @@
     
     @Autowired
     private ApplicationEventPublisher eventPublisher;
+    
+    @Autowired
+    private ImageUrlConfig imageUrlConfig;
+    
+    @Autowired(required = false)
+    private ITaskAttachmentSyncService taskAttachmentSyncService;
+
+    @Autowired
+    private SysUserMapper sysUserMapper;
 
     /**
      * 鏌ヨ浠诲姟绠$悊
@@ -505,23 +515,23 @@
      */
     @Override
     @Transactional
-    public int uploadAttachment(Long taskId, MultipartFile file, String category) {
+    public Long uploadAttachment(Long taskId, MultipartFile file, String category) {
         try {
-            // 涓婁紶鏂囦欢
+            // 涓婁紶鏂囦欢锛岃繑鍥炵浉瀵硅矾寰勶紙濡傦細/task/2025/01/15/xxx.jpg锛�
             String fileName = FileUploadUtils.upload("/task", file);
-            String filePath = FileUploadUtils.getDefaultBaseDir() + fileName;
             
             SysTaskAttachment attachment = new SysTaskAttachment();
             attachment.setTaskId(taskId);
             attachment.setFileName(file.getOriginalFilename());
-            attachment.setFilePath(filePath);
+            // 淇濆瓨鐩稿璺緞锛屼笉鍖呭惈 baseDir
+            attachment.setFilePath(fileName);
             attachment.setFileSize(file.getSize());
             attachment.setFileType(getFileType(file.getOriginalFilename()));
             attachment.setAttachmentCategory(category);
             attachment.setUploadTime(DateUtils.getNowDate());
             attachment.setUploadBy(SecurityUtils.getUsername());
             
-            int result = sysTaskAttachmentMapper.insertSysTaskAttachment(attachment);
+            Long result = sysTaskAttachmentMapper.insertSysTaskAttachment(attachment);
             
             // 璁板綍鎿嶄綔鏃ュ織
             if (result > 0) {
@@ -529,6 +539,8 @@
                 recordTaskLog(taskId, "UPDATE", "涓婁紶闄勪欢", null, 
                              "涓婁紶鏂囦欢锛�" + file.getOriginalFilename() + "(鍒嗙被锛�" + categoryDesc + ")", 
                              SecurityUtils.getUserId(), SecurityUtils.getUsername());
+                
+
             }
             
             return result;
@@ -544,11 +556,11 @@
      * @param accessToken 寰俊AccessToken
      * @param mediaId 寰俊mediaId
      * @param category 闄勪欢鍒嗙被
-     * @return 缁撴灉
+     * @return 杩斿洖闄勪欢ID
      */
     @Override
     @Transactional
-    public int uploadAttachmentFromWechat(Long taskId, String accessToken, String mediaId, String category) {
+    public Long uploadAttachmentFromWechat(Long taskId, String accessToken, String mediaId, String category) {
         try {
             // 浠庡井淇℃湇鍔″櫒涓嬭浇鏂囦欢
             String wechatUrl = String.format(
@@ -582,18 +594,22 @@
                 fos.write(fileBytes);
             }
             
+            // 鐢熸垚鐩稿璺緞锛堜笉鍖呭惈baseDir锛�
+            String relativeFilePath = "/task/" + datePath + "/" + fileName;
+            
             // 淇濆瓨闄勪欢璁板綍
             SysTaskAttachment attachment = new SysTaskAttachment();
             attachment.setTaskId(taskId);
             attachment.setFileName(fileName);
-            attachment.setFilePath(filePath);
+            // 淇濆瓨鐩稿璺緞
+            attachment.setFilePath(relativeFilePath);
             attachment.setFileSize((long) fileBytes.length);
             attachment.setFileType("jpg");
             attachment.setAttachmentCategory(category);
             attachment.setUploadTime(DateUtils.getNowDate());
             attachment.setUploadBy(SecurityUtils.getUsername());
             
-            int result = sysTaskAttachmentMapper.insertSysTaskAttachment(attachment);
+            Long result = sysTaskAttachmentMapper.insertSysTaskAttachment(attachment);
             
             // 璁板綍鎿嶄綔鏃ュ織
             if (result > 0) {
@@ -601,9 +617,11 @@
                 recordTaskLog(taskId, "UPDATE", "涓婁紶闄勪欢", null, 
                              "閫氳繃寰俊涓婁紶鏂囦欢锛�" + fileName + "(鍒嗙被锛�" + categoryDesc + ")", 
                              SecurityUtils.getUserId(), SecurityUtils.getUsername());
+                
+
             }
             
-            return result;
+            return attachment.getAttachmentId();
         } catch (Exception e) {
             throw new RuntimeException("浠庡井淇′笂浼犳枃浠跺け璐ワ細" + e.getMessage());
         }
@@ -675,7 +693,17 @@
      */
     @Override
     public SysTaskAttachment getAttachmentById(Long attachmentId) {
-        return sysTaskAttachmentMapper.selectSysTaskAttachmentByAttachmentId(attachmentId);
+        SysTaskAttachment attachment = sysTaskAttachmentMapper.selectSysTaskAttachmentByAttachmentId(attachmentId);
+        if (attachment != null) {
+            // 鎷兼帴瀹屾暣URL
+            buildAttachmentUrl(attachment);
+        }
+        return attachment;
+    }
+
+    @Override
+    public List<SysTaskAttachment> getAttachmentsByTaskId(Long taskId) {
+        return sysTaskAttachmentMapper.selectSysTaskAttachmentByTaskId(taskId);
     }
 
     /**
@@ -876,7 +904,12 @@
             // 鏌ヨ鍏宠仈杞﹁締
             task.setAssignedVehicles(sysTaskVehicleMapper.selectSysTaskVehicleByTaskId(taskId));
             // 鏌ヨ闄勪欢
-            task.setAttachments(sysTaskAttachmentMapper.selectSysTaskAttachmentByTaskId(taskId));
+            List<SysTaskAttachment> attachments = sysTaskAttachmentMapper.selectSysTaskAttachmentByTaskId(taskId);
+            // 涓烘瘡涓檮浠舵嫾鎺ュ畬鏁碪RL
+            if (attachments != null && !attachments.isEmpty()) {
+                attachments.forEach(this::buildAttachmentUrl);
+            }
+            task.setAttachments(attachments);
             // 鏌ヨ鎿嶄綔鏃ュ織
             task.setOperationLogs(sysTaskLogMapper.selectSysTaskLogByTaskId(taskId));
             // 鍔犺浇鎬ユ晳杞繍鎵╁睍淇℃伅
@@ -1191,4 +1224,24 @@
             default: return "鍏朵粬";
         }
     }
+    
+    /**
+     * 鏋勫缓闄勪欢鐨勫畬鏁碪RL
+     * 
+     * @param attachment 闄勪欢瀵硅薄
+     */
+    private void buildAttachmentUrl(SysTaskAttachment attachment) {
+        if (attachment != null && StringUtils.isNotEmpty(attachment.getFilePath())) {
+            String imageUrl = imageUrlConfig.getImageUrl();
+            if (StringUtils.isNotEmpty(imageUrl)) {
+                // 鎷兼帴瀹屾暣URL锛氬煙鍚� + 鐩稿璺緞
+                attachment.setFileUrl(imageUrl + attachment.getFilePath());
+            } else {
+                // 濡傛灉鏈厤缃煙鍚嶏紝鐩存帴浣跨敤鐩稿璺緞
+                attachment.setFileUrl(attachment.getFilePath());
+            }
+        }
+    }
+    
+   
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TaskAttachmentSyncServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TaskAttachmentSyncServiceImpl.java
new file mode 100644
index 0000000..4b4ea83
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TaskAttachmentSyncServiceImpl.java
@@ -0,0 +1,204 @@
+package com.ruoyi.system.service.impl;
+
+import com.ruoyi.common.annotation.DataSource;
+import com.ruoyi.common.config.LegacySystemConfig;
+import com.ruoyi.common.config.RuoYiConfig;
+import com.ruoyi.common.enums.DataSourceType;
+import com.ruoyi.system.domain.ImageData;
+import com.ruoyi.system.domain.SysTaskAttachment;
+import com.ruoyi.system.file.FileUploadResponse;
+import com.ruoyi.system.file.IFileUploadService;
+import com.ruoyi.system.imagedata.IImageDataService;
+import com.ruoyi.system.mapper.SysTaskAttachmentMapper;
+import com.ruoyi.system.service.ITaskAttachmentSyncService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.StringUtils;
+
+import java.io.File;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 浠诲姟闄勪欢鍚屾鏈嶅姟瀹炵幇
+ * 灏嗕换鍔¢檮浠跺悓姝ュ埌ImageData琛�
+ * 
+ * @author ruoyi
+ */
+@Service
+@DataSource(DataSourceType.SQLSERVER)
+public class TaskAttachmentSyncServiceImpl implements ITaskAttachmentSyncService {
+    
+    private static final Logger log = LoggerFactory.getLogger(TaskAttachmentSyncServiceImpl.class);
+    
+
+    @Autowired
+    private IImageDataService imageDataService;
+    
+    @Autowired
+    private LegacySystemConfig legacyConfig;
+    
+    @Autowired
+    private IFileUploadService fileUploadService;
+    
+    @Autowired
+    private RuoYiConfig ruoYiConfig;
+
+
+    
+    /**
+     * 鍚屾鍗曚釜闄勪欢鍒癐mageData
+     */
+    @Override
+    public Long syncAttachmentToImageData(SysTaskAttachment attachment, Long serviceOrderId, Long dispatchOrdId,Integer oaUserId) {
+        if (attachment == null) {
+            log.error("闄勪欢瀵硅薄涓虹┖锛屾棤娉曞悓姝�");
+            return 0L;
+        }
+        
+        // 妫�鏌ユ槸鍚﹀凡鍚屾
+        if (attachment.getSyncedToImageData() != null && attachment.getSyncedToImageData() == 1) {
+            log.info("闄勪欢ID={} 宸插悓姝ワ紝璺宠繃", attachment.getAttachmentId());
+            return 0L;
+        }
+        
+        // 妫�鏌ュ繀瑕佸弬鏁�
+        if (dispatchOrdId == null || serviceOrderId == null) {
+            log.error("璋冨害鍗旾D鍜屾湇鍔″崟ID閮戒负绌猴紝鏃犳硶鍚屾闄勪欢ID={}", attachment.getAttachmentId());
+            return 0L;
+        }
+        
+        try {
+            // 鑾峰彇闄勪欢鍒嗙被瀵瑰簲鐨処mageType
+            Integer imageType = getImageTypeByCategory(attachment.getAttachmentCategory());
+            
+            // 鑾峰彇闄勪欢鏈湴鏂囦欢璺緞
+            String filePath = attachment.getFilePath();
+            if (!StringUtils.hasText(filePath)) {
+                log.error("闄勪欢ID={} 鐨勬枃浠惰矾寰勪负绌�", attachment.getAttachmentId());
+                return 0L;
+            }
+            
+            // 鏋勫缓瀹屾暣鐨勬湰鍦版枃浠惰矾寰�
+            String fullFilePath = ruoYiConfig.getProfile() + filePath;
+            File file = new File(fullFilePath);
+            
+            if (!file.exists()) {
+                log.error("闄勪欢ID={} 瀵瑰簲鐨勬枃浠朵笉瀛樺湪: {}", attachment.getAttachmentId(), fullFilePath);
+                return 0L;
+            }
+            
+            // 鐢熸垚鐩爣璺緞锛堜娇鐢╠ispatchOrdId浣滀负鐩綍锛�
+            String targetPath = dispatchOrdId != null ? dispatchOrdId.toString() : "default";
+            
+            // 浣跨敤鏂囦欢涓婁紶鏈嶅姟涓婁紶鍒版枃浠舵湇鍔″櫒锛堝寘鍚缉鐣ュ浘鐢熸垚锛�
+            log.info("寮�濮嬩笂浼犻檮浠禝D={} 鍒版枃浠舵湇鍔″櫒锛岀洰鏍囪矾寰�={}", attachment.getAttachmentId(), targetPath);
+            FileUploadResponse uploadResponse = fileUploadService.uploadLocalFileWithThumbnail(file, targetPath);
+            
+            if (!uploadResponse.isSuccess()) {
+                log.error("闄勪欢ID={} 涓婁紶鍒版枃浠舵湇鍔″櫒澶辫触: {}", attachment.getAttachmentId(), uploadResponse.getMessage());
+                return 0L;
+            }
+            
+            log.info("闄勪欢ID={} 涓婁紶鎴愬姛锛屽師鍥捐矾寰�={}, 缂╃暐鍥捐矾寰�={}", 
+                attachment.getAttachmentId(), uploadResponse.getFilePath(), uploadResponse.getThumbnailPath());
+            
+            // 鍒涘缓ImageData瀵硅薄
+            ImageData imageData = new ImageData();
+            imageData.setDOrdIDDt(dispatchOrdId);
+            imageData.setSOrdIDDt(serviceOrderId);
+            imageData.setImageType(imageType);
+            imageData.setImageUrl(uploadResponse.getFilePath());
+            imageData.setImageUrls(uploadResponse.getThumbnailPath()); // 缂╃暐鍥捐矾寰�
+            imageData.setUpImageTime(attachment.getUploadTime() != null ? attachment.getUploadTime() : new Date());
+            imageData.setUpImageOAid(oaUserId);
+            imageData.setImageDel(0);
+            
+            // 鎻掑叆ImageData
+            int result = imageDataService.insertImageData(imageData);
+            
+            if (result > 0) {                
+                
+                log.info("鎴愬姛鍚屾闄勪欢ID={} 鍒癐mageData锛孖mageDataId={}", 
+                    attachment.getAttachmentId(), imageData.getId());
+                return imageData.getId();
+            } else {
+                log.error("鍚屾闄勪欢ID={} 鍒癐mageData澶辫触", attachment.getAttachmentId());
+                return 0L;
+            }
+            
+        } catch (Exception e) {
+            log.error("鍚屾闄勪欢ID={} 鍒癐mageData鏃跺彂鐢熷紓甯�", attachment.getAttachmentId(), e);
+            return 0L;
+        }
+    }
+    
+    /**
+     * 鎵归噺鍚屾浠诲姟鐨勬墍鏈夐檮浠跺埌ImageData
+     */
+    @Override
+    public List<SysTaskAttachment> syncTaskAttachmentsToImageData(List<SysTaskAttachment> attachments, Long serviceOrderId, Long dispatchOrdId,Integer oaUserId) {
+
+
+        if (attachments == null || attachments.isEmpty()) {
+            log.info("娌℃湁闄勪欢锛屾棤闇�鍚屾");
+            return null;
+        }
+
+        int successCount = 0;
+        for (SysTaskAttachment attachment : attachments) {
+            Long imageDataId = syncAttachmentToImageData(attachment, serviceOrderId, dispatchOrdId,oaUserId);
+            if (imageDataId>0)
+            {
+                attachment.setSyncedToImageData(1);
+                attachment.setSyncTime(new Date());
+                attachment.setImageDataId(imageDataId);
+                successCount++;
+            }
+        }
+        
+        log.info(" 鍏卞悓姝� {}/{} 涓檮浠跺埌ImageData",
+             successCount, attachments.size());
+        
+        return null;
+    }
+    
+
+    
+    /**
+     * 鏍规嵁闄勪欢鍒嗙被鑾峰彇瀵瑰簲鐨処mageType
+     * 
+     * 闄勪欢鍒嗙被鏄犲皠锛�
+     * 1-鐭ユ儏鍚屾剰涔� -> 0
+     * 2-鐥呬汉璧勬枡 -> 1
+     * 3-鎿嶄綔璁板綍 -> 2
+     * 4-鍑鸿溅鍓� -> 3
+     * 5-鍑鸿溅鍚� -> 4
+     * 6-绯诲畨鍏ㄥ甫 -> 5
+     */
+    private Integer getImageTypeByCategory(String category) {
+        if (category == null) {
+            return 1;
+        }
+        
+        switch (category) {
+            case "1": // 鐭ユ儏鍚屾剰涔�
+                return 1;
+            case "2": // 鐥呬汉璧勬枡
+                return 2;
+            case "3": // 鎿嶄綔璁板綍
+                return 3;
+            case "4": // 鍑鸿溅鍓�
+                return 4;
+            case "5": // 鍑鸿溅鍚�
+                return 5;
+            case "6": // 绯诲畨鍏ㄥ甫
+                return 6;
+            default:
+                return 1;
+        }
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/task/ITaskAttachmentService.java b/ruoyi-system/src/main/java/com/ruoyi/system/task/ITaskAttachmentService.java
new file mode 100644
index 0000000..20176e8
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/task/ITaskAttachmentService.java
@@ -0,0 +1,9 @@
+package com.ruoyi.system.task;
+
+import com.ruoyi.system.domain.SysTaskAttachment;
+
+public interface ITaskAttachmentService {
+    boolean isAttachmentSynced(Long taskId);
+
+    boolean updateAttachment(SysTaskAttachment attachment);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/task/TaskAttachmentServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/task/TaskAttachmentServiceImpl.java
new file mode 100644
index 0000000..a9a2a8b
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/task/TaskAttachmentServiceImpl.java
@@ -0,0 +1,35 @@
+package com.ruoyi.system.task;
+
+import com.ruoyi.system.domain.SysTaskAttachment;
+import com.ruoyi.system.mapper.SysTaskAttachmentMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class TaskAttachmentServiceImpl implements ITaskAttachmentService{
+
+    @Autowired
+    private SysTaskAttachmentMapper taskAttachmentMapper;
+
+    /**
+     * 妫�鏌ラ檮浠舵槸鍚﹀凡鍚屾
+     */
+    @Override
+    public boolean isAttachmentSynced(Long attachmentId) {
+        if (attachmentId == null) {
+            return false;
+        }
+
+        SysTaskAttachment attachment = taskAttachmentMapper.selectSysTaskAttachmentByAttachmentId(attachmentId);
+        if (attachment == null) {
+            return false;
+        }
+
+        return attachment.getSyncedToImageData() != null && attachment.getSyncedToImageData() == 1;
+    }
+
+    @Override
+    public boolean updateAttachment(SysTaskAttachment attachment) {
+        return taskAttachmentMapper.updateSysTaskAttachment(attachment) > 0;
+    }
+}
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysTaskAttachmentMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysTaskAttachmentMapper.xml
index 49220e7..05a426a 100644
--- a/ruoyi-system/src/main/resources/mapper/system/SysTaskAttachmentMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/SysTaskAttachmentMapper.xml
@@ -14,10 +14,13 @@
         <result property="attachmentCategory" column="attachment_category" />
         <result property="uploadTime"       column="upload_time"       />
         <result property="uploadBy"         column="upload_by"         />
+        <result property="syncedToImageData" column="synced_to_image_data" />
+        <result property="syncTime"         column="sync_time"         />
+        <result property="imageDataId"      column="image_data_id"     />
     </resultMap>
 
     <sql id="selectSysTaskAttachmentVo">
-        select attachment_id, task_id, file_name, file_path, file_size, file_type, attachment_category, upload_time, upload_by 
+        select attachment_id, task_id, file_name, file_path, file_size, file_type, attachment_category, upload_time, upload_by, synced_to_image_data, sync_time, image_data_id
         from sys_task_attachment
     </sql>
 
@@ -55,6 +58,9 @@
             <if test="attachmentCategory != null and attachmentCategory != ''">attachment_category,</if>
             <if test="uploadTime != null">upload_time,</if>
             <if test="uploadBy != null and uploadBy != ''">upload_by,</if>
+            <if test="syncedToImageData != null">synced_to_image_data,</if>
+            <if test="syncTime != null">sync_time,</if>
+            <if test="imageDataId != null">image_data_id,</if>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="taskId != null">#{taskId},</if>
@@ -65,6 +71,9 @@
             <if test="attachmentCategory != null and attachmentCategory != ''">#{attachmentCategory},</if>
             <if test="uploadTime != null">#{uploadTime},</if>
             <if test="uploadBy != null and uploadBy != ''">#{uploadBy},</if>
+            <if test="syncedToImageData != null">#{syncedToImageData},</if>
+            <if test="syncTime != null">#{syncTime},</if>
+            <if test="imageDataId != null">#{imageDataId},</if>
          </trim>
     </insert>
 
@@ -79,6 +88,9 @@
             <if test="attachmentCategory != null and attachmentCategory != ''">attachment_category = #{attachmentCategory},</if>
             <if test="uploadTime != null">upload_time = #{uploadTime},</if>
             <if test="uploadBy != null and uploadBy != ''">upload_by = #{uploadBy},</if>
+            <if test="syncedToImageData != null">synced_to_image_data = #{syncedToImageData},</if>
+            <if test="syncTime != null">sync_time = #{syncTime},</if>
+            <if test="imageDataId != null">image_data_id = #{imageDataId},</if>
         </trim>
         where attachment_id = #{attachmentId}
     </update>
diff --git a/sql/update_sys_task_attachment_sync_fields.sql b/sql/update_sys_task_attachment_sync_fields.sql
new file mode 100644
index 0000000..1364cb7
--- /dev/null
+++ b/sql/update_sys_task_attachment_sync_fields.sql
@@ -0,0 +1,16 @@
+-- 涓簊ys_task_attachment琛ㄦ坊鍔犲悓姝ョ浉鍏冲瓧娈�
+-- 鐢ㄤ簬灏嗕换鍔¢檮浠跺悓姝ュ埌ImageData琛�
+
+-- 娣诲姞鏄惁宸插悓姝ュ埌ImageData瀛楁
+ALTER TABLE sys_task_attachment ADD COLUMN synced_to_image_data TINYINT(1) DEFAULT 0 COMMENT '鏄惁宸插悓姝ュ埌ImageData (0-鏈悓姝� 1-宸插悓姝�)';
+
+-- 娣诲姞鍚屾鏃堕棿瀛楁
+ALTER TABLE sys_task_attachment ADD COLUMN sync_time DATETIME COMMENT '鍚屾鏃堕棿';
+
+-- 娣诲姞鍏宠仈鐨処mageData ID瀛楁
+ALTER TABLE sys_task_attachment ADD COLUMN image_data_id BIGINT COMMENT '鍏宠仈鐨処mageData琛ㄧ殑ID';
+
+-- 娣诲姞绱㈠紩浠ユ彁楂樻煡璇㈡�ц兘
+CREATE INDEX idx_synced_to_image_data ON sys_task_attachment(synced_to_image_data);
+CREATE INDEX idx_image_data_id ON sys_task_attachment(image_data_id);
+CREATE INDEX idx_task_id_synced ON sys_task_attachment(task_id, synced_to_image_data);

--
Gitblit v1.9.1