zouyu
8 天以前 1c0863efe062af3ebcdecb8c10568d779f5c8295
src/views/equipmentManagement/inspectionManagement/components/viewFiles.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,246 @@
<template>
  <div>
    <el-dialog title="查看附件"
               v-model="dialogVisitable" width="800px" @close="cancel">
      <div class="upload-container">
        <!-- ç”Ÿäº§å‰ -->
        <div class="form-container">
          <div class="title">生产前</div>
          <!-- å›¾ç‰‡åˆ—表 -->
          <div style="display: flex; flex-wrap: wrap;">
            <img v-for="(item, index) in beforeProductionImgs" :key="index"
                 @click="showMedia(beforeProductionImgs, index, 'image')"
                 :src="item" style="max-width: 100px; height: 100px; margin: 5px;" alt="">
          </div>
          <!-- è§†é¢‘列表 -->
          <div style="display: flex; flex-wrap: wrap;">
            <div
                v-for="(videoUrl, index) in beforeProductionVideos"
                :key="index"
                @click="showMedia(beforeProductionVideos, index, 'video')"
                style="position: relative; margin: 10px; cursor: pointer;"
            >
              <div style="width: 160px; height: 90px; background-color: #333; display: flex; align-items: center; justify-content: center;">
                <img src="@/assets/images/video.png" alt="播放" style="width: 30px; height: 30px; opacity: 0.8;" />
              </div>
              <div style="text-align: center; font-size: 12px; color: #666;">点击播放</div>
            </div>
          </div>
        </div>
        <!-- ç”Ÿäº§åŽ -->
        <div class="form-container">
          <div class="title">生产中</div>
          <!-- å›¾ç‰‡åˆ—表 -->
          <div style="display: flex; flex-wrap: wrap;">
            <img v-for="(item, index) in afterProductionImgs" :key="index"
                 @click="showMedia(afterProductionImgs, index, 'image')"
                 :src="item" style="max-width: 100px; height: 100px; margin: 5px;" alt="">
          </div>
          <!-- è§†é¢‘列表 -->
          <div style="display: flex; flex-wrap: wrap;">
            <div
                v-for="(videoUrl, index) in afterProductionVideos"
                :key="index"
                @click="showMedia(afterProductionVideos, index, 'video')"
                style="position: relative; margin: 10px; cursor: pointer;"
            >
              <div style="width: 160px; height: 90px; background-color: #333; display: flex; align-items: center; justify-content: center;">
                <img src="@/assets/images/video.png" alt="播放" style="width: 30px; height: 30px; opacity: 0.8;" />
              </div>
              <div style="text-align: center; font-size: 12px; color: #666;">点击播放</div>
            </div>
          </div>
        </div>
        <!-- ç”Ÿäº§é—®é¢˜ -->
        <div class="form-container">
          <div class="title">生产后</div>
          <!-- å›¾ç‰‡åˆ—表 -->
          <div style="display: flex; flex-wrap: wrap;">
            <img v-for="(item, index) in productionIssuesImgs" :key="index"
                 @click="showMedia(productionIssuesImgs, index, 'image')"
                 :src="item" style="max-width: 100px; height: 100px; margin: 5px;" alt="">
          </div>
          <!-- è§†é¢‘列表 -->
          <div style="display: flex; flex-wrap: wrap;">
            <div
                v-for="(videoUrl, index) in productionIssuesVideos"
                :key="index"
                @click="showMedia(productionIssuesVideos, index, 'video')"
                style="position: relative; margin: 10px; cursor: pointer;"
            >
              <div style="width: 160px; height: 90px; background-color: #333; display: flex; align-items: center; justify-content: center;">
                <img src="@/assets/images/video.png" alt="播放" style="width: 30px; height: 30px; opacity: 0.8;" />
              </div>
              <div style="text-align: center; font-size: 12px; color: #666;">点击播放</div>
            </div>
          </div>
        </div>
      </div>
    </el-dialog>
    <!-- ç»Ÿä¸€åª’体查看器 -->
    <div v-if="isMediaViewerVisible" class="media-viewer-overlay" @click.self="closeMediaViewer">
      <div class="media-viewer-content" @click.stop>
        <!-- å›¾ç‰‡ -->
        <vue-easy-lightbox
            v-if="mediaType === 'image'"
            :visible="isMediaViewerVisible"
            :imgs="mediaList"
            :index="currentMediaIndex"
            @hide="closeMediaViewer"
        ></vue-easy-lightbox>
        <!-- è§†é¢‘ -->
        <div v-else-if="mediaType === 'video'" style="position: relative;">
          <Video
              :src="mediaList[currentMediaIndex]"
              autoplay
              controls
              style="max-width: 90vw; max-height: 80vh;"
          />
        </div>
      </div>
    </div>
  </div>
</template>
<script setup>
import { ref } from 'vue';
import VueEasyLightbox from 'vue-easy-lightbox';
// æŽ§åˆ¶å¼¹çª—显示
const dialogVisitable = ref(false);
// å›¾ç‰‡æ•°ç»„
const beforeProductionImgs = ref([]);
const afterProductionImgs = ref([]);
const productionIssuesImgs = ref([]);
// è§†é¢‘数组
const beforeProductionVideos = ref([]);
const afterProductionVideos = ref([]);
const productionIssuesVideos = ref([]);
// åª’体查看器状态
const isMediaViewerVisible = ref(false);
const currentMediaIndex = ref(0);
const mediaList = ref([]); // å­˜å‚¨å½“前要查看的媒体列表(含图片和视频对象)
const mediaType = ref('image'); // image | video
// å¤„理每一类数据:分离图片和视频
function processItems(items) {
  const images = [];
  const videos = [];
  items.forEach(item => {
    if (item.contentType?.startsWith('image/')) {
      images.push(item.url);
    } else if (item.contentType?.startsWith('video/')) {
      videos.push(item.url);
    }
  });
  return { images, videos };
}
// æ‰“开弹窗并加载数据
const openDialog = async (row) => {
  const { images: beforeImgs, videos: beforeVids } = processItems(row.beforeProduction);
  const { images: afterImgs, videos: afterVids } = processItems(row.afterProduction);
  const { images: issueImgs, videos: issueVids } = processItems(row.productionIssues);
  beforeProductionImgs.value = beforeImgs;
  beforeProductionVideos.value = beforeVids;
  afterProductionImgs.value = afterImgs;
  afterProductionVideos.value = afterVids;
  productionIssuesImgs.value = issueImgs;
  productionIssuesVideos.value = issueVids;
  dialogVisitable.value = true;
};
// æ˜¾ç¤ºåª’体(图片 or è§†é¢‘)
function showMedia(mediaArray, index, type) {
  mediaList.value = mediaArray;
  currentMediaIndex.value = index;
  mediaType.value = type;
  isMediaViewerVisible.value = true;
}
// å…³é—­åª’体查看器
function closeMediaViewer() {
  isMediaViewerVisible.value = false;
  mediaList.value = [];
  mediaType.value = 'image';
}
// è¡¨å•关闭方法
const cancel = () => {
  dialogVisitable.value = false;
};
defineExpose({ openDialog });
</script>
<style scoped lang="scss">
.upload-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 20px;
  border: 1px solid #dcdfe6;
  box-sizing: border-box;
  .form-container {
    flex: 1;
    width: 100%;
    margin-bottom: 20px;
  }
}
.title {
  font-size: 14px;
  color: #165dff;
  line-height: 20px;
  font-weight: 600;
  padding-left: 10px;
  position: relative;
  margin: 6px 0;
  &::before {
    content: "";
    position: absolute;
    left: 0;
    top: 3px;
    width: 4px;
    height: 14px;
    background-color: #165dff;
  }
}
.media-viewer-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.8);
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
}
.media-viewer-content {
  position: relative;
  max-width: 90vw;
  max-height: 90vh;
  overflow: hidden;
}
</style>