【Vue】树状节点接口 与 级联选择框组件

 

原来有一个组织机构的渲染,

我自己写的我自己看也8太明白了:

1
https://www.cnblogs.com/mindzone/p/14888046.html

 

现在,有一个位置选择,使用这个级联选择器做的

1
https://element.eleme.cn/#/zh-CN/component/cascader#cascader-ji-lian-xuan-ze-qi

 

后台接口部分

首先是组件需要的节点数据结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package cn.ymcd.aisw.store.dto;
 
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
 
import java.io.Serializable;
import java.util.List;
 
/**
 * 树状节点PO
 * @author cloud9
 * @createTime 2022/5/18 09:55
 *
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class TreeNode implements Serializable {
    private static final long serialVersionUID = 1L;
    private String label;
    private Integer value;
    private List<TreeNode> children;
 
    public TreeNode(String label, Integer value) {
        this.label = label;
        this.value = value;
    }
}

 

数据库PO

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package cn.ymcd.aisw.store.dto;
 
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
 
import java.io.Serializable;
 
/**
 * 行政区域PO
 * @author cloud9
 * @createTime 2022/5/18 09:57
 *
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("PT_AREA")
public class AreaDTO implements Serializable {
    private static final long serialVersionUID = 1L;
    /**
     * 区域Id<br/> TYPE:NUMBER(22)
     */
    @TableField("AREAID")
    private Integer areaid;
 
    /**
     * 区域编码<br/> TYPE:NUMBER(22)
     */
    @TableField("AREACODE")
    private Integer areacode;
 
    /**
     * 区域名称<br/> TYPE:VARCHAR2(200)
     */
    @TableField("AREANAME")
    private String areaname;
 
    /**
     * 区域等级<br/> TYPE:VARCHAR2(2)
     */
    @TableField("AREALEVEL")
    private String arealevel;
 
    /**
     * 区域父级<br/> TYPE:NUMBER(22)
     */
    @TableField("AREAPARENT")
    private Integer areaparent;
 
    /**
     * 区域序号<br/> TYPE:NUMBER(22)
     */
    @TableField("AREASEQ")
    private Integer areaseq;
 
    /**
     * 是否可用<br/> TYPE:VARCHAR2(2)
     */
    @TableField("ISENABLED")
    private String isenabled;
 
}

 

接口业务实现类,就是如何组装级联选择器需要的数据结构:

省市县,全部最多的情况是四千多个不到,使用这种递归,还是能处理的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package cn.ymcd.aisw.store.service.impl;
 
import cn.ymcd.aisw.common.ApiConstants;
import cn.ymcd.aisw.store.dao.AreaDAO;
import cn.ymcd.aisw.store.dto.AreaDTO;
import cn.ymcd.aisw.store.dto.TreeNode;
import cn.ymcd.aisw.store.service.IAreaService;
import cn.ymcd.comm.base.BaseService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
 
import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;
 
/**
 * @projectName: aisw-root
 * @author: cloud9
 * @date: 2022年05月18日 10:02
 * @version: 1.0
 */
@Service("iAreaService")
public class AreaServiceImpl extends BaseService<AreaDAO, AreaDTO> implements IAreaService {
 
    @Resource
    private AreaDAO areaDAO;
 
    @Override
    public List<TreeNode> getAreaCodeList() {
        // 筛选所有(可用的 -> isenabled = 1)区域列表
        final List<AreaDTO> ALL_AVAILABLE_AREAS = areaDAO.selectList(
            new QueryWrapper<AreaDTO>()
            .lambda()
            .eq(AreaDTO::getIsenabled, ApiConstants.STATUS_NORMAL)
        );
 
        // 筛选第一级区域的 TreeNode列表,此时每一个节点都没有子集
        List<TreeNode> headerTreeNodes = ALL_AVAILABLE_AREAS
                .stream()
                .filter(area -> area.getAreaparent().equals(0))
                .map(area -> new TreeNode(area.getAreaname(), area.getAreacode()))
                .collect(Collectors.toList());
 
        // 然后对头的每个节点进行递归获取内部节点
        headerTreeNodes.forEach(header -> buildTreeNodeWithRecursive(header, ALL_AVAILABLE_AREAS));
        return headerTreeNodes;
    }
 
    /**
     * 使用递归进行树状节点集构建
     * @param treeNode 需要被装填(若干层级)的节点
     * @param ALL_AREA_LIST 树状节点的数据源
     * @return void
     * @author cloud9
     * @createTime 2022/5/18 11:53
     *
     */
    private void buildTreeNodeWithRecursive(TreeNode treeNode, final List<AreaDTO> ALL_AREA_LIST) {
        // 获取入参节点的的子节点列表, 从总集合中过滤
        List<TreeNode> recursiveTreeNodeList = ALL_AREA_LIST
                .stream()
                .filter(area -> area.getAreaparent().equals(treeNode.getValue()))
                .map(area -> new TreeNode(area.getAreaname(), area.getAreacode()))
                .collect(Collectors.toList());
 
        // 如果这子节点是最后一层了,也就是查不到子节点集合,则终止这个递归
        if (CollectionUtils.isEmpty(recursiveTreeNodeList)) return;
 
        // 1、否则继续下去, 将子节点存入这个节点下面
        treeNode.setChildren(recursiveTreeNodeList);
 
        // 2、然后将这个子节点列表遍历, 获取它的后代
        recursiveTreeNodeList.forEach(childTreeNode -> this.buildTreeNodeWithRecursive(childTreeNode, ALL_AREA_LIST));
    }
 
}

  

前台渲染部分:

1
2
3
4
5
6
7
8
9
10
11
12
<el-form-item label="门店位置" prop="areaName">
  <el-cascader
    :ref="selectorRefTag"
    v-model="store.areaAddrs"
    placeholder="试试搜索:南昌"
    :props="{ value: 'label' }"
    :options="areaTreeNode"
    style="width: 220px"
    filterable
    @change="handleAreaSelectChange"
  />
</el-form-item>

数据来源,接口就是GET请求,不进行任何认证校验:

1
2
3
4
5
async created() {
  const { data: res } = await getAreaTreeNodeList()
  console.log(res)
  this.areaTreeNode = res
},

绑定的Change事件方法:

选中的数据会排在第一个,这里因为业务需要,我要的是路径标签

就是把这个PathLabels数组,转成拼接字符,也可以取PathValues取ID值

1
2
3
4
5
6
7
handleAreaSelectChange() {
  // 获取选中的所有节点的路径,并且用join()方法分割转换为字符串
  this.labels = this.$refs[this.selectorRefTag]
    .getCheckedNodes()[0]
    .pathLabels.join('')
  console.log(this.labels)
},

  

回显的问题:

设置的v-model值就是绑定选中数据,所以回显的时候,把这个绑定值赋值上去即可

1
2
/* 区域回显 */
if (this.store.areaName) this.store.areaAddrs = this.store.areaName.split(',')

  

 

 

posted @   emdzz  阅读(334)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
历史上的今天:
2020-05-18 【Tutorial C】04 基本输入输出
2020-05-18 【Tutorial C】01 概述
2020-05-18 【Git】01 下载安装(Windows)
2020-05-18 【PL/SQL】05 异常处理
2020-05-18 【PL/SQL】04 游标 Cursor
2020-05-18 【PL/SQL】03 流程控制
2020-05-18 【PL/SQL】02 基础语法
点击右上角即可分享
微信分享提示