建表语句

DROP TABLE IF EXISTS `sys_dept`;
CREATE TABLE `sys_dept` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '部门id',
`parent_id` bigint(20) DEFAULT '0' COMMENT '父部门id',
`ancestors` varchar(256) DEFAULT '' COMMENT '祖级列表',
`dept_name` varchar(64) DEFAULT '' COMMENT '部门名称',
`order_num` int(4) DEFAULT '0' COMMENT '显示顺序',
`status` tinyint(1) DEFAULT '0' COMMENT '部门状态(0正常 1停用)',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`create_user_id` bigint(20) DEFAULT NULL COMMENT '创建人id',
`create_user_name` varchar(64) DEFAULT NULL COMMENT '创建人姓名',
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
`update_user_id` bigint(20) DEFAULT NULL COMMENT '修改人id',
`update_user_name` varchar(64) DEFAULT NULL COMMENT '修改人姓名',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `uk_dept_name` (`parent_id`,`dept_name`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8 COMMENT='部门表'; -- ----------------------------
-- Records of sys_dept
-- ----------------------------
BEGIN;
INSERT INTO `sys_dept` VALUES (1, 0, '0', 'XX科技', 0, 0, '2021-10-09 10:31:47', 1, '系统管理员', NULL, NULL, NULL);
INSERT INTO `sys_dept` VALUES (2, 1, '0,1', '商务部', 3, 0, '2021-12-06 15:33:20', 1, '系统管理员', '2021-12-06 15:58:30', 1234, '管理');
INSERT INTO `sys_dept` VALUES (3, 1, '0,1', 'XX关务部', 4, 0, '2021-12-06 15:37:01', 1, '系统管理员', '2021-12-06 15:40:15', 1, '系统管理员');
INSERT INTO `sys_dept` VALUES (4, 1, '0,1', 'XX货主', 6, 0, '2021-12-06 15:38:34', 1, '系统管理员', '2021-12-06 17:17:27', 1, '系统管理员');
INSERT INTO `sys_dept` VALUES (5, 1, '0,1', '技术部', 1, 0, '2021-12-06 15:39:22', 1, '系统管理员', '2021-12-06 15:57:48', 1234, '管理');
INSERT INTO `sys_dept` VALUES (6, 4, '0,1,4', '货主-A', 1, 0, '2021-12-06 16:15:26', 1234, '小A', '2021-12-06 17:16:33', 1, '系统管理员');
INSERT INTO `sys_dept` VALUES (7, 4, '0,1,4', '货主-B', 2, 0, '2021-12-06 16:15:39', 1234, '小A', '2021-12-06 17:17:37', 1, '系统管理员');
INSERT INTO `sys_dept` VALUES (8, 6, '0,1,4,6', '1', 11, 0, '2022-03-16 10:27:28', 1, '系统管理员', '2022-03-16 10:27:37', 1, '系统管理员');
INSERT INTO `sys_dept` VALUES (9, 8, '0,1,4,6,8', '111111', 0, 0, '2022-03-16 10:27:45', 1, '系统管理员', NULL, NULL, NULL);
COMMIT;

新增

@Data
@ApiModel(value = "部门编辑对象", description = "部门编辑请求对象")
public class DeptEditRequest {
@ApiModelProperty(value = "主键id", example = "-1")
@DecimalMin(value = "1", message = "角色id最小为1")
private Long id; @ApiModelProperty(value = "父部门id", example = "-1")
@NotNull(message = "上级部门" + HibernateConstant.NOT_NULL)
@JsonProperty("parent_id")
private Long parentId; @ApiModelProperty(value = "部门名称", example = "IT部")
@NotBlank(message = "部门名称" + HibernateConstant.NOT_NULL)
@JsonProperty("dept_name")
private String deptName; @ApiModelProperty(value = "显示顺序", example = "0")
@NotNull(message = "显示" + HibernateConstant.NOT_NULL)
@JsonProperty("order_num")
private Integer orderNum; @ApiModelProperty(value = "部门状态(0正常 1停用)", example = "0")
@Min(value = 0, message = "部门状态(0正常 1停用)")
@Max(value = 1, message = "部门状态(0正常 1停用)")
private byte status;
}
    @ApiOperation("部门添加")
@PostMapping("add")
public JsonData add(
@RequestBody DeptAddRequest request
) {
return deptService.add(request);
}
    @Override
public JsonData add(DeptAddRequest request) {
DeptEditRequest deptEditRequest = new DeptEditRequest();
BeanUtils.copyProperties(request, deptEditRequest);
//同级部门下,部门名称重复
checkDeptNameUnique(deptEditRequest);
DeptDO deptDO = new DeptDO();
deptDO.setDeptName(request.getDeptName());
deptDO.setParentId(request.getParentId());
deptDO.setStatus(request.getStatus());
deptDO.setOrderNum(request.getOrderNum());
deptDO.setCreateTime(CommonUtil.getCurrentDate());
deptDO.setCreateUserId(CommonUtil.getCurrentUserId());
deptDO.setCreateUserName(CommonUtil.getCurrentUserName());
//检查上级部门状态
checkParentDeptState(deptDO);
int rows = deptMapper.add(deptDO);
if (rows > 0) {
log.info("部门添加,rows:{},添加成功:{}", rows, deptDO);
return JsonData.buildAddSuccess();
}
return JsonData.buildError("添加失败");
} /**
* 部门名称唯一值
*
* @param request
*/
private void checkDeptNameUnique(DeptEditRequest request) {
List<DeptDO> deptList = deptMapper.selectList(
new LambdaQueryWrapper<DeptDO>()
.eq(DeptDO::getDeptName, request.getDeptName())
.eq(DeptDO::getParentId, request.getParentId())
);
for (DeptDO deptDO : deptList) {
if (deptDO.getId() != request.getId()) {
throw new BizException(500, "部门已存在");
}
}
} /**
* 检查上级部门状态
*
* @param dept 部门对象
*/
private void checkParentDeptState(DeptDO dept) {
DeptDO deptDO = deptMapper.selectOne(
new LambdaQueryWrapper<DeptDO>()
.eq(DeptDO::getId, dept.getParentId())
);
if (deptDO == null) {
throw new BizException(500, "上级部门不存在");
}
if (1 == deptDO.getStatus()) {
throw new BizException(500, "上级部门已停用,不允许新增");
}
dept.setAncestors(deptDO.getAncestors() + "," + dept.getParentId());
}

编辑

@Data
@ApiModel(value = "部门编辑对象", description = "部门编辑请求对象")
public class DeptEditRequest {
@ApiModelProperty(value = "主键id", example = "-1")
@DecimalMin(value = "1", message = "角色id最小为1")
private Long id; @ApiModelProperty(value = "父部门id", example = "-1")
@NotNull(message = "上级部门" + HibernateConstant.NOT_NULL)
@JsonProperty("parent_id")
private Long parentId; @ApiModelProperty(value = "部门名称", example = "IT部")
@NotBlank(message = "部门名称" + HibernateConstant.NOT_NULL)
@JsonProperty("dept_name")
private String deptName; @ApiModelProperty(value = "显示顺序", example = "0")
@NotNull(message = "显示" + HibernateConstant.NOT_NULL)
@JsonProperty("order_num")
private Integer orderNum; @ApiModelProperty(value = "部门状态(0正常 1停用)", example = "0")
@Min(value = 0, message = "部门状态(0正常 1停用)")
@Max(value = 1, message = "部门状态(0正常 1停用)")
private byte status;
}
    @ApiOperation("部门修改")
@PostMapping("edit")
public JsonData edit(
@RequestBody DeptEditRequest request
) {
if (request.getId() == 1) {
throw new BizException(500, "不允许操作系统默认部门");
}
return deptService.edit(request);
}
    @Override
@Transactional
public JsonData edit(DeptEditRequest request) {
DeptDO deptDO = new DeptDO();
BeanUtils.copyProperties(request, deptDO);
//同级部门下,部门名称重复
checkDeptNameUnique(request);
//检查上级部门状态
checkParentDeptState(deptDO);
//上级部门不能是自己
checkParentDept(request);
//父级对象
DeptDO parentDept = deptMapper.selectOne(
new LambdaQueryWrapper<DeptDO>()
.eq(DeptDO::getId, deptDO.getParentId())
);
if (parentDept == null) {
throw new BizException(500, "上级部门不存在");
}
DeptDO oldDept = deptMapper.selectOne(
new LambdaQueryWrapper<DeptDO>()
.eq(DeptDO::getId, deptDO.getId())
);
if (oldDept == null) {
throw new BizException(500, "记录不存在,请稍后重试");
}
String newAncestors = parentDept.getAncestors() + "," + parentDept.getId();
String oldAncestors = oldDept.getAncestors();
deptDO.setAncestors(newAncestors);
byte oldState = oldDept.getStatus();
int rows = deptMapper.updateById(deptDO);
if (rows > 0) {
log.info("部门修改,rows:{},修改成功:{}", rows, deptDO);
//递归处理子部门状态
if (oldState != deptDO.getStatus()) {
updateChildDeptState(deptDO, newAncestors, oldAncestors);
}
return JsonData.buildEditSuccess();
}
return JsonData.buildError("修改失败");
} /**
* 部门名称唯一值
*
* @param request
*/
private void checkDeptNameUnique(DeptEditRequest request) {
List<DeptDO> deptList = deptMapper.selectList(
new LambdaQueryWrapper<DeptDO>()
.eq(DeptDO::getDeptName, request.getDeptName())
.eq(DeptDO::getParentId, request.getParentId())
);
for (DeptDO deptDO : deptList) {
if (deptDO.getId() != request.getId()) {
throw new BizException(500, "部门已存在");
}
}
} /**
* 检查上级部门状态
*
* @param dept 部门对象
*/
private void checkParentDeptState(DeptDO dept) {
DeptDO deptDO = deptMapper.selectOne(
new LambdaQueryWrapper<DeptDO>()
.eq(DeptDO::getId, dept.getParentId())
);
if (deptDO == null) {
throw new BizException(500, "上级部门不存在");
}
if (1 == deptDO.getStatus()) {
throw new BizException(500, "上级部门已停用,不允许新增");
}
dept.setAncestors(deptDO.getAncestors() + "," + dept.getParentId());
} /**
* 上级部门不能是自己
*
* @param request
*/
private void checkParentDept(DeptEditRequest request) {
if (request.getId().equals(request.getParentId())) {
throw new BizException(500, "上级部门不能是自己");
}
} /**
* 处理子部门状态
*
* @param deptDO 部门对象
* @param newAncestors 新的父ID集合
* @param oldAncestors 旧的父ID集合
*/
private void updateChildDeptState(DeptDO deptDO, String newAncestors, String oldAncestors) {
deptMapper.batchUpdateChildDeptState(deptDO.getId(), deptDO.getStatus());
//找所有子部门
List<DeptDO> deptList = deptMapper.selectChildrenDeptById(deptDO.getId());
for (DeptDO dpt : deptList) {
dpt.setAncestors(dpt.getAncestors().replaceFirst(oldAncestors, newAncestors));
deptMapper.updateById(dpt);
}
}
    /**
* 批量更新子部门状态
*
* @param id 部门id
* @param state 状态
* @return
*/
int batchUpdateChildDeptState(
@Param("id") Long id,
@Param("state") Byte state
); <!-- 批量更新子部门状态 -->
<update id="batchUpdateChildDeptState">
UPDATE
sys_dept
SET
`status`=#{state}
WHERE ancestors LIKE CONCAT('%',#{id},'%')
</update> /**
* 根据id找所有子部门
*
* @param id
* @return
*/
List<DeptDO> selectChildrenDeptById(@Param("id") Long id); <!-- 根据id找所有子部门 -->
<select id="selectChildrenDeptById" resultMap="BaseResultMap">
SELECT
id,
parent_id,
ancestors,
dept_name,
order_num,
`status`,
create_time,
create_user_id,
create_user_name,
update_time,
update_user_id,
update_user_name
FROM
sys_dept
WHERE
FIND_IN_SET(#{id},ancestors)
</select>

删除

    @ApiOperation("部门删除")
@GetMapping("remove")
public JsonData remove(
@ApiParam(value = "部门id", required = true) @RequestParam(value = "id", required = true) Long id
) {
if (id == 1) {
throw new BizException(500, "不允许操作系统默认部门");
}
return deptService.remove(id);
}
    @Override
public JsonData remove(Long id) {
int rows = deptMapper.deleteById(id);
if (rows > 0) {
log.info("部门删除,rows:{},删除成功:{}", rows, id);
//递归删除子部门
removeChildDept(id);
return JsonData.buildRemoveSuccess();
}
return JsonData.buildError("部门删除失败");
} /**
* 删除子部门
*
* @param parentId
*/
private void removeChildDept(Long parentId) {
List<DeptDO> deptList = deptMapper.selectList(
new LambdaQueryWrapper<DeptDO>()
.eq(DeptDO::getParentId, parentId)
);
for (DeptDO deptDO : deptList) {
deptMapper.deleteById(deptDO.getId());
removeChildDept(deptDO.getId());
}
}

递归树

@Data
@ApiModel(value = "DeptTreeVo对象", description = "部门树对象信息")
public class DeptTreeVo {
@ApiModelProperty("节点id")
@JsonSerialize(using = ToStringSerializer.class)
private Long id; @ApiModelProperty("节点名称")
private String label; @ApiModelProperty("子节点")
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private List<DeptTreeVo> children;
}
    @ApiOperation("部门树")
@GetMapping("deptTree")
public JsonData<List<DeptTreeVo>> deptTree() {
return deptService.deptTree();
}
    private static final ThreadPoolExecutor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(
APS * 2,
APS * 4,
KEEP_ALIVE_TIME,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(256),
new ThreadFactoryBuilder().setNameFormat("部门-pool-%d").build(),
new ThreadPoolExecutor.CallerRunsPolicy()
); @Override
public JsonData<List<DeptTreeVo>> deptTree() {
LambdaQueryWrapper<DeptDO> wrapper = new LambdaQueryWrapper<DeptDO>();
wrapper.orderByAsc(DeptDO::getParentId, DeptDO::getOrderNum);
List<DeptDO> deptList = deptMapper.selectList(wrapper);
return buildDeptTree(deptList);
} /**
* 构建前端需要构建树结构
*
* @param deptList 部门集合
* @return
*/
private JsonData<List<DeptTreeVo>> buildDeptTree(List<DeptDO> deptList) {
List<DeptTreeVo> deptTreeList = new ArrayList<>();
List<DeptDO> rootDeptList = deptList.stream().filter(obj -> 1 == obj.getId()).collect(Collectors.toList());
CountDownLatch latch = new CountDownLatch(rootDeptList.size());
for (DeptDO deptDO : rootDeptList) {
THREAD_POOL_EXECUTOR.execute(() -> {
DeptTreeVo vo = new DeptTreeVo();
vo.setId(deptDO.getId());
vo.setLabel(deptDO.getDeptName());
buildChildrentDeptTree(deptList, deptDO.getId(), vo);
deptTreeList.add(vo);
latch.countDown();
});
}
try {
latch.await();
} catch (InterruptedException e) {
log.error("构建部门树结构线程报错:{}", e);
}
return JsonData.buildSuccess(deptTreeList);
} /**
* 构建子部门树
*
* @param deptList 部门集合
* @param parentId 父ID
* @param vo 部门树
*/
private void buildChildrentDeptTree(List<DeptDO> deptList, Long parentId, DeptTreeVo vo) {
List<DeptDO> childList = deptList.stream().filter(obj -> parentId == obj.getParentId()).collect(Collectors.toList());
List<DeptTreeVo> childDeptTreeList = new ArrayList<>();
for (DeptDO deptDO : childList) {
DeptTreeVo dtv = new DeptTreeVo();
dtv.setId(deptDO.getId());
dtv.setLabel(deptDO.getDeptName());
buildChildrentDeptTree(deptList, deptDO.getId(), dtv);
childDeptTreeList.add(dtv);
}
vo.setChildren(childDeptTreeList);
} @Data
@TableName("sys_dept")
@ApiModel(value = "SysDeptDO对象", description = "部门表")
public class DeptDO implements Serializable { private static final long serialVersionUID = 1L; @ApiModelProperty(value = "部门id")
@TableId(value = "id", type = IdType.AUTO)
private Long id; @ApiModelProperty(value = "父部门id")
private Long parentId; @ApiModelProperty(value = "祖级列表")
private String ancestors; @ApiModelProperty(value = "部门名称")
private String deptName; @ApiModelProperty(value = "显示顺序")
private Integer orderNum; @ApiModelProperty(value = "部门状态(0正常 1停用)")
private byte status; @ApiModelProperty(value = "创建时间")
@TableField(value = "create_time", fill = FieldFill.INSERT)
private Date createTime; @ApiModelProperty(value = "创建人id")
@TableField(value = "create_user_id", fill = FieldFill.INSERT)
private Long createUserId; @ApiModelProperty(value = "创建人姓名")
@TableField(value = "create_user_name", fill = FieldFill.INSERT)
private String createUserName; @ApiModelProperty(value = "修改时间")
@TableField(value = "update_time", fill = FieldFill.UPDATE)
private Date updateTime; @ApiModelProperty(value = "修改人id")
@TableField(value = "update_user_id", fill = FieldFill.UPDATE)
private Long updateUserId; @ApiModelProperty(value = "修改人姓名")
@TableField(value = "update_user_name", fill = FieldFill.UPDATE)
private String updateUserName;
}

树通用工具类

    /**
* 递归深度
*/
private static final int DEPTH = 20; /**
* 集合转树
* @param treeList 集合
* @param rootId 父节点
* @param <T>
*/
public static <T extends TreeNode<T>> void list2Tree(List<T> treeList,Long rootId){
if (CollUtil.isEmpty(treeList)){
return;
}
if (rootId==null){
throw new Exception("根节点不能为空");
}
List<T> rootList = getRoot(treeList, rootId);
if (CollUtil.isNotEmpty(rootList)){
List<T> result = new LinkedList<>();
rootList.stream().forEach(t-> result.add(getChildNode(t,0,treeList)));
treeList.clear();
treeList.addAll(rootList);
}
} private static <T extends TreeNode<T>> List<T> getRoot(List<T> treeList,Long rootId){
return treeList.stream().filter(t->Objects.equals(t.rootId(),rootId)).collect(Collectors.toList());
} private static <T extends TreeNode<T>> T getChildNode(T t,int depthCount,List<T> treeList){
if (depthCount>DEPTH){
throw new Exception("超过递归限制");
}
List<T> childList = treeList.stream().filter(item -> Objects.equals(item.rootId(), t.nodeId())).collect(Collectors.toList());
if (CollUtil.isNotEmpty(childList)){
int tempCount = ++depthCount;
childList.stream().forEach(child->t.childList().add(getChildNode(child,tempCount,treeList)));
}
return t;
}
import java.util.List;

public interface TreeNode<T> {
/**
* 节点id
* @return
*/
Long nodeId(); /**
* 父节点
* @return
*/
Long rootId(); /**
* 子级列表
* @return
*/
List<T> childList();
}
/**
* @description: 树VO
* @author: alex
* @create: 2024-03-16 15:46
*/
@Data
public class XxxxVO implements TreeNode<XxxxVO > { @ApiModelProperty("主键id")
private Long id; @ApiModelProperty("父ID")
private Long parentId; @ApiModelProperty("编码")
private String code; @ApiModelProperty("名称")
private String name; private List<XxxxVO> subList = new LinkedList<>(); @ApiModelProperty("是否尾节点")
private boolean isLastNode; @Override
public Long nodeId() {
return getId();
} @Override
public Long rootId() {
return getParentId();
} @Override
public List<XxxxVO> childList() {
return this.subList;
} public boolean isLastNode() {
return this.subList.size() == 0;
}
}

使用

//数据库中查询出来列表
List<XxxxVO> treeList=new LinkedList<>();
//转换树
TreeUtil.listToTree(treeList,0L);

java 高效递归查询树 find_in_set 处理递归树的更多相关文章

  1. 【转载】Oracle递归查询:使用prior实现树操作【本文出自叶德华博客】

    本文标题:Oracle递归查询:使用prior实现树操作 本文链接:http://yedward.net/?id=41 本文版权归作者所有,欢迎转载,转载请以文字链接的形式注明文章出处. Oracle ...

  2. Best Coder Round#25 1003 树的非递归访问

    虽然官方解释是这题目里的树看作无向无环图,从答案来看还是在“以1作为根节点”这一前提下进行的,这棵树搭建好以后,从叶节点开始访问,一直推到根节点即可——很像动态规划的“自底向上”. 但这棵树的搭建堪忧 ...

  3. Java数据结构和算法 - 什么是2-3-4树

    Q1: 什么是2-3-4树? A1: 在介绍2-3-4树之前,我们先说明二叉树和多叉树的概念. 二叉树:每个节点有一个数据项,最多有两个子节点. 多叉树:(multiway tree)允许每个节点有更 ...

  4. react封装组织架构递归树

    想用react实现一个递归树,但一些框架里面的有些不符合需求,于是自己写了个,功能比较简单,欢迎批评指正.. react实现这样一个组织架构递归树,下级部门的收起和展开,点击部门名称时请求接口获取下级 ...

  5. Java数据结构和算法(一)树

    Java数据结构和算法(一)树 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 前面讲到的链表.栈和队列都是一对一的线性结构, ...

  6. MIT6.006Lec03:插入排序,归并排序,递归树

    MIT6.006是算法导论课,Lec03主要讲插入排序,归并排序,以及分析方法(递归树)等. 插入排序,可以分为线性插入排序.二分插入排序,区别在于当把数组中某元素插入到前面的有序列表中时,前者遍历, ...

  7. java数据结构和算法07(2-3-4树)

    上一篇我们大概了解了红黑树到底是个什么鬼,这篇我们可以看看另外一种树-----2-3-4树,看这个树的名字就觉得很奇怪.... 我们首先要知道这里的2.3.4指的是任意一个节点拥有的子节点个数,所以我 ...

  8. java数据结构和算法08(B树的简单原理)

    这一篇首先会说说前面剩余的一点知识2-3树,然后简单说说B树,不写代码,只是简单看看原理吧! 为什么要说一下2-3树呢?了解2-3树之后能更快的了解B树: 1.简单看看2-3树 其实我们学过了前面的2 ...

  9. 【整理】iview Tree数据格式问题,无限递归树处理数据

    iview Tree数据格式问题,无限递归树处理数据 https://juejin.im/post/5b51a8a4e51d455d6825be20

  10. 递归树处理,配合vue的vueTreeselect组件使用

    在项目中经常会使用到tree,并且需要对递归树进行操作. 在vue项目中,使用vue-treeselect插件(https://vue-treeselect.js.org/) 使用中遇到的问题: 1. ...

随机推荐

  1. Django 安全性与防御性编程:如何保护 Django Web 应用

    title: Django 安全性与防御性编程:如何保护 Django Web 应用 date: 2024/5/13 20:26:58 updated: 2024/5/13 20:26:58 cate ...

  2. AIRIOT答疑第5期|如何使用低代码业务流引擎?

    推拉拽! AIRIOT平台业务流引擎可创建丰富的业务流程,实现从流程定义.数据处理.任务工单.消息通知.日志追踪的闭环流转.多类型节点任意组合,可视化流程日志,精准追踪流程流转.人工任务统一管理,审批 ...

  3. Vue 3.3 发布

    本文为翻译 原文地址:宣布推出 Vue 3.3 |The Vue Point (vuejs.org) 今天我们很高兴地宣布 Vue 3.3 "Rurouni Kenshin" 的发 ...

  4. 树莓派 ubuntu server 22.x 连接无线网络

    前言 树莓派系统安装完成后,需要配置网络,由于家里没有多余的网线(网线多少有点乱),所以决定配置无线上网的方式,现在记录下来操作过程 具体操作 sudo nano /etc/netplan/xxxxx ...

  5. .net程序员学习java篇一(搭建SSM)

    一.安装IDE 相比于.net环境的一气呵成,java可能麻烦一点,这里记录下来,避免萌新踩坑 1.1安装JDK,这里不要玩什么花哨,老老实实选个大众版(Oracle JDK1.8x),设置环境变量, ...

  6. RBD与Cephfs

    目录 1. RBD 1. RBD特性 2. 创建rbd池并使用 2.1 创建rbd 2.2 创建用户 2.3 下发用户key与ceph.conf 2.4 客户端查看pool 2.5 创建rbd块 2. ...

  7. Vue cli之使用Vue-CLI初始化创建前端项目

    1.生成项目目录 使用vue自动化工具可以快速搭建单页应用项目目录. 该工具为现代化的前端开发工作流提供了开箱即用的构建配置.只需几分钟即可创建并启动一个带热重载.保存时静态检查以及可用于生产环境的构 ...

  8. Python实现求多个集合之间的并集-方法2

    之前使用过一种方法实现求集合间的并集,参考文章:https://www.cnblogs.com/mrlayfolk/p/12373532.html,这次使用另外一种方法实现,这种方法效率更高. 目的: ...

  9. Redux之combineReducers方法

    Redux 提供了一个combineReducers方法,用于 Reducer 的拆分.你只要定义各个子 Reducer 函数,然后用这个方法,将它们合成一个大的 Reducer. import { ...

  10. 2024 Web 新特性 - 使用 Popover API 创建弹窗

    Popover API 为开发者提供了一种声明式的方式来创建各种类型的弹窗.目前已在所有三大浏览器引擎中可用,并正式成为 Baseline 2024 的一部分. 一直以来,我们在实现弹出式菜单.提示框 ...