wlzboy
2025-11-09 13a31edf7f569cdcf15d3c43a476a2c947f47fbf
app/pages/task/detail.vue
@@ -195,33 +195,13 @@
      </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="任务附件"
        :readonly="isTaskFinished"
        @uploaded="onAttachmentUploaded"
        @deleted="onAttachmentDeleted"
      />
      
      <!-- 福祉车任务特有信息 -->
      <view class="detail-section" v-if="taskDetail.taskType === 'WELFARE' && taskDetail.welfareInfo">
@@ -343,69 +323,32 @@
      
      <!-- 已完成/已取消: 不显示按钮 -->
    </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: {
      // 判断任务是否已结束(已完成或已取消)
      isTaskFinished() {
        if (!this.taskDetail || !this.taskDetail.taskStatus) {
          return false
        }
        return ['COMPLETED', 'CANCELLED'].includes(this.taskDetail.taskStatus)
      },
      // 显示任务类型
      displayTaskType() {
        if (!this.taskDetail || !this.taskDetail.taskType) {
@@ -464,12 +407,6 @@
    onLoad(options) {
      this.taskId = options.id
      this.loadTaskDetail()
      this.loadAttachmentList()
      // 检测是否是微信小程序环境
      // #ifdef MP-WEIXIN
      this.isWechatMiniProgram = true
      // #endif
    },
    methods: {
      // 加载任务详情
@@ -923,6 +860,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 +985,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 +1036,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;
          }
        }
      }
    }