From 802f9516b59f342d7aa8a734d35061a1ab910520 Mon Sep 17 00:00:00 2001
From: xiangpei <xiangpei@timesnew.cn>
Date: 星期日, 03 十一月 2024 23:12:45 +0800
Subject: [PATCH] 教学资源附件查看/下载

---
 src/views/folder/index.vue |  489 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 483 insertions(+), 6 deletions(-)

diff --git a/src/views/folder/index.vue b/src/views/folder/index.vue
index 9e6d722..3b6c849 100644
--- a/src/views/folder/index.vue
+++ b/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>
\ No newline at end of file
+.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>

--
Gitblit v1.8.0