el树形列表增删改查

前端:

<el-upload
            :before-remove="beforeRemove"
            :file-list="fileList"
            :limit="1"
            :on-exceed="handleExceed"
            :on-success="handleAvatarSuccess"
            accept=".json"
            action="http://127.0.0.1:8000/crud/"
            class="upload-demo"
            method="POST"
            name="jsonfile"
            style="margin-top: 50px"
        >
          <el-button round size="large" type="primary">点击上传</el-button>
          <template #tip>
            <div class="el-upload__tip" style="font-size: 15px">只能上传 json 文件,建议不超过 1M</div>
          </template>
        </el-upload>
        <div style="display: flex;justify-content: space-between">
          <el-button round size="large" type="danger" @click="submit">确定提交</el-button>
          <el-link :underline="false" download href="http://127.0.0.1:8000/download_json/" style="border-radius: 50px;">
            <el-button round size="large" type="success">下载文件</el-button>
          </el-link>
        </div>
        <div class="view">
          <el-input v-model="filterText" placeholder="输入关键字进行过滤"></el-input>
          <el-tree
              ref="tree"
              :data="data"
              :expand-on-click-node="false"
              :filter-node-method="filterNode"
              class="filter-tree"
              draggable
              node-key="id"
          >
            <!--              default-expand-all-->
            <template #default="{ node, data }">
              <span class="custom-tree-node">
                <span>{{ node.label }}</span>
                <span>
                  <el-button style="font-size: 18px" type="text" @click="append(data)">
                    <CirclePlus style="width: 1em; height: 1em;"/>
                  </el-button>
                  <el-button style="font-size: 18px" type="text" @click="remove(node, data)">
                    <Delete style="width: 1em; height: 1em;"/>
                  </el-button>
                  <el-button style="font-size: 18px" type="text" @click="change(data);">
                    <EditPen style="width: 1em; height: 1em;"/>
                  </el-button>
                </span>
              </span>
            </template>
          </el-tree>
        </div>

文件上传成功调用接口返回数据:(需要使用push添加到data)

async handleAvatarSuccess() {
      console.log(this.fileList)
      const {data: res} = await this.$http.get(`http://127.0.0.1:8000/crud_json/`)
      console.log(res)
      this.data = []
      this.data.push(res.tree)
      this.id = res.size
    },

增加节点以及修改节点使用elementui-plus 消息弹框组件

MessageBox 消息弹框 | Element Plus (gitee.io)

增:

append(data) {
      console.log(data)
      let id = this.id
      this.$prompt('请输入内容', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
      })
          .then(({value}) => {
            const newChild = {id: this.id++, label: value, children: []}
            if (!data.children) {
              data.children = []
            }
            data.children.unshift(newChild)
            this.data = [...this.data]
            console.log(id)
          })
          .catch(() => {
            this.$message({
              type: 'info',
              message: '取消输入',
            })
          })
    },

删:

remove(node, data) {
      const parent = node.parent
      const children = parent.data.children || parent.data
      const index = children.findIndex((d) => d.id === data.id)
      children.splice(index, 1)
      this.data = [...this.data]
    },

改:

change(data) {
      this.$prompt('请输入更改内容', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
      })
          .then(({value}) => {
            data.label = value
          })
          .catch(() => {
            this.$message({
              type: 'info',
              message: '取消输入',
            })
          })
    },

查:

filterNode(value, data) {
      if (!value) return true
      return data.label.indexOf(value) !== -1
    },

注:提供给树形列表的数据需要有id值,不然删除节点时会删错

提交:

async submit() {
      const tree = JSON.stringify(this.data)
      var axios = require('axios');
      var config = {
        method: 'post',
        url: 'http://127.0.0.1:8000/crud_get/',
        headers: {
          'Content-Type': 'application/json'
        },
        data: tree
      };

      axios(config)
          .then(function (response) {
            console.log(JSON.stringify(response.data));
          })
          .catch(function (error) {
            console.log(error);
          });
    },

注:推荐使用post方法,数据过多时get字符串拼接方式会报错 414 message Request-URL Too Long

 下载:

<el-link download href="http://127.0.0.1:8000/download_json/">
    <el-button>下载文件</el-button>
</el-link>

后端:

def crud(request):
    #   接收用户上传json
    if request.method == 'POST':
        image = request.FILES.get('jsonfile')
        if image.name.split('.')[-1] in ['json']:
            # 这里的file_path指的是服务器上保存图片的路径
            file_path = settings.JSON_ROOT + image.name[-10:]
            file_path = default_storage.save(file_path, image)
            path_root = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))

            return JsonResponse({
                'success': True,
                # 这里的file_path指的是访问该图片的url
                # 'file_path': settings.MEDIA_URL + file_path.split('/')[-1],
                'file_path': path_root + settings.JSON_URL + file_path.split('/')[-1],
                'msg': 'Success!'
            })
        else:
            return JsonResponse({
                'success': False,
                'file_path': '',
                'msg': 'Unexpected File Format'
            })
    else:
        raise PermissionDenied('Only Accept POST Request!')

接收用户上传的json文件保存到服务器

如果文件上传成功后调用接口返回el树形列表需要的data:

def crud_json(request):
    #   从后端返回json
    file_dir = r"E:\Code\PycharmProjects\test718\media\json"
    file_dict = {}
    lists = os.listdir(file_dir)  # 先获取文件夹内的所有文件
    for i in lists:  # 遍历所有文件
        ctime = os.stat(os.path.join(file_dir, i)).st_ctime
        file_dict[ctime] = i  # 添加创建时间和文件名到字典
    max_ctime = max(file_dict.keys())  # 取值最大的时间
    print(file_dict[max_ctime])  # 打印出最新文件名
    a = file_dict[max_ctime]
    json_path = os.path.join(file_dir, a)
    with open(json_path, encoding='utf-8') as f:
        res = json.load(f)
        # print(res)
        res = json.dumps(res)
        # print(res)
    return HttpResponse(res)

注:遍历最新上传的文件返回给前端

前端提交后后端拿到el树形列表data调用方法(获取总结点个数用于第二次使用)保存到固定json文件内:

class ResetTreeId:
    def __init__(self):
        return

    def reset_tree_ids(self, dic):
        """
        :param dic:
        :return:
        """
        dic["id"] = self.reset_id
        self.reset_id += 1
        if "children" not in dic:
            return dic
        tmp_children = []
        for nt in dic["children"]:
            tmp_children.append(self.reset_tree_ids(nt))
        dic["children"] = tmp_children
        return dic

    def reset(self, js):
        self.reset_id = 1
        # 中括号
        dic = self.reset_tree_ids(js["tree"][0])
        js = {"size": self.reset_id, "tree": dic}
        self.reset_id = 1
        return js


RTI = ResetTreeId()
def crud_get(request):
    #   保存修改后json文件
    data = request.body.decode()
    tree = json.loads(data)
    jsonfile = {"size": 1000, "tree": tree}
    jsonfile = RTI.reset(jsonfile)
    jsonfile = json.dumps(jsonfile, indent=4, ensure_ascii=False)
    # print(json)
    json_path = os.path.join(root_dir, "data/result.json")
    with open(json_path, "w", encoding='utf-8') as f:
        f.write(jsonfile)
    return HttpResponse('保存成功')

前端点击下载后返回给前端二进制文件流:

def read_file(file_name, chunk_size=512):
    with open(file_name, "rb") as f:
        while True:
            c = f.read(chunk_size)
            if c:
                yield c
            else:
                break
def download_json(request):
    #   下载Json

    file_path = os.path.join(root_dir, "data/result.json")
    file_name = "result.json"
    response = StreamingHttpResponse(read_file(file_path))
    response["Content-Type"] = "application/octet-stream"
    response["Content-Disposition"] = 'attachment; filename={0}'.format(file_name)
    response["Access-Control-Expose-Headers"] = "Content-Disposition"  # 为了使前端获取到Content-Disposition属性

    return response

避坑:

el树形列表数据必须要有id值

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值