ZhangXianQiang
2024-07-05 98f494cf633e3acf5c20f3e9de0d708f2a6c2045
src/views/folder/index.vue
@@ -9,27 +9,27 @@
            <div class="card-wrapper w-full h-full flex flex-col px-8 box-border">
              <div class="card-header flex justify-between items-center shrink-0">
                <div class="header-search flex items-center">
                  <el-input v-model="searchText" placeholder="请输入搜索内容" :prefix-icon="Search" />
                  <el-button type="primary" class="ml-4">搜索</el-button>
                  <el-input v-model="searchText" placeholder="请输入搜索内容" :prefix-icon="Search" maxlength="20" />
                  <el-button type="primary" class="ml-4" @click="searchFile">搜索</el-button>
                </div>
              </div>
              <div class="card-main flex-1 my-5 relative">
                <div class="main-content absolute top-0 bottom-0 left-0 right-0">
                  <el-table :data="fileList" height="100%">
                  <el-table :data="fileList" height="100%" v-loading="loading">
                    <el-table-column label="文件名称">
                      <template #default="scope">
                        <div class="row-info">
                          <div class="icon">
                            <img :src="fileType[scope.row.type].iconPath" class="width-img" />
                            <img :src="getIcon(scope.row.contentType)" class="width-img" />
                          </div>
                          <div class="label">{{ scope.row.name }}</div>
                          <div class="label">{{ scope.row.introduction }}</div>
                        </div>
                      </template>
                    </el-table-column>
                    <el-table-column prop="class" label="班级" align="center" />
                    <el-table-column prop="subject" label="科目" align="center" />
                    <el-table-column prop="date" label="上传时间" align="center" />
                    <el-table-column prop="className" label="班级" align="center" />
                    <el-table-column prop="typeName" label="科目" align="center" />
                    <el-table-column prop="updateTime" label="上传时间" align="center" />
                    <el-table-column>
                      <template #default="scope">
                        <el-button link type="primary" @click.prevent="checkRow(scope.row)">
@@ -42,91 +42,180 @@
              </div>
              <div class="card-footer flex justify-center mb-7 shrink-0">
                <el-pagination background layout="prev, pager, next" :total="1000" />
                <el-pagination background layout="prev, pager, next" :total="fileList.length"
                :default-page-size="20"
                :currentPage="currentIndex"
                :hide-on-single-page="true"
                @current-change="handleCurrentChange" />
              </div>
            </div>
          </el-card>
        </div>
      </div>
    </div>
    <!-- pdf查看 -->
    <div class="pdf-container" v-show="pdfViewer">
      <PDFViewer :pdfUrl="pdfFile"></PDFViewer>
      <div class="close-btn">
        <el-button type="danger" size="large" circle @click="closeViewer">
          <template #icon>
            <el-icon :size="18">
              <Close />
            </el-icon>
          </template>
        </el-button>
      </div>
    </div>
    <!-- image查看 -->
    <div class="image-container" v-show="imageViewer">
      <el-image-viewer :url-list="imageList" @close="closeViewer"></el-image-viewer>
    </div>
    <!-- 视频查看 -->
    <div class="video-container" v-show="videoViewer">
      <VideoViewer :videoUrl="videoUrl"></VideoViewer>
      <div class="close-btn">
        <el-button type="danger" size="large" circle @click="closeViewer">
          <template #icon>
            <el-icon :size="20">
              <Close />
            </el-icon>
          </template>
        </el-button>
      </div>
    </div>
  </div>
</template>
<script setup>
import { ref } from 'vue';
import { ref, onMounted, onBeforeUnmount } from 'vue';
import { storeToRefs } from 'pinia';
import { Close } from '@element-plus/icons-vue';
import NormalHeader from '@/components/NormalHeader/index.vue';
import { Search } from '@element-plus/icons-vue';
import { getFileList } from '@/api/modules/file.js';
import PDFViewer from '@/components/PDFViewer/index.vue';
import VideoViewer from '@/components/VideoViewer/index.vue';
import { useUserStore } from '@/store/index.js';
import useWebScoket from '@/hooks/useWebScoket.js';
const userStore = useUserStore();
const { userInfo } = storeToRefs(userStore);
const { status, message, error, connect, disconnect, sendMessage } = useWebScoket({
  url: 'ws://192.168.3.64:8000/websocket/' + userInfo.value.id,
  heartBeatData: 'ping'
});
const time = ref(null);
const fileType = {
  'img': {
    iconPath: '/static/icons/file_type_image.png',
    handle: (item) => {
      console.log(item);
      imageViewer.value = true;
      imageList.value = [item.contentUrl.url];
      resendMessage();
    }
  },
  'video': {
    iconPath: '/static/icons/file_type_video.png',
    handle: (item) => {
      console.log(item);
      videoViewer.value = true;
      videoUrl.value = [item.contentUrl.url];
      resendMessage();
    }
  },
  'pdf': {
    iconPath: '/static/icons/file_type_image.png',
    iconPath: '/static/icons/file_type_pdf.png',
    handle: (item) => {
      console.log(item);
      pdfViewer.value = true;
      pdfFile.value = item.contentUrl.url;
      resendMessage();
    }
  },
};
const searchText = ref('');
const fileList = ref([
  {
    id: 1,
    name: '测试测试测试',
    url: '',
    date: '2024-12-12',
    class: 'test',
    subject: '测试',
    type: 'img'
  },
  {
    id: 2,
    name: '测试测试测试',
    url: '',
    date: '2024-12-12',
    class: 'test',
    subject: '测试',
    type: 'video'
  },
  {
    id: 3,
    name: '测试测试测试',
    url: '',
    date: '2024-12-12',
    class: 'test',
    subject: '测试',
    type: 'pdf'
  }
]);
const loading = ref(false);
const pdfViewer = ref(false);
const imageViewer = ref(false);
const videoViewer = ref(false);
const imageList = ref([]);
const pdfFile = ref('');
const videoUrl = ref('');
const fileList = ref([]);
const currentIndex = ref(1);
const checkRow = (item) => {
  fileType[item.type] && fileType[item.type].handle(item);
  fileType[item.contentType] && fileType[item.contentType].handle(item);
};
const closeViewer = () => {
  pdfViewer.value = false;
  imageViewer.value = false;
  videoViewer.value = false;
  clearInterval(time.value);
};
const getData = () => {
  loading.value = true;
  getFileList().then(res => {
    loading.value = false;
    fileList.value = res.data;
  }).catch(() => {
    loading.value = false;
  });
};
getData();
const resendMessage = () => {
  if (time.value) {
    clearInterval(time.value);
  }
  sendMessage({ id: userInfo.value.id, command: 'recordStudyTime' });
  time.value = setInterval(() => {
    sendMessage({ id: userInfo.value.id, command: 'recordStudyTime' });
  }, 5000);
};
const getIcon = (type) => {
  if (fileType[type]) {
    return fileType[type].iconPath;
  }
};
const handleCurrentChange = (val) => {
  getData();
}
const searchFile = () => {
  getData();
}
// -----------------------------------生命周期
onMounted(() => {
  // 连接webscoket
  connect();
});
onBeforeUnmount(() => {
  clearInterval(time.value);
});
</script>
<style lang="scss" scoped>
@@ -143,4 +232,50 @@
    margin-right: 20px;
  }
}
.pdf-container {
  width: 100%;
  height: 100%;
  position: absolute;
  z-index: 99999;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  .close-btn {
    position: absolute;
    top: 2px;
    right: 30px;
    z-index: 9999999;
    :deep(.el-button) {
      width: fit-content;
      height: fit-content;
      padding: 5px !important;
    }
  }
}
.video-container {
  width: 100%;
  height: 100%;
  position: absolute;
  z-index: 99999;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  .close-btn {
    position: absolute;
    top: 60px;
    right: 100px;
    z-index: 9999999;
    :deep(.el-button) {
      width: fit-content;
      height: fit-content;
      padding: 10px !important;
    }
  }
}
</style>