一、创建标准项目工程
注意:node.js版本要正确
以下都要管理员身份打开cmd窗口
若遇到创建项目的时候,出现卡顿不停,解决方案:
npm config set registry https://registry.npmmirror.com
npm config get registry #检查是否正确
创建myProject工程,使用vue模板:
npm init vite@latest myProject -- --template vue
进入创建的项目
cd .\myProject\
下载elemen-plus模板
npm install element-plus --save
进入项目的main.js下:
原始:
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
createApp(App).mount('#app')
修改成:
注意:要先下载:element-plus
npm install element-plus
import { createApp } from 'vue'
// 1.引入element - plus组件
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import './style.css'
import App from './App.vue'
const app = createApp(App);
// 2.挂载到根节点
app.use(ElementPlus);
app.mount('#app');
二、Tree树形控件使用
Element-plus官网:Button 按钮 | Element Plus
去Element-plus官网找到对应的树形控件使用即可
选择自定义节点内容——这个有添加和删除,比较方便
将其代码复制放到前端项目工程即可(我的放在App.Vue)
项目需求只用到这个,上面部分没使用
<template>
<div class="custom-tree-container">
<el-tree
:data="data"
show-checkbox
node-key="id"
default-expand-all
:expand-on-click-node="false"
>
<template #default="{ node, data }">
<span class="custom-tree-node">
<span>{{ node.label }}</span>
<span>
<a @click="append(data)"> + </a>
</span>
</span>
</template>
</el-tree>
</div>
<el-button @click="handleNodeClick">hello</el-button>
</template>
官网源代码的JS使用Vue3的可以直接使用和更改即可,我使用的是Vue2,所以直接自己改
因为是前后端分离项目,故需要下载axios
npm install axios
JS代码如下:
script>
import axios from 'axios';
export default {
name: 'App',
data() {
return {
data: [], // 数据
label:{}, // 父亲节点对象
defaultProps: {
children: 'children',
label: 'label',
},
};
},
created() {
},
methods: {
handleNodeClick(data) {
axios
.get('http://localhost:8080/showNode', {
params: {
nodeId: data.label,
},
})
.then((response) => {
this.data = response.data.data
})
.catch((error) => {
console.error(error);
});
},
// 添加节点
append(data) {
// 获取弹框的值
this.$prompt('请输入要添加的产品类型', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
}).then(({ value }) => {
const newChild = {
// 将弹框的值赋值给label,既节点名称
label: value,
fatherId: data.id // 添加节点时传递父节点的ID信息
};
axios
.post('http://localhost:8080/addNode', newChild)
.then((response) => {
data.children.push(response.data.data);
console.log(response)
})
.catch((error) => {
console.error(error);
});
});
},
},
};
</script>
数据库结构如下:
对应的实体:
package com.example.demo.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import java.util.List;
/**
* 节点实体
*/
@Data
public class Node {
/**
* 设置自动增长生产主键值
*/
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
/**
* 节点名称
*/
private String label;
/**
* 父亲节点id
*/
private Integer fatherId;
@TableField(exist = false)
/**
* 孩子节点
*/
private List<Node> children;
}
统一异常处理:
package com.example.demo.domain;
import lombok.Data;
/**
* 统一异常处理
*
* @param <T>
*/
@Data
public class R<T> {
/**
* 响应编码
*/
private String code;
/**
* 响应信息
*/
private String msg;
/**
* 响应数据
*/
private T data;
/**
* 请求成功
*/
public static <T> R success(T data) {
R<Object> objectR = new R<>();
objectR.setCode("200");
objectR.setMsg("请求成功");
objectR.setData(data);
return objectR;
}
/**
* 请求失败
*
* @param <T>
* @return
*/
public static <T> R error() {
R<Object> objectR = new R<>();
objectR.setCode("500");
objectR.setMsg("请求失败");
return objectR;
}
}
跨域问题解决:
package com.example.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* 跨域问题解决
*/
@Configuration
public class CrosConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowCredentials(false)
.allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")
.allowedOrigins("*");
}
};
}
}
配置文件:
server:
port: 8080
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/数据库名?serverTimezone=UTC
username: 账户
password: 密码
引入所需依赖:
<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3</version>
</dependency>
<dependency>
<!--主要groupId是mysql-->
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
数据访问层:
package com.example.demo.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo.domain.Node;
import org.apache.ibatis.annotations.Mapper;
/**
* 数据访问层
*/
@Mapper
public interface NodeMapper extends BaseMapper<Node> {
}
业务逻辑层:
package com.example.demo.service;
import com.example.demo.domain.Node;
import com.example.demo.domain.R;
import com.fasterxml.jackson.core.JsonProcessingException;
import java.util.List;
public interface NodeService {
/**
* 展示节点
*
* @return
*/
R showNode();
/**
* 添加节点
*
* @param node
* @return
*/
R addNode(Node node);
}
package com.example.demo.service.impl;
import com.example.demo.dao.NodeMapper;
import com.example.demo.domain.Node;
import com.example.demo.domain.R;
import com.example.demo.service.NodeService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.LinkedList;
import java.util.List;
/**
* 业务逻辑层
*/
@Service
public class NodeServiceImpl implements NodeService {
@Autowired
private NodeMapper nodeMapper;
/**
* 展示节点信息
*
* @return
*/
@Override
public R showNode() {
List<Node> nodes = nodeMapper.selectList(null);
// 有fatherId的节点,走递归
LinkedList<Node> childNode = new LinkedList<>();
// 所有的节点
LinkedList<Node> allNode = new LinkedList<>();
// 遍历节点
for (Node node : nodes) {
if (node.getFatherId().equals(0)) {
allNode.add(node);
} else {
childNode.add(node);
allNode.add(node);
}
}
List<Node> nodes1 = forEach(childNode, allNode);
LinkedList<Node> allNodes = new LinkedList<>();
for (Node node : nodes1) {
if (node.getFatherId().equals(0)) {
allNodes.add(node);
}
}
return R.success(allNodes);
}
/**
* 添加节点信息
*
* @param node
* @return
*/
@Override
public R addNode(Node node) {
int insert = nodeMapper.insert(node);
if (insert > 0) {
return R.success(node);
}
return R.error();
}
// 遍历所有节点的孩子
public List<Node> forEach(List<Node> childNode, List<Node> allNode) {
// 遍历所有节点
for (Node node : allNode) {
LinkedList<Node> childs = new LinkedList<>();
// 遍历所有有fatherId的节点
for (Node node1 : childNode) {
// 如果孩子节点的fatherId与节点的Id相同,则为其孩子
if (node1.getFatherId().equals(node.getId())) {
// 将该节点添加为孩子节点
childs.add(node1);
}
}
// 将孩子集合设为节点的孩子集合
node.setChildren(childs);
}
return allNode;
}
}
控制层:
package com.example.demo.controller;
import com.example.demo.domain.Node;
import com.example.demo.domain.R;
import com.example.demo.service.NodeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
public class NodeController {
@Autowired
private NodeService nodeService;
@GetMapping("/showNode")
R nodeShow() {
R r = nodeService.showNode();
return r;
}
@PostMapping("/addNode")
R addNode(@RequestBody Node node) {
R r = nodeService.addNode(node);
return r;
}
}