前端展示ftp文件目录

文章目录

1.前言

项目需求:后端发送ftp目录tree需要前端展示出来,可以搜索文件,并且可以对文件进行操作(创建文件夹,删除文件,重命名等一些操作),这里用用的是element-ui tree控件!技术上没有什么难度!

2. 思路

展示目录结构应该很简单,需要对文件做一些操作,这里可以想象下window系统是怎么操作文件,鼠标右键,弹框显示,我们也可以模拟下,鼠标右键可以获取到tree得当前坐标,然后可以根据坐标显示弹框,当前点击其他地方弹框也要消失!先看下效果图!
在这里插入图片描述

这里作了一些判断,如果是文件夹都显示新建文件夹,删除文件夹,文件夹重命名,如果是文件就显示,删除文件,文件重命名
在这里插入图片描述

下面是后端传过来的数据,这个是我自己定义的,你需要什么数据可以和后端商量

let data = [
 {
   id: 1,
   fileName: "文件夹1",
   path: "c:/文件夹1",
   type: "folder",
   children: [
     {
       id: 4,
       fileName: "文件夹2",
       path: "c:/文件夹1/文件夹2",
       type: "folder",
       children: [
         {
           id: 9,
           fileName: "1.js",
           path: "c:/文件夹1/文件夹2/1.js",
           type: "file"
         },
         {
           id: 10,
           fileName: "文件夹3",
           path: "c:/文件夹1/文件夹2",
           type: "folder"
         }
       ]
     }
   ]
 },
 {
   id: 2,
   fileName: "文件夹4",
   path: "c:/文件夹1/文件夹4",
   type: "folder",
   children: [
     {
       id: 5,
       fileName: "2.js",
       path: "c:/文件夹1/文件夹4/2.js",
       type: "file"
     },
     {
       id: 6,
       fileName: "3.js",
       path: "c:/文件夹1/文件夹4/3.js",
       type: "file"
     }
   ]
 },
 {
   id: 3,
   fileName: "文件夹5",
   path: "c:/文件夹1/文件夹4",
   type: "folder",
   children: [
     {
       id: 7,
       fileName: "4.js",
       path: "c:/文件夹1/文件夹5/4.js",
       type: "file"
     },
     {
       id: 8,
       fileName: "5.js",
       path: "c:/文件夹1/文件夹5/5.js",
       type: "file"
     }
   ]
 }
]

html部分

 <div class="tab-container">
    <el-tabs v-model="activeName">
      <el-tab-pane label="视频管理" name="first">视频管理</el-tab-pane>
      <el-tab-pane label="图片管理" name="second">图片管理</el-tab-pane>
      <el-tab-pane label="文件列表" name="third">
        <div class="custom-tree-container">
          <el-input placeholder="输入关键字进行过滤" v-model="filterText">
          </el-input>
          <!-- show-checkbox -->
          <div class="block">
            <el-tree
              :data="data"
              node-key="id"
              default-expand-all
              :filter-node-method="filterNode"
              ref="tree"
              @node-contextmenu="operationFile"
              @node-click="operationClose"
            >
              <span class="custom-tree-node" slot-scope="{ node, data }">
                <i
                  :class="[
                    data.type == 'folder'
                      ? 'el-icon-folder'
                      : 'el-icon-notebook-2'
                  ]"
                  style="color: #FFE791; margin-right: 5px;"
                ></i>
                <span style="font-size: 15px;">{{ data.fileName }}</span>
              </span>
            </el-tree>
          </div>
        </div></el-tab-pane
      >
      <el-tab-pane label="文件位置" name="fourth">文件位置</el-tab-pane>
    </el-tabs>

    <div
      :style="{
        left: btnX + 'px',
        top: btnY + 'px'
      }"
      v-show="dialogVisible"
      id="operation-list"
    >
      <el-button
        v-if="isFolder"
        @click="append"
        class="operation-btn"
        size="small"
        >新建文件夹
      </el-button>
      <el-button
        v-if="isFolder"
        @click="remove"
        class="operation-btn"
        size="small"
        >删除文件夹
      </el-button>

      <el-button v-else @click="remove" class="operation-btn" size="small"
        >删除文件
      </el-button>

      <el-button
        v-if="isFolder"
        @click="rename"
        class="operation-btn"
        size="small"
        >文件夹重命名
      </el-button>
      <el-button v-else @click="rename" class="operation-btn" size="small"
        >文件重命名
      </el-button>
    </div>
  </div>

js部分:

let id = 100,
  data = [
    {
      id: 1,
      fileName: "文件夹1",
      path: "c:/文件夹1",
      type: "folder",
      children: [
        {
          id: 4,
          fileName: "文件夹2",
          path: "c:/文件夹1/文件夹2",
          type: "folder",
          children: [
            {
              id: 9,
              fileName: "1.js",
              path: "c:/文件夹1/文件夹2/1.js",
              type: "file"
            },
            {
              id: 10,
              fileName: "文件夹3",
              path: "c:/文件夹1/文件夹2",
              type: "folder"
            }
          ]
        }
      ]
    },
    {
      id: 2,
      fileName: "文件夹4",
      path: "c:/文件夹1/文件夹4",
      type: "folder",
      children: [
        {
          id: 5,
          fileName: "2.js",
          path: "c:/文件夹1/文件夹4/2.js",
          type: "file"
        },
        {
          id: 6,
          fileName: "3.js",
          path: "c:/文件夹1/文件夹4/3.js",
          type: "file"
        }
      ]
    },
    {
      id: 3,
      fileName: "文件夹5",
      path: "c:/文件夹1/文件夹4",
      type: "folder",
      children: [
        {
          id: 7,
          fileName: "4.js",
          path: "c:/文件夹1/文件夹5/4.js",
          type: "file"
        },
        {
          id: 8,
          fileName: "5.js",
          path: "c:/文件夹1/文件夹5/5.js",
          type: "file"
        }
      ]
    }
  ];
export default {
  name: "tree",
  data() {
    return {
      activeName: "second", //tab栏被选中的模块
      filterText: "", //搜索过滤
      dialogVisible: false, //弹框是否显示
      btnX: "", //显示框x坐标
      btnY: "", //显示框y坐标
      operationFileData: "", //右键选中节点属性
      node: "", //右键选中节点所有信息
      isFolder: false, //是否是文件夹
      data: JSON.parse(JSON.stringify(data)) //拷贝一份tree数据,不影响之前的
    };
  },

  mounted() {
    let that = this;
    $(document).on("click", function(event) {
      if (event.target != document.getElementById("operation-list")) {
        that.dialogVisible = false;
      }
    });
  },
  watch: {
    filterText(val) {
      this.$refs.tree.filter(val);
    }
  },

  methods: {
    filterNode(value, data) {
      if (!value) return true;
      return data.fileName.indexOf(value) !== -1;
    },

    //关闭操作
    operationClose(evt, data, node) {
      this.dialogVisible = false;
    },

    // 操作tree列表鼠标右键触发
    operationFile(event, data, node, context) {
      this.btnX = event.x;
      this.btnY = event.y;
      this.operationFileData = data; //当前节点数据
      this.node = node; // 将当前节点所有信息
      this.isFolder = data.type == "folder"; //是否是文件夹
      this.dialogVisible = true; // 展示右键菜单
      console.log(event, data, node, context == this);
    },

    //添加文件夹
    append() {
      this.dialogVisible = false;
      this.$prompt("请输入文件名", "提示", {
        // 弹出框用于输入文件名
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        inputPattern: /^[^/\\\:\*\?\"\<\>\|\\]{1,255}$/,
        inputErrorMessage: "文件名格式不对"
      })
        .then(({ value }) => {
          //添加新节点
          let child = {
            id: id++,
            fileName: value,
            type: "folder",
            children: []
          };
          if (!this.operationFileData.children) {
            this.$set(this.operationFileData, "children", []);
          }
          this.operationFileData.children.push(child);
          //展开节点
          if (!this.node.expanded) {
            this.node.expanded = true;
          }
          this.$message({
            type: "success",
            message: "文件夹新建成功!"
          });
        })
        .catch(() => {
          this.$message({
            type: "info",
            message: "取消输入"
          });
        });
    },

    //删除文件夹/文件
    remove() {
      this.dialogVisible = false;
      this.$confirm("此操作将永久删除该文件夹/文件, 是否继续?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(() => {
          const parent = this.node.parent;
          const children = parent.data.children || parent.data;

          const index = children.findIndex(
            d => d.id === this.operationFileData.id
          );
          children.splice(index, 1);
          this.$message({
            type: "success",
            message: "删除成功!"
          });
        })
        .catch(() => {
          this.$message({
            type: "info",
            message: "已取消删除"
          });
        });
    },

    //给文件/文件夹重新命名
    rename() {
      this.dialogVisible = false;
      this.$prompt("请输入文件名", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        inputPlaceholder: this.node.data.fileName,
        inputPattern: /^[^/\\\:\*\?\"\<\>\|\\]{1,255}$/,
        inputErrorMessage: "文件名格式不对"
      })
        .then(({ value }) => {
          this.node.data.fileName = value;
          this.$message({
            type: "success",
            message: "重命名成功!"
          });
        })
        .catch(() => {
          this.$message({
            type: "info",
            message: "取消重命名"
          });
        });
    }
  }
};

style部分:

.tab-container {
  width: 400px;
  height: 500px;
  margin: 100px auto;
  border: 1px solid #eee;
  padding: 20px;
}

.el-tabs.el-tabs--top {
  height: 100%;
}

.el-tabs__content {
  height: calc(100% - 55px);
  border: 1px solid #eee;
  padding: 10px;
}

.operation-btn {
  width: 100%;
  margin-left: 0 !important;
  font-size: 10px;
  border-radius: 0;
  border-top: none;
}

#operation-list {
  z-index: 999999;
  position: absolute;
  width: 100px;
  background: white;
  box-shadow: 1px 1px 5px #aaa;
}

源码已经奉上,效果图如下:
在这里插入图片描述

  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值