美文网首页GIS加油站
node快速搭建一个学习资料共享平台

node快速搭建一个学习资料共享平台

作者: 牛老师讲webgis | 来源:发表于2023-10-20 19:51 被阅读0次

    概述

    本文要实现的功能比较简单:1、将想要共享的文件分文件夹的组织起来;2、别人可以通过界面进行搜索;3、可以在线预览或下载文件。基于这样的需求,本文分享通过node如何实现这样的功能。

    实现效果

    效果

    实现

    1. node端服务

    node端服务通过express实现,并通过递归,读取目录下的所有文件。实现代码如下:

    const express = require('express');
    const app = express();
    const { listFiles } = require('./utils/file');
    
    app.use(express.static('./www'));
    
    app.get('/files', function (req, res) {
        res.send({
            code: 200,
            data: listFiles('./www/')
        });
    });
    
    app.listen(18888, () => {
        console.log('running at http://localhost:18888');
    })
    

    listFiles的实现代码如下:

    function listFiles(path, rootPath = "") {
      const items = fs.readdirSync(path);
      const result = [];
      items.forEach((item) => {
        const itemPath = `${path}/${item}`;
        const stat = fs.statSync(itemPath);
        if (stat.isDirectory()) {
          let data = {
            // 文件夹
            type: "folder",
            name: item,
          };
          let children = listFiles(
            itemPath,
            rootPath ? `${rootPath}/${item}` : item
          );
          if (children && children.length) {
            data.children = children;
          }
          result.push(data);
        } else {
          // 文件
          if (item.indexOf("index.html") === -1) {
            result.push({
              type: "file",
              name: item,
              url: rootPath ? `${rootPath}/${item}` : item,
            });
          }
        }
      });
      return result;
    }
    

    返回后的数据格式如下:


    image.png

    思考:这样的方式, 1. 文件上传不太方便,可以用网盘;2. 当文件数量比较多的时候创建结构树效率比较低。

    2. 前端页面

    前端页面简单使用VueElement实现,实现代码如下:

    <!DOCTYPE html>
    <html lang="en">
     <head>
       <meta charset="UTF-8" />
       <meta http-equiv="X-UA-Compatible" content="IE=edge" />
       <meta name="viewport" content="width=device-width, initial-scale=1.0" />
       <title>学习资料</title>
       <!-- 引入样式 -->
       <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
       <!-- 引入组件库 -->
       <script src="https://unpkg.com/vue@2/dist/vue.js"></script>
       <script src="https://unpkg.com/element-ui/lib/index.js"></script>
       <style>
         * {
           margin: 0;
           padding: 0;
         }
         body {
           font-size: 14px;
           overflow: hidden;
         }
         h1 {
           padding: 1rem;
           background-color: #0062ff;
           color: white;
           font-size: 1.2rem;
         }
         .file-tree {
           padding: 1rem;
         }
         .filter-tree {
           margin-top: 1rem;
           height: calc(100vh - 9rem);
           overflow-y: auto;
         }
         .el-tree-node__content {
           height: 2.4rem;
         }
         .tree-text {
           font-size: 0.98rem;
         }
         .slot-t-node-file:hover {
           text-decoration: underline;
         }
       </style>
     </head>
     <body>
       <div id="app" class="container">
         <h1>学习资料</h1>
         <div class="file-tree">
           <el-input
             placeholder="输入关键字进行过滤"
             v-model="filterText"
             clearable
           ></el-input>
           <el-tree
             class="filter-tree"
             :data="filteredFileData"
             default-expand-all
             @node-click="handleNodeClick"
             ref="tree"
           >
             <span slot-scope="{ node, data }" class="slot-t-node" :class="data.type === 'file' ? 'slot-t-node-file' : ''">
               <template>
                 <i :class="getIcon(node, data)" class="tree-text"></i>
                 <span class="tree-text">{{ data.name }}</span>
               </template>
             </span>
           </el-tree>
         </div>
       </div>
       <script>
         const app = new Vue({
           el: "#app",
           mounted() {
             this.getFileList();
           },
           computed: {
             filteredFileData() {
               const that = this
               if(that.filterText === '') return that.fileData;
               let filter = function (data) {
                 let result = []
                 data.forEach(d => {
                   if(d.children) {
                     const res = filter(d.children)
                     if(res.length > 0) result.push({...d, children: res})
                   } else {
                     if(d.name.toLowerCase().indexOf(that.filterText.toLowerCase()) !== -1) result.push(d)
                   }
                 })
                 return result
               }
               return filter(that.fileData)
             },
           },
           data() {
             return {
               filterText: "",
               fileData: [],
             };
           },
           methods: {
             getIcon(node, data) {
               if (data.type === "file") {
                 return "el-icon-document";
               } else {
                 return node.expanded ? "el-icon-folder-opened" : "el-icon-folder";
               }
             },
             getFileList() {
               const url = `/files`;
               fetch(url)
                 .then((res) => res.json())
                 .then((res) => {
                   this.fileData = res.data;
                 });
             },
             handleNodeClick(data, node, component) {
               const { url } = data;
               if (url) window.open(url, "_blank");
             },
           },
         });
       </script>
     </body>
    </html>
    

    相关文章

      网友评论

        本文标题:node快速搭建一个学习资料共享平台

        本文链接:https://www.haomeiwen.com/subject/yfnkidtx.html