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,48 +61,21 @@
                  v-for="(videoUrl, index) in beforeProductionVideos"
                  :key="index"
                  class="video-item"
                  @click="playVideo(videoUrl, index)"
                  @click="playVideo(`video_${index}`, videoUrl)"
                >
                  <video
                  <image
                    :src="videoUrl" 
                    mode="aspectFill"
                    class="video-thumbnail"
                    :poster="videoUrl"
                    :controls="false"
                    :show-center-play-btn="true"
                    @play="onVideoPlay"
                  />
                  <video
                    :id="`video_${index}`"
                    :src="videoUrl"
                    class="hidden-video"
                  ></video>
                  <view class="video-overlay">
                    <u-icon name="play-circle-fill" size="40" color="#fff"></u-icon>
                  </view>
                </view>
              </view>
            </view>
            <!-- 视频播放弹窗 -->
            <u-popup
              :show="showVideoPlayer"
              mode="center"
              width="100%"
              height="100%"
              :closeable="true"
              @close="closeVideoPlayer"
              :safeAreaInsetBottom="false"
            >
              <view class="video-player-container">
                <video
                  v-if="currentVideoUrl"
                  :src="currentVideoUrl"
                  class="video-player"
                  :controls="true"
                  :show-center-play-btn="true"
                  :enable-play-gesture="true"
                  :show-fullscreen-btn="true"
                  :enable-progress-gesture="true"
                  :object-fit="'contain'"
                  @fullscreenchange="onFullscreenChange"
                ></video>
              </view>
            </u-popup>
            
            <!-- 空状态 -->
            <view v-if="beforeProductionImgs.length === 0 && beforeProductionVideos.length === 0" class="empty-state">
@@ -101,7 +86,7 @@
              ></u-empty>
            </view>
          </view>
        </view>
        </scroll-view>
      </view>
    </u-popup>
  </view>
@@ -116,9 +101,8 @@
const beforeProductionImgs = ref([])
// 视频数组
const beforeProductionVideos = ref([])
// 视频播放器
const showVideoPlayer = ref(false)
const currentVideoUrl = ref('')
// 图片加载状态
const imageLoadingStates = ref({})
// 打开弹窗并加载数据
const openDialog = async (row) => {
@@ -129,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
  }
}
// 预览图片
@@ -148,29 +158,33 @@
}
// 播放视频
const playVideo = (url, index) => {
  currentVideoUrl.value = url
  showVideoPlayer.value = true
}
// 关闭视频播放器
const closeVideoPlayer = () => {
  showVideoPlayer.value = false
  currentVideoUrl.value = ''
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: '播放失败',
        icon: 'error'
      })
    }
  }, 100)
}
// 视频播放事件
const onVideoPlay = () => {
  // 可以在这里处理播放事件
}
// 全屏变化事件
const onFullscreenChange = (e) => {
  console.log('全屏状态变化:', e)
  // 如果退出全屏,可以选择关闭弹窗
  if (e.detail && e.detail.fullScreen === false) {
    // 可以选择保持弹窗打开或关闭
  }
}
// 表单关闭方法
@@ -188,8 +202,21 @@
  if (url.startsWith('http://') || url.startsWith('https://')) {
    return url
  }
  // 否则添加基础域名
  return `https://nj477vg8876.vicp.fun${url.startsWith('/') ? '' : '/'}${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
}
// 处理每一类数据:分离图片和视频
@@ -236,6 +263,7 @@
  width: 100%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.popup-header {
@@ -254,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 {
@@ -285,6 +316,10 @@
.media-section {
  margin-bottom: 30px;
  &:last-child {
    margin-bottom: 0;
  }
}
.section-title {
@@ -311,57 +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-thumbnail {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.video-overlay {
.hidden-video {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.3);
  display: flex;
  align-items: center;
  justify-content: center;
  top: -9999px;
  left: -9999px;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}
.video-player-container {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: #000;
  position: relative;
}
.video-player {
  width: 100%;
  height: 100%;
  max-width: 100vw;
  max-height: 100vh;
}
.empty-state {