每日学习两篇文章

vue千位分隔符

MyBatis的xml写法

idea启动控制台tomcat中文乱码

常见的stream流方法

Collection集合、数组的遍历方式

vue页面浏览器缩放自适应

JVM的理解–理论篇

BigDecimal的常用运算

触发器的使用

存储过程的使用

el-input等显示框鼠标悬浮显示全部内容

el-table在JS中赋值内容后表格数据刷新

JS对象赋值,操作新对象影响原对象

java将数据处理成JSON树形结构

千位分隔符

场景:金额显示123,456 123456 =>123,456

方式1:js方法
numberExchange(value){
	   if (!value) return 0
	   // 获取整数部分
	   const intPart = Math.trunc(value)
	   // 整数部分处理,增加,
	   const intPartFormat = intPart.toString().replace(/(\d)(?=(?:\d{3})+$)/g, '$1,')
	   // 预定义小数部分
	   let floatPart = ''
	   // 将数值截取为小数部分和整数部分
	   const valueArray = value.toString().split('.')
	   if (valueArray.length === 2) {
	       // 有小数部分
	       floatPart = valueArray[1].toString() // 取得小数部分
	       return intPartFormat + '.' + floatPart
	   }
	   return intPartFormat + floatPart
	   }

 }
方式2:el-table表格
加入 :formatter="numberFormat"
<el-table-column
    prop="htsno"
    label="合同序号"
    width="100"
    :formatter="numberFormat"
    >
</el-table-column>

 js部分:
numberFormat (row, column, cellValue) {
     cellValue += ''
     if (!cellValue.includes('.')) cellValue += '.'
     return cellValue.replace(/(\d)(?=(\d{3})+\.)/g, function ($0, $1) {
       		return $1 + ','
     }).replace(/\.$/, '')
  },

MyBatis的xml写法

1.foreach
2.<、>、>=、<=
1.foreach

场景:编写sql语句:select name,sex from student where name in (’小谭‘,‘小花’);

 <select id="selectStudent" resultType="com.broad.emc.entity.Student" parameterType="java.util.List">
     select name sex from student
     where name in
     <foreach item="name" collection="nameList" open="(" separator="," close=")">
         #{name}
     </foreach>
 </select>
 
-- 参数是List集合nameList,元素是name
2.<、>、>=、<=

场景:sql语句 select name from student where age<=16,xml无法识别<=,需要转义

大于	 >					==>  &gt;
大于等于	 >=				==>  &gt;=
小于	 <	       			==>  &lt;
小于等于	 <=				==>  &lt;=
不等于	 <> !=			==>  &lt;&gt;

select name from student where age &lt;=16

idea启动控制台tomcat中文乱码

场景:在idea中启动项目,但是控制台中tomcat信息乱码了

方法1:找到tomcat的文件夹的conf文件夹的配置文件logging.properties,新增java.util.logging.ConsoleHandler.encoding =GBK

在这里插入图片描述

方法2:打开tomcat的配置页面,在VM options 新增 -Dfile.encoding=UTF-8

在这里插入图片描述

然后在idea中修改encoding,在File-setting-Editor-File Encodings修改对应的encoding为UTF-8

在这里插入图片描述

方法3: 打开idea本地安装目录的bin文件夹,打开idea.exe.vmoptions跟idea64.exe.vmoptions,在文件末尾添加 -Dfile.encoding=UTF-8

在这里插入图片描述

常见的stream流方法

stream流的创建:

		//集合创建流对象 list/set
        //1.1 创建Collection系列集合Stream流对象 list
        List<String> list=new ArrayList<>();
        Collections.addAll(list,"a","b","c");
        Stream<String> stream=list.stream();
        
        //1.2 创建Collection系列集合Stream流对象 set
        Set<String> set =new HashSet<>();
        Collections.addAll(set,"a","b","c");
        Stream<String> stream1=set.stream();
        
        //2.创建Map系列集合Stream流对象
        Map<String,Integer> map=new HashMap<>();
        map.put("张三",19);
        map.put("李四",20);
        //方法1:把键值对 封装成一个整体
        Set<Map.Entry<String, Integer>> entries=map.entrySet();
        Stream<Map.Entry<String, Integer>> stream2=entries.stream();
        //方法2: 分别把集合中的键和值取出单独放在集合中
        Set<String> key=map.keySet();
        Collection<Integer> value= map.values();
        Stream<String> stream3=key.stream();
        Stream<Integer> stream4=value.stream();
        
        //3. 创建数组Stream流对象
        String[] strings=new String[]{"a","b","c"};
        //方法1:Arrays.stream()
        Stream<String> stream5=Arrays.stream(strings);
        //方法2:Stream.of() 对于集合也适用
        Stream<String> stream6=Stream.of(strings);

		//4. 补充: stream对象转list对象
        List<String> newList=stream.collect(Collectors.toList());
常见的stream API:
  1. filter(Predicate predicate):根据给定的条件过滤元素
  2. forEach(Consumer action):对每个元素执行给定的操作
  3. anyMatch(Predicate predicate):检查是否有至少一个元素符合给定的条件
  4. map(Function<T, R> mapper): 将每个元素转换为另一个元素
  5. distinct():去重,去掉重复的元素
  6. sorted(): 排序,将元素排序 自然排序/逆向排序
  1. filter 根据给定的条件过滤元素

场景:数组、集合根据需求快速过滤到需要的数据
Predicate 接口有一个抽象方法 test(T t),它接受一个类型为 T 的参数,返回一个布尔值。

		List<String> lists=new ArrayList<>();
        Collections.addAll(lists,"a","aaaaaaaaa","aaa","aaaaa");
        Stream<String> stream=lists.stream();

        Stream<String> result=stream.filter(res -> !res.equals("a"));
        //result.forEach(System.out::println);
        result.forEach(s -> System.out.println(s));
  1. anyMatch 检查是否有至少一个元素符合给定的条件 返回boolean

场景:判断数组中是否有小于3的数据,无需遍历对每个数进行判断

		Integer[] nums=new Integer[]{1,2,3,4,5,6,7};
        Stream<Integer> stream=Arrays.stream(nums);
        
        //判断数组中是否有小于3的数据
        Boolean flag=stream.anyMatch(res ->res<3);
        System.out.println(flag);   //true
  1. map将每个元素转换为另一个元素

场景:将集合list中的每个数乘2输出

	    Integer[] nums=new Integer[]{1,2,3,4,5,6,7};
        Stream<Integer> stream=Arrays.stream(nums);

        Stream<Integer> stream1=stream.map(s -> s*2);
        stream1.forEach(s-> System.out.println(s));
  1. distinct():去重,去掉重复的元素

场景:快速过滤掉一个集合/数组中重复元素

	    String[] strings=new String[]{"aaa","b","aaa","cc","张三","李四","张三","b"};
        Stream<String> stream=Arrays.stream(strings);
        Stream<String> stringStream=stream.distinct();
        
        stringStream.forEach(s -> System.out.println(s));
  1. sorted(): 排序,将元素排序 自然排序/逆向排序

场景:对一个数组/集合的数据进行排序,从大到小或从小到大排序;
班级学生按年龄进行排序;

		Integer[] nums=new Integer[]{2,5,3,5,6,21,1};
        Stream<Integer> stream=Arrays.stream(nums);
        //自然排序
        //Stream<Integer> stream1=stream.sorted();
        //逆向排序
        //Stream<Integer> stream2=stream.sorted(Comparator.reverseOrder());
        //列表排序 Student实体类按学生年龄排序
        //stream.sorted(Comparator.comparing(Student::getAge));
        //stream.sorted(Comparator.comparing(Student::getAge).reversed());

Collection集合、数组的遍历方式

场景:面试官提问,Collection集合有哪些遍历方式?普通for循环可以吗?
Q:一般情况下,普通for循环不能遍历集合,原因有二:其一是集合类的元素个数是动态变化的,普通for只能遍历固定长度元素,若集合类的元素个数发生变化,可能会出现索引越界异常;其二,对于有些集合如LinkedList,元素个数越多,循环次数越多,查询时间越慢

集合遍历方式:

  1. 增强型for循环
  2. 迭代器
  3. Java 8的 Stream API
增强型for循环,本质是迭代器
      //增强型for循环
       List<String> list=new ArrayList<>();
       list.add("张三");
       list.add("李四");
       list.add("王五");
       list.add("老六");
       
       for(String s : list){
           System.out.println(s);
       }```



迭代器
   //迭代器遍历
   List<String> list=new ArrayList<>();
   list.add("张三");
   list.add("李四");
   list.add("王五");
   list.add("老六");

   Iterator iterator= list.iterator();
   while(iterator.hasNext()){
       System.out.println(iterator.next());
   }
Java 8的 Stream API,源码是增强型for循环,本质是迭代器(增强for本质就是迭代器)
		//stream forEach遍历
        List<String> list=new ArrayList<>();
        list.add("张三");
        list.add("李四");
        list.add("王五");
        list.add("老六");

        //list.stream().forEach(s -> System.out.println(s));
        list.forEach(s -> System.out.println(s));

数组的遍历方式:

  1. 普通for循环
  2. 增强型for循环
  3. Arrays工具类的toString静态方法(将一维数组转化为字符串形式)

vue页面浏览器缩放自适应

场景:vue项目页面在不同电脑上浏览器缩放比例不同,显示内容页面发生变化,需要自适应浏览器的缩放

在项目的 utils 下新建 devicePixelRatio.js 文件

class devicePixelRatio {
    /* 获取系统类型 */
    getSystem() {
      const agent = navigator.userAgent.toLowerCase();
      const isMac = /macintosh|mac os x/i.test(navigator.userAgent);
      if (isMac) return false;
      // 目前只针对 win 处理,其它系统暂无该情况,需要则继续在此添加即可
      if (agent.indexOf("windows") >= 0) return true;
    }
    /* 监听方法兼容写法 */
    addHandler(element, type, handler) {
      if (element.addEventListener) {
        element.addEventListener(type, handler, false);
      } else if (element.attachEvent) {
        element.attachEvent("on" + type, handler);
      } else {
        element["on" + type] = handler;
      }
    }
    /* 校正浏览器缩放比例 */
    correct() {
      // 页面devicePixelRatio(设备像素比例)变化后,计算页面body标签zoom修改其大小,来抵消devicePixelRatio带来的变化
      document.getElementsByTagName("body")[0].style.zoom =
        1 / window.devicePixelRatio;
    }
    /* 监听页面缩放 */
    watch() {
      const that = this;
      // 注意: 这个方法是解决全局有两个window.resize
      that.addHandler(window, "resize", function () {
        that.correct(); // 重新校正浏览器缩放比例
      });
    }
    /* 初始化页面比例 */
    init() {
      const that = this;
      // 判断设备,只在 win 系统下校正浏览器缩放比例
      if (that.getSystem()) {
        that.correct(); // 校正浏览器缩放比例
        that.watch(); // 监听页面缩放
      }
    }
  }
  export default devicePixelRatio;

在App.vue 中引入并使用

<template>
    <div id="app">
      <router-view></router-view>
    </div>
  </template>

<script>
import devPixelRatio from "./utils/devicePixelRatio";
export default {
    name: "App",
    created() {
        new devPixelRatio().init(); // 初始化页面比例
    },
};
</script>

<style >
body {
  margin: 0;
  padding: 0;
}
</style>

BigDecimal的常用运算

场景: 项目在计算财务合同提成时表示金额,使用浮点型可能会丢失精度,使用BigDecimal类型表示金额,涉及到常用加减乘除,保留小数,两个BigDecimal数值比较
注意 :BigDecimal有多种构造函数,常用的有2种。建议使用String构造方式,不建议使用double构造方式,会丢失精度。
BigDecimal num=new BigDecimal(“12345.59”);

  1. 加法:add()函数
  2. 减法:subtract()函数
  3. 乘法:multiply()函数
  4. 除法:divide(除数,精确的小数位数,舍入模式) ROUND_HALF_UP 四舍五入
  5. 绝对值:abs()函数
  6. 保留小数:setScale(保留小数,舍入模式)
	BigDecimal Lrl=( ( (sr.subtract(nhcb).subtract(sbft).subtract(fy)) .multiply  ( new BigDecimal(“0.9892”)  ) .multiply ( new BigDecimal(0.85) ) )
                    .divide(sr,4,BigDecimal.ROUND_HALF_UP)  ) .doubleValue();
	Lrl=Lrl.setScale(6, BigDecimal.ROUND_HALF_UP);

两个BigDecimal大小比较 compareTo

 		BigDecimal num1=new BigDecimal("123");
        BigDecimal num2=new BigDecimal("456");
        int flag = num1.compareTo(num2);
        flag = -1,表示num1小于num2;
        flag =0,表示num1等于num2;
        flag =1,表示num1大于num2;

触发器的使用

场景:监视某种情况,并触发某种操作。当对主表进行操作( insert,delete, update)时,就会激活它执行对从表进行操作。

  1. MySQL中对主表student(id,name)进行新增,从表成绩表socre(stu_id,score)添加学生id
  2. SQLServer中对主表ht_tcjg进行新增时,从表复制表ht_tcjg_copy进行备份操作

MySQL触发器语法:

triggerName :触发器名称,不能同名
after/before ::触发时间,可以为before(在检查约束前触发)或after(在检查约束后触发)
insert/update/delete :触发事件
new :引用触发器中发生变化的记录内容
old :引用触发器中发生变化的记录内容

create trigger triggerName	

after/before 

insert/update/delete on 表名

for each row 

begin

-- 触发器的逻辑代码;

end;

请添加图片描述

SQLServer触发器语法:

deleted: 更新前的数据
inserted: 更新后的数据

CREATE TRIGGER trigger_name
ON table_name
AFTER INSERT, UPDATE, DELETE  
AS
BEGIN
   -- 触发器的逻辑代码;
END

请添加图片描述

存储过程的使用

介绍:SQL语句需要先编译然后执行,而存储过程是一组为了完成特定功能的SQL语句集,经编译后存储在数据库中,用户通过指定存储过程的名字并给定参数(如果该存储过程带有参数)来调用执行它,个人将它理解为可调用的函数方法。

存储过程的创建

1. MySQL存储过程创建
2.SQLServer存储过程创建
MySQL存储过程创建
delimiter //
Create producedure 过程名([[in|out|inout]参数名 参数类型,[in|out|inout]参数名 数据类型...]])
	begin
		-- 逻辑代码
	end
	//
delimiter ;

-- delimiter (可省略):Mysql默认以“;”为分隔符,如果没有什么分隔符,则编译器会把存储过程当成SQL语句进行处理,因此编译过程会报错,所以要事先用“DELIMITER //声明当前段分隔符,让编译器把两个“//”之间的内容当做存储过程的代码,不会执行这些代码;"DELIMITER;"的意为把分隔符还原。
-- 参数:输入in、输出out、输入输出inout
	--	In:参数的值必须在调用存储过程时指定,在存储过程中修改该参数的值不能被返回,为默认值(参数值不受过程体影响,参数参与过程体逻辑,仅当作参数输入 )
	--	OUT:该值可在存储过程内部被改变,并可返回(参数值受过程体影响,参数不参与过程体逻辑 ,仅输出参数)
	--	InOUT:调用时指定,并且可被改变和返回(既当作参数输入,又输出参数)
-- 过程体:过程体的开始与结束使用begin和end进行标识


ex:in参数

delimiter //
create PROCEDURE in_example (in param int )
	begin
		select param;
		set param=2;
		select param;
	end
//
delimiter ;


set @param=1;		-- 设置in参数
call in_example(@param);	-- 调用存储过程   1 2
select @param		-- 查询参数   1

ex:out参数

delimiter //
create procedure out_example (out param int)
	begin
		select param;
		set param=4;
		select param;		
	end
//
delimiter;

set @param=1;		
call out_example(@param);		-- null  4
select @param;					-- 4

ex:inout参数

delimiter //
  create procedure inout_example(inout param int)
    begin
      select param;
      set param=2;
      select param;
    end;
    //
delimiter;

set @param=1;
call inout_example(@param);		--	1 2
select @param;					-- 2

SQLServer存储过程创建
create proc proc_ht
	@htsno varchar,
	@swsid varchar
as
select * from ht_ht where ht_sno=@htsno and sws_id=@swsid

#调用
exec proc_ht @htsno=11663,@swsid=17;

el-input等显示框鼠标悬浮显示全部内容

场景:在使用element组件如el-input时,由于显示框长度受限,内容文本超出显示框长度,导致显示不全,解决办法:当鼠标在显示框停留时悬浮显示文本内容,鼠标移开不显示文本内容

使用elementUI的el-tooltip组件
<!--light为背景白色 dark为背景黑色-->
 <el-tooltip
   class="item"
    effect="light"
    :content="value"
    placement="top-start"
    :disabled="isShowTooltip"
>
	<el-input v-model="value" style="width:55%;"></el-input>
</el-tooltip>

// js代码
data(){
  return {
	  value:"",
	  isShowTooltip:false
  }
},
methods:{
  inputOnMouseOver(e){
    const target = event.target;
      // 判断是否开启tooltip功能
      if (target.offsetWidth < target.scrollWidth) {
        this.isShowTooltip = false;
      } else {
        this.isShowTooltip = true;
      }
  }
}
效果图

请添加图片描述

JS对象赋值,操作新对象影响原对象

场景:在写js代码时,原对象a,将a赋值b,操作b对象,结果a对象也跟着变化,影响其他地方调用a对象的结果。
//a.id=‘1’;
var b=a;
b.id=‘2’;
console.log(a.id); //2
console.log(b.id); //2

原因:JavaScript 中对象的赋值是默认引用赋值的(两个对象指向相同的内存地址)

法1:使用Object.assign() 深拷贝

Object.assign(obj) --浅拷贝
Object.assign({},obj) --深拷贝(只有第一层深拷贝)

// 使用 Object.assign() 方法复制对象
let obj1 = { a: 0 , b: { c: 0}};
let obj2 = Object.assign({}, obj1);
console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}}

obj2.a = 1;
console.log(JSON.stringify(obj1)); // { a: 0, b: { c: 0}}
console.log(JSON.stringify(obj2)); // { a: 1, b: { c: 0}}

obj2.b.c = 3;
console.log(JSON.stringify(obj1)); // { a: 0, b: { c: 3}}		//只有第一层深拷贝
console.log(JSON.stringify(obj2)); // { a: 1, b: { c: 3}}  


法2:使用 JSON.parse(JSON.stringify(obj))

//JSON.stringfy();    把对象转换成JSON字符串
//JSON.parse();		把JSON字符串转换成对象
let obj1 = { a: 0 , b: { c: 0}};
let obj2=JSON.parse( JSON.stringify(obj1) );

obj2.a=1;
console.log(JSON.stringify(obj1)); // { a: 0, b: { c: 0}}
console.log(JSON.stringify(obj2)); // { a: 1, b: { c: 0}}

# el-table在JS中赋值内容后表格数据刷新

场景:el-table的表格内容在js代码中赋值,但是表格内容无变化,需要增加刷新table的操作

无效情况:push()、pop(),实际效果不理想

this.fkgdTableData=res.data;		//table内容赋值
//刷新table数据 
this.fkgdTableData.push({});
this.fkgdTableData.pop();

解决方法:在el-table增加 :key,在赋值处随机设置key的值,使得el-table强制刷新

<el-table
  :data="fkgdTableData"
   :key="itemKey"
   height="400px"
>
</el-table>

//JS代码
//在赋值的方法中设置key的值 实现表格内容刷新
this.itemKey=Math.random();

java将数据处理成JSON树形结构

场景:数据库表有公司的部门关系表,需要根据部门关联关系在前端显示一个树形结构图;
思路:前端可使用tree相关组件,在后端查询部门数据并使用树形结构封装成JSON对象,传递给前端直接调用。

效果:

请添加图片描述

实现过程

1. 定义TreeNode实体类(定义树结构属性)
package com.broad.emc.entity;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;
import java.util.Objects;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class TreeNode {
    private Integer id;
    private String bmmc;
    private Integer pid;
    // children属性用于保存当前记录的子节点信息
    // 注意:数据中对应的实体没有该字段,我们可以从数据库中查询所有记录后,再使用BeanUtils或MapStruct相关工具进行转换
    private List<TreeNode> children;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        TreeNode treeNode = (TreeNode) o;
        return Objects.equals(id, treeNode.id) && Objects.equals(bmmc, treeNode.bmmc) && Objects.equals(pid, treeNode.pid) && Objects.equals(children, treeNode.children);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, bmmc, pid, children);
    }
}
2. 数据处理和封装(树节点关系:上下级关系为下级的pid=上级的id)
@RestController
@RequestMapping("/treeNode")
@Slf4j
public class infoController {
    /**
     * 单个父节点模式
     *
     * @return
     */
    @GetMapping("/oneFather")
    public TreeNode listOne() {
        List<TreeNode> nodes = new ArrayList<>();
        // 封装数据:模拟数据数据
        // 注意:从数据库中查询到的数据没有childrenNode属性,那我们可以使用BeanUtils和mapstruct进行对象转换
        // id可自定义 为避免重复可从10000开始自增
        Collections.addAll(nodes,
        		//根节点
                TreeNode.builder().id(1).pid(0).bmmc("xxxx公司").build(),
	                //子节点1
	                TreeNode.builder().id(2).pid(1).bmmc("总裁办").build(),
	                	//1.1
	                	TreeNode.builder().id(3).pid(2).bmmc("美术组").build(),
	                	//1.2
	                	TreeNode.builder().id(4).pid(2).bmmc("信息化部").build(),
	                		//1.2.1
	                		TreeNode.builder().id(5).pid(4).bmmc("软件开发课").build(),
	                 //子节点2
	                TreeNode.builder().id(6).pid(1).bmmc("人力部").build(),
					 //子节点3
	                TreeNode.builder().id(7).pid(1).bmmc("财经部").build()
               
        );
        // 获取树节点
        TreeNode root = nodes.stream().filter(node -> Objects.equals(node.getPid(), 0)).findFirst().orElse(null);
        if (root == null) {
            return null;
        }
        root.setChildren(getChildren(root, nodes));
        return root;
    }
 
    /**
     * 多个父节点模式
     *
     * @return
     */
    @GetMapping("/manyFather")
    public Set<TreeNode> listMany() {
        List<TreeNode> nodes = new ArrayList<>();
        // 封装数据
        Collections.addAll(nodes,
                TreeNode.builder().id(1).pid(0).name("江西省").build(),
                TreeNode.builder().id(2).pid(1).name("吉安市").build(),
                TreeNode.builder().id(3).pid(2).name("遂川县").build(),
                TreeNode.builder().id(5).pid(1).name("赣州市").build(),
                TreeNode.builder().id(6).pid(5).name("章贡").build(),
                TreeNode.builder().id(7).pid(0).name("浙江省").build(),
                TreeNode.builder().id(8).pid(7).name("杭州").build()
        );
        // 封装树节点
        Set<TreeNode> root = nodes.stream().filter(node -> Objects.equals(node.getPid(), 0)).collect(Collectors.toSet());
        if (CollectionUtils.isEmpty(root)) {
            return null;
        }
        // 遍历树节点
        root.stream().forEach(rootNode -> {
            rootNode.setChildrenNode(getChildren(rootNode, nodes));
        });
 
        return root;
    }
 
    /**
     * 递归获取根节点的子节点信息
     *
     * @param root  根节点
     * @param nodes 要遍历的节点
     * @return
     */
    private List<TreeNode> getChildren(TreeNode root, List<TreeNode> nodes) {
        List<TreeNode> childrenNodes = nodes.stream()
                // 使用stream流过滤出数据的父级id信息等于根节点的id信息的数据
                .filter(node -> Objects.equals(node.getPid(), root.getId()))
                .map(childNode -> {
                    // 同时使用map方法对每个过滤后的数据进行处理,递归找到其对应的子数据
                    childNode.setChildrenNode(getChildren(childNode, nodes));
                    return childNode;
                })
                .collect(Collectors.toList());
        return childrenNodes;
    }
}

调用单个父节点方法返回结果

{
    "id": 1,
    "bmmc": "xxxx公司",
    "pid": 0,
    "children": [
        {
            "id": 2,
            "bmmc": "总裁办",
            "pid": 1,
            "children": [
                {
                    "id": 3,
                    "bmmc": "美术组",
                    "pid": 2,
                    "children": []
                },
                {
                    "id": 4,
                    "bmmc": "信息化部",
                    "pid": 2,
                    "children": [
                        {
                            "id": 5,
                            "bmmc": "软件开发课",
                            "pid": 4,
                            "children": []
                        }
                    ]
                }
            ]
        },
        {
            "id": 6,
            "bmmc": "人力部",
            "pid": 1,
            "children": []
        },
        {
            "id": 7,
            "bmmc": "财经部",
            "pid": 1,
            "children": []
        }
    ]
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值