gaoluyang
2025-12-29 bbdd646b82cb8c84079598b7200b1102fd247b28
src/pages/inspectionUpload/components/formDia.vue
@@ -1,6 +1,6 @@
<template>
  <u-popup 
    v-model="dialogVisitable"
    :show="dialogVisitable"
    mode="center" 
    :round="10"
    :closeable="true"
@@ -14,47 +14,68 @@
      <view class="upload-container">
        <view class="form-container">
          <view class="title">生产前</view>
          <u-upload
            :fileList="beforeModelValue"
            @afterRead="afterRead"
            @delete="deleteFile"
            name="before"
            multiple
            :maxCount="10"
            :maxSize="1024 * 1024"
            accept="video/*"
            :previewFullImage="true"
          ></u-upload>
          <view class="upload-buttons">
            <u-button type="primary" size="small" @click="chooseVideo('before')" :disabled="beforeModelValue.length >= 10">
              <u-icon name="video" size="16" color="#fff" style="margin-right: 5px;"></u-icon>
              选择视频
            </u-button>
            <text class="file-count">{{ beforeModelValue.length }}/10</text>
          </view>
          <view class="file-list" v-if="beforeModelValue.length > 0">
            <view v-for="(file, index) in beforeModelValue" :key="index" class="file-item">
              <text class="file-name">视频{{ index + 1 }}</text>
              <u-button
                type="error"
                size="mini"
                :customStyle="{ minWidth: '120rpx', width: 'auto', padding: '0 20rpx', height: '60rpx' }"
                @click="deleteFile(index, 'before')"
              >删除</u-button>
            </view>
          </view>
        </view>
        
        <view class="form-container">
          <view class="title">生产后</view>
          <u-upload
            :fileList="afterModelValue"
            @afterRead="afterRead"
            @delete="deleteFile"
            name="after"
            multiple
            :maxCount="10"
            :maxSize="1024 * 1024"
            accept="video/*"
            :previewFullImage="true"
          ></u-upload>
          <view class="upload-buttons">
            <u-button type="primary" size="small" @click="chooseVideo('after')" :disabled="afterModelValue.length >= 10">
              <u-icon name="video" size="16" color="#fff" style="margin-right: 5px;"></u-icon>
              选择视频
            </u-button>
            <text class="file-count">{{ afterModelValue.length }}/10</text>
          </view>
          <view class="file-list" v-if="afterModelValue.length > 0">
            <view v-for="(file, index) in afterModelValue" :key="index" class="file-item">
              <text class="file-name">视频{{ index + 1 }}</text>
              <u-button
                type="error"
                size="mini"
                :customStyle="{ minWidth: '120rpx', width: 'auto', padding: '0 20rpx', height: '60rpx' }"
                @click="deleteFile(index, 'after')"
              >删除</u-button>
            </view>
          </view>
        </view>
        
        <view class="form-container">
          <view class="title">生产问题</view>
          <u-upload
            :fileList="issueModelValue"
            @afterRead="afterRead"
            @delete="deleteFile"
            name="issue"
            multiple
            :maxCount="10"
            :maxSize="1024 * 1024"
            accept="video/*"
            :previewFullImage="true"
          ></u-upload>
          <view class="upload-buttons">
            <u-button type="primary" size="small" @click="chooseVideo('issue')" :disabled="issueModelValue.length >= 10">
              <u-icon name="video" size="16" color="#fff" style="margin-right: 5px;"></u-icon>
              选择视频
            </u-button>
            <text class="file-count">{{ issueModelValue.length }}/10</text>
          </view>
          <view class="file-list" v-if="issueModelValue.length > 0">
            <view v-for="(file, index) in issueModelValue" :key="index" class="file-item">
              <text class="file-name">视频{{ index + 1 }}</text>
              <u-button
                type="error"
                size="mini"
                :customStyle="{ minWidth: '120rpx', width: 'auto', padding: '0 20rpx', height: '60rpx' }"
                @click="deleteFile(index, 'issue')"
              >删除</u-button>
            </view>
          </view>
        </view>
      </view>
      
@@ -67,10 +88,23 @@
</template>
<script setup>
import { ref } from 'vue'
import { ref, computed } from 'vue'
import { submitInspectionRecord } from '@/api/equipmentManagement/inspection.js'
import { getToken } from '@/utils/auth'
import config from '@/config.js'
const emit = defineEmits(['closeDia'])
// 上传接口URL
const uploadFileUrl = computed(() => {
  return config.baseUrl + '/common/minioUploads'
})
// 上传请求头
const uploadHeaders = computed(() => {
  const token = getToken()
  return token ? { Authorization: 'Bearer ' + token } : {}
})
const dialogVisitable = ref(false)
const beforeModelValue = ref([])
@@ -78,63 +112,171 @@
const issueModelValue = ref([])
const infoData = ref(null)
// 文件上传处理
const afterRead = (event) => {
  const { name, file } = event
// 选择视频
const chooseVideo = (type) => {
  const currentList = type === 'before' ? beforeModelValue : type === 'after' ? afterModelValue : issueModelValue;
  
  // 上传文件到服务器
  uni.uploadFile({
    url: '/api/upload', // 替换为实际的上传接口
    filePath: file.url,
    name: 'file',
  if (currentList.value.length >= 10) {
    uni.showToast({
      title: '最多只能选择10个视频',
      icon: 'none'
    });
    return;
  }
  uni.chooseVideo({
    sourceType: ['camera', 'album'],
    maxDuration: 60,
    camera: 'back',
    success: (res) => {
      const data = JSON.parse(res.data)
      if (data.code === 200) {
      try {
        if (!res.tempFilePath) {
          throw new Error('未获取到视频文件');
        }
        // 从临时路径中提取文件名,做为初始展示
        const tempName = res.tempFilePath.split('/').pop() || `video_${Date.now()}.mp4`
        const fileItem = {
          url: data.data.url,
          name: file.name,
          status: 'success'
        }
          url: res.tempFilePath,
          name: tempName,
          originalFilename: tempName,
          size: res.size || 0,
          duration: res.duration || 0,
          status: 'pending' // 待上传状态
        };
        
        // 根据name添加到对应的数组
        if (name === 'before') {
          beforeModelValue.value.push(fileItem)
        } else if (name === 'after') {
          afterModelValue.value.push(fileItem)
        } else if (name === 'issue') {
          issueModelValue.value.push(fileItem)
        }
        // 添加到对应的数组
        currentList.value.push(fileItem);
        
        // 自动上传
        uploadFile(fileItem, type, currentList.value.length - 1);
      } catch (error) {
        console.error('处理视频失败:', error);
        uni.showToast({
          title: '上传成功',
          icon: 'success'
        })
      } else {
        uni.showToast({
          title: '上传失败',
          title: '处理视频失败',
          icon: 'error'
        })
        });
      }
    },
    fail: () => {
    fail: (err) => {
      console.error('选择视频失败:', err);
      uni.showToast({
        title: '上传失败',
        title: '选择视频失败: ' + (err.errMsg || '未知错误'),
        icon: 'error'
      })
      });
    }
  })
  });
}
// 上传文件到服务器
const uploadFile = (fileItem, type, index) => {
  fileItem.status = 'uploading';
  // 确保token存在
  const token = getToken();
  if (!token) {
    fileItem.status = 'failed';
    uni.showToast({
      title: '用户未登录',
      icon: 'error'
    });
    return;
  }
  uni.uploadFile({
    url: uploadFileUrl.value,
    filePath: fileItem.url,
    name: 'files', // 注意:接口使用的是 'files' 而不是 'file'
    header: {
      'Authorization': `Bearer ${token}`
    },
    success: (res) => {
      try {
        if (res.statusCode === 200) {
          const response = typeof res.data === 'string' ? JSON.parse(res.data) : res.data;
          if (response.code === 200) {
            // 响应数据是数组格式,取第一个元素
            const uploadedFile = Array.isArray(response.data) ? response.data[0] : response.data;
            console.log('上传成功,返回的文件信息:', uploadedFile);
            console.log('原始文件名:', uploadedFile.originalFilename);
            // 更新文件信息 - 使用 Object.assign 确保响应式更新
            const displayName = uploadedFile.originalFilename
              || uploadedFile.bucketFilename
              || fileItem.name
              || '未命名文件';
            Object.assign(fileItem, {
              url: uploadedFile.url || uploadedFile.downloadUrl,
              status: 'success',
              id: uploadedFile.id,
              name: displayName,
              originalFilename: uploadedFile.originalFilename || displayName, // 保存原始文件名
              bucketFilename: uploadedFile.bucketFilename,
              downloadUrl: uploadedFile.downloadUrl || uploadedFile.url,
              size: uploadedFile.byteSize || fileItem.size,
              createTime: uploadedFile.createTime || new Date().getTime()
            });
            console.log('更新后的文件项:', fileItem);
            uni.showToast({
              title: '上传成功',
              icon: 'success'
            });
          } else {
            fileItem.status = 'failed';
            uni.showToast({
              title: response.msg || '上传失败',
              icon: 'error'
            });
          }
        } else {
          fileItem.status = 'failed';
          uni.showToast({
            title: `服务器错误,状态码: ${res.statusCode}`,
            icon: 'error'
          });
        }
      } catch (e) {
        fileItem.status = 'failed';
        console.error('解析响应失败:', e);
        console.error('原始响应数据:', res.data);
        uni.showToast({
          title: '解析响应失败',
          icon: 'error'
        });
      }
    },
    fail: (err) => {
      fileItem.status = 'failed';
      console.error('上传失败:', err);
      let errorMessage = '上传失败';
      if (err.errMsg) {
        if (err.errMsg.includes('statusCode: null')) {
          errorMessage = '网络连接失败,请检查网络设置';
        } else if (err.errMsg.includes('timeout')) {
          errorMessage = '上传超时,请重试';
        } else {
          errorMessage = err.errMsg;
        }
      }
      uni.showToast({
        title: errorMessage,
        icon: 'error'
      });
    }
  });
}
// 删除文件
const deleteFile = (event) => {
  const { name, index } = event
  if (name === 'before') {
    beforeModelValue.value.splice(index, 1)
  } else if (name === 'after') {
    afterModelValue.value.splice(index, 1)
  } else if (name === 'issue') {
    issueModelValue.value.splice(index, 1)
const deleteFile = (index, type) => {
  if (type === 'before') {
    beforeModelValue.value.splice(index, 1);
  } else if (type === 'after') {
    afterModelValue.value.splice(index, 1);
  } else if (type === 'issue') {
    issueModelValue.value.splice(index, 1);
  }
}
@@ -253,4 +395,42 @@
  border-top: 1px solid #f0f0f0;
  background-color: #fafafa;
}
.upload-buttons {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
}
.file-count {
  font-size: 12px;
  color: #999;
}
.file-list {
  margin-top: 10px;
}
.file-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 0;
  border-bottom: 1px solid #f0f0f0;
}
.file-item:last-child {
  border-bottom: none;
}
.file-name {
  font-size: 14px;
  color: #333;
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  margin-right: 10px;
}
</style>