xiangpei
2024-11-03 802f9516b59f342d7aa8a734d35061a1ab910520
src/views/folder/index.vue
@@ -1,26 +1,503 @@
<template>
  <div class="folder-container w-screen h-screen bg-slate-50 flex flex-col items-center">
  <div
    class="train-container w-screen h-screen bg-slate-50 flex flex-col items-center"
  >
    <NormalHeader class="shrink-0"></NormalHeader>
    <div class="list-container container grow relative">
      <div class="list-content absolute top-0 bottom-0 left-0 right-0 py-4">
        <div class="list-wrapper w-full h-full">
          <el-card class="h-full" :body-style="{ height: '100%' }">
            <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="请输入搜索内容"
                    class="long-input"
                    :prefix-icon="Search"
                    @input="searchFile"
                  />
                  <el-select
                    v-model="searchSubject"
                    placeholder="请选择科目"
                    class="ml-4 long-select"
                    @change="searchFile"
                    clearable
                  >
                    <el-option
                      v-for="item in subjectList"
                      :key="item.id"
                      :label="item.name"
                      :value="item.id"
                    />
                  </el-select>
                  <el-select
                    v-model="searchContentType"
                    placeholder="请选择文件类型"
                    class="ml-4 long-select"
                    @change="searchFile"
                    clearable
                  >
                    <el-option
                      v-for="item in contentTypeList"
                      :key="item.value"
                      :label="item.name"
                      :value="item.value"
                    >
                    </el-option>
                  </el-select>
                  <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%" v-loading="loading">
                    <el-table-column label="文件名称">
                      <template #default="scope">
                        <div class="row-info">
                          <div class="icon">
                            <img
                              :src="getIcon(scope.row.contentType)"
                              class="width-img"
                            />
                          </div>
                          <div class="label">{{ scope.row.introduction }}</div>
                        </div>
                      </template>
                    </el-table-column>
                    <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)"
                          v-if="
                            scope.row.contentType == 'video' ||
                            scope.row.contentType == 'audio'
                          "
                        >
                          查看
                        </el-button>
                        <el-button
                          link
                          type="primary"
                          @click.prevent="download(scope.row)"
                          v-else
                        >
                          下载
                        </el-button>
                        <el-button
                            link
                            type="primary"
                            @click.prevent="showAttachment(scope.row.attachment)"
                            v-if="scope.row.attachment && scope.row.attachment.length > 0"
                        >
                          查看附件
                        </el-button>
                      </template>
                    </el-table-column>
                  </el-table>
                </div>
              </div>
              <div class="card-footer flex justify-center mb-7 shrink-0">
                <el-pagination
                  background
                  layout="total, sizes, prev, pager, next, jumper"
                  :total="total"
                  :page-sizes="[10, 20, 50]"
                  :page-size="pageSize"
                  :currentPage="currentIndex"
                  @size-change="handleSizeChange"
                  @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-if="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>
    <!-- 弹窗 -->
    <!-- <el-drawer
      v-model="fileViewer"
      direction="btt"
      size="90%"
      :before-close="handleClose"
    >
      <DocumentViewer :fileUrl="fileUrl"></DocumentViewer>
    </el-drawer> -->
    <el-dialog
        v-model="attachmentShow"
        title="附件"
        width="500"
        :close-on-click-modal="false"
        :before-close="handleClose"
    >
      <div v-for="(attachment, index) in attachmentList" :key="index">
        <el-link type="primary" :href="'/api/upload/download?url=' + attachment.url +'&fileName=' + attachment.name">
          {{ attachment.name }}
        </el-link>
      </div>
      <div></div>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="handleClose">取消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import { ref } from 'vue';
import NormalHeader from '@/components/NormalHeader/index.vue';
import { Search } from '@element-plus/icons-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 { getSubjectList } from "@/api/modules/subject.js";
import PDFViewer from "@/components/PDFViewer/index.vue";
import VideoViewer from "@/components/VideoViewer/index.vue";
import DocumentViewer from "@/components/DocumentViewer/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: "wss://www.kgmeet.com:18443/websocket/" + userInfo.value.id,
    heartBeatData: "ping",
  });
const time = ref(null);
const attachmentShow = ref(false)
const fileType = {
  img: {
    iconPath: "/static/icons/file_type_image.png",
    handle: (item) => {
      imageViewer.value = true;
      imageList.value = ["/api/files/" + item.contentUrl.url];
      resendMessage();
    },
  },
  video: {
    iconPath: "/static/icons/file_type_video.png",
    handle: (item) => {
      videoViewer.value = true;
      videoUrl.value = ["/api/files/" + item.contentUrl.url];
      resendMessage();
    },
  },
  pdf: {
    iconPath: "/static/icons/file_type_pdf.png",
    handle: (item) => {
      pdfViewer.value = true;
      pdfFile.value = "/api/files/" + item.contentUrl.url;
      resendMessage();
    },
  },
  word: {
    iconPath: "/static/icons/file_type_word.png",
    handle: (item) => {
      pdfViewer.value = true;
      pdfFile.value = "/api/files/" + item.contentUrl.url;
      resendMessage();
    },
  },
  ppt: {
    iconPath: "/static/icons/file_type_ppt.png",
    handle: (item) => {
      pdfViewer.value = true;
      pdfFile.value = "/api/files/" + item.contentUrl.url;
      resendMessage();
    },
  },
  audio: {
    iconPath: "/static/icons/file_type_audio.png",
    handle: (item) => {
      console.log(item);
      videoViewer.value = true;
      videoUrl.value = "/api/files/" + item.contentUrl.url;
      resendMessage();
    },
  },
  excel: {
    iconPath: "/static/icons/file_type_excel.png",
    handle: (item) => {
      console.log(item);
      pdfViewer.value = true;
      pdfFile.value = "/api/files/" + item.contentUrl.url;
      resendMessage();
    },
  },
};
const searchText = ref("");
const searchSubject = ref("");
const searchContentType = ref("");
const attachmentList = ref([]);
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 subjectList = ref([]);
const contentTypeList = ref([
  { name: "视频", value: "video" },
  { name: "图片", value: "img" },
  { name: "音频", value: "audio" },
  { name: "PDF", value: "pdf" },
  { name: "EXCEL", value: "excel" },
  { name: "WORD", value: "word" },
  { name: "PPT", value: "ppt" },
]);
const currentIndex = ref(1);
const pageSize = ref(10);
const total = ref(0);
// const fileUrl = ref("");
const fileViewer = ref(false);
const handleClose = () => {
  attachmentShow.value = false
}
const showAttachment = (attachmentListParam) => {
  attachmentList.value = attachmentListParam
  console.log(attachmentList.value, "ww")
  attachmentShow.value = true
}
const checkRow = (item) => {
  // fileUrl.value = item.contentUrl.url;
  fileType[item.contentType] && fileType[item.contentType].handle(item);
};
// const handleClose = () => {
//   fileViewer.value = false;
//   fileUrl.value = "";
//   console.log("我是否关闭:", fileUrl.value);
// };
const closeViewer = () => {
  pdfViewer.value = false;
  imageViewer.value = false;
  videoViewer.value = false;
  clearInterval(time.value);
};
const getData = () => {
  loading.value = true;
  getFileList({
    introduction: searchText.value,
    subjectId: searchSubject.value,
    contentType: searchContentType.value,
    pageSize: pageSize.value,
    pageNum: currentIndex.value,
  })
    .then((res) => {
      loading.value = false;
      fileList.value = res.data;
      total.value = res.total;
    })
    .catch(() => {
      loading.value = false;
    });
};
getData();
const getSubject = () => {
  loading.value = true;
  getSubjectList()
    .then((res) => {
      loading.value = false;
      subjectList.value = res.data;
    })
    .catch(() => {
      loading.value = false;
    });
};
getSubject();
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 handleSizeChange = (val) => {
  currentIndex.value = 1;
  pageSize.value = val;
  getData();
};
const handleCurrentChange = (val) => {
  currentIndex.value = val;
  getData();
};
const searchFile = () => {
  getData();
};
//下载
const download = (row) => {
  window.open(row.visitUrl, '_blank');
};
// -----------------------------------生命周期
onMounted(() => {
  // 连接webscoket
  connect();
});
onBeforeUnmount(() => {
  clearInterval(time.value);
});
</script>
<style lang="scss" scoped>
:deep(.el-tabs__nav-wrap:after) {
  display: none;
}
</style>
.row-info {
  display: flex;
  align-items: center;
  .icon {
    width: 35px;
    margin-right: 20px;
  }
}
.long-input {
  width: 200px;
}
.long-select {
  width: 200px;
}
.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>