gaoluyang
2025-12-31 98b00c97565276acd51a9e188f8f2bf9ed0f6ebc
src/components/imageUpload/viewQrCodeFiles.vue
@@ -18,7 +18,12 @@
          <text class="popup-title">查看附件</text>
        </view>
        
        <view class="upload-container">
        <scroll-view
          class="upload-container"
          scroll-y="true"
          :enable-back-to-top="true"
          :scroll-with-animation="true"
        >
          <view class="form-container">
            <view class="title">巡检附件</view>
            
@@ -36,7 +41,14 @@
                    :src="item" 
                    mode="aspectFill"
                    class="image-preview"
                    :lazy-load="true"
                    :data-index="index"
                    @error="handleImageError"
                    @load="handleImageLoad"
                  />
                  <view v-if="imageLoadingStates[index]" class="image-loading">
                    <u-loading-icon mode="spinner" color="#409eff" />
                  </view>
                </view>
              </view>
            </view>
@@ -49,12 +61,18 @@
                  v-for="(videoUrl, index) in beforeProductionVideos"
                  :key="index"
                  class="video-item"
                  @click="previewVideo(videoUrl)"
                  @click="playVideo(`video_${index}`, videoUrl)"
                >
                  <view class="video-preview">
                    <u-icon name="play-circle-fill" size="40" color="#fff"></u-icon>
                  </view>
                  <view class="video-tip">点击播放</view>
                  <image
                    :src="videoUrl"
                    mode="aspectFill"
                    class="video-thumbnail"
                  />
                  <video
                    :id="`video_${index}`"
                    :src="videoUrl"
                    class="hidden-video"
                  ></video>
                </view>
              </view>
            </view>
@@ -68,7 +86,7 @@
              ></u-empty>
            </view>
          </view>
        </view>
        </scroll-view>
      </view>
    </u-popup>
  </view>
@@ -83,6 +101,8 @@
const beforeProductionImgs = ref([])
// 视频数组
const beforeProductionVideos = ref([])
// 图片加载状态
const imageLoadingStates = ref({})
// 打开弹窗并加载数据
const openDialog = async (row) => {
@@ -93,7 +113,33 @@
  
  beforeProductionImgs.value = beforeImgs
  beforeProductionVideos.value = beforeVids
  // 初始化图片加载状态
  beforeProductionImgs.value.forEach((_, index) => {
    imageLoadingStates.value[index] = true
  })
  console.log('处理后的图片URLs:', beforeProductionImgs.value)
  console.log('处理后的视频URLs:', beforeVids)
  dialogVisitable.value = true
}
// 图片加载错误处理
const handleImageError = (e) => {
  console.error('图片加载失败:', e)
  const index = e.target.dataset?.index
  if (index !== undefined) {
    imageLoadingStates.value[index] = false
  }
}
// 图片加载成功处理
const handleImageLoad = (e) => {
  const index = e.target.dataset?.index
  if (index !== undefined) {
    imageLoadingStates.value[index] = false
  }
}
// 预览图片
@@ -111,20 +157,34 @@
  })
}
// 预览视频
const previewVideo = (url) => {
  uni.previewVideo({
    sources: [{
      src: url
    }],
    fail: (err) => {
      console.error('视频预览失败:', err)
// 播放视频
const playVideo = (videoId, url) => {
  // 创建video context并进入全屏
  setTimeout(() => {
    try {
      const videoContext = uni.createVideoContext(videoId)
      console.log('视频上下文创建成功:', videoContext, 'videoId:', videoId)
      // 先播放视频
      videoContext.play()
      // 然后进入全屏
      setTimeout(() => {
        videoContext.requestFullScreen({
          direction: 90 // 横屏全屏
        })
      }, 100)
    } catch (error) {
      console.error('创建视频上下文或进入全屏失败:', error)
      uni.showToast({
        title: '视频预览失败',
        title: '播放失败',
        icon: 'error'
      })
    }
  })
  }, 100)
}
// 视频播放事件
const onVideoPlay = () => {
  // 可以在这里处理播放事件
}
// 表单关闭方法
@@ -133,6 +193,30 @@
  // 重置数据
  beforeProductionImgs.value = []
  beforeProductionVideos.value = []
}
// 处理URL,添加基础域名
function formatUrl(url) {
  if (!url) return ''
  // 如果已经是完整URL,直接返回
  if (url.startsWith('http://') || url.startsWith('https://')) {
    return url
  }
  // 处理反斜杠路径格式,如 "\\zd\\prod\\file\\xxx.jpg"
  let formattedUrl = url
  // 将反斜杠转换为正斜杠
  formattedUrl = formattedUrl.replace(/\\/g, '/')
  // 确保以 / 开头
  if (!formattedUrl.startsWith('/')) {
    formattedUrl = '/' + formattedUrl
  }
  // 添加基础域名
  const baseUrl = 'https://nj477vg8876.vicp.fun'
  const fullUrl = `${baseUrl}${formattedUrl}`
  console.log('格式化URL:', url, '->', fullUrl)
  return fullUrl
}
// 处理每一类数据:分离图片和视频
@@ -145,10 +229,15 @@
  const videos = []
  
  items.forEach(item => {
    const fileUrl = item.url || item.downloadUrl || item.fileUrl
    if (!fileUrl) return
    const fullUrl = formatUrl(fileUrl)
    if (item.contentType?.startsWith('image/')) {
      images.push(item.url)
      images.push(fullUrl)
    } else if (item.contentType?.startsWith('video/')) {
      videos.push(item.url)
      videos.push(fullUrl)
    }
  })
  
@@ -174,6 +263,7 @@
  width: 100%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.popup-header {
@@ -192,8 +282,11 @@
.upload-container {
  flex: 1;
  height: 0;
  min-height: 0;
  padding: 20px;
  overflow-y: auto;
  box-sizing: border-box;
  overflow: hidden;
}
.form-container {
@@ -223,6 +316,10 @@
.media-section {
  margin-bottom: 30px;
  &:last-child {
    margin-bottom: 0;
  }
}
.section-title {
@@ -249,42 +346,54 @@
.image-preview {
  width: 100%;
  height: 100%;
  background-color: #f5f5f5;
  display: block;
}
.image-loading {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: rgba(255, 255, 255, 0.8);
}
.video-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 15px;
  margin-bottom: 0;
}
.video-item {
  width: 160px;
  height: 90px;
  width: 300rpx;
  height: 190rpx;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  position: relative;
  background-color: #000;
  flex-shrink: 0;
}
.video-preview {
.video-thumbnail {
  width: 100%;
  height: 100%;
  background-color: #333;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  display: block;
}
.video-tip {
.hidden-video {
  position: absolute;
  bottom: 5px;
  left: 50%;
  transform: translateX(-50%);
  font-size: 12px;
  color: #fff;
  background-color: rgba(0, 0, 0, 0.6);
  padding: 2px 8px;
  border-radius: 4px;
  top: -9999px;
  left: -9999px;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}
.empty-state {